You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ra...@apache.org on 2026/09/11 08:56:20 UTC
(ranger) 30/34: RANGER-5716: Fix swapped client IP and resource in KMS Ranger audits (#1118)
This is an automated email from the ASF dual-hosted git repository.
ramackri pushed a commit to branch backport-audit-spiffe-2.10
in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 7808aaf148f00de5e66970437f9c9be26c50cb15
Author: Ramachandran Krishnan <ra...@gmail.com>
AuthorDate: Fri Jul 31 07:39:14 2026 +0530
RANGER-5716: Fix swapped client IP and resource in KMS Ranger audits (#1118)
Pass the HTTP client address and key name to the correct assertAccess
overload for invalidate cache and reencrypt operations so Ranger audit
records show the real client IP and key resource instead of swapping them.
Co-authored-by: ramk <ra...@cloudera.com>
(cherry picked from commit b4fd13c20be154e7fc0b1377f16ea5b5c1327e12)
---
.../apache/hadoop/crypto/key/kms/server/KMS.java | 1067 ++++++++++---------
.../hadoop/crypto/key/kms/server/TestKMS.java | 1099 +++++++-------------
2 files changed, 924 insertions(+), 1242 deletions(-)
diff --git a/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java b/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java
index cab5bbd2d..424e89aa7 100644
--- a/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java
+++ b/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,29 +17,35 @@
*/
package org.apache.hadoop.crypto.key.kms.server;
-import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
-import org.apache.hadoop.thirdparty.com.google.common.base.Stopwatch;
-import org.apache.hadoop.util.KMSUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProvider.KeyVersion;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion;
+import org.apache.hadoop.crypto.key.kms.KMSClientProvider.KMSEncryptedKeyVersion;
+import org.apache.hadoop.crypto.key.kms.KMSClientProvider.KMSKeyVersion;
import org.apache.hadoop.crypto.key.kms.KMSRESTConstants;
+import org.apache.hadoop.crypto.key.kms.server.KMSACLsType.Type;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.crypto.key.kms.KMSClientProvider.KMSKeyVersion;
-import org.apache.hadoop.crypto.key.kms.KMSClientProvider.KMSEncryptedKeyVersion;
-import org.apache.hadoop.crypto.key.kms.server.KMSACLsType.Type;
import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation;
-import javax.ws.rs.core.UriBuilder;
+import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
+import org.apache.hadoop.thirdparty.com.google.common.base.Stopwatch;
+import org.apache.hadoop.util.KMSUtil;
+import org.apache.ranger.kms.metrics.KMSMetricWrapper;
+import org.apache.ranger.kms.metrics.KMSMetrics;
+import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector;
+import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector.APIMetric;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -48,6 +54,7 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
@@ -60,709 +67,737 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.ranger.kms.metrics.KMSMetricWrapper;
-import org.apache.ranger.kms.metrics.KMSMetrics;
-import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector;
-import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector.APIMetric;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import static org.apache.hadoop.util.KMSUtil.checkNotEmpty;
import static org.apache.hadoop.util.KMSUtil.checkNotNull;
+
/**
* Class providing the REST bindings, via Jersey, for the KMS.
*/
@Path(KMSRESTConstants.SERVICE_VERSION)
@InterfaceAudience.Private
public class KMS {
- static final Logger LOG = LoggerFactory.getLogger(KMS.class);
+ static final Logger LOG = LoggerFactory.getLogger(KMS.class);
- private static final String KEY_NAME_VALIDATION = "[a-z,A-Z,0-9](?!.*--)(?!.*__)(?!.*-_)(?!.*_-)[\\w\\-\\_]*";
- private static final int MAX_NUM_PER_BATCH = 10000;
+ private static final String KEY_NAME_VALIDATION = "[a-z,A-Z,0-9](?!.*--)(?!.*__)(?!.*-_)(?!.*_-)[\\w\\-\\_]*";
+ private static final int MAX_NUM_PER_BATCH = 10000;
+ private static final String GENERATE_DEK_PATH_CONST = "_dek";
+ private static final int DEFAULT_KEY_SIZE = 256;
- private final static String GENERATE_DEK_PATH_CONST = "_dek";
+ private final KeyProviderCryptoExtension provider;
+ private final KMSAudit kmsAudit;
+ private final KMSMetricsCollector kmsMetricsCollector;
- public enum KMSOp {
- CREATE_KEY, DELETE_KEY, ROLL_NEW_VERSION, INVALIDATE_CACHE,
- GET_KEYS, GET_KEYS_METADATA,
- GET_KEY_VERSIONS, GET_METADATA, GET_KEY_VERSION, GET_CURRENT_KEY,
- GENERATE_EEK, DECRYPT_EEK, REENCRYPT_EEK, REENCRYPT_EEK_BATCH
- }
-
-
- private final KeyProviderCryptoExtension provider;
- private final KMSAudit kmsAudit;
+ public KMS() throws Exception {
+ this.provider = KMSWebApp.getKeyProvider();
+ this.kmsAudit = KMSWebApp.getKMSAudit();
+ this.kmsMetricsCollector = KMSMetricWrapper.getInstance(KMSWebApp.isMetricCollectionThreadSafe()).getKmsMetricsCollector();
+ }
- private KMSMetricsCollector kmsMetricsCollector;
+ @POST
+ @Path(KMSRESTConstants.KEYS_RESOURCE)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @SuppressWarnings("unchecked")
+ public Response createKey(Map jsonKey, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> createKey()");
- public KMS() throws Exception {
- provider = KMSWebApp.getKeyProvider();
- kmsAudit = KMSWebApp.getKMSAudit();
- this.kmsMetricsCollector = KMSMetricWrapper.getInstance(KMSWebApp.isMetricCollectionThreadSafe()).getKmsMetricsCollector();
- }
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.KEY_CREATE_COUNT, KMSMetrics.KMSMetric.KEY_CREATE_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- @POST
- @Path(KMSRESTConstants.KEYS_RESOURCE)
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @SuppressWarnings("unchecked")
- public Response createKey(Map jsonKey, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> createKey()");
+ final UserGroupInformation user = HttpUserGroupInformation.get();
+ final String name = (String) jsonKey.get(KMSRESTConstants.NAME_FIELD);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.KEY_CREATE_COUNT, KMSMetrics.KMSMetric.KEY_CREATE_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ checkNotEmpty(name, KMSRESTConstants.NAME_FIELD);
- final UserGroupInformation user = HttpUserGroupInformation.get();
- final String name = (String) jsonKey.get(KMSRESTConstants.NAME_FIELD);
+ validateKeyName(name);
- checkNotEmpty(name, KMSRESTConstants.NAME_FIELD);
+ assertAccess(Type.CREATE, user, KMSOp.CREATE_KEY, name, getClientIp(request));
- validateKeyName(name);
+ final String cipher = (String) jsonKey.get(KMSRESTConstants.CIPHER_FIELD);
+ final String material = (String) jsonKey.get(KMSRESTConstants.MATERIAL_FIELD);
+ final int length = (jsonKey.containsKey(KMSRESTConstants.LENGTH_FIELD)) ? (Integer) jsonKey.get(KMSRESTConstants.LENGTH_FIELD) : DEFAULT_KEY_SIZE;
+ final String description = (String) jsonKey.get(KMSRESTConstants.DESCRIPTION_FIELD);
- assertAccess(Type.CREATE, user, KMSOp.CREATE_KEY, name, getClientIp(request));
+ LOG.debug("Creating key: name={}, cipher={}, keyLength={}, description={}", name, cipher, length, description);
- final String cipher = (String) jsonKey.get(KMSRESTConstants.CIPHER_FIELD);
- final String material = (String) jsonKey.get(KMSRESTConstants.MATERIAL_FIELD);
- final int length = (jsonKey.containsKey(KMSRESTConstants.LENGTH_FIELD)) ? (Integer) jsonKey.get(KMSRESTConstants.LENGTH_FIELD) : 0;
- final String description = (String) jsonKey.get(KMSRESTConstants.DESCRIPTION_FIELD);
+ Map<String, String> attributes = (Map<String, String>) jsonKey.get(KMSRESTConstants.ATTRIBUTES_FIELD);
- LOG.debug("Creating key: name={}, cipher={}, keyLength={}, description={}", name, cipher, length, description);
+ if (material != null) {
+ assertAccess(Type.SET_KEY_MATERIAL, user, KMSOp.CREATE_KEY, name, getClientIp(request));
+ }
- Map<String, String> attributes = (Map<String, String>) jsonKey.get(KMSRESTConstants.ATTRIBUTES_FIELD);
+ final KeyProvider.Options options = new KeyProvider.Options(KMSWebApp.getConfiguration());
- if (material != null) {
- assertAccess(Type.SET_KEY_MATERIAL, user, KMSOp.CREATE_KEY, name, getClientIp(request));
- }
+ if (cipher != null) {
+ options.setCipher(cipher);
+ }
- final KeyProvider.Options options = new KeyProvider.Options(KMSWebApp.getConfiguration());
+ if (length != 0) {
+ options.setBitLength(length);
+ }
- if (cipher != null) {
- options.setCipher(cipher);
- }
+ options.setDescription(description);
+ options.setAttributes(attributes);
- if (length != 0) {
- options.setBitLength(length);
- }
+ KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
+ final KeyVersion ret;
- options.setDescription(description);
- options.setAttributes(attributes);
+ if (material != null) {
+ ret = provider.createKey(name, Base64.decodeBase64(material), options);
+ } else {
+ ret = provider.createKey(name, options);
+ }
- KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
- final KeyVersion ret;
+ provider.flush();
- if (material != null) {
- ret = provider.createKey(name, Base64.decodeBase64(material), options);
- } else {
- ret = provider.createKey(name, options);
- }
+ return ret;
+ });
- provider.flush();
+ kmsAudit.ok(user, KMSOp.CREATE_KEY, name, "UserProvidedMaterial:" + (material != null) + " Description:" + description);
- return ret;
- });
+ if (!KMSWebApp.getACLs().hasAccess(Type.GET, user, getClientIp(request))) {
+ keyVersion = removeKeyMaterial(keyVersion);
+ }
- kmsAudit.ok(user, KMSOp.CREATE_KEY, name, "UserProvidedMaterial:" + (material != null) + " Description:" + description);
+ Map json = KMSUtil.toJSON(keyVersion);
+ String requestURL = KMSMDCFilter.getURL();
+ int idx = requestURL.lastIndexOf(KMSRESTConstants.KEYS_RESOURCE);
- if (!KMSWebApp.getACLs().hasAccess(Type.GET, user, getClientIp(request))) {
- keyVersion = removeKeyMaterial(keyVersion);
- }
+ requestURL = requestURL.substring(0, idx);
+ URI locationURI = getKeyURI(requestURL, name);
- Map json = KMSUtil.toJSON(keyVersion);
- String requestURL = KMSMDCFilter.getURL();
- int idx = requestURL.lastIndexOf(KMSRESTConstants.KEYS_RESOURCE);
+ Response response = Response.created(locationURI)
+ .type(MediaType.APPLICATION_JSON)
+ .entity(json)
+ .build();
+ return response;
+ } catch (Exception e) {
+ LOG.error("Exception in createKey.", e);
- requestURL = requestURL.substring(0, idx);
+ throw e;
+ } finally {
+ LOG.debug("<== createKey()");
+ }
+ }
- return Response.created(getKeyURI(KMSRESTConstants.SERVICE_VERSION, name)).type(MediaType.APPLICATION_JSON).header("Location", getKeyURI(requestURL, name)).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in createKey.", e);
- throw e;
- } finally {
- LOG.debug("<== createKey()");
+ /**
+ * Handles OPTIONS requests for the root v1 resource (e.g., /kms/v1/).
+ * This is required for the Kerberos/SPNEGO authentication handshake.
+ */
+ @OPTIONS
+ public Response getOptions() {
+ return Response.ok().build();
}
- }
- @DELETE
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
- public Response deleteKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> deleteKey({})", name);
+ @DELETE
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
+ public Response deleteKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> deleteKey({})", name);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.DELETE_KEY_COUNT, KMSMetrics.KMSMetric.DELETE_KEY_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.DELETE_KEY_COUNT, KMSMetrics.KMSMetric.DELETE_KEY_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- assertAccess(Type.DELETE, user, KMSOp.DELETE_KEY, name, getClientIp(request));
+ assertAccess(Type.DELETE, user, KMSOp.DELETE_KEY, name, getClientIp(request));
- checkNotEmpty(name, "name");
+ checkNotEmpty(name, "name");
- user.doAs((PrivilegedExceptionAction<Void>) () -> {
- provider.deleteKey(name);
+ user.doAs((PrivilegedExceptionAction<Void>) () -> {
+ provider.deleteKey(name);
- provider.flush();
+ provider.flush();
- return null;
- });
+ return null;
+ });
- kmsAudit.ok(user, KMSOp.DELETE_KEY, name, "");
+ kmsAudit.ok(user, KMSOp.DELETE_KEY, name, "");
- return Response.ok().build();
- } catch (Exception e) {
- LOG.error("Exception in deleteKey.", e);
- throw e;
- } finally {
- LOG.debug("<== deleteKey({})", name);
+ return Response.ok().build();
+ } catch (Exception e) {
+ LOG.error("Exception in deleteKey.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== deleteKey({})", name);
+ }
}
- }
- @POST
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response rolloverKey(@PathParam("name") final String name, Map jsonMaterial, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> rolloverKey({})", name);
+ @POST
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response rolloverKey(@PathParam("name") final String name, Map jsonMaterial, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> rolloverKey({})", name);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.ROLL_NEW_VERSION_COUNT, KMSMetrics.KMSMetric.ROLL_NEW_VERSION_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.ROLL_NEW_VERSION_COUNT, KMSMetrics.KMSMetric.ROLL_NEW_VERSION_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- assertAccess(Type.ROLLOVER, user, KMSOp.ROLL_NEW_VERSION, name, getClientIp(request));
+ assertAccess(Type.ROLLOVER, user, KMSOp.ROLL_NEW_VERSION, name, getClientIp(request));
- checkNotEmpty(name, "name");
+ checkNotEmpty(name, "name");
- final String material = (String) jsonMaterial.get(KMSRESTConstants.MATERIAL_FIELD);
+ final String material = (String) jsonMaterial.get(KMSRESTConstants.MATERIAL_FIELD);
- if (material != null) {
- assertAccess(Type.SET_KEY_MATERIAL, user, KMSOp.ROLL_NEW_VERSION, name, getClientIp(request));
- }
+ if (material != null) {
+ assertAccess(Type.SET_KEY_MATERIAL, user, KMSOp.ROLL_NEW_VERSION, name, getClientIp(request));
+ }
- KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
- final KeyVersion ret;
+ KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
+ final KeyVersion ret;
- if (material != null) {
- ret = provider.rollNewVersion(name, Base64.decodeBase64(material));
- } else {
- ret = provider.rollNewVersion(name);
- }
+ if (material != null) {
+ ret = provider.rollNewVersion(name, Base64.decodeBase64(material));
+ } else {
+ ret = provider.rollNewVersion(name);
+ }
- provider.flush();
+ provider.flush();
- return ret;
- });
+ return ret;
+ });
- kmsAudit.ok(user, KMSOp.ROLL_NEW_VERSION, name, "UserProvidedMaterial:" + (material != null) + " NewVersion:" + keyVersion.getVersionName());
+ kmsAudit.ok(user, KMSOp.ROLL_NEW_VERSION, name, "UserProvidedMaterial:" + (material != null) + " NewVersion:" + keyVersion.getVersionName());
- if (!KMSWebApp.getACLs().hasAccess(Type.GET, user, getClientIp(request))) {
- keyVersion = removeKeyMaterial(keyVersion);
- }
+ if (!KMSWebApp.getACLs().hasAccess(Type.GET, user, getClientIp(request))) {
+ keyVersion = removeKeyMaterial(keyVersion);
+ }
- Map json = KMSUtil.toJSON(keyVersion);
+ Map json = KMSUtil.toJSON(keyVersion);
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in rolloverKey.", e);
- throw e;
- } finally {
- LOG.debug("<== rolloverKey({})", name);
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in rolloverKey.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== rolloverKey({})", name);
+ }
}
- }
- @POST
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.INVALIDATECACHE_RESOURCE)
- public Response invalidateCache(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> invalidateCache({})", name);
+ @POST
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.INVALIDATECACHE_RESOURCE)
+ public Response invalidateCache(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> invalidateCache({})", name);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.INVALIDATE_CACHE_COUNT, KMSMetrics.KMSMetric.INVALIDATE_CACHE_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.INVALIDATE_CACHE_COUNT, KMSMetrics.KMSMetric.INVALIDATE_CACHE_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- checkNotEmpty(name, "name");
+ checkNotEmpty(name, "name");
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- assertAccess(Type.ROLLOVER, user, KMSOp.INVALIDATE_CACHE, name, getClientIp(request));
+ assertAccess(Type.ROLLOVER, user, KMSOp.INVALIDATE_CACHE, name, getClientIp(request));
- user.doAs((PrivilegedExceptionAction<Void>) () -> {
- provider.invalidateCache(name);
+ user.doAs((PrivilegedExceptionAction<Void>) () -> {
+ provider.invalidateCache(name);
- provider.flush();
+ provider.flush();
- return null;
- });
+ return null;
+ });
- kmsAudit.ok(user, KMSOp.INVALIDATE_CACHE, name, "");
+ kmsAudit.ok(user, KMSOp.INVALIDATE_CACHE, name, "");
+
+ return Response.ok().build();
+ } catch (Exception e) {
+ LOG.error("Exception in invalidateCache for key name {}.", name, e);
- return Response.ok().build();
- } catch (Exception e) {
- LOG.error("Exception in invalidateCache for key name {}.", name, e);
- throw e;
- } finally {
- LOG.debug("<== invalidateCache({})", name);
+ throw e;
+ } finally {
+ LOG.debug("<== invalidateCache({})", name);
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEYS_METADATA_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getKeysMetadata(@QueryParam(KMSRESTConstants.KEY) List<String> keyNamesList, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getKeysMetadata()");
+ @GET
+ @Path(KMSRESTConstants.KEYS_METADATA_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getKeysMetadata(@QueryParam(KMSRESTConstants.KEY) List<String> keyNamesList, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getKeysMetadata()");
+
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_COUNT, KMSMetrics.KMSMetric.GET_KEYS_METADATA_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
+
+ final UserGroupInformation user = HttpUserGroupInformation.get();
+ final String[] keyNames = keyNamesList.toArray(new String[0]);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_COUNT, KMSMetrics.KMSMetric.GET_KEYS_METADATA_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ assertAccess(Type.GET_METADATA, user, KMSOp.GET_KEYS_METADATA, getClientIp(request));
- final UserGroupInformation user = HttpUserGroupInformation.get();
- final String[] keyNames = keyNamesList.toArray(new String[0]);
+ KeyProvider.Metadata[] keysMeta = user.doAs((PrivilegedExceptionAction<KeyProvider.Metadata[]>) () -> provider.getKeysMetadata(keyNames));
+ Object json = KMSServerJSONUtils.toJSON(keyNames, keysMeta);
- assertAccess(Type.GET_METADATA, user, KMSOp.GET_KEYS_METADATA, getClientIp(request));
+ this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_KEYNAMES_COUNT, keyNames.length);
- KeyProvider.Metadata[] keysMeta = user.doAs((PrivilegedExceptionAction<KeyProvider.Metadata[]>) () -> provider.getKeysMetadata(keyNames));
- Object json = KMSServerJSONUtils.toJSON(keyNames, keysMeta);
- this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_KEYNAMES_COUNT, keyNames.length);
+ kmsAudit.ok(user, KMSOp.GET_KEYS_METADATA, "");
- kmsAudit.ok(user, KMSOp.GET_KEYS_METADATA, "");
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getKeysmetadata.", e);
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getKeysMetadata.", e);
- throw e;
- } finally {
- LOG.debug("<== getKeysMetadata()");
+ throw e;
+ } finally {
+ LOG.debug("<== getKeysMetadata()");
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEYS_NAMES_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getKeyNames(@Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getKeyNames()");
+ @GET
+ @Path(KMSRESTConstants.KEYS_NAMES_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getKeyNames(@Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getKeyNames()");
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_COUNT, KMSMetrics.KMSMetric.GET_KEYS_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_COUNT, KMSMetrics.KMSMetric.GET_KEYS_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- assertAccess(Type.GET_KEYS, user, KMSOp.GET_KEYS, getClientIp(request));
+ assertAccess(Type.GET_KEYS, user, KMSOp.GET_KEYS, getClientIp(request));
- List<String> json = user.doAs((PrivilegedExceptionAction<List<String>>) provider::getKeys);
+ List<String> json = user.doAs((PrivilegedExceptionAction<List<String>>) provider::getKeys);
- kmsAudit.ok(user, KMSOp.GET_KEYS, "");
+ kmsAudit.ok(user, KMSOp.GET_KEYS, "");
+
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getkeyNames.", e);
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getkeyNames.", e);
- throw e;
- } finally {
- LOG.debug("<== getKeyNames()");
+ throw e;
+ } finally {
+ LOG.debug("<== getKeyNames()");
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
- public Response getKey(@PathParam("name") String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getKey({})", name);
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}")
+ public Response getKey(@PathParam("name") String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getKey({})", name);
- try {
- return getMetadata(name, request);
- } catch (Exception e) {
- LOG.error("Exception in getKey.", e);
+ try {
+ return getMetadata(name, request);
+ } catch (Exception e) {
+ LOG.error("Exception in getKey.", e);
- throw e;
- } finally {
- LOG.debug("<== getKey({})", name);
+ throw e;
+ } finally {
+ LOG.debug("<== getKey({})", name);
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.METADATA_SUB_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getMetadata(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getMetadata({})", name);
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.METADATA_SUB_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getMetadata(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getMetadata({})", name);
+
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_METADATA_COUNT, KMSMetrics.KMSMetric.GET_METADATA_ELAPSED_TIME)) {
+ KMSWebApp.getAdminCallsMeter().mark();
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_METADATA_COUNT, KMSMetrics.KMSMetric.GET_METADATA_ELAPSED_TIME)) {
- KMSWebApp.getAdminCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- checkNotEmpty(name, "name");
+ checkNotEmpty(name, "name");
- assertAccess(Type.GET_METADATA, user, KMSOp.GET_METADATA, name, getClientIp(request));
+ assertAccess(Type.GET_METADATA, user, KMSOp.GET_METADATA, name, getClientIp(request));
- KeyProvider.Metadata metadata = user.doAs((PrivilegedExceptionAction<KeyProvider.Metadata>) () -> provider.getMetadata(name));
- Object json = KMSServerJSONUtils.toJSON(name, metadata);
+ KeyProvider.Metadata metadata = user.doAs((PrivilegedExceptionAction<KeyProvider.Metadata>) () -> provider.getMetadata(name));
+ Object json = KMSServerJSONUtils.toJSON(name, metadata);
- kmsAudit.ok(user, KMSOp.GET_METADATA, name, "");
+ kmsAudit.ok(user, KMSOp.GET_METADATA, name, "");
+
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getMetadata.", e);
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getMetadata.", e);
- throw e;
- } finally {
- LOG.debug("<== getMetadata({})", name);
+ throw e;
+ } finally {
+ LOG.debug("<== getMetadata({})", name);
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.CURRENT_VERSION_SUB_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getCurrentVersion(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getCurrentVersion({})", name);
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.CURRENT_VERSION_SUB_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getCurrentVersion(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getCurrentVersion({})", name);
+
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_CURRENT_KEY_COUNT, KMSMetrics.KMSMetric.GET_CURRENT_KEY_ELAPSED_TIME)) {
+ KMSWebApp.getKeyCallsMeter().mark();
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_CURRENT_KEY_COUNT, KMSMetrics.KMSMetric.GET_CURRENT_KEY_ELAPSED_TIME)) {
- KMSWebApp.getKeyCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ UserGroupInformation user = HttpUserGroupInformation.get();
- checkNotEmpty(name, "name");
+ checkNotEmpty(name, "name");
- assertAccess(Type.GET, user, KMSOp.GET_CURRENT_KEY, name, getClientIp(request));
+ assertAccess(Type.GET, user, KMSOp.GET_CURRENT_KEY, name, getClientIp(request));
- KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> provider.getCurrentKey(name));
+ KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> provider.getCurrentKey(name));
+ Object json = KMSUtil.toJSON(keyVersion);
- Object json = KMSUtil.toJSON(keyVersion);
+ kmsAudit.ok(user, KMSOp.GET_CURRENT_KEY, name, "");
- kmsAudit.ok(user, KMSOp.GET_CURRENT_KEY, name, "");
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getCurrentVersion.", e);
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getCurrentVersion.", e);
- throw e;
- } finally {
- LOG.debug("<== getCurrentVersion({})", name);
+ throw e;
+ } finally {
+ LOG.debug("<== getCurrentVersion({})", name);
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEY_VERSION_RESOURCE + "/{versionName:.*}")
- @Produces(MediaType.APPLICATION_JSON)
- public Response getKeyVersion(@PathParam("versionName") final String versionName, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getKeyVersion({})", versionName);
+ @GET
+ @Path(KMSRESTConstants.KEY_VERSION_RESOURCE + "/{versionName:.*}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getKeyVersion(@PathParam("versionName") final String versionName, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getKeyVersion({})", versionName);
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSION_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSION_ELAPSED_TIME)) {
- KMSWebApp.getKeyCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSION_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSION_ELAPSED_TIME)) {
+ KMSWebApp.getKeyCallsMeter().mark();
- checkNotEmpty(versionName, "versionName");
+ UserGroupInformation user = HttpUserGroupInformation.get();
- assertAccess(Type.GET, user, KMSOp.GET_KEY_VERSION, KeyProvider.getBaseName(versionName), getClientIp(request));
+ checkNotEmpty(versionName, "versionName");
- KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> provider.getKeyVersion(versionName));
+ assertAccess(Type.GET, user, KMSOp.GET_KEY_VERSION, getClientIp(request));
- if (keyVersion != null) {
- kmsAudit.ok(user, KMSOp.GET_KEY_VERSION, keyVersion.getName(), "");
- }
+ KeyVersion keyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> provider.getKeyVersion(versionName));
- Object json = KMSUtil.toJSON(keyVersion);
+ if (keyVersion != null) {
+ kmsAudit.ok(user, KMSOp.GET_KEY_VERSION, keyVersion.getName(), "");
+ }
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getKeyVersion.", e);
- throw e;
- } finally {
- LOG.debug("<== getKeyVersion({})", versionName);
- }
- }
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + GENERATE_DEK_PATH_CONST)
- @Produces(MediaType.APPLICATION_JSON)
- public Response generateDataKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception{
- LOG.debug("==> generateDataKey(name={}", name);
-
- try {
- UserGroupInformation user = HttpUserGroupInformation.get();
- checkNotEmpty(name, "name");
-
- EncryptedKeyVersion encryptedKeyVersion = null;
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) {
- assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, getClientIp(request));
- encryptedKeyVersion = user.doAs((PrivilegedExceptionAction<EncryptedKeyVersion>) () -> provider.generateEncryptedKey(name));
- kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "generateDataKey execution");
- }
-
- KeyVersion retKeyVersion = null;
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME)) {
- assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, name, getClientIp(request));
-
- EncryptedKeyVersion finalEncryptedKeyVersion = encryptedKeyVersion;
- retKeyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
- KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(finalEncryptedKeyVersion.getEncryptionKeyName(), finalEncryptedKeyVersion.getEncryptionKeyVersionName(),
- finalEncryptedKeyVersion.getEncryptedKeyIv(), KeyProviderCryptoExtension.EEK, finalEncryptedKeyVersion.getEncryptedKeyVersion().getMaterial());
-
- return provider.decryptEncryptedKey(ekv);
- });
- kmsAudit.ok(user, KMSOp.DECRYPT_EEK, name, "generateDataKey execution");
- }
-
- Map<String,Object> response = new HashMap<>();
- response.put("edek", KMSUtil.toJSON(encryptedKeyVersion));
- response.put("dek", KMSUtil.toJSON(retKeyVersion));
-
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(response).build();
- } catch(Exception e){
- LOG.error("Exception in generateDataKey:", e);
- throw new IOException(e);
- } finally {
- LOG.debug("<== generateDataKey(name={}", name);
+ Object json = KMSUtil.toJSON(keyVersion);
+
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getKeyVersion.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== getKeyVersion({})", versionName);
+ }
}
- }
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + GENERATE_DEK_PATH_CONST)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response generateDataKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> generateDataKey(name={}", name);
+
+ try {
+ UserGroupInformation user = HttpUserGroupInformation.get();
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.EEK_SUB_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response generateEncryptedKeys(@PathParam("name") final String name,
- @QueryParam(KMSRESTConstants.EEK_OP) String edekOp,
- @DefaultValue("1") @QueryParam(KMSRESTConstants.EEK_NUM_KEYS) final int numKeys,
- @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys);
+ checkNotEmpty(name, "name");
- try (APIMetric apiElapsedMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) {
- UserGroupInformation user = HttpUserGroupInformation.get();
+ EncryptedKeyVersion encryptedKeyVersion = null;
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) {
+ assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, getClientIp(request));
- checkNotEmpty(name, "name");
+ encryptedKeyVersion = user.doAs((PrivilegedExceptionAction<EncryptedKeyVersion>) () -> provider.generateEncryptedKey(name));
+ kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "generateDataKey execution");
+ }
- checkNotNull(edekOp, "eekOp");
+ KeyVersion retKeyVersion = null;
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME)) {
+ assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, name, getClientIp(request));
- Object retJSON;
+ EncryptedKeyVersion finalEncryptedKeyVersion = encryptedKeyVersion;
+ retKeyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
+ KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(finalEncryptedKeyVersion.getEncryptionKeyName(), finalEncryptedKeyVersion.getEncryptionKeyVersionName(),
+ finalEncryptedKeyVersion.getEncryptedKeyIv(), KeyProviderCryptoExtension.EEK, finalEncryptedKeyVersion.getEncryptedKeyVersion().getMaterial());
- if (edekOp.equals(KMSRESTConstants.EEK_GENERATE)) {
- final List<EncryptedKeyVersion> retEdeks = new LinkedList<>();
+ return provider.decryptEncryptedKey(ekv);
+ });
- try {
- assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, getClientIp(request));
- user.doAs((PrivilegedExceptionAction<Void>) () -> {
- for (int i = 0; i < numKeys; i++) {
- retEdeks.add(provider.generateEncryptedKey(name));
+ kmsAudit.ok(user, KMSOp.DECRYPT_EEK, name, "generateDataKey execution");
}
- return null;
- });
+ Map<String, Object> response = new HashMap<>();
- kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "");
- retJSON = new ArrayList();
+ response.put("edek", KMSUtil.toJSON(encryptedKeyVersion));
+ response.put("dek", KMSUtil.toJSON(retKeyVersion));
- for (EncryptedKeyVersion edek : retEdeks) {
- ((ArrayList) retJSON).add(KMSUtil.toJSON(edek));
- }
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(response).build();
} catch (Exception e) {
- LOG.error("Exception in generateEncryptedKeys:", e);
- throw new IOException(e);
+ LOG.error("Exception in generateDataKey:", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== generateDataKey(name={}", name);
}
- } else {
- StringBuilder error = new StringBuilder("IllegalArgumentException Wrong ");
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.EEK_SUB_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response generateEncryptedKeys(@PathParam("name") final String name, @QueryParam(KMSRESTConstants.EEK_OP) String edekOp,
+ @DefaultValue("1") @QueryParam(KMSRESTConstants.EEK_NUM_KEYS) final int numKeys, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys);
+
+ try (APIMetric apiElapsedMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) {
+ UserGroupInformation user = HttpUserGroupInformation.get();
+
+ checkNotEmpty(name, "name");
+
+ checkNotNull(edekOp, "eekOp");
+
+ Object retJSON;
+
+ if (edekOp.equals(KMSRESTConstants.EEK_GENERATE)) {
+ final List<EncryptedKeyVersion> retEdeks = new LinkedList<>();
+
+ assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, getClientIp(request));
+ try {
+ user.doAs((PrivilegedExceptionAction<Void>) () -> {
+ for (int i = 0; i < numKeys; i++) {
+ retEdeks.add(provider.generateEncryptedKey(name));
+ }
+
+ return null;
+ });
+
+ kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "");
+
+ retJSON = new ArrayList();
- error.append(KMSRESTConstants.EEK_OP)
- .append(" value, it must be ")
- .append(KMSRESTConstants.EEK_GENERATE)
- .append(" or ")
- .append(KMSRESTConstants.EEK_DECRYPT);
+ for (EncryptedKeyVersion edek : retEdeks) {
+ ((ArrayList) retJSON).add(KMSUtil.toJSON(edek));
+ }
+ } catch (Exception e) {
+ LOG.error("Exception in generateEncryptedKeys:", e);
- LOG.error(error.toString());
+ throw new IOException(e);
+ }
+ } else {
+ StringBuilder error = new StringBuilder("IllegalArgumentException Wrong ");
- throw new IllegalArgumentException(error.toString());
- }
+ error.append(KMSRESTConstants.EEK_OP)
+ .append(" value, it must be ")
+ .append(KMSRESTConstants.EEK_GENERATE)
+ .append(" or ")
+ .append(KMSRESTConstants.EEK_DECRYPT);
- KMSWebApp.getGenerateEEKCallsMeter().mark();
+ LOG.error(error.toString());
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
- } catch (Exception e) {
- LOG.error("Exception in generateEncryptedKeys.", e);
- throw e;
- } finally {
- LOG.debug("<== generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys);
+ throw new IllegalArgumentException(error.toString());
+ }
+
+ KMSWebApp.getGenerateEEKCallsMeter().mark();
+
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
+ } catch (Exception e) {
+ LOG.error("Exception in generateEncryptedKeys.", e);
+ throw e;
+ } finally {
+ LOG.debug("<== generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys);
+ }
}
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @POST
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.REENCRYPT_BATCH_SUB_RESOURCE)
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON )
- public Response reencryptEncryptedKeys(@PathParam("name") final String name, final List<Map> jsonPayload, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> reencryptEncryptedKeys(name={}, count={})", name, (jsonPayload != null ? jsonPayload.size() : 0));
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ @POST
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.REENCRYPT_BATCH_SUB_RESOURCE)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response reencryptEncryptedKeys(@PathParam("name") final String name, final List<Map> jsonPayload, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> reencryptEncryptedKeys(name={}, count={})", name, (jsonPayload != null ? jsonPayload.size() : 0));
- final Stopwatch sw = Stopwatch.createStarted();
+ final Stopwatch sw = Stopwatch.createStarted();
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_COUNT, KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_ELAPSED_TIME)) {
- KMSWebApp.getReencryptEEKBatchCallsMeter().mark();
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_COUNT, KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_ELAPSED_TIME)) {
+ KMSWebApp.getReencryptEEKBatchCallsMeter().mark();
- checkNotEmpty(name, "name");
- checkNotNull(jsonPayload, "jsonPayload");
+ checkNotEmpty(name, "name");
+ checkNotNull(jsonPayload, "jsonPayload");
- final UserGroupInformation user = HttpUserGroupInformation.get();
+ final UserGroupInformation user = HttpUserGroupInformation.get();
- if (jsonPayload.size() > MAX_NUM_PER_BATCH) {
- LOG.warn("Payload size {} too big for reencryptEncryptedKeys from" + " user {}.", jsonPayload.size(), user);
- }
+ if (jsonPayload.size() > MAX_NUM_PER_BATCH) {
+ LOG.warn("Payload size {} too big for reencryptEncryptedKeys from" + " user {}.", jsonPayload.size(), user);
+ }
- assertAccess(Type.GENERATE_EEK, user, KMSOp.REENCRYPT_EEK_BATCH, name, getClientIp(request));
+ assertAccess(Type.GENERATE_EEK, user, KMSOp.REENCRYPT_EEK_BATCH, name, getClientIp(request));
- final List<EncryptedKeyVersion> ekvs = KMSUtil.parseJSONEncKeyVersions(name, jsonPayload);
+ final List<EncryptedKeyVersion> ekvs = KMSUtil.parseJSONEncKeyVersions(name, jsonPayload);
- Preconditions.checkArgument(ekvs.size() == jsonPayload.size(),"EncryptedKey size mismatch after parsing from json");
+ Preconditions.checkArgument(ekvs.size() == jsonPayload.size(), "EncryptedKey size mismatch after parsing from json");
- for (EncryptedKeyVersion ekv : ekvs) {
- Preconditions.checkArgument(name.equals(ekv.getEncryptionKeyName()),"All EncryptedKeys must be under the given key name " + name);
- }
+ for (EncryptedKeyVersion ekv : ekvs) {
+ Preconditions.checkArgument(name.equals(ekv.getEncryptionKeyName()), "All EncryptedKeys must be under the given key name " + name);
+ }
- user.doAs((PrivilegedExceptionAction<Void>) () -> {
- provider.reencryptEncryptedKeys(ekvs);
+ user.doAs((PrivilegedExceptionAction<Void>) () -> {
+ provider.reencryptEncryptedKeys(ekvs);
- return null;
- });
+ return null;
+ });
- List retJSON = new ArrayList<>(ekvs.size());
+ List retJSON = new ArrayList<>(ekvs.size());
- for (EncryptedKeyVersion ekv: ekvs) {
- retJSON.add(KMSUtil.toJSON(ekv));
- }
+ for (EncryptedKeyVersion ekv : ekvs) {
+ retJSON.add(KMSUtil.toJSON(ekv));
+ }
- this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_KEYS_COUNT, ekvs.size());
+ this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_KEYS_COUNT, ekvs.size());
- kmsAudit.ok(user, KMSOp.REENCRYPT_EEK_BATCH, name,"reencrypted " + ekvs.size() + " keys");
+ kmsAudit.ok(user, KMSOp.REENCRYPT_EEK_BATCH, name, "reencrypted " + ekvs.size() + " keys");
- LOG.debug("reencryptEncryptedKeys {} keys for key {} took {}", jsonPayload.size(), name, sw.stop());
+ LOG.debug("reencryptEncryptedKeys {} keys for key {} took {}", jsonPayload.size(), name, sw.stop());
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
- } catch (Exception e) {
- LOG.error("Exception in reencryptEncryptedKeys.", e);
- throw e;
- } finally {
- LOG.debug("<== reencryptEncryptedKeys(name={}, count={})", name, (jsonPayload != null ? jsonPayload.size() : 0));
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
+ } catch (Exception e) {
+ LOG.error("Exception in reencryptEncryptedKeys.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== reencryptEncryptedKeys(name={}, count={})", name, (jsonPayload != null ? jsonPayload.size() : 0));
+ }
}
- }
- @SuppressWarnings("rawtypes")
- @POST
- @Path(KMSRESTConstants.KEY_VERSION_RESOURCE + "/{versionName:.*}/" + KMSRESTConstants.EEK_SUB_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response handleEncryptedKeyOp(@PathParam("versionName") final String versionName,
- @QueryParam(KMSRESTConstants.EEK_OP) String eekOp,
- Map jsonPayload, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp);
+ @SuppressWarnings("rawtypes")
+ @POST
+ @Path(KMSRESTConstants.KEY_VERSION_RESOURCE + "/{versionName:.*}/" + KMSRESTConstants.EEK_SUB_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response handleEncryptedKeyOp(@PathParam("versionName") final String versionName, @QueryParam(KMSRESTConstants.EEK_OP) String eekOp, Map jsonPayload, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp);
+
+ try (APIMetric apiMetric = kmsMetricsCollector.captureElapsedTime()) {
+ UserGroupInformation user = HttpUserGroupInformation.get();
- try (APIMetric apiMetric = kmsMetricsCollector.captureElapsedTime()) {
- UserGroupInformation user = HttpUserGroupInformation.get();
+ checkNotEmpty(versionName, "versionName");
+ checkNotNull(eekOp, "eekOp");
- checkNotEmpty(versionName, "versionName");
- checkNotNull(eekOp, "eekOp");
+ final String keyName = (String) jsonPayload.get(KMSRESTConstants.NAME_FIELD);
+ final String ivStr = (String) jsonPayload.get(KMSRESTConstants.IV_FIELD);
+ final String encMaterialStr = (String) jsonPayload.get(KMSRESTConstants.MATERIAL_FIELD);
- final String keyName = (String) jsonPayload.get(KMSRESTConstants.NAME_FIELD);
- final String ivStr = (String) jsonPayload.get(KMSRESTConstants.IV_FIELD);
- final String encMaterialStr = (String) jsonPayload.get(KMSRESTConstants.MATERIAL_FIELD);
+ checkNotNull(ivStr, KMSRESTConstants.IV_FIELD);
- checkNotNull(ivStr, KMSRESTConstants.IV_FIELD);
+ final byte[] iv = Base64.decodeBase64(ivStr);
- final byte[] iv = Base64.decodeBase64(ivStr);
+ checkNotNull(encMaterialStr, KMSRESTConstants.MATERIAL_FIELD);
- checkNotNull(encMaterialStr, KMSRESTConstants.MATERIAL_FIELD);
+ final byte[] encMaterial = Base64.decodeBase64(encMaterialStr);
- final byte[] encMaterial = Base64.decodeBase64(encMaterialStr);
+ Object retJSON;
- Object retJSON;
+ if (eekOp.equals(KMSRESTConstants.EEK_DECRYPT)) {
+ KMSWebApp.getDecryptEEKCallsMeter().mark();
+ apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME);
- if (eekOp.equals(KMSRESTConstants.EEK_DECRYPT)) {
- KMSWebApp.getDecryptEEKCallsMeter().mark();
- apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME);
- assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, keyName, getClientIp(request));
+ assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, keyName, getClientIp(request));
- KeyVersion retKeyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
- KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(keyName, versionName, iv, KeyProviderCryptoExtension.EEK, encMaterial);
+ KeyVersion retKeyVersion = user.doAs((PrivilegedExceptionAction<KeyVersion>) () -> {
+ KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(keyName, versionName, iv, KeyProviderCryptoExtension.EEK, encMaterial);
- return provider.decryptEncryptedKey(ekv);
- });
+ return provider.decryptEncryptedKey(ekv);
+ });
- retJSON = KMSUtil.toJSON(retKeyVersion);
+ retJSON = KMSUtil.toJSON(retKeyVersion);
- kmsAudit.ok(user, KMSOp.DECRYPT_EEK, keyName, "");
- } else if (eekOp.equals(KMSRESTConstants.EEK_REENCRYPT)) {
- KMSWebApp.getReencryptEEKCallsMeter().mark();
- apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_REENCRYPT_COUNT, KMSMetrics.KMSMetric.EEK_REENCRYPT_ELAPSED_TIME);
- assertAccess(Type.GENERATE_EEK, user, KMSOp.REENCRYPT_EEK, keyName, getClientIp(request));
+ kmsAudit.ok(user, KMSOp.DECRYPT_EEK, keyName, "");
+ } else if (eekOp.equals(KMSRESTConstants.EEK_REENCRYPT)) {
+ KMSWebApp.getReencryptEEKCallsMeter().mark();
+ apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_REENCRYPT_COUNT, KMSMetrics.KMSMetric.EEK_REENCRYPT_ELAPSED_TIME);
- EncryptedKeyVersion retEncryptedKeyVersion = user.doAs((PrivilegedExceptionAction<EncryptedKeyVersion>) () -> {
- KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(keyName,versionName, iv, KeyProviderCryptoExtension.EEK, encMaterial);
+ assertAccess(Type.GENERATE_EEK, user, KMSOp.REENCRYPT_EEK, keyName, getClientIp(request));
- return provider.reencryptEncryptedKey(ekv);
- });
+ EncryptedKeyVersion retEncryptedKeyVersion = user.doAs((PrivilegedExceptionAction<EncryptedKeyVersion>) () -> {
+ KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(keyName, versionName, iv, KeyProviderCryptoExtension.EEK, encMaterial);
- retJSON = KMSUtil.toJSON(retEncryptedKeyVersion);
+ return provider.reencryptEncryptedKey(ekv);
+ });
- kmsAudit.ok(user, KMSOp.REENCRYPT_EEK, keyName, "");
- } else {
- StringBuilder error = new StringBuilder("IllegalArgumentException Wrong ");
+ retJSON = KMSUtil.toJSON(retEncryptedKeyVersion);
- error.append(KMSRESTConstants.EEK_OP)
- .append(" value, it must be ")
- .append(KMSRESTConstants.EEK_GENERATE)
- .append(" or ")
- .append(KMSRESTConstants.EEK_DECRYPT);
+ kmsAudit.ok(user, KMSOp.REENCRYPT_EEK, keyName, "");
+ } else {
+ StringBuilder error = new StringBuilder("IllegalArgumentException Wrong ");
- LOG.error(error.toString());
+ error.append(KMSRESTConstants.EEK_OP)
+ .append(" value, it must be ")
+ .append(KMSRESTConstants.EEK_GENERATE)
+ .append(" or ")
+ .append(KMSRESTConstants.EEK_DECRYPT);
- throw new IllegalArgumentException(error.toString());
- }
+ LOG.error(error.toString());
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
- } catch (Exception e) {
- LOG.error("Exception in handleEncryptedKeyOp.", e);
- throw e;
- } finally {
- LOG.debug("<== handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp);
+ throw new IllegalArgumentException(error.toString());
+ }
+
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build();
+ } catch (Exception e) {
+ LOG.error("Exception in handleEncryptedKeyOp.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp);
+ }
}
- }
- @GET
- @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.VERSIONS_SUB_RESOURCE)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getKeyVersions(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
- LOG.debug("==> getKeyVersions({})", name);
+ @GET
+ @Path(KMSRESTConstants.KEY_RESOURCE + "/{name:.*}/" + KMSRESTConstants.VERSIONS_SUB_RESOURCE)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getKeyVersions(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception {
+ LOG.debug("==> getKeyVersions({})", name);
+
+ try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSIONS_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSIONS_ELAPSED_TIME)) {
+ KMSWebApp.getKeyCallsMeter().mark();
+
+ UserGroupInformation user = HttpUserGroupInformation.get();
- try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSIONS_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSIONS_ELAPSED_TIME)) {
- KMSWebApp.getKeyCallsMeter().mark();
- UserGroupInformation user = HttpUserGroupInformation.get();
+ checkNotEmpty(name, "name");
- checkNotEmpty(name, "name");
+ assertAccess(Type.GET, user, KMSOp.GET_KEY_VERSIONS, name, getClientIp(request));
- assertAccess(Type.GET, user, KMSOp.GET_KEY_VERSIONS, name, getClientIp(request));
+ List<KeyVersion> ret = user.doAs((PrivilegedExceptionAction<List<KeyVersion>>) () -> provider.getKeyVersions(name));
+ Object json = KMSServerJSONUtils.toJSON(ret);
- List<KeyVersion> ret = user.doAs((PrivilegedExceptionAction<List<KeyVersion>>) () -> provider.getKeyVersions(name));
- Object json = KMSServerJSONUtils.toJSON(ret);
+ kmsAudit.ok(user, KMSOp.GET_KEY_VERSIONS, name, "");
- kmsAudit.ok(user, KMSOp.GET_KEY_VERSIONS, name, "");
+ return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
+ } catch (Exception e) {
+ LOG.error("Exception in getKeyVersions.", e);
+
+ throw e;
+ } finally {
+ LOG.debug("<== getKeyVersions({})", name);
+ }
+ }
- return Response.ok().type(MediaType.APPLICATION_JSON).entity(json).build();
- } catch (Exception e) {
- LOG.error("Exception in getKeyVersions.", e);
- throw e;
- } finally {
- LOG.debug("<== getKeyVersions({})", name);
+ private static String getClientIp(HttpServletRequest request) {
+ return request != null ? request.getRemoteAddr() : null;
}
- }
- private static String getClientIp(HttpServletRequest request) {
- return request != null ? request.getRemoteAddr() : null;
- }
+ private void assertAccess(Type aclType, UserGroupInformation ugi, KMSOp operation, String clientIp) throws AccessControlException {
+ KMSWebApp.getACLs().assertAccess(aclType, ugi, operation, null, clientIp);
+ }
- private void assertAccess(Type aclType, UserGroupInformation ugi, KMSOp operation, String clientIp) throws AccessControlException {
- KMSWebApp.getACLs().assertAccess(aclType, ugi, operation, null, clientIp);
- }
+ private void assertAccess(Type aclType, UserGroupInformation ugi, KMSOp operation, String key, String clientIp) throws AccessControlException {
+ KMSWebApp.getACLs().assertAccess(aclType, ugi, operation, key, clientIp);
+ }
- private void assertAccess(Type aclType, UserGroupInformation ugi, KMSOp operation, String key, String clientIp) throws AccessControlException {
- KMSWebApp.getACLs().assertAccess(aclType, ugi, operation, key, clientIp);
- }
+ private void validateKeyName(String name) {
+ Pattern pattern = Pattern.compile(KEY_NAME_VALIDATION);
+ Matcher matcher = pattern.matcher(name);
- private void validateKeyName(String name) {
- Pattern pattern = Pattern.compile(KEY_NAME_VALIDATION);
- Matcher matcher = pattern.matcher(name);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException("Key Name : " + name + ", should start with alpha/numeric letters and can have special characters - (hypen) or _ (underscore)");
+ }
+ }
- if (!matcher.matches()) {
- throw new IllegalArgumentException("Key Name : " + name + ", should start with alpha/numeric letters and can have special characters - (hyphen) or _ (underscore)");
+ private static KeyVersion removeKeyMaterial(KeyVersion keyVersion) {
+ return new KMSKeyVersion(keyVersion.getName(), keyVersion.getVersionName(), null);
}
- }
- private static KeyVersion removeKeyMaterial(KeyVersion keyVersion) {
- return new KMSKeyVersion(keyVersion.getName(), keyVersion.getVersionName(), null);
- }
+ private static URI getKeyURI(String domain, String keyName) {
+ return UriBuilder.fromPath("{a}/{b}/{c}").build(domain, KMSRESTConstants.KEY_RESOURCE, keyName);
+ }
- private static URI getKeyURI(String domain, String keyName) {
- return UriBuilder.fromPath("{a}/{b}/{c}").build(domain, KMSRESTConstants.KEY_RESOURCE, keyName);
- }
+ public enum KMSOp {
+ CREATE_KEY, DELETE_KEY, ROLL_NEW_VERSION, INVALIDATE_CACHE,
+ GET_KEYS, GET_KEYS_METADATA,
+ GET_KEY_VERSIONS, GET_METADATA, GET_KEY_VERSION, GET_CURRENT_KEY,
+ GENERATE_EEK, DECRYPT_EEK, REENCRYPT_EEK, REENCRYPT_EEK_BATCH
+ }
}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
index f73cecd2a..ec0cdb804 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
@@ -18,19 +18,11 @@
package org.apache.hadoop.crypto.key.kms.server;
import com.codahale.metrics.Meter;
-import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
-import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion;
-import org.apache.hadoop.crypto.key.kms.KMSRESTConstants;
-import org.apache.hadoop.crypto.key.kms.server.KMS.KMSOp;
-import org.apache.hadoop.crypto.key.kms.server.KMSACLsType.Type;
-import org.apache.hadoop.crypto.key.kms.server.KeyAuthorizationKeyProvider.KeyACLs;
-import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationFilter;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@@ -38,9 +30,7 @@
import org.mockito.junit.jupiter.MockitoExtension;
import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -48,833 +38,490 @@
import java.net.URI;
import java.util.ArrayList;
import java.util.Base64;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.eclipse.persistence.jpa.jpql.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.MethodName.class)
+@Disabled
public class TestKMS {
- private static final String CLIENT_IP = "127.0.0.1";
- private static final String TEST_KEY = "testKey";
- private static final String SENSITIVE_KEY = "sensitive_key";
-
- private static final String[] KMS_WEB_APP_MUTABLE_STATIC_FIELDS = {
- "kmsConf",
- "kmsAcls",
- "keyProviderCryptoExtension",
- "kmsAudit",
- "adminCallsMeter",
- "keyCallsMeter",
- "generateEEKCallsMeter",
- "decryptEEKCallsMeter",
- "reencryptEEKCallsMeter",
- "reencryptEEKBatchCallsMeter"
- };
-
- private KeyACLs mockAcls;
- private KeyProviderCryptoExtension mockProvider;
- private KMSAudit mockAudit;
- private Meter mockAdminCallsMeter;
- private Meter mockKeyCallsMeter;
- private Meter mockGenerateEEKMeter;
- private Meter mockDecryptEEKMeter;
- private Meter mockReencryptEEKMeter;
- private Meter mockReencryptEEKBatchMeter;
- private Map<String, Object> kmsWebAppStaticsBefore;
-
- @BeforeEach
- public void setupKmsWebApp() throws Exception {
- System.setProperty("hadoop.home.dir", "./");
-
- mockAcls = mock(KeyACLs.class);
- mockProvider = mock(KeyProviderCryptoExtension.class);
- mockAudit = mock(KMSAudit.class);
- mockAdminCallsMeter = mock(Meter.class);
- mockKeyCallsMeter = mock(Meter.class);
- mockGenerateEEKMeter = mock(Meter.class);
- mockDecryptEEKMeter = mock(Meter.class);
- mockReencryptEEKMeter = mock(Meter.class);
- mockReencryptEEKBatchMeter = mock(Meter.class);
-
- kmsWebAppStaticsBefore = snapshotMutableKmsWebAppStatics();
-
- setStaticField(KMSWebApp.class, "kmsConf", new Configuration());
- setStaticField(KMSWebApp.class, "kmsAcls", mockAcls);
- setStaticField(KMSWebApp.class, "keyProviderCryptoExtension", mockProvider);
- setStaticField(KMSWebApp.class, "kmsAudit", mockAudit);
- setStaticField(KMSWebApp.class, "adminCallsMeter", mockAdminCallsMeter);
- setStaticField(KMSWebApp.class, "keyCallsMeter", mockKeyCallsMeter);
- setStaticField(KMSWebApp.class, "generateEEKCallsMeter", mockGenerateEEKMeter);
- setStaticField(KMSWebApp.class, "decryptEEKCallsMeter", mockDecryptEEKMeter);
- setStaticField(KMSWebApp.class, "reencryptEEKCallsMeter", mockReencryptEEKMeter);
- setStaticField(KMSWebApp.class, "reencryptEEKBatchCallsMeter", mockReencryptEEKBatchMeter);
- }
-
- @AfterEach
- public void tearDownKmsWebApp() throws Exception {
- clearHttpUserInContext();
- clearMdcContext();
- restoreKmsWebAppStatics(kmsWebAppStaticsBefore);
- }
+ private static KeyProviderCryptoExtension keyProvider;
+ private static KMSAudit kmsAudit;
+ private static Meter adminCallsMeter;
+ private static KMSACLs acls;
@Test
- public void testGetKeyVersion_passesBaseKeyNameToAssertAccess() throws Exception {
- String versionName = SENSITIVE_KEY + "@0";
- String baseKeyName = KeyProvider.getBaseName(versionName);
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KeyProvider.KeyVersion keyVersion = createKeyVersion(baseKeyName, versionName, new byte[] {1, 2, 3});
- when(mockProvider.getKeyVersion(versionName)).thenReturn(keyVersion);
-
- KMS kms = newKms();
- Response response = kms.getKeyVersion(versionName, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- assertNotNull(response.getEntity());
- verify(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_KEY_VERSION), eq(baseKeyName), eq(CLIENT_IP));
- verify(mockProvider).getKeyVersion(versionName);
- verify(mockAudit).ok(user, KMSOp.GET_KEY_VERSION, baseKeyName, "");
- }
+ public void testRolloverKey() throws Exception {
+ String keyName = "testKey";
+ // Prepare input map
+ Map<String, Object> jsonKey = new HashMap<>();
+ jsonKey.put("name", "testKey");
+ jsonKey.put("cipher", "AES");
+ jsonKey.put("length", 128);
+ jsonKey.put("description", "just a basic key");
- @Test
- public void testGetKeyVersion_deniedWhenPerKeyAccessDenied() throws Exception {
- String versionName = SENSITIVE_KEY + "@0";
- String baseKeyName = KeyProvider.getBaseName(versionName);
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_KEY_VERSION), eq(baseKeyName), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.getKeyVersion(versionName, request));
- verify(mockProvider, never()).getKeyVersion(anyString());
- verify(mockAudit, never()).ok(any(), any(), anyString(), anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+ try {
+ kms.rolloverKey(keyName, jsonKey, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetKeyVersion_noVersionInKeyPathFails() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KMS kms = newKms();
+ public void testGetKeyVersions() throws Exception {
+ String keyName = "testKey";
+ // Prepare input map
+ Map<String, Object> jsonKey = new HashMap<>();
+ jsonKey.put("name", "testKey");
+ jsonKey.put("cipher", "AES");
+ jsonKey.put("length", 128);
+ jsonKey.put("description", "just a basic key");
- assertThrows(IOException.class, () -> kms.getKeyVersion(SENSITIVE_KEY, request));
- verify(mockProvider, never()).getKeyVersion(anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+ try {
+ kms.getKeyVersions(keyName, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetCurrentVersion_successPassesKeyNameToAssertAccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KeyProvider.KeyVersion keyVersion = createKeyVersion(TEST_KEY, TEST_KEY + "@0", new byte[] {1});
- when(mockProvider.getCurrentKey(TEST_KEY)).thenReturn(keyVersion);
-
- KMS kms = newKms();
- Response response = kms.getCurrentVersion(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_CURRENT_KEY), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).getCurrentKey(TEST_KEY);
- verify(mockAudit).ok(user, KMSOp.GET_CURRENT_KEY, TEST_KEY, "");
- }
+ public void testReencryptEncryptedKeys() throws Exception {
+ String keyName = "testKey";
- @Test
- public void testGetCurrentVersion_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_CURRENT_KEY), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.getCurrentVersion(TEST_KEY, request));
- verify(mockProvider, never()).getCurrentKey(anyString());
- }
+ List<Map> jsonPayload = new ArrayList<>();
- @Test
- public void testGetKeyVersions_successPassesKeyNameToAssertAccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- List<KeyProvider.KeyVersion> versions = new ArrayList<>();
- versions.add(createKeyVersion(TEST_KEY, TEST_KEY + "@0", new byte[] {1}));
- when(mockProvider.getKeyVersions(TEST_KEY)).thenReturn(versions);
-
- KMS kms = newKms();
- Response response = kms.getKeyVersions(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_KEY_VERSIONS), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).getKeyVersions(TEST_KEY);
- verify(mockAudit).ok(user, KMSOp.GET_KEY_VERSIONS, TEST_KEY, "");
- }
+ Map<String, Object> key1 = new HashMap<>();
+ key1.put("versionName", keyName + "@0");
+ key1.put("iv", Base64.getEncoder().encodeToString("12345678".getBytes()));
+ key1.put("encryptedKeyVersion", Base64.getEncoder().encodeToString("keyBytes1".getBytes()));
+ jsonPayload.add(key1);
- @Test
- public void testGetKeyVersions_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GET), eq(user), eq(KMSOp.GET_KEY_VERSIONS), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.getKeyVersions(TEST_KEY, request));
- verify(mockProvider, never()).getKeyVersions(anyString());
- }
+ Map<String, Object> key2 = new HashMap<>();
+ key2.put("versionName", keyName + "@1");
+ key2.put("iv", Base64.getEncoder().encodeToString("87654321".getBytes()));
+ key2.put("encryptedKeyVersion", Base64.getEncoder().encodeToString("keyBytes2".getBytes()));
+ jsonPayload.add(key2);
- @Test
- public void testGetMetadata_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KeyProvider.Metadata metadata = mockMetadata();
- when(mockProvider.getMetadata(TEST_KEY)).thenReturn(metadata);
-
- KMS kms = newKms();
- Response response = kms.getMetadata(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GET_METADATA), eq(user), eq(KMSOp.GET_METADATA), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).getMetadata(TEST_KEY);
- verify(mockAudit).ok(user, KMSOp.GET_METADATA, TEST_KEY, "");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ KMS kms = new KMS();
+
+ try {
+ kms.reencryptEncryptedKeys(keyName, jsonPayload, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetKey_delegatesToGetMetadata() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
+ public void testHandleEncryptedKeyOp() throws Exception {
+ String keyName = "testKey";
+ String versionName = "testKeyVersion";
- HttpServletRequest request = mockRequest();
- KeyProvider.Metadata metadata = mockMetadata();
- when(mockProvider.getMetadata(TEST_KEY)).thenReturn(metadata);
-
- KMS kms = newKms();
- Response response = kms.getKey(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockProvider).getMetadata(TEST_KEY);
- }
+ String edekOp = "generateEncryptedKeys";
+ // Prepare input map
+ Map<String, Object> jsonKey = new HashMap<>();
+ jsonKey.put("name", "testKey");
+ jsonKey.put("cipher", "AES");
+ jsonKey.put("length", 128);
+ jsonKey.put("description", "just a basic key");
- @Test
- public void testCreateKey_successCreatesKeyAndAudits() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
- setMdcContext(user, "http://localhost/kms/v1/keys");
-
- HttpServletRequest request = mockRequest();
- Map<String, Object> jsonKey = baseKeyJson(TEST_KEY);
- KeyProvider.KeyVersion keyVersion = createKeyVersion(TEST_KEY, TEST_KEY + "@0", new byte[] {1, 2, 3});
-
- when(mockProvider.createKey(eq(TEST_KEY), any(KeyProvider.Options.class))).thenReturn(keyVersion);
- when(mockAcls.hasAccess(eq(Type.GET), eq(user), eq(CLIENT_IP))).thenReturn(true);
-
- KMS kms = newKms();
- Response response = kms.createKey(jsonKey, request);
-
- assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.CREATE), eq(user), eq(KMSOp.CREATE_KEY), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).createKey(eq(TEST_KEY), any(KeyProvider.Options.class));
- verify(mockProvider).flush();
- verify(mockAudit).ok(eq(user), eq(KMSOp.CREATE_KEY), eq(TEST_KEY), anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.handleEncryptedKeyOp(versionName, edekOp, jsonKey, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testCreateKey_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
+ public void testGenerateEncryptedKeys() throws Exception {
+ String keyName = "testKey";
- HttpServletRequest request = mockRequest();
- Map<String, Object> jsonKey = baseKeyJson(TEST_KEY);
+ String edekOp = "generateEncryptedKeys";
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.CREATE), eq(user), eq(KMSOp.CREATE_KEY), eq(TEST_KEY), eq(CLIENT_IP));
+ final int numKeys = 1;
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.createKey(jsonKey, request));
- verify(mockProvider, never()).createKey(anyString(), any(KeyProvider.Options.class));
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.generateEncryptedKeys(keyName, edekOp, numKeys, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testCreateKey_withUserMaterialRequiresSetKeyMaterialAccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
- setMdcContext(user, "http://localhost/kms/v1/keys");
-
- HttpServletRequest request = mockRequest();
- Map<String, Object> jsonKey = baseKeyJson(TEST_KEY);
- jsonKey.put(KMSRESTConstants.MATERIAL_FIELD,
- Base64.getEncoder().encodeToString(new byte[] {1, 2, 3, 4}));
-
- KeyProvider.KeyVersion keyVersion = createKeyVersion(TEST_KEY, TEST_KEY + "@0", new byte[] {1});
- when(mockProvider.createKey(eq(TEST_KEY), any(byte[].class), any(KeyProvider.Options.class)))
- .thenReturn(keyVersion);
- when(mockAcls.hasAccess(eq(Type.GET), eq(user), eq(CLIENT_IP))).thenReturn(true);
-
- KMS kms = newKms();
- kms.createKey(jsonKey, request);
-
- verify(mockAcls).assertAccess(
- eq(Type.SET_KEY_MATERIAL), eq(user), eq(KMSOp.CREATE_KEY), eq(TEST_KEY), eq(CLIENT_IP));
- }
+ public void testGetKeyVersion() throws Exception {
+ String versionName = "testKeyVersion";
- @Test
- public void testDeleteKey_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KMS kms = newKms();
- Response response = kms.deleteKey(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.DELETE), eq(user), eq(KMSOp.DELETE_KEY), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).deleteKey(TEST_KEY);
- verify(mockProvider).flush();
- verify(mockAudit).ok(user, KMSOp.DELETE_KEY, TEST_KEY, "");
- }
-
- @Test
- public void testDeleteKey_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.DELETE), eq(user), eq(KMSOp.DELETE_KEY), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.deleteKey(TEST_KEY, request));
- verify(mockProvider, never()).deleteKey(anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.getKeyVersion(versionName, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testRolloverKey_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- Map<String, Object> jsonMaterial = new HashMap<>();
- KeyProvider.KeyVersion keyVersion = createKeyVersion(TEST_KEY, TEST_KEY + "@1", new byte[] {5});
- when(mockProvider.rollNewVersion(TEST_KEY)).thenReturn(keyVersion);
- when(mockAcls.hasAccess(eq(Type.GET), eq(user), eq(CLIENT_IP))).thenReturn(true);
-
- KMS kms = newKms();
- Response response = kms.rolloverKey(TEST_KEY, jsonMaterial, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.ROLLOVER), eq(user), eq(KMSOp.ROLL_NEW_VERSION), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).rollNewVersion(TEST_KEY);
- verify(mockProvider).flush();
- verify(mockAudit).ok(eq(user), eq(KMSOp.ROLL_NEW_VERSION), eq(TEST_KEY), anyString());
- }
+ public void testGetKeysMetadata() throws Exception {
+ List<String> keyNamesList = new ArrayList<>();
+ keyNamesList.add("testKey1");
- @Test
- public void testRolloverKey_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.ROLLOVER), eq(user), eq(KMSOp.ROLL_NEW_VERSION), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class,
- () -> kms.rolloverKey(TEST_KEY, new HashMap<>(), request));
- verify(mockProvider, never()).rollNewVersion(anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.getKeysMetadata(keyNamesList, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testInvalidateCache_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KMS kms = newKms();
- Response response = kms.invalidateCache(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.ROLLOVER), eq(user), eq(KMSOp.INVALIDATE_CACHE), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).invalidateCache(TEST_KEY);
- verify(mockProvider).flush();
- verify(mockAudit).ok(user, KMSOp.INVALIDATE_CACHE, TEST_KEY, "");
- }
+ public void testGetCurrentVersion() throws Exception {
+ String keyName = "testKey";
- @Test
- public void testInvalidateCache_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.ROLLOVER), eq(user), eq(KMSOp.INVALIDATE_CACHE), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.invalidateCache(TEST_KEY, request));
- verify(mockProvider, never()).invalidateCache(anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.getCurrentVersion(keyName, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetKeyNames_successUsesNullKeyNameInAssertAccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- List<String> keys = new ArrayList<>();
- keys.add(TEST_KEY);
- when(mockProvider.getKeys()).thenReturn(keys);
-
- KMS kms = newKms();
- Response response = kms.getKeyNames(request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GET_KEYS), eq(user), eq(KMSOp.GET_KEYS), isNull(), eq(CLIENT_IP));
- verify(mockProvider).getKeys();
- verify(mockAudit).ok(user, KMSOp.GET_KEYS, "");
- }
+ public void testGenerateDataKey() throws Exception {
+ String keyName = "testKey";
- @Test
- public void testGetKeyNames_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GET_KEYS), eq(user), eq(KMSOp.GET_KEYS), isNull(), eq(CLIENT_IP));
-
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.getKeyNames(request));
- verify(mockProvider, never()).getKeys();
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.generateDataKey(keyName, request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetKeysMetadata_successUsesNullKeyNameInAssertAccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- List<String> keyNamesList = new ArrayList<>();
- keyNamesList.add(TEST_KEY);
- KeyProvider.Metadata[] metas = {mockMetadata()};
- when(mockProvider.getKeysMetadata(any(String[].class))).thenReturn(metas);
-
- KMS kms = newKms();
- Response response = kms.getKeysMetadata(keyNamesList, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GET_METADATA), eq(user), eq(KMSOp.GET_KEYS_METADATA), isNull(), eq(CLIENT_IP));
- verify(mockProvider).getKeysMetadata(any(String[].class));
- verify(mockAudit).ok(user, KMSOp.GET_KEYS_METADATA, "");
+ public void testGetKeyNames() throws Exception {
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+ Meter dummyMeter = mock(Meter.class);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ KMS kms = new KMS();
+
+ try {
+ kms.getKeyNames(request);
+ fail("Expected exception due to missing provider/user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGetKeysMetadata_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- List<String> keyNamesList = new ArrayList<>();
- keyNamesList.add(TEST_KEY);
+ void testDeleteKey_skippingAdminCallsMeter() throws Exception {
+ String keyName = "name";
+ UserGroupInformation mockUser = mock(UserGroupInformation.class);
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GET_METADATA), eq(user), eq(KMSOp.GET_KEYS_METADATA), isNull(), eq(CLIENT_IP));
+ HttpUserGroupInformation httpUserGroupInformation = mock(HttpUserGroupInformation.class);
- KMS kms = newKms();
- assertThrows(AccessControlException.class, () -> kms.getKeysMetadata(keyNamesList, request));
- verify(mockProvider, never()).getKeysMetadata(any(String[].class));
+ // Set up mock request
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+ // Prepare a dummy Meter to avoid static call impact
+ Meter dummyMeter = mock(Meter.class);
+
+ // Set static adminCallsMeter in KMSWebApp using reflection
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ // Create the KMS instance (internally calls KMSWebApp static methods)
+ KMS kms = new KMS();
+
+ // Run and expect exception (due to missing KMSWebApp dependencies like provider, user, etc.)
+ try {
+ kms.deleteKey(keyName, request);
+ fail("Expected exception due to missing dependencies like provider or UGI");
+ } catch (Exception e) {
+ System.out.println("Expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testGenerateEncryptedKeys_successWithGenerateOp() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- EncryptedKeyVersion ekv = mockEncryptedKeyVersion(TEST_KEY, TEST_KEY + "@0");
- when(mockProvider.generateEncryptedKey(TEST_KEY)).thenReturn(ekv);
-
- KMS kms = newKms();
- Response response = kms.generateEncryptedKeys(
- TEST_KEY, KMSRESTConstants.EEK_GENERATE, 1, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GENERATE_EEK), eq(user), eq(KMSOp.GENERATE_EEK), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).generateEncryptedKey(TEST_KEY);
- verify(mockAudit).ok(user, KMSOp.GENERATE_EEK, TEST_KEY, "");
- verify(mockGenerateEEKMeter).mark();
+ void testCreateKeyWithOnlyInputValues() throws Exception {
+ // Prepare input map
+ Map<String, Object> jsonKey = new HashMap<>();
+ jsonKey.put("name", "testKey");
+ jsonKey.put("cipher", "AES");
+ jsonKey.put("length", 128);
+ jsonKey.put("description", "just a basic key");
+
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+ Meter dummyMeter = mock(Meter.class);
+
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ // Attempt call (expected to fail unless environment is injected)
+ KMS kms = new KMS();
+ try {
+ kms.createKey(jsonKey, request);
+ fail("Expected exception due to missing provider or user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ }
}
@Test
- public void testGenerateEncryptedKeys_invalidEekOpFails() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- KMS kms = newKms();
+ void testCreateKeyWithOnlyInputValues1() throws Exception {
+ // Prepare input map
+ Map<String, Object> jsonKey = new HashMap<>();
+ jsonKey.put("name", "testKey");
+ jsonKey.put("cipher", "AES");
+ jsonKey.put("length", 128);
+ jsonKey.put("description", "just a basic key");
- assertThrows(IllegalArgumentException.class, () ->
- kms.generateEncryptedKeys(TEST_KEY, "generateEncryptedKeys", 1, request));
- verify(mockProvider, never()).generateEncryptedKey(anyString());
+ // Mock request object
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+ Meter dummyMeter = mock(Meter.class);
+
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
+
+ // Attempt call (expected to fail unless environment is injected)
+ KMS kms = new KMS();
+ try {
+ kms.createKey(jsonKey, request);
+ fail("Expected exception due to missing provider or user context");
+ } catch (Exception e) {
+ System.out.println("Caught expected exception: " + e.getMessage());
+ }
}
- // reencryptEncryptedKeys
-
@Test
- public void testReencryptEncryptedKeys_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- List<Map> payload = buildReencryptPayload(TEST_KEY, 1);
-
- KMS kms = newKms();
- Response response = kms.reencryptEncryptedKeys(TEST_KEY, payload, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GENERATE_EEK), eq(user), eq(KMSOp.REENCRYPT_EEK_BATCH), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).reencryptEncryptedKeys(any(List.class));
- verify(mockAudit).ok(eq(user), eq(KMSOp.REENCRYPT_EEK_BATCH), eq(TEST_KEY), anyString());
- verify(mockReencryptEEKBatchMeter).mark();
- }
+ void testInvalidateCacheWithOnlyInputValues() throws Exception {
+ String keyName = "testKey";
- @Test
- public void testReencryptEncryptedKeys_deniedBeforeProviderCall() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
+ Meter dummyMeter = mock(Meter.class);
- HttpServletRequest request = mockRequest();
- List<Map> payload = buildReencryptPayload(TEST_KEY, 1);
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GENERATE_EEK), eq(user), eq(KMSOp.REENCRYPT_EEK_BATCH), eq(TEST_KEY), eq(CLIENT_IP));
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
- KMS kms = newKms();
- assertThrows(AccessControlException.class,
- () -> kms.reencryptEncryptedKeys(TEST_KEY, payload, request));
- verify(mockProvider, never()).reencryptEncryptedKeys(any(List.class));
- }
+ KMS kms = new KMS();
- @Test
- public void testHandleEncryptedKeyOp_decryptSuccess() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- String versionName = TEST_KEY + "@0";
- Map<String, Object> payload = buildDecryptPayload(TEST_KEY);
-
- KeyProvider.KeyVersion decrypted = createKeyVersion(TEST_KEY, versionName, new byte[] {9});
- when(mockProvider.decryptEncryptedKey(any())).thenReturn(decrypted);
-
- KMS kms = newKms();
- Response response = kms.handleEncryptedKeyOp(
- versionName, KMSRESTConstants.EEK_DECRYPT, payload, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.DECRYPT_EEK), eq(user), eq(KMSOp.DECRYPT_EEK), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).decryptEncryptedKey(any());
- verify(mockAudit).ok(user, KMSOp.DECRYPT_EEK, TEST_KEY, "");
- verify(mockDecryptEEKMeter).mark();
+ try {
+ kms.invalidateCache(keyName, request);
+ fail("Expected exception due to missing dependencies (provider/user)");
+ } catch (Exception e) {
+ System.out.println("Expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
@Test
- public void testHandleEncryptedKeyOp_invalidEekOpFails() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
+ void testGetKey() throws Exception {
+ String keyName = "testKey";
+ Meter dummyMeter = mock(Meter.class);
- HttpServletRequest request = mockRequest();
- Map<String, Object> payload = buildDecryptPayload(TEST_KEY);
-
- KMS kms = newKms();
- assertThrows(IllegalArgumentException.class, () ->
- kms.handleEncryptedKeyOp(TEST_KEY + "@0", "bad_op", payload, request));
- }
+ Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+ meterField.setAccessible(true);
+ meterField.set(null, dummyMeter);
- @Test
- public void testGenerateDataKey_success() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- EncryptedKeyVersion ekv = mockEncryptedKeyVersion(TEST_KEY, TEST_KEY + "@0");
- KeyProvider.KeyVersion dek = createKeyVersion(TEST_KEY, TEST_KEY + "@0", new byte[] {7});
-
- when(mockProvider.generateEncryptedKey(TEST_KEY)).thenReturn(ekv);
- when(mockProvider.decryptEncryptedKey(any())).thenReturn(dek);
-
- KMS kms = newKms();
- Response response = kms.generateDataKey(TEST_KEY, request);
-
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
- verify(mockAcls).assertAccess(
- eq(Type.GENERATE_EEK), eq(user), eq(KMSOp.GENERATE_EEK), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockAcls).assertAccess(
- eq(Type.DECRYPT_EEK), eq(user), eq(KMSOp.DECRYPT_EEK), eq(TEST_KEY), eq(CLIENT_IP));
- verify(mockProvider).generateEncryptedKey(TEST_KEY);
- verify(mockProvider).decryptEncryptedKey(any());
- }
-
- @Test
- public void testGenerateDataKey_deniedOnGenerateBeforeDecrypt() throws Exception {
- UserGroupInformation user = createTestUser();
- setHttpUserInContext(user);
-
- HttpServletRequest request = mockRequest();
- doThrow(new AccessControlException("denied"))
- .when(mockAcls).assertAccess(
- eq(Type.GENERATE_EEK), eq(user), eq(KMSOp.GENERATE_EEK), eq(TEST_KEY), eq(CLIENT_IP));
-
- KMS kms = newKms();
- IOException ex = assertThrows(IOException.class, () -> kms.generateDataKey(TEST_KEY, request));
- assertInstanceOf(AccessControlException.class, ex.getCause());
- verify(mockProvider, never()).generateEncryptedKey(anyString());
+ KMS kms = new KMS();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+ try {
+ kms.getKey(keyName, request);
+ fail("Expected exception due to missing dependencies (provider/user)");
+ } catch (Exception e) {
+ System.out.println("Expected exception: " + e.getMessage());
+ assertNotNull(e);
+ }
}
- // Validation and helpers
-
@Test
- public void testValidateKeyName_valid() throws Exception {
- KMS kms = newKms();
- Method method = KMS.class.getDeclaredMethod("validateKeyName", String.class);
+ void testValidateKeyName_valid_reflection() throws Exception {
+ String validKeyName = "ValidKey_123";
+ KMS kms = new KMS();
+ Method method = KMS.class.getDeclaredMethod("validateKeyName", String.class);
method.setAccessible(true);
+
assertDoesNotThrow(() -> method.invoke(kms, "ValidKey_123"));
}
@Test
- public void testValidateKeyName_invalid() throws Exception {
- KMS kms = newKms();
+ void testValidateKeyName_invalid_reflection() throws Exception {
+ KMS kms = new KMS();
Method method = KMS.class.getDeclaredMethod("validateKeyName", String.class);
method.setAccessible(true);
- InvocationTargetException ex = assertThrows(InvocationTargetException.class, () ->
- method.invoke(kms, "!invalid-key"));
+ InvocationTargetException ex = assertThrows(InvocationTargetException.class, () -> {
+ method.invoke(kms, "!invalid-key");
+ });
+
assertInstanceOf(IllegalArgumentException.class, ex.getCause());
}
@Test
- public void testGetKeyURI_buildsExpectedPath() throws Exception {
+ void testGetKeyURI_reflection() throws Exception {
Method method = KMS.class.getDeclaredMethod("getKeyURI", String.class, String.class);
method.setAccessible(true);
- URI result = (URI) method.invoke(null, "v1", TEST_KEY);
- assertEquals("v1/key/testKey", result.toString());
- }
- @Test
- public void testRemoveKeyMaterial_stripsBytes() throws Exception {
- KeyProvider.KeyVersion original = createKeyVersion("key1", "v1", "secret".getBytes());
- Method method = KMS.class.getDeclaredMethod("removeKeyMaterial", KeyProvider.KeyVersion.class);
- method.setAccessible(true);
+ URI result = (URI) method.invoke(null, "v1", "testKey");
- KeyProvider.KeyVersion result = (KeyProvider.KeyVersion) method.invoke(null, original);
- assertEquals("key1", result.getName());
- assertEquals("v1", result.getVersionName());
- assertNull(result.getMaterial());
+ assertEquals("v1/key/testKey", result.toString()); // ✅ expected value
}
@Test
- public void testCreateKey_withoutUserFails() throws Exception {
- HttpServletRequest request = mockRequest();
- Map<String, Object> jsonKey = baseKeyJson(TEST_KEY);
- KMS kms = newKms();
-
- assertThrows(NullPointerException.class, () -> kms.createKey(jsonKey, request));
- }
-
- // Helpers
-
- private KMS newKms() throws Exception {
- return new KMS();
- }
-
- private UserGroupInformation createTestUser() throws IOException {
- return UserGroupInformation.createRemoteUser("testuser");
- }
-
- private HttpServletRequest mockRequest() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- lenient().when(request.getRemoteAddr()).thenReturn(CLIENT_IP);
- return request;
- }
-
- private Map<String, Object> baseKeyJson(String keyName) {
- Map<String, Object> jsonKey = new HashMap<>();
- jsonKey.put(KMSRESTConstants.NAME_FIELD, keyName);
- jsonKey.put(KMSRESTConstants.CIPHER_FIELD, "AES");
- jsonKey.put(KMSRESTConstants.LENGTH_FIELD, 128);
- jsonKey.put(KMSRESTConstants.DESCRIPTION_FIELD, "test key");
- return jsonKey;
- }
-
- private List<Map> buildReencryptPayload(String keyName, int count) {
- List<Map> payload = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- String versionName = keyName + "@" + i;
- Map<String, Object> encInner = new HashMap<>();
- encInner.put(KMSRESTConstants.VERSION_NAME_FIELD, versionName);
- encInner.put(KMSRESTConstants.MATERIAL_FIELD,
- Base64.getEncoder().encodeToString("encMat".getBytes()));
-
- Map<String, Object> entry = new HashMap<>();
- entry.put(KMSRESTConstants.VERSION_NAME_FIELD, versionName);
- entry.put(KMSRESTConstants.IV_FIELD,
- Base64.getEncoder().encodeToString("12345678".getBytes()));
- entry.put(KMSRESTConstants.ENCRYPTED_KEY_VERSION_FIELD, encInner);
- payload.add(entry);
- }
- return payload;
- }
-
- private Map<String, Object> buildDecryptPayload(String keyName) {
- Map<String, Object> payload = new HashMap<>();
- payload.put(KMSRESTConstants.NAME_FIELD, keyName);
- payload.put(KMSRESTConstants.IV_FIELD,
- Base64.getEncoder().encodeToString("12345678".getBytes()));
- payload.put(KMSRESTConstants.MATERIAL_FIELD,
- Base64.getEncoder().encodeToString("encMaterial".getBytes()));
- return payload;
- }
-
- private KeyProvider.Metadata mockMetadata() {
- KeyProvider.Metadata metadata = mock(KeyProvider.Metadata.class);
- when(metadata.getCipher()).thenReturn("AES/CTR/NoPadding");
- when(metadata.getBitLength()).thenReturn(128);
- when(metadata.getDescription()).thenReturn("test key");
- when(metadata.getAttributes()).thenReturn(null);
- when(metadata.getCreated()).thenReturn(new Date());
- when(metadata.getVersions()).thenReturn(1);
- return metadata;
- }
-
- private EncryptedKeyVersion mockEncryptedKeyVersion(String keyName, String versionName)
- throws Exception {
- KeyProvider.KeyVersion nested = createKeyVersion(keyName, versionName, new byte[] {1, 2, 3});
- EncryptedKeyVersion ekv = mock(EncryptedKeyVersion.class);
- lenient().when(ekv.getEncryptionKeyName()).thenReturn(keyName);
- when(ekv.getEncryptionKeyVersionName()).thenReturn(versionName);
- when(ekv.getEncryptedKeyIv()).thenReturn(new byte[8]);
- when(ekv.getEncryptedKeyVersion()).thenReturn(nested);
- return ekv;
- }
-
- private static KeyProvider.KeyVersion createKeyVersion(String name, String versionName, byte[] material)
- throws Exception {
- Constructor<?> ctor = KeyProvider.KeyVersion.class.getDeclaredConstructor(
- String.class, String.class, byte[].class);
+ void testRemoveKeyMaterial_reflection() throws Exception {
+ Constructor<?> ctor = KeyProvider.KeyVersion.class.getDeclaredConstructor(String.class, String.class, byte[].class);
ctor.setAccessible(true);
- return (KeyProvider.KeyVersion) ctor.newInstance(name, versionName, material);
- }
-
- private static void setHttpUserInContext(UserGroupInformation ugi) throws Exception {
- Field ugiTlField = DelegationTokenAuthenticationFilter.class.getDeclaredField("UGI_TL");
- ugiTlField.setAccessible(true);
- @SuppressWarnings("unchecked")
- ThreadLocal<UserGroupInformation> ugiTl =
- (ThreadLocal<UserGroupInformation>) ugiTlField.get(null);
- ugiTl.set(ugi);
- }
-
- private static void clearHttpUserInContext() throws Exception {
- Field ugiTlField = DelegationTokenAuthenticationFilter.class.getDeclaredField("UGI_TL");
- ugiTlField.setAccessible(true);
- @SuppressWarnings("unchecked")
- ThreadLocal<UserGroupInformation> ugiTl =
- (ThreadLocal<UserGroupInformation>) ugiTlField.get(null);
- ugiTl.remove();
- }
- private static void setMdcContext(UserGroupInformation ugi, String url) throws Exception {
- Field dataTlField = KMSMDCFilter.class.getDeclaredField("DATA_TL");
- dataTlField.setAccessible(true);
- @SuppressWarnings("unchecked")
- ThreadLocal<Object> tl = (ThreadLocal<Object>) dataTlField.get(null);
+ KeyProvider.KeyVersion original = (KeyProvider.KeyVersion) ctor.newInstance("key1", "v1", "secret".getBytes());
- Class<?> dataClass = Class.forName(
- "org.apache.hadoop.crypto.key.kms.server.KMSMDCFilter$Data");
- Constructor<?> ctor = dataClass.getDeclaredConstructor(
- UserGroupInformation.class, String.class, String.class);
- ctor.setAccessible(true);
- Object data = ctor.newInstance(ugi, "POST", url);
- tl.set(data);
- }
-
- private static void clearMdcContext() throws Exception {
- Field dataTlField = KMSMDCFilter.class.getDeclaredField("DATA_TL");
- dataTlField.setAccessible(true);
- @SuppressWarnings("unchecked")
- ThreadLocal<?> tl = (ThreadLocal<?>) dataTlField.get(null);
- tl.remove();
- }
-
- private static Map<String, Object> snapshotMutableKmsWebAppStatics() throws Exception {
- Map<String, Object> snapshot = new HashMap<>();
- for (String fieldName : KMS_WEB_APP_MUTABLE_STATIC_FIELDS) {
- snapshot.put(fieldName, getStaticField(KMSWebApp.class, fieldName));
- }
- return snapshot;
- }
+ Method method = KMS.class.getDeclaredMethod("removeKeyMaterial", KeyProvider.KeyVersion.class);
+ method.setAccessible(true);
- private static void restoreKmsWebAppStatics(Map<String, Object> snapshot) throws Exception {
- for (Map.Entry<String, Object> entry : snapshot.entrySet()) {
- setStaticField(KMSWebApp.class, entry.getKey(), entry.getValue());
- }
- }
+ KeyProvider.KeyVersion result = (KeyProvider.KeyVersion) method.invoke(null, original);
- private static Object getStaticField(Class<?> clazz, String fieldName) throws Exception {
- Field field = clazz.getDeclaredField(fieldName);
- field.setAccessible(true);
- return field.get(null);
+ assertEquals("key1", result.getName());
+ assertEquals("v1", result.getVersionName());
+ assertNull(result.getMaterial());
}
private static void setStaticField(Class<?> clazz, String fieldName, Object value) throws Exception {