-
Notifications
You must be signed in to change notification settings - Fork 224
Expand file tree
/
Copy pathLogicalUtilities.java
More file actions
187 lines (172 loc) · 8.25 KB
/
LogicalUtilities.java
File metadata and controls
187 lines (172 loc) · 8.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package com.bettercloud.vault.api;
import com.bettercloud.vault.json.JsonObject;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class LogicalUtilities {
/**
* Convenience method to split a Vault path into its path segments.
*
* @param path The Vault path to check or mutate, based on the operation.
* @return The path potentially mutated, based on the operation
*/
private static List<String> getPathSegments(final String path) {
final List<String> segments = new ArrayList<>();
final StringTokenizer tokenizer = new StringTokenizer(path, "/");
while (tokenizer.hasMoreTokens()) {
segments.add(tokenizer.nextToken());
}
return segments;
}
/**
* Injects the supplied qualifier (either "data" or "metadata") into the second-from-the-root segment position, for a Vault
* path to be converted for use with a Version 2 secret engine.
*
* @param segments The Vault path split into segments.
* @param prefixPathDepth number of path elements in the prefix part of
* the path (the part before the qualifier)
* @param qualifier The String to add to the path, based on the operation.
* @return The final path with the needed qualifier.
*/
public static String addQualifierToPath(final List<String> segments, final int prefixPathDepth, final String qualifier) {
final StringBuilder adjustedPath = new StringBuilder();
int index;
for (index=0;index < prefixPathDepth;index++) {
adjustedPath.append(segments.get(index))
.append('/');
}
adjustedPath.append(qualifier);
for (;index < segments.size(); index++) {
adjustedPath.append('/')
.append(segments.get(index));
}
return adjustedPath.toString();
}
/**
* In version 1 style secret engines, the same path is used for all CRUD operations on a secret. In version 2 though, the
* path varies depending on the operation being performed. When reading or writing a secret, you must inject the path
* segment "data" right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
* @param operation The operation being performed, e.g. readV2 or writeV1.
* @return The Vault path mutated based on the operation.
*/
public static String adjustPathForReadOrWrite(final String path, final int prefixPathLength,final Logical.logicalOperations operation) {
final List<String> pathSegments = getPathSegments(path);
if (operation.equals(Logical.logicalOperations.readV2) || operation.equals(Logical.logicalOperations.writeV2)) {
// Version 2
final StringBuilder adjustedPath = new StringBuilder(addQualifierToPath(pathSegments, prefixPathLength, "data"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
return adjustedPath.toString();
} else {
// Version 1
return path;
}
}
/**
* In version 1 style secret engines, the same path is used for all CRUD operations on a secret. In version 2 though, the
* path varies depending on the operation being performed. When listing secrets available beneath a path, you must inject the
* path segment "metadata" right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
* @param operation The operation being performed, e.g. readV2 or writeV1.
* @return The Vault path mutated based on the operation.
*/
public static String adjustPathForList(final String path, int prefixPathDepth, final Logical.logicalOperations operation) {
final List<String> pathSegments = getPathSegments(path);
final StringBuilder adjustedPath = new StringBuilder();
if (operation.equals(Logical.logicalOperations.listV2)) {
// Version 2
adjustedPath.append(addQualifierToPath(pathSegments, prefixPathDepth, "metadata"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
} else {
// Version 1
adjustedPath.append(path);
}
adjustedPath.append("?list=true");
return adjustedPath.toString();
}
/**
* In version 1 style secret engines, the same path is used for all CRUD operations on a secret. In version 2 though, the
* path varies depending on the operation being performed. When deleting secrets, you must inject the path segment "metadata"
* right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
* @param operation The operation being performed, e.g. readV2 or writeV1.
*
* @return The modified path
*/
public static String adjustPathForDelete(final String path, final int prefixPathDepth, final Logical.logicalOperations operation) {
final List<String> pathSegments = getPathSegments(path);
if (operation.equals(Logical.logicalOperations.deleteV2)) {
final StringBuilder adjustedPath = new StringBuilder(addQualifierToPath(pathSegments, prefixPathDepth, "metadata"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
return adjustedPath.toString();
} else {
return path;
}
}
/**
* When deleting secret versions, you must inject the path segment "delete" right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
*
* @return The modified path
*/
public static String adjustPathForVersionDelete(final String path,final int prefixPathDepth) {
final List<String> pathSegments = getPathSegments(path);
final StringBuilder adjustedPath = new StringBuilder(addQualifierToPath(pathSegments, prefixPathDepth, "delete"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
return adjustedPath.toString();
}
/**
* When undeleting secret versions, you must inject the path segment "undelete" right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
* @return The path mutated depending on the operation.
*/
public static String adjustPathForVersionUnDelete(final String path, final int prefixPathDepth) {
final List<String> pathSegments = getPathSegments(path);
final StringBuilder adjustedPath = new StringBuilder(addQualifierToPath(pathSegments, prefixPathDepth, "undelete"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
return adjustedPath.toString();
}
/**
* When destroying secret versions, you must inject the path segment "destroy" right after the lowest-level path segment.
*
* @param path The Vault path to check or mutate, based on the operation.
* @return The path mutated depending on the operation.
*/
public static String adjustPathForVersionDestroy(final String path,final int prefixPathDepth) {
final List<String> pathSegments = getPathSegments(path);
final StringBuilder adjustedPath = new StringBuilder(addQualifierToPath(pathSegments, prefixPathDepth, "destroy"));
if (path.endsWith("/")) {
adjustedPath.append("/");
}
return adjustedPath.toString();
}
/**
* In version two, when writing a secret, the JSONObject must be nested with "data" as the key.
*
* @param operation The operation being performed, e.g. writeV1, or writeV2.
* @param jsonObject The jsonObject that is going to be written.
* @return This jsonObject mutated for the operation.
*/
public static JsonObject jsonObjectToWriteFromEngineVersion(final Logical.logicalOperations operation, final JsonObject jsonObject) {
if (operation.equals(Logical.logicalOperations.writeV2)) {
final JsonObject wrappedJson = new JsonObject();
wrappedJson.add("data", jsonObject);
return wrappedJson;
} else return jsonObject;
}
}