From cb05a2464d275d18c781e0b5b8e28c112c183706 Mon Sep 17 00:00:00 2001 From: Justin Field Date: Thu, 21 Jun 2018 14:13:59 -0700 Subject: [PATCH] Add new admin endpoint for getting kms key metadata (#166) --- API.md | 28 ++++++++ build.gradle | 2 +- gradle.properties | 2 +- .../com/nike/cerberus/dao/AwsIamRoleDao.java | 4 ++ .../cerberus/domain/AuthKmsKeyMetadata.java | 67 +++++++++++++++++++ .../domain/AuthKmsKeyMetadataResult.java | 22 ++++++ .../admin/GetAuthKmsKeyMetadata.java | 53 +++++++++++++++ .../cerberus/mapper/AwsIamRoleMapper.java | 2 + .../server/config/guice/CmsGuiceModule.java | 11 ++- .../com/nike/cerberus/service/KmsService.java | 29 ++++++++ .../nike/cerberus/mapper/AwsIamRoleMapper.xml | 9 ++- 11 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadata.java create mode 100644 src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadataResult.java create mode 100644 src/main/java/com/nike/cerberus/endpoints/admin/GetAuthKmsKeyMetadata.java diff --git a/API.md b/API.md index d683a1924..43b4f13b7 100644 --- a/API.md +++ b/API.md @@ -1549,6 +1549,34 @@ A 400 response code is given if the job wasn't found. + Response 204 No Content +## Get all the kms key metadata for all the kms keys creating for IAM auth [/v1/admin/authentication-kms-metadata] + +### [PUT] + ++ Request + + + Headers + + X-Cerberus-Token: AaAAAaaaAAAabCdEF0JkLMNZ01iGabcdefGHIJKLtClQabcCVabEYab1aDaZZz12a + X-Cerberus-Client: MyClientName/1.0.0 + ++ Response 200 (application/json) + + + Body + + { + "authentication_kms_key_metadata": [ + { + "aws_iam_role_arn": "arn:aws:iam::222222222222:role/foo-role", + "aws_kms_key_id": "arn:aws:kms:us-west-2:222222222222:key/b74225a6-2222-4444-baf0-abc123456", + "aws_region": "us-west-2", + "created_ts": "2018-06-20T14:39:56-07:00", + "last_updated_ts": "2018-06-20T14:39:56-07:00", + "last_validated_ts": null + } + ] + } + ## Healthcheck [/healthcheck] ### Healthcheck [GET] diff --git a/build.gradle b/build.gradle index 5b1eccf11..55ce16e01 100644 --- a/build.gradle +++ b/build.gradle @@ -152,4 +152,4 @@ task copyDashboardResources(type: Copy, dependsOn: buildDashboard) { into dashboardResourceFolder } -apply from: file('gradle/develop.gradle') \ No newline at end of file +apply from: file('gradle/develop.gradle') diff --git a/gradle.properties b/gradle.properties index fbc6d7e99..d960ff62b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,6 @@ # limitations under the License. # -version=3.16.2 +version=3.17.0 groupId=com.nike.cerberus artifactId=cms diff --git a/src/main/java/com/nike/cerberus/dao/AwsIamRoleDao.java b/src/main/java/com/nike/cerberus/dao/AwsIamRoleDao.java index 115ffcb83..32f0f74cb 100644 --- a/src/main/java/com/nike/cerberus/dao/AwsIamRoleDao.java +++ b/src/main/java/com/nike/cerberus/dao/AwsIamRoleDao.java @@ -101,4 +101,8 @@ public int deleteIamRoleById(final String id) { public int deleteKmsKeyById(final String id) { return awsIamRoleMapper.deleteKmsKeyById(id); } + + public Optional> getAllKmsKeys() { + return Optional.ofNullable(awsIamRoleMapper.getAllKmsKeys()); + } } diff --git a/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadata.java b/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadata.java new file mode 100644 index 000000000..0b18e387e --- /dev/null +++ b/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadata.java @@ -0,0 +1,67 @@ +package com.nike.cerberus.domain; + +import java.time.OffsetDateTime; + +public class AuthKmsKeyMetadata { + + private String awsIamRoleArn; + private String awsKmsKeyId; + private String awsRegion; + private OffsetDateTime createdTs; + private OffsetDateTime lastUpdatedTs; + private OffsetDateTime lastValidatedTs; + + public String getAwsIamRoleArn() { + return awsIamRoleArn; + } + + public AuthKmsKeyMetadata setAwsIamRoleArn(String awsIamRoleArn) { + this.awsIamRoleArn = awsIamRoleArn; + return this; + } + + public String getAwsKmsKeyId() { + return awsKmsKeyId; + } + + public AuthKmsKeyMetadata setAwsKmsKeyId(String awsKmsKeyId) { + this.awsKmsKeyId = awsKmsKeyId; + return this; + } + + public String getAwsRegion() { + return awsRegion; + } + + public AuthKmsKeyMetadata setAwsRegion(String awsRegion) { + this.awsRegion = awsRegion; + return this; + } + + public OffsetDateTime getCreatedTs() { + return createdTs; + } + + public AuthKmsKeyMetadata setCreatedTs(OffsetDateTime createdTs) { + this.createdTs = createdTs; + return this; + } + + public OffsetDateTime getLastUpdatedTs() { + return lastUpdatedTs; + } + + public AuthKmsKeyMetadata setLastUpdatedTs(OffsetDateTime lastUpdatedTs) { + this.lastUpdatedTs = lastUpdatedTs; + return this; + } + + public OffsetDateTime getLastValidatedTs() { + return lastValidatedTs; + } + + public AuthKmsKeyMetadata setLastValidatedTs(OffsetDateTime lastValidatedTs) { + this.lastValidatedTs = lastValidatedTs; + return this; + } +} diff --git a/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadataResult.java b/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadataResult.java new file mode 100644 index 000000000..24636f7a2 --- /dev/null +++ b/src/main/java/com/nike/cerberus/domain/AuthKmsKeyMetadataResult.java @@ -0,0 +1,22 @@ +package com.nike.cerberus.domain; + +import java.util.List; + +public class AuthKmsKeyMetadataResult { + private List authenticationKmsKeyMetadata; + + public AuthKmsKeyMetadataResult() { + } + + public AuthKmsKeyMetadataResult(List authenticationKmsKeyMetadata) { + this.authenticationKmsKeyMetadata = authenticationKmsKeyMetadata; + } + + public List getAuthenticationKmsKeyMetadata() { + return authenticationKmsKeyMetadata; + } + + public void setAuthenticationKmsKeyMetadata(List authenticationKmsKeyMetadata) { + this.authenticationKmsKeyMetadata = authenticationKmsKeyMetadata; + } +} diff --git a/src/main/java/com/nike/cerberus/endpoints/admin/GetAuthKmsKeyMetadata.java b/src/main/java/com/nike/cerberus/endpoints/admin/GetAuthKmsKeyMetadata.java new file mode 100644 index 000000000..13478f217 --- /dev/null +++ b/src/main/java/com/nike/cerberus/endpoints/admin/GetAuthKmsKeyMetadata.java @@ -0,0 +1,53 @@ +package com.nike.cerberus.endpoints.admin; + +import com.nike.cerberus.domain.AuthKmsKeyMetadataResult; +import com.nike.cerberus.endpoints.AdminStandardEndpoint; +import com.nike.cerberus.service.KmsService; +import com.nike.riposte.server.http.RequestInfo; +import com.nike.riposte.server.http.ResponseInfo; +import com.nike.riposte.server.http.impl.FullResponseInfo; +import com.nike.riposte.util.AsyncNettyHelper; +import com.nike.riposte.util.Matcher; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpMethod; + +import javax.inject.Inject; +import javax.ws.rs.core.SecurityContext; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +/** + * Endpoint for retrieving kms key metadata for all created keys in the db + */ +public class GetAuthKmsKeyMetadata extends AdminStandardEndpoint { + + private final KmsService kmsService; + + @Inject + public GetAuthKmsKeyMetadata(KmsService kmsService) { + this.kmsService = kmsService; + } + + @Override + public CompletableFuture> doExecute(RequestInfo request, + Executor longRunningTaskExecutor, + ChannelHandlerContext ctx, + SecurityContext securityContext) { + + return CompletableFuture.supplyAsync( + AsyncNettyHelper.supplierWithTracingAndMdc(() -> getAuthKmsKeyMetadata(request), ctx), + longRunningTaskExecutor + ); + } + + private FullResponseInfo getAuthKmsKeyMetadata(RequestInfo request) { + return ResponseInfo.newBuilder(new AuthKmsKeyMetadataResult( + kmsService.getAuthenticationKmsMetadata() + )).build(); + } + + @Override + public Matcher requestMatcher() { + return Matcher.match("/v1/admin/authentication-kms-metadata", HttpMethod.GET); + } +} diff --git a/src/main/java/com/nike/cerberus/mapper/AwsIamRoleMapper.java b/src/main/java/com/nike/cerberus/mapper/AwsIamRoleMapper.java index 2cacf86d9..199d62615 100644 --- a/src/main/java/com/nike/cerberus/mapper/AwsIamRoleMapper.java +++ b/src/main/java/com/nike/cerberus/mapper/AwsIamRoleMapper.java @@ -62,4 +62,6 @@ int deleteIamRolePermission(@Param("safeDepositBoxId") String safeDepositBoxId, int deleteIamRoleById(@Param("id") final String id); int deleteKmsKeyById(@Param("id") final String id); + + List getAllKmsKeys(); } diff --git a/src/main/java/com/nike/cerberus/server/config/guice/CmsGuiceModule.java b/src/main/java/com/nike/cerberus/server/config/guice/CmsGuiceModule.java index 3f5f6c88a..2f23b97f8 100644 --- a/src/main/java/com/nike/cerberus/server/config/guice/CmsGuiceModule.java +++ b/src/main/java/com/nike/cerberus/server/config/guice/CmsGuiceModule.java @@ -30,11 +30,7 @@ import com.nike.cerberus.endpoints.GetDashboardRedirect; import com.nike.cerberus.endpoints.HealthCheckEndpoint; import com.nike.cerberus.endpoints.RobotsEndpoint; -import com.nike.cerberus.endpoints.admin.GetSDBMetadata; -import com.nike.cerberus.endpoints.admin.OverrideSdbOwner; -import com.nike.cerberus.endpoints.admin.PutSDBMetadata; -import com.nike.cerberus.endpoints.admin.RestoreSafeDepositBox; -import com.nike.cerberus.endpoints.admin.TriggerScheduledJob; +import com.nike.cerberus.endpoints.admin.*; import com.nike.cerberus.endpoints.authentication.AuthenticateIamPrincipal; import com.nike.cerberus.endpoints.authentication.AuthenticateIamRole; import com.nike.cerberus.endpoints.authentication.AuthenticateUser; @@ -212,7 +208,8 @@ public Set> appEndpoints( ReadSecureFile readSecureFile, HeadSecureFile headSecureFile, GetSecureFiles getSecureFiles, - DeleteSecureFile deleteSecureFile + DeleteSecureFile deleteSecureFile, + GetAuthKmsKeyMetadata getAuthKmsKeyMetadata ) { return new LinkedHashSet<>(Arrays.>asList( healthCheckEndpoint, @@ -229,7 +226,7 @@ public Set> appEndpoints( getDashboard, getDashboardRedirect, writeSecureFile, readSecureFile, deleteSecureFile, headSecureFile, getSecureFiles, restoreSafeDepositBox, - getSecretVersionPathsForSdb, getSecureDataVersions + getSecretVersionPathsForSdb, getSecureDataVersions, getAuthKmsKeyMetadata )); } diff --git a/src/main/java/com/nike/cerberus/service/KmsService.java b/src/main/java/com/nike/cerberus/service/KmsService.java index 25f21751f..6da8d08e6 100644 --- a/src/main/java/com/nike/cerberus/service/KmsService.java +++ b/src/main/java/com/nike/cerberus/service/KmsService.java @@ -33,6 +33,7 @@ import com.nike.backstopper.exception.ApiException; import com.nike.cerberus.aws.KmsClientFactory; import com.nike.cerberus.dao.AwsIamRoleDao; +import com.nike.cerberus.domain.AuthKmsKeyMetadata; import com.nike.cerberus.error.DefaultApiError; import com.nike.cerberus.record.AwsIamRoleKmsKeyRecord; import com.nike.cerberus.util.AwsIamRoleArnParser; @@ -48,6 +49,8 @@ import javax.inject.Singleton; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; +import java.util.LinkedList; +import java.util.List; import java.util.Optional; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; @@ -125,6 +128,9 @@ public AwsIamRoleKmsKeyRecord provisionKmsKey(final String iamRoleRecordId, final String kmsKeyRecordId = uuidSupplier.get(); final String awsKmsKeyArn = createKmsKeyInAws(iamPrincipalArn, kmsKeyRecordId, awsRegion); + + logger.info("Created KMS Key with id: {} for ARN: {}, REGION: {}", awsKmsKeyArn, iamPrincipalArn, awsRegion); + return createKmsKeyRecord(iamRoleRecordId, kmsKeyRecordId, awsKmsKeyArn, awsRegion, user, @@ -243,6 +249,29 @@ public void deleteKmsKeyById(final String kmsKeyId) { awsIamRoleDao.deleteKmsKeyById(kmsKeyId); } + public List getAuthenticationKmsMetadata() { + List result = new LinkedList<>(); + + Optional> keysOptional = awsIamRoleDao.getAllKmsKeys(); + List keys = keysOptional.orElse(new LinkedList<>()); + + keys.forEach(key -> { + AuthKmsKeyMetadata metadata = new AuthKmsKeyMetadata() + .setAwsKmsKeyId(key.getAwsKmsKeyId()) + .setAwsRegion(key.getAwsRegion()) + .setCreatedTs(key.getCreatedTs()) + .setLastUpdatedTs(key.getLastUpdatedTs()) + .setLastUpdatedTs(key.getLastUpdatedTs()); + + awsIamRoleDao.getIamRoleById(key.getAwsIamRoleId()) + .ifPresent(awsIamRoleRecord -> metadata.setAwsIamRoleArn(awsIamRoleRecord.getAwsIamRoleArn())); + + result.add(metadata); + }); + + return result; + } + /** * Generate a unique and descriptive alias name for a KMS key * @param awsIamRoleKmsKeyId UUID diff --git a/src/main/resources/com/nike/cerberus/mapper/AwsIamRoleMapper.xml b/src/main/resources/com/nike/cerberus/mapper/AwsIamRoleMapper.xml index 7dba218a3..d5ebc1b2f 100644 --- a/src/main/resources/com/nike/cerberus/mapper/AwsIamRoleMapper.xml +++ b/src/main/resources/com/nike/cerberus/mapper/AwsIamRoleMapper.xml @@ -62,6 +62,13 @@ AWS_IAM_ROLE.ID = AWS_IAM_ROLE_PERMISSIONS.AWS_IAM_ROLE_ID) + +