|
6 | 6 | import com.bettercloud.vault.json.Json; |
7 | 7 | import com.bettercloud.vault.json.JsonObject; |
8 | 8 | import com.bettercloud.vault.response.AuthResponse; |
| 9 | +import com.bettercloud.vault.response.LogicalResponse; |
9 | 10 | import com.bettercloud.vault.response.LookupResponse; |
10 | | -import com.bettercloud.vault.rest.RestResponse; |
11 | 11 | import com.bettercloud.vault.rest.Rest; |
| 12 | +import com.bettercloud.vault.rest.RestResponse; |
12 | 13 | import lombok.Getter; |
13 | 14 |
|
14 | 15 | import java.io.Serializable; |
| 16 | +import java.net.URI; |
15 | 17 | import java.util.List; |
16 | 18 | import java.util.Map; |
17 | 19 | import java.util.UUID; |
@@ -1084,17 +1086,17 @@ public AuthResponse renewSelf(final long increment, final String tokenAuthMount) |
1084 | 1086 |
|
1085 | 1087 | /** |
1086 | 1088 | * <p>Returns information about the current client token.</p> |
1087 | | - * |
| 1089 | + * |
1088 | 1090 | * @return The response information returned from Vault |
1089 | 1091 | * @throws VaultException If any error occurs, or unexpected response received from Vault |
1090 | 1092 | */ |
1091 | 1093 | public LookupResponse lookupSelf() throws VaultException { |
1092 | 1094 | return lookupSelf("token"); |
1093 | 1095 | } |
1094 | | - |
| 1096 | + |
1095 | 1097 | /** |
1096 | 1098 | * <p>Returns information about the current client token.</p> |
1097 | | - * |
| 1099 | + * |
1098 | 1100 | * @param tokenAuthMount The mount name of the token authentication back end. If null, defaults to "token" |
1099 | 1101 | * @return The response information returned from Vault |
1100 | 1102 | * @throws VaultException If any error occurs, or unexpected response received from Vault |
@@ -1142,6 +1144,68 @@ public LookupResponse lookupSelf(final String tokenAuthMount) throws VaultExcept |
1142 | 1144 | } |
1143 | 1145 | } |
1144 | 1146 |
|
| 1147 | + /** |
| 1148 | + * <p>Returns information about the current client token for a wrapped token, for which the lookup endpoint is |
| 1149 | + * different at "sys/wrapping/lookup". Example usage:</p> |
| 1150 | + * |
| 1151 | + * <blockquote> |
| 1152 | + * <pre>{@code |
| 1153 | + * final String wrappingToken = "..."; |
| 1154 | + * final VaultConfig config = new VaultConfig().address(...).token(wrappingToken).build(); |
| 1155 | + * final Vault vault = new Vault(config); |
| 1156 | + * final LogicalResponse response = vault.auth().lookupWarp(); |
| 1157 | + * // Then you can validate "path" for example ... |
| 1158 | + * final String path = response.getData().get("path"); |
| 1159 | + * }</pre> |
| 1160 | + * </blockquote> |
| 1161 | + * |
| 1162 | + * @return The response information returned from Vault |
| 1163 | + * @throws VaultException If any error occurs, or unexpected response received from Vault |
| 1164 | + */ |
| 1165 | + public LogicalResponse lookupWrap() throws VaultException { |
| 1166 | + int retryCount = 0; |
| 1167 | + while (true) { |
| 1168 | + try { |
| 1169 | + // HTTP request to Vault |
| 1170 | + final RestResponse restResponse = new Rest()//NOPMD |
| 1171 | + .url(config.getAddress() + "/v1/sys/wrapping/lookup") |
| 1172 | + .header("X-Vault-Token", config.getToken()) |
| 1173 | + .connectTimeoutSeconds(config.getOpenTimeout()) |
| 1174 | + .readTimeoutSeconds(config.getReadTimeout()) |
| 1175 | + .sslVerification(config.getSslConfig().isVerify()) |
| 1176 | + .sslContext(config.getSslConfig().getSslContext()) |
| 1177 | + .get(); |
| 1178 | + // Validate restResponse |
| 1179 | + if (restResponse.getStatus() != 200) { |
| 1180 | + throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus(), |
| 1181 | + restResponse.getStatus()); |
| 1182 | + } |
| 1183 | + final String mimeType = restResponse.getMimeType(); |
| 1184 | + if (mimeType == null || !"application/json".equals(mimeType)) { |
| 1185 | + throw new VaultException("Vault responded with MIME type: " + mimeType, restResponse.getStatus()); |
| 1186 | + } |
| 1187 | + return new LogicalResponse(restResponse, retryCount); |
| 1188 | + } catch (Exception e) { |
| 1189 | + // If there are retries to perform, then pause for the configured interval and then execute the loop |
| 1190 | + // again... |
| 1191 | + if (retryCount < config.getMaxRetries()) { |
| 1192 | + retryCount++; |
| 1193 | + try { |
| 1194 | + final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds(); |
| 1195 | + Thread.sleep(retryIntervalMilliseconds); |
| 1196 | + } catch (InterruptedException e1) { |
| 1197 | + e1.printStackTrace(); //NOPMD |
| 1198 | + } |
| 1199 | + } else if (e instanceof VaultException) { //NOPMD |
| 1200 | + // ... otherwise, give up. |
| 1201 | + throw (VaultException) e; |
| 1202 | + } else { |
| 1203 | + throw new VaultException(e); |
| 1204 | + } |
| 1205 | + } |
| 1206 | + } |
| 1207 | + } |
| 1208 | + |
1145 | 1209 | /** |
1146 | 1210 | * <p>Revokes current client token.</p> |
1147 | 1211 | * |
@@ -1196,4 +1260,111 @@ public void revokeSelf(final String tokenAuthMount) throws VaultException { |
1196 | 1260 | } |
1197 | 1261 | } |
1198 | 1262 |
|
| 1263 | + /** |
| 1264 | + * <p>Returns the original response inside the wrapped auth token. This method is useful if you need to unwrap a |
| 1265 | + * token without being authenticated. See {@link #unwrap(String)} if you need to do that authenticated.</p> |
| 1266 | + * |
| 1267 | + * <p>In the example below, you cannot use twice the {@code VaultConfig}, since |
| 1268 | + * after the first usage of the {@code wrappingToken}, it is not usable anymore. You need to use the |
| 1269 | + * {@code unwrappedToken} in a new vault configuration to continue. Example usage:</p> |
| 1270 | + * |
| 1271 | + * <blockquote> |
| 1272 | + * <pre>{@code |
| 1273 | + * final String wrappingToken = "..."; |
| 1274 | + * final VaultConfig config = new VaultConfig().address(...).token(wrappingToken).build(); |
| 1275 | + * final Vault vault = new Vault(config); |
| 1276 | + * final AuthResponse response = vault.auth().unwrap(); |
| 1277 | + * final String unwrappedToken = response.getAuthClientToken(); |
| 1278 | + * }</pre> |
| 1279 | + * </blockquote> |
| 1280 | + * |
| 1281 | + * @return The response information returned from Vault |
| 1282 | + * @throws VaultException If any error occurs, or unexpected response received from Vault |
| 1283 | + * @see #unwrap(String) |
| 1284 | + */ |
| 1285 | + public AuthResponse unwrap() throws VaultException { |
| 1286 | + return unwrap(null); |
| 1287 | + } |
| 1288 | + |
| 1289 | + /** |
| 1290 | + * <p>Returns the original response inside the given wrapped auth token. This method is useful if you need to unwrap |
| 1291 | + * a token, while being already authenticated. Do NOT authenticate in vault with your wrapping token, since it will |
| 1292 | + * both fail authentication and invalidate the wrapping token at the same time. See {@link #unwrap()} if you need to |
| 1293 | + * do that without being authenticated.</p> |
| 1294 | + * |
| 1295 | + * <p>In the example below, {@code authToken} is NOT your wrapped token, and should have unwrapping permissions. |
| 1296 | + * The unwrapped token in {@code unwrappedToken}. Example usage:</p> |
| 1297 | + * |
| 1298 | + * <blockquote> |
| 1299 | + * <pre>{@code |
| 1300 | + * final String authToken = "..."; |
| 1301 | + * final String wrappingToken = "..."; |
| 1302 | + * final VaultConfig config = new VaultConfig().address(...).token(authToken).build(); |
| 1303 | + * final Vault vault = new Vault(config); |
| 1304 | + * final AuthResponse response = vault.auth().unwrap(wrappingToken); |
| 1305 | + * final String unwrappedToken = response.getAuthClientToken(); |
| 1306 | + * }</pre> |
| 1307 | + * </blockquote> |
| 1308 | + * |
| 1309 | + * @param wrappedToken Specifies the wrapping token ID, do NOT also put this in your {@link VaultConfig#token}, |
| 1310 | + * if token is {@code null}, this method will unwrap the auth token in {@link VaultConfig#token} |
| 1311 | + * @return The response information returned from Vault |
| 1312 | + * @throws VaultException If any error occurs, or unexpected response received from Vault |
| 1313 | + * @see #unwrap() |
| 1314 | + */ |
| 1315 | + public AuthResponse unwrap(final String wrappedToken) throws VaultException { |
| 1316 | + int retryCount = 0; |
| 1317 | + while (true) { |
| 1318 | + try { |
| 1319 | + // Parse parameters to JSON |
| 1320 | + final JsonObject jsonObject = Json.object(); |
| 1321 | + if (wrappedToken != null) { |
| 1322 | + jsonObject.add("token", wrappedToken); |
| 1323 | + } |
| 1324 | + |
| 1325 | + final String requestJson = jsonObject.toString(); |
| 1326 | + final String url = config.getAddress() + "/v1/sys/wrapping/unwrap"; |
| 1327 | + |
| 1328 | + // HTTP request to Vault |
| 1329 | + final RestResponse restResponse = new Rest() |
| 1330 | + .url(url) |
| 1331 | + .header("X-Vault-Token", config.getToken()) |
| 1332 | + .body(requestJson.getBytes("UTF-8")) |
| 1333 | + .connectTimeoutSeconds(config.getOpenTimeout()) |
| 1334 | + .readTimeoutSeconds(config.getReadTimeout()) |
| 1335 | + .sslVerification(config.getSslConfig().isVerify()) |
| 1336 | + .sslContext(config.getSslConfig().getSslContext()) |
| 1337 | + .post(); |
| 1338 | + |
| 1339 | + // Validate restResponse |
| 1340 | + if (restResponse.getStatus() != 200) { |
| 1341 | + throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus(), |
| 1342 | + restResponse.getStatus()); |
| 1343 | + } |
| 1344 | + final String mimeType = restResponse.getMimeType() == null ? "null" : restResponse.getMimeType(); |
| 1345 | + if (!mimeType.equals("application/json")) { |
| 1346 | + throw new VaultException("Vault responded with MIME type: " + mimeType, restResponse.getStatus()); |
| 1347 | + } |
| 1348 | + return new AuthResponse(restResponse, retryCount); |
| 1349 | + } catch (final Exception e) { |
| 1350 | + // If there are retries to perform, then pause for the configured interval and then execute the |
| 1351 | + // loop again... |
| 1352 | + if (retryCount < config.getMaxRetries()) { |
| 1353 | + retryCount++; |
| 1354 | + try { |
| 1355 | + final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds(); |
| 1356 | + Thread.sleep(retryIntervalMilliseconds); |
| 1357 | + } catch (InterruptedException e1) { |
| 1358 | + e1.printStackTrace(); |
| 1359 | + } |
| 1360 | + } else if (e instanceof VaultException) { |
| 1361 | + // ... otherwise, give up. |
| 1362 | + throw (VaultException) e; |
| 1363 | + } else { |
| 1364 | + throw new VaultException(e); |
| 1365 | + } |
| 1366 | + } |
| 1367 | + } |
| 1368 | + } |
| 1369 | + |
1199 | 1370 | } |
0 commit comments