-
Notifications
You must be signed in to change notification settings - Fork 223
/
Copy pathLogicalUtilities.java
204 lines (189 loc) · 8.46 KB
/
LogicalUtilities.java
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package com.bettercloud.vault.api;
import com.bettercloud.vault.json.JsonObject;
import java.util.Arrays;
import java.util.List;
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) {
return Arrays.asList(path.split("/"));
}
/**
* 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 prefixPathLength prefixPathLength
* @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) {
if (operation.equals(Logical.logicalOperations.readV2) || operation
.equals(Logical.logicalOperations.writeV2)) {
// Version 2
final List<String> pathSegments = getPathSegments(path);
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 prefixPathDepth prefixPathDepth
* @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 StringBuilder adjustedPath = new StringBuilder();
if (operation.equals(Logical.logicalOperations.listV2)) {
// Version 2
final List<String> pathSegments = getPathSegments(path);
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 prefixPathDepth prefixPathDepth
* @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) {
if (operation.equals(Logical.logicalOperations.deleteV2)) {
final List<String> pathSegments = getPathSegments(path);
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.
* @param prefixPathDepth prefixPathDepth
* @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.
* @param prefixPathDepth prefixPathDepth
* @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.
* @param prefixPathDepth prefixPathDepth
* @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;
}
}
}