From 0208d0d1a2309a26277f3793dc3e7ba6c13c1141 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 10:22:10 -0700 Subject: [PATCH 01/55] chore(deps-dev): bump mockito-core from 3.12.3 to 3.12.4 (#323) Bumps [mockito-core](https://github.com/mockito/mockito) from 3.12.3 to 3.12.4. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.12.3...v3.12.4) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6c2c8e9d5..59e7e4a42 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.mockito mockito-core - 3.12.3 + 3.12.4 test From 693e43fb9606824e8b4f5336ef8d06cf454338de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 12:10:33 -0700 Subject: [PATCH 02/55] chore(deps): bump maven-javadoc-plugin from 3.3.0 to 3.3.1 (#333) Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.3.0...maven-javadoc-plugin-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59e7e4a42..3133e4832 100644 --- a/pom.xml +++ b/pom.xml @@ -123,7 +123,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.0 + 3.3.1 128m 1024m From 2338b92358b655ee057ba15b4a6b4282988f8875 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 13:12:18 -0700 Subject: [PATCH 03/55] chore(deps-dev): bump junit-vintage-engine from 5.7.2 to 5.8.0 (#337) Bumps [junit-vintage-engine](https://github.com/junit-team/junit5) from 5.7.2 to 5.8.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.7.2...r5.8.0) --- updated-dependencies: - dependency-name: org.junit.vintage:junit-vintage-engine dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3133e4832..61c800b81 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ org.junit.vintage junit-vintage-engine - 5.7.2 + 5.8.0 test From 6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 14:56:12 -0700 Subject: [PATCH 04/55] chore(deps-dev): bump junit-jupiter-api from 5.7.2 to 5.8.0 (#339) Bumps [junit-jupiter-api](https://github.com/junit-team/junit5) from 5.7.2 to 5.8.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.7.2...r5.8.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 61c800b81..b261d55ff 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ org.junit.jupiter junit-jupiter-api - 5.7.2 + 5.8.0 test From 291be0a722567697cb2fe5174837c83276d626bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 16:10:15 -0700 Subject: [PATCH 05/55] chore(deps): bump aws-java-sdk from 1.12.54 to 1.12.68 (#341) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.54 to 1.12.68. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.54...1.12.68) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b261d55ff..982994e3f 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.54 + 1.12.68 true From 456dda0a8d6a2b3ce67024cc0b52edd24ec2816b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Thu, 23 Sep 2021 15:56:03 -0700 Subject: [PATCH 06/55] chore: source controlling cfn templates that will be used for our release process (#345) * chore: Adding cfn template for the release code build project * chore: Adding parameter map and code artifact cfn template * chore: removing cloud designer metadata --- cfn/code_artifact.yml | 44 ++++++ cfn/code_build_parameter_map.json | 6 + cfn/prod-release.yml | 243 ++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 cfn/code_artifact.yml create mode 100644 cfn/code_build_parameter_map.json create mode 100644 cfn/prod-release.yml diff --git a/cfn/code_artifact.yml b/cfn/code_artifact.yml new file mode 100644 index 000000000..461009846 --- /dev/null +++ b/cfn/code_artifact.yml @@ -0,0 +1,44 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +AWSTemplateFormatVersion: 2010-09-09 +Description: "Template for CodeArtifact repositories. Creates Domain if CreateDomainFlag is True" +Parameters: + DomainName: + Type: String + Description: The name of the CodeArtifact Domain + Default: crypto-tools-internal + RepositoryName: + Type: String + Description: Base Name for the Repositories + Default: esdk-java + CreateDomainFlag: + Type: String + Description: Attempt to create Domain or not + Default: False + AllowedValues: + - True + - False + +Conditions: + CreateDomain: !Equals + - !Ref CreateDomainFlag + - True + +Resources: + Domain: + Type: AWS::CodeArtifact::Domain + Condition: CreateDomain + Properties: + DomainName: !Ref DomainName + + CIRepo: + Type: AWS::CodeArtifact::Repository + Properties: + DomainName: !Ref DomainName + RepositoryName: !Sub "${RepositoryName}-ci" + + StagingRepo: + Type: AWS::CodeArtifact::Repository + Properties: + DomainName: !Ref DomainName + RepositoryName: !Sub "${RepositoryName}-staging" diff --git a/cfn/code_build_parameter_map.json b/cfn/code_build_parameter_map.json new file mode 100644 index 000000000..385c4d08b --- /dev/null +++ b/cfn/code_build_parameter_map.json @@ -0,0 +1,6 @@ +{ + "NumberOfBuildsInBatch": 50, + "ProjectDescription": "CD for Java ESDK", + "ProjectName": "java-esdk", + "SourceLocation": "https://github.com/aws/aws-encryption-sdk-java.git" +} diff --git a/cfn/prod-release.yml b/cfn/prod-release.yml new file mode 100644 index 000000000..ebdf0ac52 --- /dev/null +++ b/cfn/prod-release.yml @@ -0,0 +1,243 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + Template to build a CodeBuild Project, assumes that GitHub credentials are + already set up. +Parameters: + ProjectName: + Type: String + Description: The name of the CodeBuild Project + Default: java-esdk-prod + ProjectDescription: + Type: String + Description: The description for the CodeBuild Project + Default: CFN stack for managing CodeBuild Release project for the ESDK-Java + SourceLocation: + Type: String + Description: The https GitHub URL for the project + Default: "https://github.com/aws/aws-encryption-sdk-java.git" + NumberOfBuildsInBatch: + Type: Number + MaxValue: 100 + MinValue: 1 + Default: 10 + Description: The number of builds you expect to run in a batch +Metadata: + "AWS::CloudFormation::Interface": + ParameterGroups: + - Label: + default: Crypto Tools CodeBuild Project Template + Parameters: + - ProjectName + - ProjectDescription + - SourceLocation +Resources: + CodeBuildProjectRelease: + Type: "AWS::CodeBuild::Project" + Properties: + Name: !Sub "${ProjectName}-release-prod" + Description: !Sub "CodeBuild project for ${ProjectName} to release to Sonatype." + Source: + Location: !Ref SourceLocation + BuildSpec: codebuild/release/prod-release.yml + GitCloneDepth: 1 + GitSubmodulesConfig: + FetchSubmodules: false + InsecureSsl: false + ReportBuildStatus: false + Type: GITHUB + Artifacts: + Type: NO_ARTIFACTS + Cache: + Type: NO_CACHE + Environment: + ComputeType: BUILD_GENERAL1_LARGE + Image: "aws/codebuild/standard:4.0" + ImagePullCredentialsType: CODEBUILD + PrivilegedMode: false + Type: LINUX_CONTAINER + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + TimeoutInMinutes: 60 + QueuedTimeoutInMinutes: 480 + EncryptionKey: !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3" + BadgeEnabled: false + BuildBatchConfig: + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + Restrictions: + MaximumBuildsAllowed: !Ref NumberOfBuildsInBatch + ComputeTypesAllowed: + - BUILD_GENERAL1_SMALL + - BUILD_GENERAL1_MEDIUM + - BUILD_GENERAL1_LARGE + TimeoutInMins: 480 + LogsConfig: + CloudWatchLogs: + Status: ENABLED + S3Logs: + Status: DISABLED + EncryptionDisabled: false + CodeBuildServiceRole: + Type: "AWS::IAM::Role" + Properties: + Path: /service-role/ + RoleName: !Sub "codebuild-${ProjectName}-service-role" + AssumeRolePolicyDocument: >- + {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"codebuild.amazonaws.com"},"Action":"sts:AssumeRole"}]} + MaxSessionDuration: 3600 + ManagedPolicyArns: + - !Ref CryptoToolsKMS + - !Ref CodeBuildBatchPolicy + - !Ref CodeBuildBasePolicy + - !Ref SecretsManagerPolicy + - !Ref ParameterStorePolicy + - "arn:aws:iam::aws:policy/AWSCodeArtifactReadOnlyAccess" + - "arn:aws:iam::aws:policy/AWSCodeArtifactAdminAccess" + CodeBuildBatchPolicy: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub >- + CodeBuildBuildBatchPolicy-${ProjectName}-${AWS::Region}-codebuild-${ProjectName}-service-role + Path: /service-role/ + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-test-release", + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-prod-release", + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}" + ], + "Action": [ + "codebuild:StartBuild", + "codebuild:StopBuild", + "codebuild:RetryBuild" + ] + } + ] + } + CodeBuildBasePolicy: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub "CodeBuildBasePolicy-${ProjectName}-${AWS::Region}" + Path: /service-role/ + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}:*", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-test-release", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-test-release:*", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-prod-release", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-prod-release:*" + ], + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + }, + { + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::codepipeline-${AWS::Region}-*" + ], + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:GetObjectVersion", + "s3:GetBucketAcl", + "s3:GetBucketLocation" + ] + }, + { + "Effect": "Allow", + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Resource": [ + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${ProjectName}-*" + ] + } + ] + } + AccountIdParameter: + Type: "AWS::SSM::Parameter" + Properties: + Description: Parameter to store our account id so CodeBuild specs can access it + Name: /CodeBuild/AccountId + Type: String + Value: !Sub "${AWS::AccountId}" + SecretsManagerPolicy: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub "CryptoTools-SecretsManager-${ProjectName}-release" + Path: /service-role/ + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Maven-GPG-Keys-GC6h0A", + "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Sonatype-Team-Account-0tWvZm", + "arn:aws:secretsmanager:us-west-2:587316601012:secret:Maven-GPG-Keys-Credentials-C0wCzI", + ], + "Action": "secretsmanager:GetSecretValue" + } + ] + } + CryptoToolsKMS: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub >- + CrypotToolsKMSPolicy-${ProjectName}-${AWS::Region}-codebuild-${ProjectName}-service-role + Path: /service-role/ + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:kms:*:658956600833:key/*", + "arn:aws:kms:*:658956600833:alias/*" + ], + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:GenerateDataKey" + ] + } + ] + } + ParameterStorePolicy: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub "CryptoTools-ParameterStore-${ProjectName}-release" + Path: /service-role/ + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/CodeBuild/*" + ], + "Action": "ssm:GetParameters" + } + ] + } From 6201c1accccd3dea2d991a1d579234842865540d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Thu, 23 Sep 2021 17:16:55 -0700 Subject: [PATCH 07/55] chore: Adding semantic release config file (#346) * chore: Adding semantic release config file * chore: fixing typo, default branch should be master not main * chore: adding revert to the config file * chore: updating .gitignore --- .gitignore | 4 ++++ .releaserc | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .releaserc diff --git a/.gitignore b/.gitignore index 875661f53..8e92eb021 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ target/ /.history /.DS_Store /specification_compliance_report.html + +## semantic-release +package-lock.json +node_modules/ diff --git a/.releaserc b/.releaserc new file mode 100644 index 000000000..21b024b2b --- /dev/null +++ b/.releaserc @@ -0,0 +1,52 @@ +{ + "branches": ["master"], + "plugins": [ + ["@semantic-release/commit-analyzer", { + "preset": "conventionalcommits", + "parserOpts": { + "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"] + }, + "presetConfig": { + "types": [ + {"type": "feat", "section": "Features"}, + {"type": "fix", "section": "Bug Fixes"}, + {"type": "chore", "section": "Maintenance"}, + {"type": "docs", "section": "Maintenance"}, + {"type": "revert", "section": "Bug Fixes"}, + {"type": "style", "hidden": true}, + {"type": "refactor", "hidden": true}, + {"type": "perf", "hidden": true}, + {"type": "test", "hidden": true} + ] + } + }], + ["@semantic-release/release-notes-generator", { + "preset": "conventionalcommits", + "parserOpts": { + "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"] + }, + "presetConfig": { + "types": [ + {"type": "feat", "section": "Features"}, + {"type": "fix", "section": "Bug Fixes"}, + {"type": "chore", "section": "Maintenance"}, + {"type": "docs", "section": "Maintenance"}, + {"type": "revert", "section": "Bug Fixes"}, + {"type": "style", "hidden": true}, + {"type": "refactor", "hidden": true}, + {"type": "perf", "hidden": true}, + {"type": "test", "hidden": true} + ] + } + }], + ["@semantic-release/changelog", { + "changelogFile": "./CHANGELOG.md" + }], + ["@semantic-release/git", { + "assets": ["./CHANGELOG.md"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }], + "@semantic-release/github" + ], + "repositoryUrl": "https://github.com/josecorella/test-semantic-release-pr", +} From 153a0b3ec3e99c3d878ac9f97176138277a35d8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 06:59:03 -0700 Subject: [PATCH 08/55] chore(deps): bump aws-java-sdk from 1.12.68 to 1.12.73 (#350) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.68 to 1.12.73. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.68...1.12.73) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 982994e3f..d0e1220e0 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.68 + 1.12.73 true From d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 07:38:20 -0700 Subject: [PATCH 09/55] chore(deps-dev): bump junit-vintage-engine from 5.8.0 to 5.8.1 (#348) Bumps [junit-vintage-engine](https://github.com/junit-team/junit5) from 5.8.0 to 5.8.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.8.0...r5.8.1) --- updated-dependencies: - dependency-name: org.junit.vintage:junit-vintage-engine dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d0e1220e0..b0cfa018f 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ org.junit.vintage junit-vintage-engine - 5.8.0 + 5.8.1 test From 7d3bb0a976746bfb56c13136e876234ea64da581 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 08:34:33 -0700 Subject: [PATCH 10/55] chore(deps-dev): bump junit-jupiter-api from 5.8.0 to 5.8.1 (#347) Bumps [junit-jupiter-api](https://github.com/junit-team/junit5) from 5.8.0 to 5.8.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.8.0...r5.8.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b0cfa018f..b4788db64 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ org.junit.jupiter junit-jupiter-api - 5.8.0 + 5.8.1 test From e5f3962f74da9b4197e37d98e68e722ee0d10e8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Sep 2021 12:53:23 -0700 Subject: [PATCH 11/55] chore(deps): bump aws-java-sdk from 1.12.73 to 1.12.74 (#351) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.73 to 1.12.74. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.73...1.12.74) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b4788db64..0b0138627 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.73 + 1.12.74 true From 3339c20b05e9cbb65317785cf72c3d46087c82c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Sep 2021 09:49:34 -0700 Subject: [PATCH 12/55] chore(deps): bump aws-java-sdk from 1.12.74 to 1.12.75 (#353) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.74 to 1.12.75. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.74...1.12.75) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0b0138627..e3e69a995 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.74 + 1.12.75 true From ecc17a6789a204fdc9bded0fa335b7087f0b371b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Mon, 4 Oct 2021 10:24:02 -0700 Subject: [PATCH 13/55] chore: updating prod template to remove resources and abstract ones (#354) * chore: removing extra log p[olicy that is not needed for prod-release * chore: adding aws account id subsitution * chore: adding accountid back to managepolicy * chore: correctly formatting secrets policy * chore: rename file and adding cfn template for our CI project * chore: format json * style: add new line between resources --- cfn/{prod-release.yml => ci_cd.yml} | 141 +++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 24 deletions(-) rename cfn/{prod-release.yml => ci_cd.yml} (66%) diff --git a/cfn/prod-release.yml b/cfn/ci_cd.yml similarity index 66% rename from cfn/prod-release.yml rename to cfn/ci_cd.yml index ebdf0ac52..c49c2de33 100644 --- a/cfn/prod-release.yml +++ b/cfn/ci_cd.yml @@ -9,11 +9,11 @@ Parameters: ProjectName: Type: String Description: The name of the CodeBuild Project - Default: java-esdk-prod + Default: AWS-ESDK-Java ProjectDescription: Type: String Description: The description for the CodeBuild Project - Default: CFN stack for managing CodeBuild Release project for the ESDK-Java + Default: CFN stack for managing CodeBuild projects for the AWS ESDK Java SourceLocation: Type: String Description: The https GitHub URL for the project @@ -22,7 +22,7 @@ Parameters: Type: Number MaxValue: 100 MinValue: 1 - Default: 10 + Default: 16 Description: The number of builds you expect to run in a batch Metadata: "AWS::CloudFormation::Interface": @@ -34,14 +34,65 @@ Metadata: - ProjectDescription - SourceLocation Resources: + CodeBuildProjectCI: + Type: "AWS::CodeBuild::Project" + Properties: + Name: !Sub "${ProjectName}-CI" + Description: !Sub "CI for the Java ESDK" + Source: + Location: !Ref SourceLocation + BuildSpec: codebuild/ci/ci.yml + GitCloneDepth: 1 + GitSubmodulesConfig: + FetchSubmodules: false + InsecureSsl: false + ReportBuildStatus: false + Type: GITHUB + Triggers: + BuildType: BUILD_BATCH + Webhook: true + FilterGroups: + - - Type: EVENT + Pattern: PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED + Artifacts: + Type: NO_ARTIFACTS + Cache: + Type: NO_CACHE + Environment: + ComputeType: BUILD_GENERAL1_LARGE + Image: "aws/codebuild/standard:5.0" + ImagePullCredentialsType: CODEBUILD + PrivilegedMode: false + Type: LINUX_CONTAINER + ServiceRole: !GetAtt CodeBuildServiceRoleCI.Arn + TimeoutInMinutes: 60 + QueuedTimeoutInMinutes: 480 + EncryptionKey: !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3" + BadgeEnabled: false + BuildBatchConfig: + ServiceRole: !GetAtt CodeBuildServiceRoleCI.Arn + Restrictions: + MaximumBuildsAllowed: !Ref NumberOfBuildsInBatch + ComputeTypesAllowed: + - BUILD_GENERAL1_SMALL + - BUILD_GENERAL1_MEDIUM + - BUILD_GENERAL1_LARGE + TimeoutInMins: 480 + LogsConfig: + CloudWatchLogs: + Status: ENABLED + S3Logs: + Status: DISABLED + EncryptionDisabled: false + CodeBuildProjectRelease: Type: "AWS::CodeBuild::Project" Properties: - Name: !Sub "${ProjectName}-release-prod" + Name: !Sub "${ProjectName}-Release" Description: !Sub "CodeBuild project for ${ProjectName} to release to Sonatype." Source: Location: !Ref SourceLocation - BuildSpec: codebuild/release/prod-release.yml + BuildSpec: codebuild/release/release.yml GitCloneDepth: 1 GitSubmodulesConfig: FetchSubmodules: false @@ -54,17 +105,17 @@ Resources: Type: NO_CACHE Environment: ComputeType: BUILD_GENERAL1_LARGE - Image: "aws/codebuild/standard:4.0" + Image: "aws/codebuild/standard:5.0" ImagePullCredentialsType: CODEBUILD PrivilegedMode: false Type: LINUX_CONTAINER - ServiceRole: !GetAtt CodeBuildServiceRole.Arn + ServiceRole: !GetAtt CodeBuildServiceRoleRelease.Arn TimeoutInMinutes: 60 QueuedTimeoutInMinutes: 480 EncryptionKey: !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3" BadgeEnabled: false BuildBatchConfig: - ServiceRole: !GetAtt CodeBuildServiceRole.Arn + ServiceRole: !GetAtt CodeBuildServiceRoleRelease.Arn Restrictions: MaximumBuildsAllowed: !Ref NumberOfBuildsInBatch ComputeTypesAllowed: @@ -78,11 +129,12 @@ Resources: S3Logs: Status: DISABLED EncryptionDisabled: false - CodeBuildServiceRole: + + CodeBuildServiceRoleCI: Type: "AWS::IAM::Role" Properties: Path: /service-role/ - RoleName: !Sub "codebuild-${ProjectName}-service-role" + RoleName: !Sub "codebuild-${ProjectName}-service-role-ci" AssumeRolePolicyDocument: >- {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"codebuild.amazonaws.com"},"Action":"sts:AssumeRole"}]} MaxSessionDuration: 3600 @@ -90,10 +142,28 @@ Resources: - !Ref CryptoToolsKMS - !Ref CodeBuildBatchPolicy - !Ref CodeBuildBasePolicy - - !Ref SecretsManagerPolicy + - !Ref SecretsManagerPolicyCI - !Ref ParameterStorePolicy - "arn:aws:iam::aws:policy/AWSCodeArtifactReadOnlyAccess" - "arn:aws:iam::aws:policy/AWSCodeArtifactAdminAccess" + + CodeBuildServiceRoleRelease: + Type: "AWS::IAM::Role" + Properties: + Path: /service-role/ + RoleName: !Sub "codebuild-${ProjectName}-service-role-release" + AssumeRolePolicyDocument: >- + {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"codebuild.amazonaws.com"},"Action":"sts:AssumeRole"}]} + MaxSessionDuration: 3600 + ManagedPolicyArns: + - !Ref CryptoToolsKMS + - !Ref CodeBuildBatchPolicy + - !Ref CodeBuildBasePolicy + - !Ref SecretsManagerPolicyRelease + - !Ref ParameterStorePolicy + - "arn:aws:iam::aws:policy/AWSCodeArtifactReadOnlyAccess" + - "arn:aws:iam::aws:policy/AWSCodeArtifactAdminAccess" + CodeBuildBatchPolicy: Type: "AWS::IAM::ManagedPolicy" Properties: @@ -107,8 +177,8 @@ Resources: { "Effect": "Allow", "Resource": [ - "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-test-release", - "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-prod-release", + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-Release", + "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}-CI", "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${ProjectName}" ], "Action": [ @@ -119,6 +189,7 @@ Resources: } ] } + CodeBuildBasePolicy: Type: "AWS::IAM::ManagedPolicy" Properties: @@ -133,10 +204,10 @@ Resources: "Resource": [ "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}", "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}:*", - "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-test-release", - "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-test-release:*", - "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-prod-release", - "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-prod-release:*" + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-CI", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-CI:*", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-Release", + "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}-Release:*" ], "Action": [ "logs:CreateLogGroup", @@ -172,18 +243,39 @@ Resources: } ] } + AccountIdParameter: Type: "AWS::SSM::Parameter" Properties: Description: Parameter to store our account id so CodeBuild specs can access it - Name: /CodeBuild/AccountId + Name: /CodeBuild/AccountIdentity Type: String Value: !Sub "${AWS::AccountId}" - SecretsManagerPolicy: + + SecretsManagerPolicyCI: Type: "AWS::IAM::ManagedPolicy" Properties: - ManagedPolicyName: !Sub "CryptoTools-SecretsManager-${ProjectName}-release" - Path: /service-role/ + ManagedPolicyName: !Sub "CryptoTools-SecretsManager-${ProjectName}-CI" + Path: "/service-role/" + PolicyDocument: !Sub | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Maven-GPG-Keys-GC6h0A" + ], + "Action": "secretsmanager:GetSecretValue" + } + ] + } + + SecretsManagerPolicyRelease: + Type: "AWS::IAM::ManagedPolicy" + Properties: + ManagedPolicyName: !Sub "CryptoTools-SecretsManager-${ProjectName}-Release" + Path: "/service-role/" PolicyDocument: !Sub | { "Version": "2012-10-17", @@ -192,13 +284,13 @@ Resources: "Effect": "Allow", "Resource": [ "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Maven-GPG-Keys-GC6h0A", - "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Sonatype-Team-Account-0tWvZm", - "arn:aws:secretsmanager:us-west-2:587316601012:secret:Maven-GPG-Keys-Credentials-C0wCzI", + "arn:aws:secretsmanager:us-west-2:${AWS::AccountId}:secret:Sonatype-Team-Account-0tWvZm" ], "Action": "secretsmanager:GetSecretValue" } ] } + CryptoToolsKMS: Type: "AWS::IAM::ManagedPolicy" Properties: @@ -223,10 +315,11 @@ Resources: } ] } + ParameterStorePolicy: Type: "AWS::IAM::ManagedPolicy" Properties: - ManagedPolicyName: !Sub "CryptoTools-ParameterStore-${ProjectName}-release" + ManagedPolicyName: !Sub "CryptoTools-ParameterStore-${ProjectName}" Path: /service-role/ PolicyDocument: !Sub | { From e259caf3c50ab4c3346ca8e203cc6d6878482aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Sat, 9 Oct 2021 09:03:03 -0700 Subject: [PATCH 14/55] chore: moving and renaming buildspec.yml (#360) --- buildspec.yml => codebuild/ci/ci.yml | 0 codebuild/ci/release-ci.yml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename buildspec.yml => codebuild/ci/ci.yml (100%) diff --git a/buildspec.yml b/codebuild/ci/ci.yml similarity index 100% rename from buildspec.yml rename to codebuild/ci/ci.yml diff --git a/codebuild/ci/release-ci.yml b/codebuild/ci/release-ci.yml index e3c6123cc..412fb3223 100644 --- a/codebuild/ci/release-ci.yml +++ b/codebuild/ci/release-ci.yml @@ -8,7 +8,7 @@ env: NAMESPACE: com.amazonaws PACKAGE: aws-encryption-sdk-java parameter-store: - ACCOUNT: /CodeBuild/AccountId + ACCOUNT: /CodeBuild/AccountIdentity secrets-manager: GPG_KEY: Maven-GPG-Keys-Credentials:Keyname GPG_PASS: Maven-GPG-Keys-Credentials:Passphrase From 63e2f054929b056bdd74328b94c5f96577626113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Thu, 14 Oct 2021 14:00:02 -0700 Subject: [PATCH 15/55] chore: update releaserc to include pom.xml file (#357) --- .gitignore | 2 ++ .releaserc | 33 +++++++++++++++++++++++---------- CHANGELOG.md | 40 ++++++++++++++++++++-------------------- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 8e92eb021..da3861280 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ target/ ## semantic-release package-lock.json +package.json node_modules/ +pom.xml.versionsBackup diff --git a/.releaserc b/.releaserc index 21b024b2b..b03c40cdc 100644 --- a/.releaserc +++ b/.releaserc @@ -1,3 +1,5 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 { "branches": ["master"], "plugins": [ @@ -9,16 +11,21 @@ "presetConfig": { "types": [ {"type": "feat", "section": "Features"}, - {"type": "fix", "section": "Bug Fixes"}, + {"type": "fix", "section": "Fixes"}, {"type": "chore", "section": "Maintenance"}, {"type": "docs", "section": "Maintenance"}, - {"type": "revert", "section": "Bug Fixes"}, + {"type": "revert", "section": "Fixes"}, {"type": "style", "hidden": true}, {"type": "refactor", "hidden": true}, {"type": "perf", "hidden": true}, {"type": "test", "hidden": true} ] - } + }, + "releaseRules": [ + {"type": "docs", "release": "patch"}, + {"type": "revert", "release": "patch"}, + {"type": "chore", "release": "patch"} + ] }], ["@semantic-release/release-notes-generator", { "preset": "conventionalcommits", @@ -28,10 +35,10 @@ "presetConfig": { "types": [ {"type": "feat", "section": "Features"}, - {"type": "fix", "section": "Bug Fixes"}, + {"type": "fix", "section": "Fixes"}, {"type": "chore", "section": "Maintenance"}, {"type": "docs", "section": "Maintenance"}, - {"type": "revert", "section": "Bug Fixes"}, + {"type": "revert", "section": "Fixes"}, {"type": "style", "hidden": true}, {"type": "refactor", "hidden": true}, {"type": "perf", "hidden": true}, @@ -40,13 +47,19 @@ } }], ["@semantic-release/changelog", { - "changelogFile": "./CHANGELOG.md" + "changelogFile": "./CHANGELOG.md", + "changelogTitle": "# Changelog" + }], + ["@semantic-release/exec", { + "prepareCmd": "mvn versions:set -DnewVersion=${nextRelease.version} \ + -DautoVersionSubmodules=true && find README.md -type f \ + -exec sed -i '' 's/.*<\\/version>/${nextRelease.version}<\\/version>/g' {} \\;" }], ["@semantic-release/git", { - "assets": ["./CHANGELOG.md"], - "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + "assets": ["./CHANGELOG.md", "./pom.xml", "./README.md"], + "message": "AWS Encryption SDK ${nextRelease.version} Release \n\n${nextRelease.notes}" }], - "@semantic-release/github" + #@semantic-release/github" ], - "repositoryUrl": "https://github.com/josecorella/test-semantic-release-pr", + "repositoryUrl": "https://github.com/aws/aws-encryption-sdk-java", } diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b8b78e5..9678bf084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2.3.3 -- 2021-08-26 +### 2.3.3 -- 2021-08-26 ### Maintenance @@ -23,7 +23,7 @@ * CI: Compilation with OpenJDK11 and validation with other JDKs ([#293](https://github.com/aws/aws-encryption-sdk-java/pull/293)) -## 2.3.2 -- 2021-07-20 +### 2.3.2 -- 2021-07-20 ### Maintenance @@ -47,11 +47,11 @@ * chore: Add support policy ([#274](https://github.com/aws/aws-encryption-sdk-java/pull/274)) -## 2.3.1 -- 2021-06-29 +### 2.3.1 -- 2021-06-29 * fix: read project properties from package's own ClassLoader [(PR #269)](https://github.com/aws/aws-encryption-sdk-java/pull/269) -## 2.3.0 -- 2021-06-16 +### 2.3.0 -- 2021-06-16 * feat: AWS KMS multi-Region Key support @@ -66,14 +66,14 @@ for more details about how the AWS Encryption SDK interoperates with AWS KMS multi-Region keys. -## 2.2.0 -- 2021-05-27 +### 2.2.0 -- 2021-05-27 * feat: Improvements to the message decryption process. See https://github.com/aws/aws-encryption-sdk-java/security/advisories/GHSA-55xh-53m6-936r -## 2.0.0 -- 2020-09-24 +### 2.0.0 -- 2020-09-24 * feat!: Updates to the AWS Encryption SDK. 4678ffa @@ -84,11 +84,11 @@ Key committing suites are now default. CommitmentPolicy requires commitment by d See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration.html -## 1.7.0 -- 2020-09-24 +### 1.7.0 -- 2020-09-24 * feat: Updates to the AWS Encryption SDK. a6be12a -## 1.6.2 -- 2020-05-26 +### 1.6.2 -- 2020-05-26 ### Patches * Validate final frame length does not exceed the frame size in the message header [PR #166](https://github.com/aws/aws-encryption-sdk-java/pull/166) @@ -98,7 +98,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration * Update AWS Java SDK version from 1.11.561 to 1.11.704. [PR #186](https://github.com/aws/aws-encryption-sdk-java/pull/186) * Upgrade Bouncy Castle from 1.61 to 1.65 [PR #179](https://github.com/aws/aws-encryption-sdk-java/pull/179) -## 1.6.1 -- 2019-10-29 +### 1.6.1 -- 2019-10-29 ### Deprecation Warnings * Deprecated `AwsCrypto.encryptString()` and `AwsCrypto.decryptString()`. @@ -121,7 +121,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration [#131](https://github.com/aws/aws-encryption-sdk-java/pull/131), and [#132](https://github.com/aws/aws-encryption-sdk-java/pull/132). -## 1.6.0 -- 2019-05-31 +### 1.6.0 -- 2019-05-31 ### Minor Changes * Remove dependency on Apache Commons Codec 1.12. @@ -129,7 +129,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration * Introduce and use utility methods for Base64 encoding/decoding so that switching the codec provider needs to be done only in one place next time. -## 1.5.0 -- 2019-05-30 +### 1.5.0 -- 2019-05-30 ### Minor Changes * Added dependency on Apache Commons Codec 1.12. @@ -142,12 +142,12 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration * Upgrade Mockito from 2.23.4 to 2.28.1. * Upgrade Apache Commons Lang from 3.4 to 3.9. -## 1.4.1 -- 2019-05-10 +### 1.4.1 -- 2019-05-10 ### Patches * Cast ByteBuffer to Buffer prior to using some methods so that it works properly in Java 8. -## 1.4.0 -- 2019-05-10 +### 1.4.0 -- 2019-05-10 ### Minor Changes * Increased BouncyCastle dependency version to 1.61 @@ -156,7 +156,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration ### Maintenance * Increased Mockito test dependency version to 2.23.4 -## 1.3.6 -- 2018-12-10 +### 1.3.6 -- 2018-12-10 ### Patches * Fixed typos in Exception messages (excryption -> encryption) #78 @@ -168,7 +168,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration * Added JML specs in #72 * Ensure that KeyBlob treats field lengths as unsigned shorts #71 -## 1.3.5 +### 1.3.5 ### Minor Changes @@ -178,7 +178,7 @@ See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration region not servicable by that MKP, the exception will now be thrown on first use of the MK, rather than at getMasterKey time. -## 1.3.4 +### 1.3.4 ### Minor Changes @@ -186,7 +186,7 @@ use of the MK, rather than at getMasterKey time. decrypting certain malformed ciphertexts. This may reduce performance slightly in some scenarios. -## 1.3.3 +### 1.3.3 ### Minor Changes * Move the `aws-encryption-sdk-java` repository from `awslabs` to `aws`. @@ -194,7 +194,7 @@ in some scenarios. * Make `JceMasterKey` case insensitive * Fix bare aliases not using default region -## 1.3.2 +### 1.3.2 ### Minor Changes * Frame size restriction removed again @@ -202,7 +202,7 @@ in some scenarios. * Fix estimateCipherText when used with cached data keys * Do not automatically set a default region in KmsMasterKeyProvider -## 1.3.1 +### 1.3.1 ### Minor changes @@ -210,7 +210,7 @@ in some scenarios. This restriction was relaxed in 1.3.0, but due to compatibility concerns we'll put this restriction back in for the time being. -## 1.3.0 +### 1.3.0 ### Major changes From 4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Mon, 18 Oct 2021 16:36:36 -0700 Subject: [PATCH 16/55] chore: release updates (#369) --- codebuild/release/release-prod.yml | 54 ++---------- codebuild/release/release-staging.yml | 58 ++----------- codebuild/release/release.yml | 112 +++++++++++++++++++++++++ codebuild/release/settings.xml | 4 + codebuild/release/validate-prod.yml | 3 + codebuild/release/validate-staging.yml | 7 +- codebuild/release/version.yml | 29 +++++++ look_4_version.sh | 29 +++++++ 8 files changed, 197 insertions(+), 99 deletions(-) create mode 100644 codebuild/release/release.yml create mode 100644 codebuild/release/version.yml create mode 100755 look_4_version.sh diff --git a/codebuild/release/release-prod.yml b/codebuild/release/release-prod.yml index 451a200bf..9699c27a8 100644 --- a/codebuild/release/release-prod.yml +++ b/codebuild/release/release-prod.yml @@ -1,3 +1,6 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + version: 0.2 env: @@ -13,13 +16,7 @@ phases: java: openjdk11 pre_build: commands: - - git checkout $COMMIT_ID - - FOUND_VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - - | - if expr ${FOUND_VERSION} != ${VERSION}; then - echo "pom.xml version (${FOUND_VERSION}) does not match expected version (${VERSION}), stopping" - exit 1; - fi + - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - export SETTINGS_FILE=$(pwd)/codebuild/release/settings.xml - aws secretsmanager get-secret-value --region us-west-2 --secret-id Maven-GPG-Keys --query SecretBinary --output text | base64 -d > ~/mvn_gpg.tgz - tar -xvf ~/mvn_gpg.tgz -C ~ @@ -38,45 +35,4 @@ phases: -Dsonatype.password="$SONA_PASSWORD" \ --no-transfer-progress \ -s $SETTINGS_FILE - - -batch: - fast-fail: false - build-graph: - - identifier: release_to_prod - - identifier: validate_prod_release_openjdk8 - depend-on: - - release_to_prod - buildspec: codebuild/release/validate-prod.yml - env: - variables: - JAVA_ENV_VERSION: openjdk8 - JAVA_NUMERIC_VERSION: 8 - image: aws/codebuild/standard:3.0 - - identifier: validate_prod_release_openjdk11 - depend-on: - - release_to_prod - buildspec: codebuild/release/validate-prod.yml - env: - variables: - JAVA_ENV_VERSION: openjdk11 - JAVA_NUMERIC_VERSION: 11 - image: aws/codebuild/standard:3.0 - - identifier: validate_prod_release_corretto8 - depend-on: - - release_to_prod - buildspec: codebuild/release/validate-prod.yml - env: - variables: - JAVA_ENV_VERSION: corretto8 - JAVA_NUMERIC_VERSION: 8 - image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - - identifier: validate_prod_release_corretto11 - depend-on: - - release_to_prod - buildspec: codebuild/release/validate-prod.yml - env: - variables: - JAVA_ENV_VERSION: corretto11 - JAVA_NUMERIC_VERSION: 11 - image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + - ./look_4_version.sh $VERSION diff --git a/codebuild/release/release-staging.yml b/codebuild/release/release-staging.yml index 4ab16d9b5..f6a00238b 100644 --- a/codebuild/release/release-staging.yml +++ b/codebuild/release/release-staging.yml @@ -1,3 +1,6 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + version: 0.2 env: @@ -14,16 +17,9 @@ env: phases: install: runtime-versions: - java: openjdk11 + java: corretto11 pre_build: commands: - - git checkout $COMMIT_ID - - FOUND_VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - - | - if expr ${FOUND_VERSION} != ${VERSION}; then - echo "pom.xml version (${FOUND_VERSION}) does not match expected version (${VERSION}), stopping" - exit 1; - fi - export SETTINGS_FILE=$(pwd)/codebuild/release/settings.xml - export CODEARTIFACT_TOKEN=$(aws codeartifact get-authorization-token --domain $DOMAIN --domain-owner $ACCOUNT --query authorizationToken --output text --region ${REGION}) - export CODEARTIFACT_REPO_URL=https://${DOMAIN}-${ACCOUNT}.d.codeartifact.${REGION}.amazonaws.com/maven/${REPOSITORY} @@ -31,6 +27,11 @@ phases: - tar -xvf ~/mvn_gpg.tgz -C ~ build: commands: + - VERSION_HASH="$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)-$CODEBUILD_RESOLVED_SOURCE_VERSION" +# See https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html + - echo "Setting version in POM to $VERSION_HASH" + - mvn versions:set -DnewVersion="$VERSION_HASH" --no-transfer-progress + - echo "Version is now $(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p')" - | mvn deploy \ -PpublishingCodeArtifact \ @@ -44,44 +45,3 @@ phases: -DaltDeploymentRepository=codeartifact::default::$CODEARTIFACT_REPO_URL \ --no-transfer-progress \ -s $SETTINGS_FILE - -batch: - fast-fail: false - build-graph: - - identifier: release_to_staging - - identifier: validate_staging_release_openjdk8 - depend-on: - - release_to_staging - buildspec: codebuild/release/validate-staging.yml - env: - variables: - JAVA_ENV_VERSION: openjdk8 - JAVA_NUMERIC_VERSION: 8 - image: aws/codebuild/standard:3.0 - - identifier: validate_staging_release_openjdk11 - depend-on: - - release_to_staging - buildspec: codebuild/release/validate-staging.yml - env: - variables: - JAVA_ENV_VERSION: openjdk11 - JAVA_NUMERIC_VERSION: 11 - image: aws/codebuild/standard:3.0 - - identifier: validate_staging_release_corretto8 - depend-on: - - release_to_staging - buildspec: codebuild/release/validate-staging.yml - env: - variables: - JAVA_ENV_VERSION: corretto8 - JAVA_NUMERIC_VERSION: 8 - image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - - identifier: validate_staging_release_corretto11 - depend-on: - - release_to_staging - buildspec: codebuild/release/validate-staging.yml - env: - variables: - JAVA_ENV_VERSION: corretto11 - JAVA_NUMERIC_VERSION: 11 - image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 diff --git a/codebuild/release/release.yml b/codebuild/release/release.yml new file mode 100644 index 000000000..3c53df696 --- /dev/null +++ b/codebuild/release/release.yml @@ -0,0 +1,112 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +version: 0.2 + +batch: + fast-fail: true + build-graph: + +# Release to CodeArtifact + - identifier: release_staging + buildspec: codebuild/release/release-staging.yml + +# Validate CodeArtifact with supported JDK and Corretto + - identifier: validate_staging_release_openjdk_8 + depend-on: + - release_staging + buildspec: codebuild/release/validate-staging.yml + env: + variables: + JAVA_ENV_VERSION: openjdk8 + JAVA_NUMERIC_VERSION: 8 + image: aws/codebuild/standard:3.0 + + - identifier: validate_staging_release_openjdk11 + depend-on: + - release_staging + buildspec: codebuild/release/validate-staging.yml + env: + variables: + JAVA_ENV_VERSION: openjdk11 + JAVA_NUMERIC_VERSION: 11 + image: aws/codebuild/standard:3.0 + + - identifier: validate_staging_release_corretto8 + depend-on: + - release_staging + buildspec: codebuild/release/validate-staging.yml + env: + variables: + JAVA_ENV_VERSION: corretto8 + JAVA_NUMERIC_VERSION: 8 + image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + + - identifier: validate_staging_release_corretto11 + depend-on: + - release_staging + buildspec: codebuild/release/validate-staging.yml + env: + variables: + JAVA_ENV_VERSION: corretto11 + JAVA_NUMERIC_VERSION: 11 + image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + +# Version Project + - identifier: version + depend-on: + - release_staging + - validate_staging_release_openjdk_8 + - validate_staging_release_openjdk11 + - validate_staging_release_corretto8 + - validate_staging_release_corretto11 + buildspec: codebuild/release/version.yml + env: + image: aws/codebuild/standard:5.0 + +# Publish to Maven Central + - identifier: publish + depend-on: + - version + buildspec: codebuild/release/release-prod.yml + +# Validate Maven Central with supported JDK and Corretto + - identifier: validate_prod_release_openjdk_8 + depend-on: + - publish + buildspec: codebuild/release/validate-prod.yml + env: + variables: + JAVA_ENV_VERSION: openjdk8 + JAVA_NUMERIC_VERSION: 8 + image: aws/codebuild/standard:3.0 + + - identifier: validate_prod_release_openjdk11 + depend-on: + - publish + buildspec: codebuild/release/validate-prod.yml + env: + variables: + JAVA_ENV_VERSION: openjdk11 + JAVA_NUMERIC_VERSION: 11 + image: aws/codebuild/standard:3.0 + + - identifier: validate_prod_release_corretto8 + depend-on: + - publish + buildspec: codebuild/release/validate-prod.yml + env: + variables: + JAVA_ENV_VERSION: corretto8 + JAVA_NUMERIC_VERSION: 8 + image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + + - identifier: validate_prod_release_corretto11 + depend-on: + - publish + buildspec: codebuild/release/validate-prod.yml + env: + variables: + JAVA_ENV_VERSION: corretto11 + JAVA_NUMERIC_VERSION: 11 + image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 diff --git a/codebuild/release/settings.xml b/codebuild/release/settings.xml index 19587de0e..6d32af9bb 100644 --- a/codebuild/release/settings.xml +++ b/codebuild/release/settings.xml @@ -1,3 +1,7 @@ + Date: Thu, 21 Oct 2021 09:16:31 -0700 Subject: [PATCH 17/55] chore(docs): updating broken javadoc link (#366) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f21b827f..83f6e6be3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AWS Encryption SDK for Java -The AWS Encryption SDK enables secure client-side encryption. It uses cryptography best practices to protect your data and the encryption keys used to protect that data. Each data object is protected with a unique data encryption key (DEK), and the DEK is protected with a key encryption key (KEK) called a *master key*. The encrypted DEK is combined with the encrypted data into a single [encrypted message](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html), so you don't need to keep track of the DEKs for your data. The SDK supports master keys in [AWS Key Management Service](https://aws.amazon.com/kms/) (KMS), and it also provides APIs to define and use other master key providers. The SDK provides methods for encrypting and decrypting strings, byte arrays, and byte streams. For details, see the [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java/javadoc/). +The AWS Encryption SDK enables secure client-side encryption. It uses cryptography best practices to protect your data and the encryption keys used to protect that data. Each data object is protected with a unique data encryption key (DEK), and the DEK is protected with a key encryption key (KEK) called a *master key*. The encrypted DEK is combined with the encrypted data into a single [encrypted message](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html), so you don't need to keep track of the DEKs for your data. The SDK supports master keys in [AWS Key Management Service](https://aws.amazon.com/kms/) (KMS), and it also provides APIs to define and use other master key providers. The SDK provides methods for encrypting and decrypting strings, byte arrays, and byte streams. For details, see the [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java). For more details about the design and architecture of the SDK, see the [official documentation](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/). From d88190b810452c29c9e48892806bc7063a75800a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:52:15 -0700 Subject: [PATCH 18/55] chore: add javadoc update to batch build (#376) --- codebuild/release/javadoc.yml | 26 ++++++++++++++++++++++++++ codebuild/release/release.yml | 19 ++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 codebuild/release/javadoc.yml diff --git a/codebuild/release/javadoc.yml b/codebuild/release/javadoc.yml new file mode 100644 index 000000000..0a751365a --- /dev/null +++ b/codebuild/release/javadoc.yml @@ -0,0 +1,26 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +version: 0.2 + +env: + variables: + BRANCH: "master" + GH_PAGES: "gh-pages" + git-credential-helper: yes + +phases: + pre_build: + commands: + - git config --global user.name "aws-crypto-tools-ci-bot" + - git config --global user.email "no-reply@noemail.local" + - git checkout $BRANCH + build: + commands: + - mvn javadoc:javadoc + - cp -r ./target/site/apidocs /tmp + - git checkout $GH_PAGES + - cp -r /tmp/apidocs/* . + - git add . + - git commit -m "docs: updating javadocs" + - git push diff --git a/codebuild/release/release.yml b/codebuild/release/release.yml index 3c53df696..768a63cf8 100644 --- a/codebuild/release/release.yml +++ b/codebuild/release/release.yml @@ -12,7 +12,7 @@ batch: buildspec: codebuild/release/release-staging.yml # Validate CodeArtifact with supported JDK and Corretto - - identifier: validate_staging_release_openjdk_8 + - identifier: validate_staging_release_openjdk8 depend-on: - release_staging buildspec: codebuild/release/validate-staging.yml @@ -56,7 +56,7 @@ batch: - identifier: version depend-on: - release_staging - - validate_staging_release_openjdk_8 + - validate_staging_release_openjdk8 - validate_staging_release_openjdk11 - validate_staging_release_corretto8 - validate_staging_release_corretto11 @@ -71,7 +71,7 @@ batch: buildspec: codebuild/release/release-prod.yml # Validate Maven Central with supported JDK and Corretto - - identifier: validate_prod_release_openjdk_8 + - identifier: validate_prod_release_openjdk8 depend-on: - publish buildspec: codebuild/release/validate-prod.yml @@ -110,3 +110,16 @@ batch: JAVA_ENV_VERSION: corretto11 JAVA_NUMERIC_VERSION: 11 image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + + - identifier: update_javadoc + depend-on: + - validate_prod_release_openjdk8 + - validate_prod_release_openjdk11 + - validate_prod_release_corretto8 + - validate_prod_release_corretto11 + buildspec: codebuild/release/javadoc.yml + env: + variables: + JAVA_ENV_VERSION: coretto11 + JAVA_NUMERIC_VERSION: 11 + image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 From 69e7914d30e8c0ecea11aed7a924f77210677991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:06:57 -0700 Subject: [PATCH 19/55] chore: add build to support uploading artifacts (#379) --- codebuild/release/release.yml | 13 ++++++++- codebuild/release/upload_artifacts.yml | 40 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 codebuild/release/upload_artifacts.yml diff --git a/codebuild/release/release.yml b/codebuild/release/release.yml index 768a63cf8..4044673b6 100644 --- a/codebuild/release/release.yml +++ b/codebuild/release/release.yml @@ -111,12 +111,23 @@ batch: JAVA_NUMERIC_VERSION: 11 image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - - identifier: update_javadoc +# Upload Artifacts + - identifier: upload_artifacts depend-on: - validate_prod_release_openjdk8 - validate_prod_release_openjdk11 - validate_prod_release_corretto8 - validate_prod_release_corretto11 + buildspec: codebuild/release/upload_artifacts.yml + env: + # Changing to standard:5.0 because we are able to install gh cli on ubuntu but + # not on AmazonLinux + image: aws/codebuild/standard:5.0 + +# Generate and update new javadocs + - identifier: update_javadoc + depend-on: + - upload_artifacts buildspec: codebuild/release/javadoc.yml env: variables: diff --git a/codebuild/release/upload_artifacts.yml b/codebuild/release/upload_artifacts.yml new file mode 100644 index 000000000..8122e09e8 --- /dev/null +++ b/codebuild/release/upload_artifacts.yml @@ -0,0 +1,40 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +version: 0.2 + +env: + variables: + BRANCH: "master" + git-credential-helper: yes + secrets-manager: + GH_TOKEN: Github/aws-crypto-tools-ci-bot:personal\ access\ token + +phases: + pre_build: + commands: + # get new project version + - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') + # install gh cli in order to upload artifacts + - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg + - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null + - apt update + - apt install gh + - git checkout $BRANCH + build: + commands: + - gh version + - gh auth login --with-token < $GH_TOKEN + - | + mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ + -DrepoUrl=https://aws.oss.sonatype.org \ + -Dartifact=com.amazonaws:aws-encryption-sdk-java:${VERSION}:jar + - | + mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ + -DrepoUrl=https://aws.oss.sonatype.org \ + -Dartifact=com.amazonaws:aws-encryption-sdk-java:${VERSION}:jar:sources + - | + mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ + -DrepoUrl=https://aws.oss.sonatype.org \ + -Dartifact=com.amazonaws:aws-encryption-sdk-java:${VERSION}:jar:javadoc + - gh release upload v${VERSION} ~/.m2/repository/com/amazonaws/aws-encryption-sdk-java/${VERSION}/*.jar From c1f3e637421c7d5d71a092fd4812aa435639c3da Mon Sep 17 00:00:00 2001 From: Ben Farley <47006790+farleyb-amazon@users.noreply.github.com> Date: Tue, 26 Oct 2021 17:15:22 -0600 Subject: [PATCH 20/55] chore: Add back removed CiphertextHeaders.deserialize method (#382) --- .../model/CiphertextHeaders.java | 27 ++++++++++++++++++- .../model/CiphertextHeadersTest.java | 26 ++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/amazonaws/encryptionsdk/model/CiphertextHeaders.java b/src/main/java/com/amazonaws/encryptionsdk/model/CiphertextHeaders.java index 94a35cc21..7015e8cc4 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/model/CiphertextHeaders.java +++ b/src/main/java/com/amazonaws/encryptionsdk/model/CiphertextHeaders.java @@ -503,11 +503,27 @@ private int parseComplete(final byte[] b, final int off) throws ParseException { return 0; } + /** + * Deserialize the provided bytes starting at the specified offset to construct an instance of + * this class. Uses the default value for maxEncryptedDataKeys, which results in no limit. + * + *

This method parses the provided bytes for the individual fields in this class. This method + * also supports partial parsing where not all the bytes required for parsing the fields + * successfully are available. + * + * @param b the byte array to deserialize. + * @param off the offset in the byte array to use for deserialization. + * @return the number of bytes consumed in deserialization. + */ + public int deserialize(final byte[] b, final int off) throws ParseException { + return deserialize(b, off, NO_MAX_ENCRYPTED_DATA_KEYS); + } + /** * Deserialize the provided bytes starting at the specified offset to construct an instance of * this class. * - *

This method parses the provided bytes for the individual fields in this class. This methods + *

This method parses the provided bytes for the individual fields in this class. This method * also supports partial parsing where not all the bytes required for parsing the fields * successfully are available. * @@ -835,6 +851,15 @@ public void setSuiteData(byte[] suiteData) { suiteData_ = suiteData.clone(); } + /** + * Return max encrypted data keys. Package scope for unit testing. + * + * @return int + */ + int getMaxEncryptedDataKeys() { + return maxEncryptedDataKeys_; + } + private static class PartialParseException extends Exception { private static final long serialVersionUID = 1L; final int bytesParsed_; diff --git a/src/test/java/com/amazonaws/encryptionsdk/model/CiphertextHeadersTest.java b/src/test/java/com/amazonaws/encryptionsdk/model/CiphertextHeadersTest.java index 8dc1cac5d..58ef933c4 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/model/CiphertextHeadersTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/model/CiphertextHeadersTest.java @@ -51,6 +51,8 @@ public class CiphertextHeadersTest { @Test public void serializeDeserialize() { + int maxEncryptedDataKeys = 42; + Map encryptionContext = new HashMap(1); encryptionContext.put("ENC", "CiphertextHeader Test"); @@ -59,10 +61,30 @@ public void serializeDeserialize() { final byte[] headerBytes = ciphertextHeaders.toByteArray(); final CiphertextHeaders reconstructedHeaders = new CiphertextHeaders(); - reconstructedHeaders.deserialize( - headerBytes, 0, CiphertextHeaders.NO_MAX_ENCRYPTED_DATA_KEYS); + reconstructedHeaders.deserialize(headerBytes, 0, maxEncryptedDataKeys); + final byte[] reconstructedHeaderBytes = reconstructedHeaders.toByteArray(); + + assertEquals(reconstructedHeaders.getMaxEncryptedDataKeys(), maxEncryptedDataKeys); + assertArrayEquals(headerBytes, reconstructedHeaderBytes); + } + } + + @Test + public void serializeDeserializeDefaultMaxEncryptedDataKeys() { + Map encryptionContext = new HashMap(1); + encryptionContext.put("ENC", "CiphertextHeader Test"); + + for (CryptoAlgorithm alg : testAlgs) { + final CiphertextHeaders ciphertextHeaders = createCiphertextHeaders(encryptionContext, alg); + + final byte[] headerBytes = ciphertextHeaders.toByteArray(); + final CiphertextHeaders reconstructedHeaders = new CiphertextHeaders(); + reconstructedHeaders.deserialize(headerBytes, 0); final byte[] reconstructedHeaderBytes = reconstructedHeaders.toByteArray(); + assertEquals( + reconstructedHeaders.getMaxEncryptedDataKeys(), + CiphertextHeaders.NO_MAX_ENCRYPTED_DATA_KEYS); assertArrayEquals(headerBytes, reconstructedHeaderBytes); } } From c0ff093c633cabc21d537ff8e27d6a41d08a772c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Mon, 1 Nov 2021 16:42:48 -0700 Subject: [PATCH 21/55] chore: update release process (#396) --- .releaserc | 5 ++--- codebuild/release/artifact-hunt.yml | 20 ++++++++++++++++++++ codebuild/release/release-prod.yml | 4 +--- codebuild/release/release.yml | 14 ++++++++++---- codebuild/release/upload_artifacts.yml | 2 +- codebuild/release/version.yml | 2 +- 6 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 codebuild/release/artifact-hunt.yml diff --git a/.releaserc b/.releaserc index b03c40cdc..4be8a8a59 100644 --- a/.releaserc +++ b/.releaserc @@ -53,13 +53,12 @@ ["@semantic-release/exec", { "prepareCmd": "mvn versions:set -DnewVersion=${nextRelease.version} \ -DautoVersionSubmodules=true && find README.md -type f \ - -exec sed -i '' 's/.*<\\/version>/${nextRelease.version}<\\/version>/g' {} \\;" + -exec sed -i 's/.*<\\/version>/${nextRelease.version}<\\/version>/g' {} \\;" }], ["@semantic-release/git", { "assets": ["./CHANGELOG.md", "./pom.xml", "./README.md"], - "message": "AWS Encryption SDK ${nextRelease.version} Release \n\n${nextRelease.notes}" + "message": "AWS Encryption SDK ${nextRelease.version} Release -- $(date +%Y-%m-%d) \n\n${nextRelease.notes}" }], - #@semantic-release/github" ], "repositoryUrl": "https://github.com/aws/aws-encryption-sdk-java", } diff --git a/codebuild/release/artifact-hunt.yml b/codebuild/release/artifact-hunt.yml new file mode 100644 index 000000000..b56c4af22 --- /dev/null +++ b/codebuild/release/artifact-hunt.yml @@ -0,0 +1,20 @@ +## Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +version: 0.2 + +env: + variables: + BRANCH: "master" + +phases: + install: + runtime-versions: + java: corretto11 + pre_build: + commands: + - git checkout $BRANCH + - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') + build: + commands: + - ./look_4_version.sh $VERSION diff --git a/codebuild/release/release-prod.yml b/codebuild/release/release-prod.yml index 9699c27a8..6d5e9d835 100644 --- a/codebuild/release/release-prod.yml +++ b/codebuild/release/release-prod.yml @@ -13,10 +13,9 @@ env: phases: install: runtime-versions: - java: openjdk11 + java: corretto11 pre_build: commands: - - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - export SETTINGS_FILE=$(pwd)/codebuild/release/settings.xml - aws secretsmanager get-secret-value --region us-west-2 --secret-id Maven-GPG-Keys --query SecretBinary --output text | base64 -d > ~/mvn_gpg.tgz - tar -xvf ~/mvn_gpg.tgz -C ~ @@ -35,4 +34,3 @@ phases: -Dsonatype.password="$SONA_PASSWORD" \ --no-transfer-progress \ -s $SETTINGS_FILE - - ./look_4_version.sh $VERSION diff --git a/codebuild/release/release.yml b/codebuild/release/release.yml index 4044673b6..cb6845c77 100644 --- a/codebuild/release/release.yml +++ b/codebuild/release/release.yml @@ -70,10 +70,16 @@ batch: - version buildspec: codebuild/release/release-prod.yml +# Search for published Artifact + - identifier: artifact_hunt + depend-on: + - publish + buildspec: codebuild/release/artifact-hunt.yml + # Validate Maven Central with supported JDK and Corretto - identifier: validate_prod_release_openjdk8 depend-on: - - publish + - artifact_hunt buildspec: codebuild/release/validate-prod.yml env: variables: @@ -83,7 +89,7 @@ batch: - identifier: validate_prod_release_openjdk11 depend-on: - - publish + - artifact_hunt buildspec: codebuild/release/validate-prod.yml env: variables: @@ -93,7 +99,7 @@ batch: - identifier: validate_prod_release_corretto8 depend-on: - - publish + - artifact_hunt buildspec: codebuild/release/validate-prod.yml env: variables: @@ -103,7 +109,7 @@ batch: - identifier: validate_prod_release_corretto11 depend-on: - - publish + - artifact_hunt buildspec: codebuild/release/validate-prod.yml env: variables: diff --git a/codebuild/release/upload_artifacts.yml b/codebuild/release/upload_artifacts.yml index 8122e09e8..871a325ee 100644 --- a/codebuild/release/upload_artifacts.yml +++ b/codebuild/release/upload_artifacts.yml @@ -37,4 +37,4 @@ phases: mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ -DrepoUrl=https://aws.oss.sonatype.org \ -Dartifact=com.amazonaws:aws-encryption-sdk-java:${VERSION}:jar:javadoc - - gh release upload v${VERSION} ~/.m2/repository/com/amazonaws/aws-encryption-sdk-java/${VERSION}/*.jar + - gh release create v${VERSION} ~/.m2/repository/com/amazonaws/aws-encryption-sdk-java/${VERSION}/*.jar -d -F CHANGELOG.md -t "AWS Encryption SDK ${VERSION} Release -- $(date +%Y-%m-%d)" diff --git a/codebuild/release/version.yml b/codebuild/release/version.yml index 5414c11b4..ade257726 100644 --- a/codebuild/release/version.yml +++ b/codebuild/release/version.yml @@ -26,4 +26,4 @@ phases: - git checkout $BRANCH build: commands: - - npx semantic-release --no-ci + - npx semantic-release --branches $BRANCH --no-ci From 98b079cb61417f3ee36035d74772f8913ef09518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Nov 2021 10:15:33 -0700 Subject: [PATCH 22/55] chore(deps): bump aws-java-sdk from 1.12.75 to 1.12.102 (#400) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.75 to 1.12.102. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.75...1.12.102) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3e69a995..c0d9ef342 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.75 + 1.12.102 true From b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Nov 2021 12:38:26 -0800 Subject: [PATCH 23/55] chore(deps): bump aws-java-sdk from 1.12.102 to 1.12.105 (#404) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.102 to 1.12.105. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.102...1.12.105) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0d9ef342..4c01eeac2 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.102 + 1.12.105 true From dd633c037caa0c7ca373cd59f554d49b5cb80448 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Nov 2021 08:41:33 -0800 Subject: [PATCH 24/55] chore(deps): bump aws-java-sdk from 1.12.105 to 1.12.106 (#405) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.105 to 1.12.106. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.105...1.12.106) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4c01eeac2..55042f08e 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.105 + 1.12.106 true From b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4 Mon Sep 17 00:00:00 2001 From: Ben Farley <47006790+farleyb-amazon@users.noreply.github.com> Date: Tue, 9 Nov 2021 15:37:51 -0700 Subject: [PATCH 25/55] chore: Add CODEOWNERS file (#406) --- .github/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..806891736 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Each line is a file pattern followed by one or more owners. +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# Default code owner for everything is our aws-crypto-tools group +* @aws/aws-crypto-tools From c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Thu, 11 Nov 2021 09:25:11 -0800 Subject: [PATCH 26/55] chore: update token name and timeout (#411) --- codebuild/release/upload_artifacts.yml | 2 +- look_4_version.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codebuild/release/upload_artifacts.yml b/codebuild/release/upload_artifacts.yml index 871a325ee..3c205540a 100644 --- a/codebuild/release/upload_artifacts.yml +++ b/codebuild/release/upload_artifacts.yml @@ -8,7 +8,7 @@ env: BRANCH: "master" git-credential-helper: yes secrets-manager: - GH_TOKEN: Github/aws-crypto-tools-ci-bot:personal\ access\ token + GH_TOKEN: Github/aws-crypto-tools-ci-bot:personal\ access\ token\ (new\ token\ format) phases: pre_build: diff --git a/look_4_version.sh b/look_4_version.sh index 8ee1a5335..dfdbc489c 100755 --- a/look_4_version.sh +++ b/look_4_version.sh @@ -19,7 +19,7 @@ while [ $STATUS -ne 0 ]; do break fi - if [ $((COUNTER+=1)) -eq 10 ]; then + if [ $((COUNTER+=1)) -eq 15 ]; then echo "It has been an awfully long time, you should check Maven Central for issues" exit 1 fi From f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Fri, 12 Nov 2021 10:26:51 -0800 Subject: [PATCH 27/55] chore: update gh token (#412) --- codebuild/release/upload_artifacts.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/codebuild/release/upload_artifacts.yml b/codebuild/release/upload_artifacts.yml index 3c205540a..0712e2d65 100644 --- a/codebuild/release/upload_artifacts.yml +++ b/codebuild/release/upload_artifacts.yml @@ -8,13 +8,17 @@ env: BRANCH: "master" git-credential-helper: yes secrets-manager: - GH_TOKEN: Github/aws-crypto-tools-ci-bot:personal\ access\ token\ (new\ token\ format) + GH_TOKEN: Github/aws-crypto-tools-ci-bot:ESDK Release Token phases: pre_build: commands: # get new project version - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') + - git config --global user.name "aws-crypto-tools-ci-bot" + - git config --global user.email "no-reply@noemail.local" + - echo $GH_TOKEN > token.txt + - export GH_TOKEN= # install gh cli in order to upload artifacts - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null @@ -24,7 +28,8 @@ phases: build: commands: - gh version - - gh auth login --with-token < $GH_TOKEN + - gh auth login --with-token < token.txt + - gh auth status - | mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ -DrepoUrl=https://aws.oss.sonatype.org \ From da0fe89836c40e33f201b792052f02abe44af92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Tue, 30 Nov 2021 13:13:58 -0800 Subject: [PATCH 28/55] chore(docs): update README get started example (#423) Co-authored-by: June Blender --- README.md | 78 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 83f6e6be3..bed34b071 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # AWS Encryption SDK for Java -The AWS Encryption SDK enables secure client-side encryption. It uses cryptography best practices to protect your data and the encryption keys used to protect that data. Each data object is protected with a unique data encryption key (DEK), and the DEK is protected with a key encryption key (KEK) called a *master key*. The encrypted DEK is combined with the encrypted data into a single [encrypted message](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html), so you don't need to keep track of the DEKs for your data. The SDK supports master keys in [AWS Key Management Service](https://aws.amazon.com/kms/) (KMS), and it also provides APIs to define and use other master key providers. The SDK provides methods for encrypting and decrypting strings, byte arrays, and byte streams. For details, see the [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java). +The AWS Encryption SDK enables secure client-side encryption. It uses cryptography best practices to protect your data and protect the encryption keys that protect your data. Each data object is protected with a unique data encryption key, and the data encryption key is protected with a key encryption key called a *wrapping key* or *master key*. The encryption method returns a single, portable [encrypted message](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html) that contains the encrypted data and the encrypted data key, so you don't need to keep track of the data encryption keys for your data. You can use KMS keys in [AWS Key Management Service](https://aws.amazon.com/kms/) (AWS KMS) as wrapping keys. The AWS Encryption SDK also provides APIs to define and use encryption keys from other key providers. -For more details about the design and architecture of the SDK, see the [official documentation](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/). +The AWS Encryption SDK for Java provides methods for encrypting and decrypting strings, byte arrays, and byte streams. For details, see the [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java). + +For more details about the design and architecture of the AWS Encryption SDK, see the [AWS Encryption SDK Developer Guide](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/). [Security issue notifications](./CONTRIBUTING.md#security-issue-notifications) @@ -11,7 +13,7 @@ See [Support Policy](./SUPPORT_POLICY.rst) for for details on the current suppor ## Getting Started ### Required Prerequisites -To use this SDK you must have: +To use the AWS Encryption SDK for Java you must have: * **A Java 8 or newer development environment** @@ -29,29 +31,25 @@ To use this SDK you must have: If you do not have Bouncy Castle, go to https://bouncycastle.org/latest_releases.html, then download the provider file that corresponds to your JDK. Or, you can pick it up from Maven (groupId: `org.bouncycastle`, artifactId: `bcprov-ext-jdk15on`). - Beginning in version 1.6.1, - the AWS Encryption SDK also works with Bouncy Castle FIPS (groupId: `org.bouncycastle`, artifactId: `bc-fips`) - as an alternative to non-FIPS Bouncy Castle. - For help installing and configuring Bouncy Castle FIPS properly, see [BC FIPS documentation](https://www.bouncycastle.org/documentation.html), - in particular, **User Guides** and **Security Policy**. + Beginning in version 1.6.1, the AWS Encryption SDK for Java also works with Bouncy Castle FIPS (groupId: `org.bouncycastle`, artifactId: `bc-fips`) + as an alternative to non-FIPS Bouncy Castle. For help installing and configuring Bouncy Castle FIPS, see [BC FIPS documentation](https://www.bouncycastle.org/documentation.html), in particular, **User Guides** and **Security Policy**. ### Optional Prerequisites #### AWS Integration -You don't need an Amazon Web Services (AWS) account to use this SDK, but some of the [example code][examples] requires an AWS account, a customer master key (CMK) in AWS KMS, and the AWS SDK for Java. +You don't need an Amazon Web Services (AWS) account to use the AWS Encryption SDK, but some of the [example code][examples] require an AWS account, an AWS KMS key, and the AWS SDK for Java 1.x. (The AWS Encryption SDK for Java does not support the AWS SDK for Java 2.x.) * **To create an AWS account**, go to [Sign In or Create an AWS Account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) and then choose **I am a new user.** Follow the instructions to create an AWS account. -* **To create a CMK in AWS KMS**, go to [Creating Keys](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) in the KMS documentation and then follow the instructions on that page. +* **To create a symmetric encryption KMS key in AWS KMS**, see [Creating Keys](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html). -* **To download and install the AWS SDK for Java**, go to [Installing the AWS SDK for Java](https://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-install-sdk.html) in the AWS SDK for Java documentation and then follow the instructions on that page. +* **To download and install the AWS SDK for Java 1.x**, see [Installing the AWS SDK for Java 1.x](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html). #### Amazon Corretto Crypto Provider Many users find that the Amazon Corretto Crypto Provider (ACCP) significantly improves the performance of the AWS Encryption SDK. -For help installing and using ACCP, see the [ACCP GitHub Respository](https://github.com/corretto/amazon-corretto-crypto-provider) . - -### Download +For help installing and using ACCP, see the [amazon-corretto-crypto-provider repository](https://github.com/corretto/amazon-corretto-crypto-provider). +### Download the AWS Encryption SDK for Java You can get the latest release from Maven: ```xml @@ -63,18 +61,19 @@ You can get the latest release from Maven: ``` ### Get Started +To get started with the AWS Encryption SDK for Java -The following code sample demonstrates how to get started: - -1. Instantiate the SDK. +1. Instantiate the AWS Encryption SDK. 2. Define the master key provider. 3. Encrypt and decrypt data. ```java -// This sample code encrypts and then decrypts a string using a KMS CMK. +// This sample code encrypts and then decrypts a string using an AWS KMS key. // You provide the KMS key ARN and plaintext string as arguments. package com.amazonaws.crypto.examples; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -86,11 +85,11 @@ import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; public class StringExample { private static String keyArn; - private static String data; + private static String plaintext; public static void main(final String[] args) { keyArn = args[0]; - data = args[1]; + plaintext = args[1]; // Instantiate the SDK final AwsCrypto crypto = AwsCrypto.standard(); @@ -98,35 +97,38 @@ public class StringExample { // Set up the master key provider final KmsMasterKeyProvider prov = KmsMasterKeyProvider.builder().buildStrict(keyArn); - // Encrypt the data - // + // Set up the encryption context // NOTE: Encrypted data should have associated encryption context - // to protect integrity. For this example, just use a placeholder - // value. For more information about encryption context, see - // https://amzn.to/1nSbe9X (blogs.aws.amazon.com) - final Map context = Collections.singletonMap("Example", "String"); + // to protect its integrity. This example uses placeholder values. + // For more information about the encryption context, see + // https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + final Map context = Collections.singletonMap("ExampleContextKey", "ExampleContextValue"); - final String ciphertext = crypto.encryptString(prov, data, context).getResult(); - System.out.println("Ciphertext: " + ciphertext); + // Encrypt the data + // + final CryptoResult encryptResult = crypto.encryptData(prov, plaintext.getBytes(StandardCharsets.UTF_8), context); + final byte[] ciphertext = encryptResult.getResult(); + System.out.println("Ciphertext: " + Arrays.toString(ciphertext)); // Decrypt the data - final CryptoResult decryptResult = crypto.decryptString(prov, ciphertext); - // Check the encryption context (and ideally the master key) to - // ensure this is the expected ciphertext + final CryptoResult decryptResult = crypto.decryptData(prov, ciphertext); + // Your application should verify the encryption context and the KMS key to + // ensure this is the expected ciphertext before returning the plaintext if (!decryptResult.getMasterKeyIds().get(0).equals(keyArn)) { throw new IllegalStateException("Wrong key id!"); } - // The SDK may add information to the encryption context, so check to - // ensure all of the values are present - for (final Map.Entry e : context.entrySet()) { - if (!e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey()))) { + // The AWS Encryption SDK may add information to the encryption context, so check to + // ensure all of the values that you specified when encrypting are *included* in the returned encryption context. + if (!context.entrySet().stream + .allMatch( e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) { throw new IllegalStateException("Wrong Encryption Context!"); - } } - // The data is correct, so output it. - System.out.println("Decrypted: " + decryptResult.getResult()); + assert Arrays.equals(decryptResult.getResult(), data.getBytes(StandardCharsets.UTF_8)); + + // The data is correct, so return it. + System.out.println("Decrypted: " + new String(decryptResult.getResult(), StandardCharsets.UTF_8)); } } ``` From 91f6ffca2ce0499d08b6ce3259459fbb7cce890d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 13:41:15 -0800 Subject: [PATCH 29/55] chore(deps): bump aws-java-sdk from 1.12.106 to 1.12.127 (#436) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.106 to 1.12.127. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.106...1.12.127) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 55042f08e..d92bbbc78 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.106 + 1.12.127 true From e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:16:33 -0800 Subject: [PATCH 30/55] chore(deps): bump fmt-maven-plugin from 2.12 to 2.13 (#429) Bumps [fmt-maven-plugin](https://github.com/coveooss/fmt-maven-plugin) from 2.12 to 2.13. - [Release notes](https://github.com/coveooss/fmt-maven-plugin/releases) - [Commits](https://github.com/coveooss/fmt-maven-plugin/compare/2.12.0...2.13.0) --- updated-dependencies: - dependency-name: com.coveo:fmt-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d92bbbc78..2d01f6f10 100644 --- a/pom.xml +++ b/pom.xml @@ -204,7 +204,7 @@ com.coveo fmt-maven-plugin - 2.12 + 2.13 From 37078ec29805ae23ce7c21e440890d68a9b0956c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:57:19 -0800 Subject: [PATCH 31/55] chore(deps): bump aws-java-sdk from 1.12.127 to 1.12.128 (#437) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.127 to 1.12.128. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.127...1.12.128) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2d01f6f10..a3747076d 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.127 + 1.12.128 true From 629dbfdaa91b6023034f808f5e4865fd7048c963 Mon Sep 17 00:00:00 2001 From: lavaleri <49660121+lavaleri@users.noreply.github.com> Date: Fri, 10 Dec 2021 09:41:29 -0800 Subject: [PATCH 32/55] chore: Upgrade mockito to 4.0.0 (#438) --- pom.xml | 2 +- .../amazonaws/encryptionsdk/kms/KmsMasterKeyProviderTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a3747076d..d3c19a0b1 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.mockito mockito-core - 3.12.4 + 4.0.0 test diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProviderTest.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProviderTest.java index 66dd72922..c70a90b7b 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProviderTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProviderTest.java @@ -18,8 +18,8 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import com.amazonaws.AmazonServiceException; @@ -326,7 +326,7 @@ public void testDecrypt() throws Exception { () -> mkp.decryptDataKey(ALGORITHM_SUITE, inputEDKs, ENCRYPTION_CONTEXT)); ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); - verifyZeroInteractions(client); + verifyNoInteractions(client); return; } From 960f3e5459d196b1d623d61d9d780fa519b106ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:48:42 -0800 Subject: [PATCH 33/55] chore: update dependabot to update mainline-1.x (#440) --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b76b89570..ee78299eb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,11 @@ updates: directory: "/" schedule: interval: "daily" + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + target-branch: "mainline-1.x" - package-ecosystem: "github-actions" directory: "/" schedule: From 065ab94d7ca57d33fac8217cdcba4f046d7e910c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 12:15:19 -0800 Subject: [PATCH 34/55] chore(deps-dev): bump junit-vintage-engine from 5.8.1 to 5.8.2 (#426) Bumps [junit-vintage-engine](https://github.com/junit-team/junit5) from 5.8.1 to 5.8.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.8.1...r5.8.2) --- updated-dependencies: - dependency-name: org.junit.vintage:junit-vintage-engine dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d3c19a0b1..cc8170056 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ org.junit.vintage junit-vintage-engine - 5.8.1 + 5.8.2 test From 6872c637b199b3df16104ce3b3b644b90f308c1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 11:15:13 -0800 Subject: [PATCH 35/55] chore(deps): bump aws-java-sdk from 1.12.128 to 1.12.129 (#447) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.128 to 1.12.129. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.128...1.12.129) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cc8170056..1f63d4ff3 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.128 + 1.12.129 true From 8dfda1ac4d28d82e069a91891743a524965a16e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 11:43:53 -0800 Subject: [PATCH 36/55] chore(deps-dev): bump mockito-core from 4.0.0 to 4.1.0 (#441) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.0.0...v4.1.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1f63d4ff3..ac6034651 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.mockito mockito-core - 4.0.0 + 4.1.0 test From 969852a4bd934f1a50d05b256e6aae82ed8832fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 12:25:38 -0800 Subject: [PATCH 37/55] chore(deps): bump bcprov-ext-jdk15on from 1.69 to 1.70 (#439) Bumps [bcprov-ext-jdk15on](https://github.com/bcgit/bc-java) from 1.69 to 1.70. - [Release notes](https://github.com/bcgit/bc-java/releases) - [Changelog](https://github.com/bcgit/bc-java/blob/master/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcprov-ext-jdk15on dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac6034651..e96688dfb 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ org.bouncycastle bcprov-ext-jdk15on - 1.69 + 1.70 From 7de569aa3766e2339a2c7bbf0bb3c474f75f99cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 12:48:07 -0800 Subject: [PATCH 38/55] chore(deps-dev): bump junit-jupiter-api from 5.8.1 to 5.8.2 (#427) Bumps [junit-jupiter-api](https://github.com/junit-team/junit5) from 5.8.1 to 5.8.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.8.1...r5.8.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e96688dfb..1b4b8e55d 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ org.junit.jupiter junit-jupiter-api - 5.8.1 + 5.8.2 test From a1b18851328a310deff388b11f0fbf691a4cfd2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 09:45:30 -0800 Subject: [PATCH 39/55] chore(deps-dev): bump mockito-core from 4.1.0 to 4.2.0 (#458) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.1.0...v4.2.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1b4b8e55d..22d650bc9 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.mockito mockito-core - 4.1.0 + 4.2.0 test From a98a321c046ef1af0343ee3c4753c5e1c361bb62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Dec 2021 11:50:23 -0700 Subject: [PATCH 40/55] chore(deps): bump aws-java-sdk from 1.12.129 to 1.12.131 (#463) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.129 to 1.12.131. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.129...1.12.131) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 22d650bc9..9829a92da 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.129 + 1.12.131 true From 433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 16:23:41 -0800 Subject: [PATCH 41/55] chore(deps): bump aws-java-sdk from 1.12.131 to 1.12.150 (#508) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.131 to 1.12.150. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.131...1.12.150) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9829a92da..f69781e8c 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.131 + 1.12.150 true From a709e69c3beca2824bc5f6c6529b30417df4bbaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Feb 2022 16:17:05 -0800 Subject: [PATCH 42/55] chore(deps-dev): bump mockito-core from 4.2.0 to 4.3.1 (#500) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.2.0 to 4.3.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.2.0...v4.3.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f69781e8c..d56048383 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.mockito mockito-core - 4.2.0 + 4.3.1 test From 369a0498127377ae3b4cdfa3649c612f18a4582a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Feb 2022 17:31:23 -0800 Subject: [PATCH 43/55] chore(deps): bump maven-compiler-plugin from 3.8.1 to 3.9.0 (#481) Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.9.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d56048383..ec1e28497 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.9.0 1.8 1.8 From 70257a5e0d7244682ce8a72c72ea20101113dd48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Feb 2022 09:42:21 -0800 Subject: [PATCH 44/55] chore(deps): bump aws-java-sdk from 1.12.150 to 1.12.151 (#510) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.150 to 1.12.151. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.150...1.12.151) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ec1e28497..0509474a9 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.150 + 1.12.151 true From 4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Feb 2022 10:24:20 -0800 Subject: [PATCH 45/55] chore(deps): bump build-helper-maven-plugin from 3.2.0 to 3.3.0 (#473) Bumps [build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/build-helper-maven-plugin-3.2.0...build-helper-maven-plugin-3.3.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:build-helper-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0509474a9..dcd140379 100644 --- a/pom.xml +++ b/pom.xml @@ -136,7 +136,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.2.0 + 3.3.0 add-test-source From 22abc6c14714ecd164fbb08936d996fd34610b05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 11:00:30 -0700 Subject: [PATCH 46/55] chore(deps): bump aws-java-sdk from 1.12.151 to 1.12.162 (#541) Bumps [aws-java-sdk](https://github.com/aws/aws-sdk-java) from 1.12.151 to 1.12.162. - [Release notes](https://github.com/aws/aws-sdk-java/releases) - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.151...1.12.162) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dcd140379..741cfd7cf 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ com.amazonaws aws-java-sdk - 1.12.151 + 1.12.162 true From 0ab1db09d10c9477167dd0545747e1391090727b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 12:20:43 -0700 Subject: [PATCH 47/55] chore(deps): bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 (#535) Bumps nexus-staging-maven-plugin from 1.6.8 to 1.6.11. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 741cfd7cf..e2690d07f 100644 --- a/pom.xml +++ b/pom.xml @@ -298,7 +298,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.11 true sonatype-nexus-staging From 006cdc4b6395536c8c1b317d85c252f4892d6172 Mon Sep 17 00:00:00 2001 From: Sean Swezey Date: Mon, 7 Mar 2022 17:27:20 +0100 Subject: [PATCH 48/55] feat: AWS SDK v2 support --- pom.xml | 21 +- .../examples/BasicEncryptionExample.java | 4 +- .../BasicMultiRegionKeyEncryptionExample.java | 4 +- .../examples/DiscoveryDecryptionExample.java | 4 +- ...DiscoveryMultiRegionDecryptionExample.java | 11 +- .../examples/EscrowedEncryptExample.java | 2 +- .../examples/MultipleCmkEncryptExample.java | 4 +- .../examples/RestrictRegionExample.java | 18 +- .../examples/SetCommitmentPolicyExample.java | 4 +- .../SetEncryptionAlgorithmExample.java | 4 +- .../examples/SimpleDataKeyCachingExample.java | 5 +- .../encryptionsdk/internal/VersionInfo.java | 20 +- .../kms/AwsKmsMrkAwareMasterKey.java | 6 - .../kms/AwsKmsMrkAwareMasterKeyProvider.java | 42 - .../kmssdkv2/AwsKmsMrkAwareMasterKey.java | 430 ++++++++ .../AwsKmsMrkAwareMasterKeyProvider.java | 739 ++++++++++++++ .../encryptionsdk/kmssdkv2/KmsMasterKey.java | 218 ++++ .../kmssdkv2/KmsMasterKeyProvider.java | 448 +++++++++ .../kmssdkv2/RegionalClientSupplier.java | 16 + .../kmssdkv2/RequestClientCacher.java | 53 + .../encryptionsdk/kmssdkv2/package-info.java | 18 + ...overyMultiRegionDecryptionExampleTest.java | 3 +- .../examples/RestrictRegionExampleTest.java | 3 +- .../encryptionsdk/AllTestsSuite.java | 4 + .../encryptionsdk/IntegrationTestSuite.java | 3 + .../encryptionsdk/TestVectorRunner.java | 124 ++- .../AwsKmsMrkAwareMasterKeyProviderTest.java | 9 - .../kms/AwsKmsMrkAwareMasterKeyTest.java | 8 - .../AwsKmsMrkAwareMasterKeyProviderTest.java | 945 ++++++++++++++++++ .../kmssdkv2/AwsKmsMrkAwareMasterKeyTest.java | 924 +++++++++++++++++ .../KMSProviderBuilderIntegrationTests.java | 472 +++++++++ .../kmssdkv2/KMSProviderBuilderMockTests.java | 189 ++++ .../kmssdkv2/KmsMasterKeyProviderTest.java | 521 ++++++++++ .../kmssdkv2/KmsMasterKeyTest.java | 408 ++++++++ .../MaxEncryptedDataKeysIntegrationTest.java | 88 ++ .../encryptionsdk/kmssdkv2/MockKmsClient.java | 254 +++++ .../kmssdkv2/ProxyCredentialsProvider.java | 17 + .../kmssdkv2/ProxyKmsClient.java | 68 ++ .../kmssdkv2/XCompatKmsDecryptTest.java | 96 ++ 39 files changed, 6102 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKey.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKey.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RegionalClientSupplier.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RequestClientCacher.java create mode 100644 src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/package-info.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProviderTest.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyTest.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderIntegrationTests.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderMockTests.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProviderTest.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyTest.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MaxEncryptedDataKeysIntegrationTest.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MockKmsClient.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyCredentialsProvider.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyKmsClient.java create mode 100644 src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/XCompatKmsDecryptTest.java diff --git a/pom.xml b/pom.xml index e2690d07f..df905b0e5 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,19 @@ UTF-8 + + + + software.amazon.awssdk + bom + 2.17.136 + true + pom + import + + + + com.amazonaws @@ -46,6 +59,13 @@ true + + software.amazon.awssdk + kms + 2.17.136 + true + + org.bouncycastle bcprov-ext-jdk15on @@ -79,7 +99,6 @@ test - com.google.code.findbugs jsr305 diff --git a/src/examples/java/com/amazonaws/crypto/examples/BasicEncryptionExample.java b/src/examples/java/com/amazonaws/crypto/examples/BasicEncryptionExample.java index 1279fa88a..bed6c6814 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/BasicEncryptionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/BasicEncryptionExample.java @@ -10,8 +10,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.CommitmentPolicy; /** diff --git a/src/examples/java/com/amazonaws/crypto/examples/BasicMultiRegionKeyEncryptionExample.java b/src/examples/java/com/amazonaws/crypto/examples/BasicMultiRegionKeyEncryptionExample.java index 36381cead..dd6e7a35c 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/BasicMultiRegionKeyEncryptionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/BasicMultiRegionKeyEncryptionExample.java @@ -6,8 +6,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.AwsKmsMrkAwareMasterKey; -import com.amazonaws.encryptionsdk.kms.AwsKmsMrkAwareMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProvider; import java.nio.charset.StandardCharsets; import java.util.Arrays; diff --git a/src/examples/java/com/amazonaws/crypto/examples/DiscoveryDecryptionExample.java b/src/examples/java/com/amazonaws/crypto/examples/DiscoveryDecryptionExample.java index 33b331abf..167bc90f6 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/DiscoveryDecryptionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/DiscoveryDecryptionExample.java @@ -10,8 +10,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; diff --git a/src/examples/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExample.java b/src/examples/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExample.java index 98ffea359..529b11924 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExample.java @@ -7,13 +7,14 @@ import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.CryptoResult; import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; -import com.amazonaws.encryptionsdk.kms.AwsKmsMrkAwareMasterKey; -import com.amazonaws.encryptionsdk.kms.AwsKmsMrkAwareMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProvider; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.Map; +import software.amazon.awssdk.regions.Region; /** *

@@ -39,7 +40,7 @@ public static void main(final String[] args) { final String keyName = args[0]; final String partition = args[1]; final String accountId = args[2]; - final String discoveryMrkRegion = args[3]; + final Region discoveryMrkRegion = Region.of(args[3]); encryptAndDecrypt(keyName, partition, accountId, discoveryMrkRegion); } @@ -48,7 +49,7 @@ static void encryptAndDecrypt( final String keyName, final String partition, final String accountId, - final String discoveryMrkRegion + final Region discoveryMrkRegion ) { // 1. Instantiate the SDK // This builds the AwsCrypto client with @@ -113,7 +114,7 @@ static void encryptAndDecrypt( // it is limited to the Region configured for the AWS SDK. final AwsKmsMrkAwareMasterKeyProvider decryptingKeyProvider = AwsKmsMrkAwareMasterKeyProvider .builder() - .withDiscoveryMrkRegion(discoveryMrkRegion) + .discoveryMrkRegion(discoveryMrkRegion) .buildDiscovery(discoveryFilter); // 7. Decrypt the data diff --git a/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java b/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java index 727cfea18..e04c35d0d 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java @@ -17,7 +17,7 @@ import com.amazonaws.encryptionsdk.CryptoOutputStream; import com.amazonaws.encryptionsdk.MasterKeyProvider; import com.amazonaws.encryptionsdk.jce.JceMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.util.IOUtils; diff --git a/src/examples/java/com/amazonaws/crypto/examples/MultipleCmkEncryptExample.java b/src/examples/java/com/amazonaws/crypto/examples/MultipleCmkEncryptExample.java index cfef2ec41..cae7f81cc 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/MultipleCmkEncryptExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/MultipleCmkEncryptExample.java @@ -10,8 +10,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.CommitmentPolicy; /** diff --git a/src/examples/java/com/amazonaws/crypto/examples/RestrictRegionExample.java b/src/examples/java/com/amazonaws/crypto/examples/RestrictRegionExample.java index d55537e44..91d1f3797 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/RestrictRegionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/RestrictRegionExample.java @@ -11,12 +11,12 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; import com.amazonaws.encryptionsdk.exception.AwsCryptoException; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; -import com.amazonaws.services.kms.AWSKMSClientBuilder; -import com.amazonaws.services.kms.AWSKMS; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; /** *

@@ -43,12 +43,12 @@ public static void main(final String[] args) { final String keyName = args[0]; final String partition = args[1]; final String accountId = args[2]; - final String region = args[3]; + final Region region = Region.of(args[3]); encryptAndDecrypt(keyName, partition, accountId, region); } - static void encryptAndDecrypt(final String keyName, final String partition, final String accountId, final String region) { + static void encryptAndDecrypt(final String keyName, final String partition, final String accountId, final Region region) { // Instantiate the SDK. // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, // which enforces that this client only encrypts using committing algorithm suites and enforces @@ -60,7 +60,7 @@ static void encryptAndDecrypt(final String keyName, final String partition, fina .build(); // 2. Instantiate the AWS KMS client for the desired region - final AWSKMS kmsClient = AWSKMSClientBuilder.standard().withRegion(region).build(); + final KmsClient kmsClient = KmsClient.builder().region(region).build(); // 3. Instantiate an AWS KMS master key provider for encryption. // @@ -101,14 +101,14 @@ static void encryptAndDecrypt(final String keyName, final String partition, fina // This example also configures the AWS KMS master key provider with a Discovery Filter to limit // the attempted AWS KMS CMKs to a particular partition and account. final KmsMasterKeyProvider decryptingKeyProvider = KmsMasterKeyProvider.builder() - .withCustomClientFactory(cmkRegion -> { + .customRegionalClientSupplier(cmkRegion -> { if(cmkRegion.equals(region)) { // return the previously built AWS KMS client so that we do // not create a new client on every decrypt call. return kmsClient; } - throw new AwsCryptoException("Only " + region + " is supported"); + throw new AwsCryptoException("Only " + region.id() + " is supported"); }) .buildDiscovery(discoveryFilter); diff --git a/src/examples/java/com/amazonaws/crypto/examples/SetCommitmentPolicyExample.java b/src/examples/java/com/amazonaws/crypto/examples/SetCommitmentPolicyExample.java index dc95f6de4..e0dec906e 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/SetCommitmentPolicyExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/SetCommitmentPolicyExample.java @@ -11,8 +11,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; /** *

diff --git a/src/examples/java/com/amazonaws/crypto/examples/SetEncryptionAlgorithmExample.java b/src/examples/java/com/amazonaws/crypto/examples/SetEncryptionAlgorithmExample.java index 0d9a972c4..b49d6bb97 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/SetEncryptionAlgorithmExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/SetEncryptionAlgorithmExample.java @@ -11,8 +11,8 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoAlgorithm; import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; /** *

diff --git a/src/examples/java/com/amazonaws/crypto/examples/SimpleDataKeyCachingExample.java b/src/examples/java/com/amazonaws/crypto/examples/SimpleDataKeyCachingExample.java index 55e525d82..633850a77 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/SimpleDataKeyCachingExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/SimpleDataKeyCachingExample.java @@ -14,9 +14,8 @@ import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager; import com.amazonaws.encryptionsdk.caching.CryptoMaterialsCache; import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; -import com.amazonaws.encryptionsdk.CommitmentPolicy; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey; +import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; /** *

diff --git a/src/main/java/com/amazonaws/encryptionsdk/internal/VersionInfo.java b/src/main/java/com/amazonaws/encryptionsdk/internal/VersionInfo.java index edaa93300..85b66602e 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/internal/VersionInfo.java +++ b/src/main/java/com/amazonaws/encryptionsdk/internal/VersionInfo.java @@ -24,13 +24,29 @@ public class VersionInfo { * Loads the version of the library */ public static String loadUserAgent() { + return USER_AGENT_PREFIX + versionNumber(); + } + + /** + * This returns the API name compatible with the AWS SDK v2 + * + * @return the name of the library with a tag indicating intended for AWS SDK v2 + */ + public static String apiName() { + return USER_AGENT_PREFIX.substring(0, USER_AGENT_PREFIX.length() - 1); + } + + /* + * String representation of the library version e.g. 2.3.3 + */ + public static String versionNumber() { try { final Properties properties = new Properties(); final ClassLoader loader = VersionInfo.class.getClassLoader(); properties.load(loader.getResourceAsStream("project.properties")); - return USER_AGENT_PREFIX + properties.getProperty("version"); + return properties.getProperty("version"); } catch (final IOException ex) { - return USER_AGENT_PREFIX + UNKNOWN_VERSION; + return UNKNOWN_VERSION; } } } diff --git a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKey.java b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKey.java index 0658816ad..1ace6395b 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKey.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKey.java @@ -90,7 +90,6 @@ private AwsKmsMrkAwareMasterKey( "AwsKmsMrkAwareMasterKey must be configured with an AWS KMS client."); } - /* Precondition: A provider is required. */ if (provider == null) { throw new IllegalArgumentException( "AwsKmsMrkAwareMasterKey must be configured with a source provider."); @@ -177,7 +176,6 @@ public DataKey generateDataKey( // # The response's "KeyId" // # MUST be valid. final String gdkResultKeyId = gdkResult.getKeyId(); - /* Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey. */ if (parseInfoFromKeyArn(gdkResultKeyId) == null) { throw new IllegalStateException("Received an empty or invalid keyId from KMS"); } @@ -212,7 +210,6 @@ public DataKey encryptDataKey( final Map encryptionContext, final DataKey dataKey) { final SecretKey key = dataKey.getKey(); - /* Precondition: The key format MUST be RAW. */ if (!key.getFormat().equals("RAW")) { throw new IllegalArgumentException("Only RAW encoded keys are supported"); } @@ -237,7 +234,6 @@ public DataKey encryptDataKey( final String encryptResultKeyId = encryptResult.getKeyId(); // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 // # The AWS KMS Encrypt response MUST contain a valid "KeyId". - /* Postcondition: Must have an AWS KMS ARN from AWS KMS encrypt. */ if (parseInfoFromKeyArn(encryptResultKeyId) == null) { throw new IllegalStateException("Received an empty or invalid keyId from KMS"); } @@ -326,7 +322,6 @@ public DataKey decryptDataKey( // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 // # The output MUST be the same as the Master Key Decrypt Data Key // # (../master-key-interface.md#decrypt-data-key) interface. - /* Exceptional Postcondition: Master key was unable to decrypt. */ .orElseThrow(() -> buildCannotDecryptDksException(exceptions)); } @@ -358,7 +353,6 @@ static DataKey decryptSingleEncryptedDataKey( .withKeyId(awsKmsIdentifier))); final String decryptResultKeyId = decryptResult.getKeyId(); - /* Exceptional Postcondition: Must have a CMK ARN from AWS KMS to match. */ if (decryptResultKeyId == null) { throw new IllegalStateException("Received an empty keyId from KMS"); } diff --git a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java index 5cec7b51e..e502e5b16 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java @@ -284,7 +284,6 @@ static KmsMasterKeyProvider.RegionalClientSupplier clientFactory( : AWSKMSClientBuilder.standard(); return region -> { - /* Check for early return (Postcondition): If a client already exists, use that. */ if (clientCache.containsKey(region)) { return clientCache.get(region); } @@ -381,10 +380,6 @@ private AwsKmsMrkAwareMasterKeyProvider( // # kms-mrk-are-unique.md#Implementation) and the function MUST return // # success. assertMrksAreUnique(keyIds); - /* Precondition: A region is required to contact AWS KMS. - * This is an edge case because the default region will be the same as the SDK default, - * but it is still possible. - */ if (!isDiscovery && defaultRegion == null && keyIds.stream() @@ -447,16 +442,6 @@ static void assertMrksAreUnique(List keyIdentifiers) { // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST // # exit successfully. // - /* Postcondition: Filter out duplicate resources that are not multi-region keys. - * I expect only have duplicates of specific multi-region keys. - * In JSON something like - * { - * "mrk-edb7fe6942894d32ac46dbb1c922d574" : [ - * "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", - * "arn:aws:kms:us-east-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574" - * ] - * } - */ .filter(maybeMrk -> isMRK(maybeMrk.getKey())) /* Flatten the duplicate identifiers into a single list. */ .flatMap(mrkEntry -> mrkEntry.getValue().stream()) @@ -481,35 +466,12 @@ static void assertMrksAreUnique(List keyIdentifiers) { */ static String getResourceForResourceTypeKey(String identifier) { final AwsKmsCmkArnInfo info = parseInfoFromKeyArn(identifier); - /* Check for early return (Postcondition): Non-ARNs may be raw resources. - * Raw aliases ('alias/my-key') - * or key ids ('mrk-edb7fe6942894d32ac46dbb1c922d574'). - */ if (info == null) return identifier; - /* Check for early return (Postcondition): Return the identifier for non-key resource types. - * I only care about duplicate multi-region *keys*. - * Any other resource type - * should get filtered out. - * I return the entire identifier - * on the off chance that - * a customer has created - * an alias with a name `mrk-*`. - * This way such an alias - * can never accidentally - * collided with an existing multi-region key - * or a duplicate alias. - */ if (!info.getResourceType().equals("key")) { return identifier; } - /* Postcondition: Return the key id. - * This will be used - * to find different regional replicas of - * the same multi-region key - * because the key id for replicas is always the same. - */ return info.getResource(); } @@ -559,10 +521,6 @@ public AwsKmsMrkAwareMasterKey getMasterKey(final String providerId, final Strin // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 // # In discovery mode, the requested // # AWS KMS key identifier MUST be a well formed AWS KMS ARN. - /* Precondition: Discovery mode requires requestedKeyArn be an ARN. - * This function is called on the encrypt path. - * It _may_ be the case that a raw key id, for example, was configured. - */ if (isDiscovery_ && requestedKeyArnInfo == null) { throw new NoSuchMasterKeyException( "Cannot use AWS KMS identifiers " + "when in discovery mode."); diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKey.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKey.java new file mode 100644 index 000000000..afe1b87ed --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKey.java @@ -0,0 +1,430 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo.*; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import com.amazonaws.encryptionsdk.kms.KmsMethods; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Supplier; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.ApiName; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.*; + +// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.5 +// # MUST implement the Master Key Interface (../master-key- +// # interface.md#interface) +// +// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.7 +// # MUST be unchanged from the Master Key interface. +// +// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.8 +// # MUST be unchanged from the Master Key interface. +/** + * Represents a single Aws KMS key and is used to encrypt/decrypt data with {@link AwsCrypto}. This + * key may be a multi region key, in which case this component is able to recognize different + * regional replicas of this multi region key as the same. + */ +public final class AwsKmsMrkAwareMasterKey extends MasterKey + implements KmsMethods { + + static final ApiName API_NAME = + ApiName.builder().name(VersionInfo.apiName()).version(VersionInfo.versionNumber()).build(); + private static final Consumer API_NAME_INTERCEPTOR = + builder -> builder.addApiName(API_NAME); + + private final KmsClient kmsClient_; + private final List grantTokens_ = new ArrayList<>(); + private final String awsKmsIdentifier_; + private final MasterKeyProvider sourceProvider_; + + /** + * A light builder method. + * + * @see KmsMasterKey#getInstance(Supplier, String, MasterKeyProvider) + * @param kms An AWS KMS Client + * @param awsKmsIdentifier An identifier for an AWS KMS key. May be a raw resource. + */ + static AwsKmsMrkAwareMasterKey getInstance( + final KmsClient kms, + final String awsKmsIdentifier, + final MasterKeyProvider provider) { + return new AwsKmsMrkAwareMasterKey(awsKmsIdentifier, kms, provider); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // # On initialization, the caller MUST provide: + private AwsKmsMrkAwareMasterKey( + final String awsKmsIdentifier, + final KmsClient kmsClient, + final MasterKeyProvider provider) { + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // # The AWS KMS key identifier MUST NOT be null or empty. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // # The AWS KMS + // # key identifier MUST be a valid identifier (aws-kms-key-arn.md#a- + // # valid-aws-kms-identifier). + validAwsKmsIdentifier(awsKmsIdentifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // # The AWS KMS SDK client MUST not be null. + if (kmsClient == null) { + throw new IllegalArgumentException( + "AwsKmsMrkAwareMasterKey must be configured with an AWS KMS client."); + } + + /* Precondition: A provider is required. */ + if (provider == null) { + throw new IllegalArgumentException( + "AwsKmsMrkAwareMasterKey must be configured with a source provider."); + } + + kmsClient_ = kmsClient; + awsKmsIdentifier_ = awsKmsIdentifier; + sourceProvider_ = provider; + } + + @Override + public String getProviderId() { + return sourceProvider_.getDefaultProviderId(); + } + + @Override + public String getKeyId() { + return awsKmsIdentifier_; + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // # The master key MUST be able to be configured with an optional list of + // # Grant Tokens. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=exception + // # This configuration SHOULD be on initialization and + // # SHOULD be immutable. + // The existing KMS Master Key + // sets grants in this way, so we continue this interface. + /** Clears and sets all grant tokens on this instance. This is not thread safe. */ + @Override + public void setGrantTokens(final List grantTokens) { + grantTokens_.clear(); + grantTokens_.addAll(grantTokens); + } + + @Override + public List getGrantTokens() { + return grantTokens_; + } + + @Override + public void addGrantToken(final String grantToken) { + grantTokens_.add(grantToken); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # The inputs MUST be the same as the Master Key Generate Data Key + // # (../master-key-interface.md#generate-data-key) interface. + /** + * This is identical behavior to + * + * @see KmsMasterKey#generateDataKey(CryptoAlgorithm, Map) + */ + @Override + public DataKey generateDataKey( + final CryptoAlgorithm algorithm, final Map encryptionContext) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # This + // # master key MUST use the configured AWS KMS client to make an AWS KMS + // # GenerateDatakey (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_GenerateDataKey.html) request constructed as follows: + final GenerateDataKeyResponse gdkResponse = + kmsClient_.generateDataKey( + GenerateDataKeyRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .keyId(awsKmsIdentifier_) + .numberOfBytes(algorithm.getDataKeyLength()) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens_) + .build()); + + final ByteBuffer plaintextBuffer = gdkResponse.plaintext().asByteBuffer(); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # If the call succeeds the AWS KMS Generate Data Key response's + // # "Plaintext" MUST match the key derivation input length specified by + // # the algorithm suite included in the input. + if (plaintextBuffer.limit() != algorithm.getDataKeyLength()) { + throw new IllegalStateException("Received an unexpected number of bytes from KMS"); + } + + final byte[] rawKey = new byte[algorithm.getDataKeyLength()]; + plaintextBuffer.get(rawKey); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # The response's "KeyId" + // # MUST be valid. + final String gdkResponseKeyId = gdkResponse.keyId(); + /* Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey. */ + if (parseInfoFromKeyArn(gdkResponseKeyId) == null) { + throw new IllegalStateException("Received an empty or invalid keyId from KMS"); + } + + final ByteBuffer ciphertextBlobBuffer = gdkResponse.ciphertextBlob().asByteBuffer(); + final byte[] encryptedKey = new byte[ciphertextBlobBuffer.remaining()]; + ciphertextBlobBuffer.get(encryptedKey); + + final SecretKeySpec key = new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # The output MUST be the same as the Master Key Generate Data Key + // # (../master-key-interface.md#generate-data-key) interface. + return new DataKey<>( + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # The response's "Plaintext" MUST be the plaintext in + // # the output. + key, + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // # The response's cipher text blob MUST be used as the + // # returned as the ciphertext for the encrypted data key in the output. + encryptedKey, + gdkResponseKeyId.getBytes(StandardCharsets.UTF_8), + this); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // # The inputs MUST be the same as the Master Key Encrypt Data Key + // # (../master-key-interface.md#encrypt-data-key) interface. + /** @see KmsMasterKey#encryptDataKey(CryptoAlgorithm, Map, DataKey) */ + @Override + public DataKey encryptDataKey( + final CryptoAlgorithm algorithm, + final Map encryptionContext, + final DataKey dataKey) { + final SecretKey key = dataKey.getKey(); + /* Precondition: The key format MUST be RAW. */ + if (!key.getFormat().equals("RAW")) { + throw new IllegalArgumentException("Only RAW encoded keys are supported"); + } + + try { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // # The master + // # key MUST use the configured AWS KMS client to make an AWS KMS Encrypt + // # (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_Encrypt.html) request constructed as follows: + final EncryptResponse encryptResponse = + kmsClient_.encrypt( + EncryptRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .keyId(awsKmsIdentifier_) + .plaintext(SdkBytes.fromByteArray(key.getEncoded())) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens_) + .build()); + + final ByteBuffer ciphertextBlobBuffer = encryptResponse.ciphertextBlob().asByteBuffer(); + final byte[] edk = new byte[ciphertextBlobBuffer.remaining()]; + ciphertextBlobBuffer.get(edk); + + final String encryptResultKeyId = encryptResponse.keyId(); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // # The AWS KMS Encrypt response MUST contain a valid "KeyId". + /* Postcondition: Must have an AWS KMS ARN from AWS KMS encrypt. */ + if (parseInfoFromKeyArn(encryptResultKeyId) == null) { + throw new IllegalStateException("Received an empty or invalid keyId from KMS"); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // # The output MUST be the same as the Master Key Encrypt Data Key + // # (../master-key-interface.md#encrypt-data-key) interface. + return new DataKey<>( + dataKey.getKey(), + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // # The + // # response's cipher text blob MUST be used as the "ciphertext" for the + // # encrypted data key. + edk, + encryptResultKeyId.getBytes(StandardCharsets.UTF_8), + this); + } catch (final AwsServiceException asex) { + throw new AwsCryptoException(asex); + } + } + + /** + * Will attempt to decrypt if awsKmsArnMatchForDecrypt returns true in {@link + * AwsKmsMrkAwareMasterKey#filterEncryptedDataKeys(String, String, EncryptedDataKey)}. An + * extension of {@link KmsMasterKey#decryptDataKey(CryptoAlgorithm, Collection, Map)} but with an + * awareness of the properties of multi-Region keys. + */ + @Override + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # The inputs MUST be the same as the Master Key Decrypt Data Key + // # (../master-key-interface.md#decrypt-data-key) interface. + public DataKey decryptDataKey( + final CryptoAlgorithm algorithm, + final Collection encryptedDataKeys, + final Map encryptionContext) + throws AwsCryptoException { + final List exceptions = new ArrayList<>(); + final String providerId = this.getProviderId(); + + return encryptedDataKeys.stream() + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # The set of encrypted data keys MUST first be filtered to match this + // # master key's configuration. + .filter(edk -> filterEncryptedDataKeys(providerId, awsKmsIdentifier_, edk)) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # For each encrypted data key in the filtered set, one at a time, the + // # master key MUST attempt to decrypt the data key. + .map( + edk -> { + try { + return decryptSingleEncryptedDataKey( + this, + kmsClient_, + awsKmsIdentifier_, + grantTokens_, + algorithm, + edk, + encryptionContext); + } catch (final AwsServiceException amazonServiceException) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # If this attempt + // # results in an error, then these errors MUST be collected. + exceptions.add(amazonServiceException); + } + return null; + }) + /* Need to filter null + * because an Optional + * of a null is crazy. + * Therefore `findFirst` will throw + * if it sees `null`. + */ + .filter(Objects::nonNull) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # If the AWS KMS response satisfies the requirements then it MUST be + // # use and this function MUST return and not attempt to decrypt any more + // # encrypted data keys. + /* Order is important. + * Process the encrypted data keys in the order they exist in the encrypted message. + */ + .findFirst() + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # If all the input encrypted data keys have been processed then this + // # function MUST yield an error that includes all the collected errors. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # The output MUST be the same as the Master Key Decrypt Data Key + // # (../master-key-interface.md#decrypt-data-key) interface. + /* Exceptional Postcondition: Master key was unable to decrypt. */ + .orElseThrow(() -> buildCannotDecryptDksException(exceptions)); + } + + /** + * Pure function for decrypting and encrypted data key. This is refactored out of `decryptDataKey` + * to facilitate testing to ensure correctness. + */ + static DataKey decryptSingleEncryptedDataKey( + final AwsKmsMrkAwareMasterKey masterKey, + final KmsClient client, + final String awsKmsIdentifier, + final List grantTokens, + final CryptoAlgorithm algorithm, + final EncryptedDataKey edk, + final Map encryptionContext) { + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # To decrypt the encrypted data key this master key MUST use the + // # configured AWS KMS client to make an AWS KMS Decrypt + // # (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_Decrypt.html) request constructed as follows: + final DecryptResponse decryptResponse = + client.decrypt( + DecryptRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .ciphertextBlob(SdkBytes.fromByteArray(edk.getEncryptedDataKey())) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens) + .keyId(awsKmsIdentifier) + .build()); + + final String decryptResponseKeyId = decryptResponse.keyId(); + /* Exceptional Postcondition: Must have a CMK ARN from AWS KMS to match. */ + if (decryptResponseKeyId == null) { + throw new IllegalStateException("Received an empty keyId from KMS"); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # If the call succeeds then the response's "KeyId" MUST be equal to the + // # configured AWS KMS key identifier otherwise the function MUST collect + // # an error. + if (!awsKmsIdentifier.equals(decryptResponseKeyId)) { + throw new IllegalStateException( + "Received an invalid response from KMS Decrypt call: Unexpected keyId."); + } + + final ByteBuffer plaintextBuffer = decryptResponse.plaintext().asByteBuffer(); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # The response's "Plaintext"'s length MUST equal the length + // # required by the requested algorithm suite otherwise the function MUST + // # collect an error. + if (plaintextBuffer.limit() != algorithm.getDataKeyLength()) { + throw new IllegalStateException("Received an unexpected number of bytes from KMS"); + } + + final byte[] rawKey = new byte[algorithm.getDataKeyLength()]; + plaintextBuffer.get(rawKey); + + return new DataKey<>( + new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()), + edk.getEncryptedDataKey(), + edk.getProviderInformation(), + masterKey); + } + + /** + * A pure function to filter encrypted data keys. This function is refactored out from + * `decryptDataKey` to facilitate testing and ensure correctness. + * + *

An AWS KMS Master key should only attempt to process an Encrypted Data Key if the + * information in the Encrypted Data Key matches the master keys configuration. + */ + static boolean filterEncryptedDataKeys( + final String providerId, final String awsKmsIdentifier_, final EncryptedDataKey edk) { + final String edkKeyId = new String(edk.getProviderInformation(), StandardCharsets.UTF_8); + + final AwsKmsCmkArnInfo providerArnInfo = parseInfoFromKeyArn(edkKeyId); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # Additionally each provider info MUST be a valid AWS KMS ARN + // # (aws-kms-key-arn.md#a-valid-aws-kms-arn) with a resource type of + // # "key". + if (providerArnInfo == null || !"key".equals(providerArnInfo.getResourceType())) { + throw new IllegalStateException("Invalid provider info in message."); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // # To match the encrypted data key's + // # provider ID MUST exactly match the value "aws-kms" and the the + // # function AWS KMS MRK Match for Decrypt (aws-kms-mrk-match-for- + // # decrypt.md#implementation) called with the configured AWS KMS key + // # identifier and the encrypted data key's provider info MUST return + // # "true". + return edk.getProviderId().equals(providerId) + && awsKmsArnMatchForDecrypt(awsKmsIdentifier_, edkKeyId); + } +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java new file mode 100644 index 000000000..468130db2 --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java @@ -0,0 +1,739 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo.*; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.NoSuchMasterKeyException; +import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException; +import com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo; +import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.KmsClientBuilder; + +// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.5 +// # MUST implement the Master Key Provider Interface (../master-key- +// # provider-interface.md#interface) +/** + * Represents a list Aws KMS keys and is used to encrypt/decrypt data with {@link AwsCrypto}. Some + * of these keys may be multi region keys, in which case this component is able to recognize + * different regional replicas of this multi region key as the same. + */ +public final class AwsKmsMrkAwareMasterKeyProvider + extends MasterKeyProvider { + private static final String PROVIDER_NAME = "aws-kms"; + private final List keyIds_; + private final List grantTokens_; + + private final boolean isDiscovery_; + private final DiscoveryFilter discoveryFilter_; + private final Region discoveryMrkRegion_; + + private final RegionalClientSupplier regionalClientSupplier_; + private final Region defaultRegion_; + + public static class Builder implements Cloneable { + private Region defaultRegion_ = getSdkDefaultRegion(); + + private Supplier builderSupplier_ = null; + private RegionalClientSupplier regionalClientSupplier_ = null; + + private DiscoveryFilter discoveryFilter_ = null; + private Region discoveryMrkRegion_ = this.defaultRegion_; + + Builder() { + // Default access: Don't allow outside classes to extend this class + } + + public Builder clone() { + try { + Builder cloned = (Builder) super.clone(); + + cloned.builderSupplier_ = builderSupplier_; + + return cloned; + } catch (CloneNotSupportedException e) { + throw new Error("Impossible: CloneNotSupportedException", e); + } + } + + /** + * Sets the default region. This region will be used when specifying key IDs for encryption or + * in {@link AwsKmsMrkAwareMasterKeyProvider#getMasterKey(String)} that are not full ARNs, but + * are instead bare key IDs or aliases. + * + *

If the default region is not specified, the AWS SDK default region will be used. + * + * @see KmsMasterKeyProvider.Builder#defaultRegion(Region) + * @param defaultRegion The default region to use. + */ + public Builder defaultRegion(Region defaultRegion) { + this.defaultRegion_ = defaultRegion; + return this; + } + + /** + * Sets the region contacted for multi-region keys when in Discovery mode. This region will be + * used when a multi-region key is discovered on decrypt by {@link + * AwsKmsMrkAwareMasterKeyProvider#getMasterKey(String)}. + * + *

+ * + * @param discoveryMrkRegion The region to contact to attempt to decrypt multi-region keys. + */ + public Builder discoveryMrkRegion(Region discoveryMrkRegion) { + this.discoveryMrkRegion_ = discoveryMrkRegion; + return this; + } + + /** + * Provides a custom factory function that will vend KMS clients. This is provided for advanced + * use cases which require complete control over the client construction process. + * + *

Because the regional client supplier fully controls the client construction process, it is + * not possible to configure the client through methods such as {@link + * #builderSupplier(Supplier)}; if you try to use these in combination, an {@link + * IllegalStateException} will be thrown. + * + * @see KmsMasterKeyProvider.Builder#customRegionalClientSupplier(RegionalClientSupplier) + */ + public Builder customRegionalClientSupplier(RegionalClientSupplier regionalClientSupplier) { + if (builderSupplier_ != null) { + throw clientSupplierComboException(); + } + + regionalClientSupplier_ = regionalClientSupplier; + return this; + } + + /** + * Configures the {@link AwsKmsMrkAwareMasterKeyProvider} to use settings from this {@link + * KmsClientBuilder} to configure KMS clients. Note that the region set on this builder will be + * ignored, but all other settings will be propagated into the regional clients. + * + * @see KmsMasterKeyProvider.Builder#builderSupplier(Supplier) + */ + public Builder builderSupplier(Supplier supplier) { + if (regionalClientSupplier_ != null) { + throw clientSupplierComboException(); + } + + this.builderSupplier_ = supplier; + return this; + } + + private RuntimeException clientSupplierComboException() { + return new IllegalStateException( + "only one of builderSupplier and customRegionalClientSupplier may be used"); + } + + /** + * Builds the master key provider in Discovery Mode. In Discovery Mode the KMS Master Key + * Provider will attempt to decrypt using any key identifier it discovers in the encrypted + * message. KMS Master Key Providers in Discovery Mode will not encrypt data keys. + * + * @see KmsMasterKeyProvider.Builder#buildDiscovery() + */ + public AwsKmsMrkAwareMasterKeyProvider buildDiscovery() { + final boolean isDiscovery = true; + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # The regional client + // # supplier MUST be defined in discovery mode. + RegionalClientSupplier clientSupplier = regionalClientSupplier_; + if (clientSupplier == null) { + clientSupplier = clientFactory(new ConcurrentHashMap<>(), builderSupplier_); + } + + return new AwsKmsMrkAwareMasterKeyProvider( + clientSupplier, + defaultRegion_, + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # The key id list MUST be empty in discovery mode. + emptyList(), + emptyList(), + isDiscovery, + discoveryFilter_, + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # In + // # discovery mode if a default MRK Region is not configured the AWS SDK + // # Default Region MUST be used. + discoveryMrkRegion_ == null ? defaultRegion_ : discoveryMrkRegion_); + } + + /** + * Builds the master key provider in Discovery Mode with a {@link DiscoveryFilter}. In Discovery + * Mode the KMS Master Key Provider will attempt to decrypt using any key identifier it + * discovers in the encrypted message that is accepted by the {@code filter}. KMS Master Key + * Providers in Discovery Mode will not encrypt data keys. + * + * @see KmsMasterKeyProvider.Builder#buildDiscovery(DiscoveryFilter) + */ + public AwsKmsMrkAwareMasterKeyProvider buildDiscovery(DiscoveryFilter filter) { + discoveryFilter_ = filter; + + return buildDiscovery(); + } + + /** + * Builds the master key provider in Strict Mode. KMS Master Key Providers in Strict Mode will + * only attempt to decrypt using key ARNs listed in {@code keyIds}. KMS Master Key Providers in + * Strict Mode will encrypt data keys using the keys listed in {@code keyIds} + * + *

In Strict Mode, one or more CMKs must be provided. For Master Key Providers that will only + * be used for encryption, you can use any valid KMS key identifier. For providers that will be + * used for decryption, you must use the key ARN; key ids, alias names, and alias ARNs are not + * supported. + * + * @see KmsMasterKeyProvider.Builder#buildStrict(List) + */ + public AwsKmsMrkAwareMasterKeyProvider buildStrict(List keyIds) { + final boolean isDiscovery = false; + + RegionalClientSupplier clientSupplier = regionalClientSupplier_; + if (clientSupplier == null) { + clientSupplier = clientFactory(new ConcurrentHashMap<>(), builderSupplier_); + } + + return new AwsKmsMrkAwareMasterKeyProvider( + clientSupplier, + defaultRegion_, + new ArrayList<>(keyIds), + emptyList(), + isDiscovery, + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # A discovery filter MUST NOT be configured in strict mode. + null, + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # A default MRK Region MUST NOT be configured in strict mode. + null); + } + + /** + * Builds the master key provider in strict mode. KMS Master Key Providers in Strict Mode will + * only attempt to decrypt using key ARNs listed in {@code keyIds}. KMS Master Key Providers in + * Strict Mode will encrypt data keys using the keys listed in {@code keyIds} + * + *

In Strict Mode, one or more CMKs must be provided. For Master Key Providers that will only + * be used for encryption, you can use any valid KMS key identifier. For providers that will be + * used for decryption, you must use the key ARN; key ids, alias names, and alias ARNs are not + * supported. + * + * @see KmsMasterKeyProvider.Builder#buildStrict(String...) + */ + public AwsKmsMrkAwareMasterKeyProvider buildStrict(String... keyIds) { + return buildStrict(asList(keyIds)); + } + + static RegionalClientSupplier clientFactory( + ConcurrentHashMap clientCache, + Supplier builderSupplier) { + + return region -> { + /* Check for early return (Postcondition): If a client already exists, use that. */ + if (clientCache.containsKey(region)) { + return clientCache.get(region); + } + + KmsClientBuilder builder = + builderSupplier != null ? builderSupplier.get() : KmsClient.builder(); + + // We can't just use computeIfAbsent as we need to avoid leaking KMS clients if we're asked + // to decrypt + // an EDK with a bogus region in its ARN. So we'll install a request handler to identify the + // first + // successful call, and cache it when we see that. + final RequestClientCacher cacher = new RequestClientCacher(clientCache, region); + KmsClient client = + builder + .region(region) + .overrideConfiguration(config -> config.addExecutionInterceptor(cacher)) + .build(); + + return cacher.setClient(client); + }; + } + + /** + * The AWS SDK has a default process for evaluating the default Region. This returns null if no + * default region is found. Because a default region _may_ not be needed. + */ + private static Region getSdkDefaultRegion() { + try { + return new DefaultAwsRegionProviderChain().getRegion(); + } catch (SdkClientException ex) { + return null; + } + } + } + + public static Builder builder() { + return new Builder(); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # On initialization the caller MUST provide: + private AwsKmsMrkAwareMasterKeyProvider( + RegionalClientSupplier supplier, + Region defaultRegion, + List keyIds, + List grantTokens, + boolean isDiscovery, + DiscoveryFilter discoveryFilter, + Region discoveryMrkRegion) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # The key id list MUST NOT be empty or null in strict mode. + if (!isDiscovery && (keyIds == null || keyIds.isEmpty())) { + throw new IllegalArgumentException( + "Strict mode must be configured with a non-empty " + "list of keyIds."); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # The key id + // # list MUST NOT contain any null or empty string values. + if (!isDiscovery && (keyIds.contains(null) || keyIds.contains(""))) { + throw new IllegalArgumentException( + "Strict mode cannot be configured with a " + "null key identifier."); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # All AWS KMS + // # key identifiers are be passed to Assert AWS KMS MRK are unique (aws- + // # kms-mrk-are-unique.md#Implementation) and the function MUST return + // # success. + assertMrksAreUnique(keyIds); + /* Precondition: A region is required to contact AWS KMS. + * This is an edge case because the default region will be the same as the SDK default, + * but it is still possible. + */ + if (!isDiscovery + && defaultRegion == null + && keyIds.stream().map(AwsKmsCmkArnInfo::parseInfoFromKeyArn).anyMatch(Objects::isNull)) { + throw new AwsCryptoException( + "Can't use non-ARN key identifiers or aliases when " + "no default region is set"); + } + /* Precondition: Discovery filter is only valid in discovery mode. */ + if (!isDiscovery && discoveryFilter != null) { + throw new IllegalArgumentException( + "Strict mode cannot be configured with a " + "discovery filter."); + } + /* Precondition: Discovery mode can not have any keys to filter. */ + if (isDiscovery && !keyIds.isEmpty()) { + throw new IllegalArgumentException("Discovery mode can not be configured with keys."); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // # If an AWS SDK Default Region can not be + // # obtained initialization MUST fail. + if (isDiscovery && discoveryMrkRegion == null) { + throw new IllegalArgumentException("Discovery MRK region can not be null."); + } + + this.regionalClientSupplier_ = supplier; + this.defaultRegion_ = defaultRegion; + this.keyIds_ = Collections.unmodifiableList(new ArrayList<>(keyIds)); + + this.isDiscovery_ = isDiscovery; + this.discoveryFilter_ = discoveryFilter; + this.discoveryMrkRegion_ = discoveryMrkRegion; + this.grantTokens_ = grantTokens; + } + + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // # The caller MUST provide: + /** Refactored into a pure function to facilitate testing and correctness. */ + static void assertMrksAreUnique(List keyIdentifiers) { + + List duplicateMultiRegionKeyIdentifiers = + keyIdentifiers.stream() + /* Collect a map of resource to identifier. + * This lets me group duplicates by "resource". + * This is because the identifier can be either an ARN or a raw identifier. + * By having the both the key id and the identifier I can ensure the uniqueness of + * the key id and the error message to the caller can contain both identifiers + * to facilitate debugging. + */ + .collect( + Collectors.groupingBy( + AwsKmsMrkAwareMasterKeyProvider::getResourceForResourceTypeKey)) + .entrySet() + .stream() + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // # If there are zero duplicate resource ids between the multi-region + // # keys, this function MUST exit successfully + .filter(maybeDuplicate -> maybeDuplicate.getValue().size() > 1) + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // # If the list does not contain any multi-Region keys (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST + // # exit successfully. + // + /* Postcondition: Filter out duplicate resources that are not multi-region keys. + * I expect only have duplicates of specific multi-region keys. + * In JSON something like + * { + * "mrk-edb7fe6942894d32ac46dbb1c922d574" : [ + * "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + * "arn:aws:kms:us-east-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574" + * ] + * } + */ + .filter(maybeMrk -> isMRK(maybeMrk.getKey())) + /* Flatten the duplicate identifiers into a single list. */ + .flatMap(mrkEntry -> mrkEntry.getValue().stream()) + .collect(Collectors.toList()); + + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // # If any duplicate multi-region resource ids exist, this function MUST + // # yield an error that includes all identifiers with duplicate resource + // # ids not only the first duplicate found. + if (duplicateMultiRegionKeyIdentifiers.size() > 1) { + throw new IllegalArgumentException( + "Duplicate multi-region keys are not allowed:\n" + + String.join(", ", duplicateMultiRegionKeyIdentifiers)); + } + } + + /** + * Helper method for + * + * @see AwsKmsMrkAwareMasterKeyProvider#assertMrksAreUnique(List) + *

Refoactored into a pure function to simplify testing and ensure correctness. + */ + static String getResourceForResourceTypeKey(String identifier) { + final AwsKmsCmkArnInfo info = parseInfoFromKeyArn(identifier); + /* Check for early return (Postcondition): Non-ARNs may be raw resources. + * Raw aliases ('alias/my-key') + * or key ids ('mrk-edb7fe6942894d32ac46dbb1c922d574'). + */ + if (info == null) return identifier; + + /* Check for early return (Postcondition): Return the identifier for non-key resource types. + * I only care about duplicate multi-region *keys*. + * Any other resource type + * should get filtered out. + * I return the entire identifier + * on the off chance that + * a customer has created + * an alias with a name `mrk-*`. + * This way such an alias + * can never accidentally + * collided with an existing multi-region key + * or a duplicate alias. + */ + if (!info.getResourceType().equals("key")) { + return identifier; + } + + /* Postcondition: Return the key id. + * This will be used + * to find different regional replicas of + * the same multi-region key + * because the key id for replicas is always the same. + */ + return info.getResource(); + } + + /** Returns "aws-kms" */ + @Override + public String getDefaultProviderId() { + return PROVIDER_NAME; + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # The input MUST be the same as the Master Key Provider Get Master Key + // # (../master-key-provider-interface.md#get-master-key) interface. + /** + * Added flexibility in matching multi-Region keys from different regions. + * + * @see KmsMasterKey#getMasterKey(String, String) + */ + @Override + public AwsKmsMrkAwareMasterKey getMasterKey(final String providerId, final String requestedKeyArn) + throws UnsupportedProviderException, NoSuchMasterKeyException { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # The function MUST only provide master keys if the input provider id + // # equals "aws-kms". + if (!canProvide(providerId)) { + throw new UnsupportedProviderException(); + } + + /* There SHOULD only be one match. + * An unambiguous multi-region key for the family + * of related multi-region keys is required. + * See `assertMrksAreUnique`. + * However, in the case of single region keys or aliases, + * duplicates _are_ possible. + */ + Optional matchedArn = + keyIds_.stream().filter(t -> awsKmsArnMatchForDecrypt(t, requestedKeyArn)).findFirst(); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # In strict mode, the requested AWS KMS key ARN MUST + // # match a member of the configured key ids by using AWS KMS MRK Match + // # for Decrypt (aws-kms-mrk-match-for-decrypt.md#implementation) + // # otherwise this function MUST error. + if (!isDiscovery_ && !matchedArn.isPresent()) { + throw new NoSuchMasterKeyException("Key must be in supplied list of keyIds."); + } + + final AwsKmsCmkArnInfo requestedKeyArnInfo = parseInfoFromKeyArn(requestedKeyArn); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # In discovery mode, the requested + // # AWS KMS key identifier MUST be a well formed AWS KMS ARN. + /* Precondition: Discovery mode requires requestedKeyArn be an ARN. + * This function is called on the encrypt path. + * It _may_ be the case that a raw key id, for example, was configured. + */ + if (isDiscovery_ && requestedKeyArnInfo == null) { + throw new NoSuchMasterKeyException( + "Cannot use AWS KMS identifiers " + "when in discovery mode."); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # In + // # discovery mode if a discovery filter is configured the requested AWS + // # KMS key ARN's "partition" MUST match the discovery filter's + // # "partition" and the AWS KMS key ARN's "account" MUST exist in the + // # discovery filter's account id set. + if (isDiscovery_ + && discoveryFilter_ != null + && !discoveryFilter_.allowsPartitionAndAccount( + requestedKeyArnInfo.getPartition(), requestedKeyArnInfo.getAccountId())) { + throw new NoSuchMasterKeyException( + "Cannot use key in partition " + + requestedKeyArnInfo.getPartition() + + " with account id " + + requestedKeyArnInfo.getAccountId() + + " with configured discovery filter."); + } + + final Region region_ = + extractRegion( + defaultRegion_, discoveryMrkRegion_, matchedArn, requestedKeyArnInfo, isDiscovery_); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # An AWS KMS client + // # MUST be obtained by calling the regional client supplier with this + // # AWS Region. + KmsClient client = regionalClientSupplier_.getClient(region_); + + String keyIdentifier = + isDiscovery_ + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # In discovery mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware- + // # master-key.md) MUST be returned configured with + ? requestedKeyArnInfo.toString(region_.id()) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # In strict mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware- + // # master-key.md) MUST be returned configured with + : matchedArn.get(); + + final AwsKmsMrkAwareMasterKey result = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, this); + result.setGrantTokens(grantTokens_); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # The output MUST be the same as the Master Key Provider Get Master Key + // # (../master-key-provider-interface.md#get-master-key) interface. + return result; + } + + /** + * Select the correct region from multiple default configurations and potentially related + * multi-Region keys from different regions. + * + *

Refactored into a pure function to facilitate testing and ensure correctness. + */ + static Region extractRegion( + final Region defaultRegion, + final Region discoveryMrkRegion, + final Optional matchedArn, + final AwsKmsCmkArnInfo requestedKeyArnInfo, + final boolean isDiscovery) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # If the requested AWS KMS key identifier is not a well formed ARN the + // # AWS Region MUST be the configured default region this SHOULD be + // # obtained from the AWS SDK. + if (requestedKeyArnInfo == null) return defaultRegion; + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # Otherwise if the requested AWS KMS key + // # identifier is identified as a multi-Region key (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key), then AWS Region MUST + // # be the region from the AWS KMS key ARN stored in the provider info + // # from the encrypted data key. + if (!isMRK(requestedKeyArnInfo.getResource()) + || !requestedKeyArnInfo.getResourceType().equals("key")) { + return Region.of(requestedKeyArnInfo.getRegion()); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # Otherwise if the mode is discovery then + // # the AWS Region MUST be the discovery MRK region. + if (isDiscovery) return discoveryMrkRegion; + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // # Finally if the + // # provider info is identified as a multi-Region key (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key) the AWS Region MUST + // # be the region from the AWS KMS key in the configured key ids matched + // # to the requested AWS KMS key by using AWS KMS MRK Match for Decrypt + // # (aws-kms-mrk-match-for-decrypt.md#implementation). + return Region.of(parseInfoFromKeyArn(matchedArn.get()).getRegion()); + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // # The input MUST be the same as the Master Key Provider Get Master Keys + // # For Encryption (../master-key-provider-interface.md#get-master-keys- + // # for-encryption) interface. + /** + * Returns all CMKs provided to the constructor of this object. + * + * @see KmsMasterKey#getMasterKeysForEncryption(MasterKeyRequest) + */ + @Override + public List getMasterKeysForEncryption(final MasterKeyRequest request) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // # If the configured mode is discovery the function MUST return an empty + // # list. + if (isDiscovery_) { + return emptyList(); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // # If the configured mode is strict this function MUST return a + // # list of master keys obtained by calling Get Master Key (aws-kms-mrk- + // # aware-master-key-provider.md#get-master-key) for each AWS KMS key + // # identifier in the configured key ids + List result = new ArrayList<>(keyIds_.size()); + for (String id : keyIds_) { + result.add(getMasterKey(id)); + } + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // # The output MUST be the same as the Master Key Provider Get Master + // # Keys For Encryption (../master-key-provider-interface.md#get-master- + // # keys-for-encryption) interface. + return result; + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # The input MUST be the same as the Master Key Provider Decrypt Data + // # Key (../master-key-provider-interface.md#decrypt-data-key) interface. + /** + * @see KmsMasterKey#decryptDataKey(CryptoAlgorithm, Collection, Map) + * @throws AwsCryptoException + */ + @Override + public DataKey decryptDataKey( + final CryptoAlgorithm algorithm, + final Collection encryptedDataKeys, + final Map encryptionContext) + throws AwsCryptoException { + final List exceptions = new ArrayList<>(); + + return encryptedDataKeys.stream() + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # The set of encrypted data keys MUST first be filtered to match this + // # master key's configuration. + .filter( + edk -> { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # To match the encrypted data key's + // # provider ID MUST exactly match the value "aws-kms". + if (!canProvide(edk.getProviderId())) return false; + + final String providerInfo = + new String(edk.getProviderInformation(), StandardCharsets.UTF_8); + final AwsKmsCmkArnInfo providerArnInfo = parseInfoFromKeyArn(providerInfo); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # Additionally + // # each provider info MUST be a valid AWS KMS ARN (aws-kms-key-arn.md#a- + // # valid-aws-kms-arn) with a resource type of "key". + if (providerArnInfo == null || !"key".equals(providerArnInfo.getResourceType())) { + throw new IllegalStateException("Invalid provider info in message."); + } + return true; + }) + .map( + edk -> { + try { + final String keyArn = + new String(edk.getProviderInformation(), StandardCharsets.UTF_8); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # For each encrypted data key in the filtered set, one at a time, the + // # master key provider MUST call Get Master Key (aws-kms-mrk-aware- + // # master-key-provider.md#get-master-key) with the encrypted data key's + // # provider info as the AWS KMS key ARN. + // This will throw if we can't use this key for whatever reason + return getMasterKey(edk.getProviderId(), keyArn) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # It MUST call Decrypt Data Key + // # (aws-kms-mrk-aware-master-key.md#decrypt-data-key) on this master key + // # with the input algorithm, this single encrypted data key, and the + // # input encryption context. + .decryptDataKey(algorithm, singletonList(edk), encryptionContext); + } catch (final Exception ex) { + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # If this attempt results in an error, then + // # these errors MUST be collected. + exceptions.add(ex); + return null; + } + }) + /* Need to filter null because an Optional of a null is crazy. + * `findFirst` will throw if it sees `null`. + */ + .filter(Objects::nonNull) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # If the decrypt data key call is + // # successful, then this function MUST return this result and not + // # attempt to decrypt any more encrypted data keys. + .findFirst() + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # If all the input encrypted data keys have been processed then this + // # function MUST yield an error that includes all the collected errors. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // # The output MUST be the same as the Master Key Provider Decrypt Data + // # Key (../master-key-provider-interface.md#decrypt-data-key) interface. + .orElseThrow(() -> buildCannotDecryptDksException(exceptions)); + } + + public List getGrantTokens() { + return new ArrayList<>(grantTokens_); + } + + /** + * Returns a new {@link AwsKmsMrkAwareMasterKeyProvider} that is configured identically to this + * one, except with the given list of grant tokens. The grant token list in the returned provider + * is immutable (but can be further overridden by invoking withGrantTokens again). + */ + public AwsKmsMrkAwareMasterKeyProvider withGrantTokens(List grantTokens) { + grantTokens = Collections.unmodifiableList(new ArrayList<>(grantTokens)); + + return new AwsKmsMrkAwareMasterKeyProvider( + regionalClientSupplier_, + defaultRegion_, + keyIds_, + grantTokens, + isDiscovery_, + discoveryFilter_, + discoveryMrkRegion_); + } + + /** + * Returns a new {@link AwsKmsMrkAwareMasterKeyProvider} that is configured identically to this + * one, except with the given list of grant tokens. The grant token list in the returned provider + * is immutable (but can be further overridden by invoking withGrantTokens again). + */ + public AwsKmsMrkAwareMasterKeyProvider withGrantTokens(String... grantTokens) { + return withGrantTokens(asList(grantTokens)); + } +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKey.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKey.java new file mode 100644 index 000000000..c87d4b035 --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKey.java @@ -0,0 +1,218 @@ +/* + * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except + * in compliance with the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import com.amazonaws.encryptionsdk.kms.KmsMethods; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.ApiName; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.*; + +/** + * Represents a single Customer Master Key (CMK) and is used to encrypt/decrypt data with {@link + * AwsCrypto}. + * + *

This component is not multi-Region key aware, and will treat every AWS KMS identifier as + * regionally isolated. + */ +public final class KmsMasterKey extends MasterKey implements KmsMethods { + private static final ApiName API_NAME = + ApiName.builder().name(VersionInfo.apiName()).version(VersionInfo.versionNumber()).build(); + private static final Consumer API_NAME_INTERCEPTOR = + builder -> builder.addApiName(API_NAME); + + private final Supplier clientSupplier_; + private final MasterKeyProvider sourceProvider_; + private final String id_; + private final List grantTokens_ = new ArrayList<>(); + + static KmsMasterKey getInstance( + final Supplier clientSupplier, + final String id, + final MasterKeyProvider provider) { + return new KmsMasterKey(clientSupplier, id, provider); + } + + private KmsMasterKey( + final Supplier clientSupplier, + final String id, + final MasterKeyProvider provider) { + clientSupplier_ = clientSupplier; + id_ = id; + sourceProvider_ = provider; + } + + @Override + public String getProviderId() { + return sourceProvider_.getDefaultProviderId(); + } + + @Override + public String getKeyId() { + return id_; + } + + @Override + public DataKey generateDataKey( + final CryptoAlgorithm algorithm, final Map encryptionContext) { + final GenerateDataKeyResponse gdkResponse = + clientSupplier_ + .get() + .generateDataKey( + GenerateDataKeyRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .keyId(getKeyId()) + .numberOfBytes(algorithm.getDataKeyLength()) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens_) + .build()); + + final ByteBuffer plaintextBuffer = gdkResponse.plaintext().asByteBuffer(); + if (plaintextBuffer.limit() != algorithm.getDataKeyLength()) { + throw new IllegalStateException("Received an unexpected number of bytes from KMS"); + } + + final byte[] rawKey = new byte[algorithm.getDataKeyLength()]; + plaintextBuffer.get(rawKey); + + final ByteBuffer ciphertextBlobBuffer = gdkResponse.ciphertextBlob().asByteBuffer(); + final byte[] encryptedKey = new byte[ciphertextBlobBuffer.remaining()]; + ciphertextBlobBuffer.get(encryptedKey); + + final String gdkResponseKeyId = gdkResponse.keyId(); + + final SecretKeySpec key = new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()); + return new DataKey<>( + key, encryptedKey, gdkResponseKeyId.getBytes(StandardCharsets.UTF_8), this); + } + + @Override + public void setGrantTokens(final List grantTokens) { + grantTokens_.clear(); + grantTokens_.addAll(grantTokens); + } + + @Override + public List getGrantTokens() { + return grantTokens_; + } + + @Override + public void addGrantToken(final String grantToken) { + grantTokens_.add(grantToken); + } + + @Override + public DataKey encryptDataKey( + final CryptoAlgorithm algorithm, + final Map encryptionContext, + final DataKey dataKey) { + final SecretKey key = dataKey.getKey(); + if (!key.getFormat().equals("RAW")) { + throw new IllegalArgumentException("Only RAW encoded keys are supported"); + } + try { + final EncryptResponse encryptResponse = + clientSupplier_ + .get() + .encrypt( + EncryptRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .keyId(id_) + .plaintext(SdkBytes.fromByteArray(key.getEncoded())) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens_) + .build()); + + final ByteBuffer ciphertextBlobBuffer = encryptResponse.ciphertextBlob().asByteBuffer(); + final byte[] edk = new byte[ciphertextBlobBuffer.remaining()]; + ciphertextBlobBuffer.get(edk); + + final String encryptResultKeyId = encryptResponse.keyId(); + + return new DataKey<>( + dataKey.getKey(), edk, encryptResultKeyId.getBytes(StandardCharsets.UTF_8), this); + } catch (final AwsServiceException asex) { + throw new AwsCryptoException(asex); + } + } + + @Override + public DataKey decryptDataKey( + final CryptoAlgorithm algorithm, + final Collection encryptedDataKeys, + final Map encryptionContext) + throws UnsupportedProviderException, AwsCryptoException { + final List exceptions = new ArrayList<>(); + for (final EncryptedDataKey edk : encryptedDataKeys) { + try { + final String edkKeyId = new String(edk.getProviderInformation(), StandardCharsets.UTF_8); + if (!edkKeyId.equals(id_)) { + continue; + } + final DecryptResponse decryptResponse = + clientSupplier_ + .get() + .decrypt( + DecryptRequest.builder() + .overrideConfiguration(API_NAME_INTERCEPTOR) + .ciphertextBlob(SdkBytes.fromByteArray(edk.getEncryptedDataKey())) + .encryptionContext(encryptionContext) + .grantTokens(grantTokens_) + .keyId(edkKeyId) + .build()); + + final String decryptResponseKeyId = decryptResponse.keyId(); + if (decryptResponseKeyId == null) { + throw new IllegalStateException("Received an empty keyId from KMS"); + } + if (decryptResponseKeyId.equals(id_)) { + final ByteBuffer plaintextBuffer = decryptResponse.plaintext().asByteBuffer(); + if (plaintextBuffer.limit() != algorithm.getDataKeyLength()) { + throw new IllegalStateException("Received an unexpected number of bytes from KMS"); + } + + final byte[] rawKey = new byte[algorithm.getDataKeyLength()]; + plaintextBuffer.get(rawKey); + + return new DataKey<>( + new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()), + edk.getEncryptedDataKey(), + edk.getProviderInformation(), + this); + } + } catch (final AwsServiceException awsex) { + exceptions.add(awsex); + } + } + + throw buildCannotDecryptDksException(exceptions); + } +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java new file mode 100644 index 000000000..0203a3326 --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java @@ -0,0 +1,448 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo.parseInfoFromKeyArn; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.NoSuchMasterKeyException; +import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException; +import com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo; +import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import com.amazonaws.encryptionsdk.kms.KmsMethods; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.KmsClientBuilder; + +/** + * Provides {@link MasterKey}s backed by the AWS Key Management Service. This object is regional and + * if you want to use keys from multiple regions, you'll need multiple copies of this object. + * + *

This component is not multi-Region key aware, and will treat every AWS KMS identifier as + * regionally isolated. + */ +public class KmsMasterKeyProvider extends MasterKeyProvider implements KmsMethods { + private static final String PROVIDER_NAME = "aws-kms"; + private final List keyIds_; + private final List grantTokens_; + + private final boolean isDiscovery_; + private final DiscoveryFilter discoveryFilter_; + + private final RegionalClientSupplier regionalClientSupplier_; + private final Region defaultRegion_; + + public static class Builder implements Cloneable { + private Region defaultRegion_ = null; + + private Supplier builderSupplier_ = null; + private RegionalClientSupplier regionalClientSupplier_ = null; + private DiscoveryFilter discoveryFilter_ = null; + + Builder() { + // Default access: Don't allow outside classes to extend this class + } + + public Builder clone() { + try { + Builder cloned = (Builder) super.clone(); + + cloned.builderSupplier_ = builderSupplier_; + + return cloned; + } catch (CloneNotSupportedException e) { + throw new Error("Impossible: CloneNotSupportedException", e); + } + } + + /** + * Sets the default region. This region will be used when specifying key IDs for encryption or + * in {@link KmsMasterKeyProvider#getMasterKey(String)} that are not full ARNs, but are instead + * bare key IDs or aliases. + * + *

If the default region is not specified, only full key ARNs will be usable. + * + * @param defaultRegion The default region to use. + * @return + */ + public Builder defaultRegion(Region defaultRegion) { + this.defaultRegion_ = defaultRegion; + return this; + } + + /** + * Provides a custom factory function that will vend KMS clients. This is provided for advanced + * use cases which require complete control over the client construction process. + * + *

Because the regional client supplier fully controls the client construction process, it is + * not possible to configure the client through methods such as {@link + * #builderSupplier(Supplier)}; if you try to use these in combination, an {@link + * IllegalStateException} will be thrown. + * + * @param regionalClientSupplier + * @return + */ + public Builder customRegionalClientSupplier(RegionalClientSupplier regionalClientSupplier) { + if (builderSupplier_ != null) { + throw clientSupplierComboException(); + } + + regionalClientSupplier_ = regionalClientSupplier; + return this; + } + + /** + * Configures the {@link KmsMasterKeyProvider} to use settings from this {@link + * KmsClientBuilder} to configure KMS clients. Note that the region set on this builder will be + * ignored, but all other settings will be propagated into the regional clients. + * + *

Trying to use this method in combination with {@link + * #customRegionalClientSupplier(RegionalClientSupplier)} will cause an {@link + * IllegalStateException} to be thrown. + * + * @param supplier Should return a new {@link KmsClientBuilder} on each invocation. + * @return + */ + public Builder builderSupplier(Supplier supplier) { + if (regionalClientSupplier_ != null) { + throw clientSupplierComboException(); + } + + this.builderSupplier_ = supplier; + return this; + } + + private RuntimeException clientSupplierComboException() { + return new IllegalStateException( + "only one of builderSupplier and customRegionalClientSupplier may be used"); + } + + /** + * Builds the master key provider in Discovery Mode. In Discovery Mode the KMS Master Key + * Provider will attempt to decrypt using any key identifier it discovers in the encrypted + * message. KMS Master Key Providers in Discovery Mode will not encrypt data keys. + * + * @return + */ + public KmsMasterKeyProvider buildDiscovery() { + final boolean isDiscovery = true; + RegionalClientSupplier supplier = clientFactory(); + + return new KmsMasterKeyProvider( + supplier, defaultRegion_, emptyList(), emptyList(), isDiscovery, discoveryFilter_); + } + + /** + * Builds the master key provider in Discovery Mode with a {@link DiscoveryFilter}. In Discovery + * Mode the KMS Master Key Provider will attempt to decrypt using any key identifier it + * discovers in the encrypted message that is accepted by the {@code filter}. KMS Master Key + * Providers in Discovery Mode will not encrypt data keys. + * + * @param filter + * @return + */ + public KmsMasterKeyProvider buildDiscovery(DiscoveryFilter filter) { + if (filter == null) { + throw new IllegalArgumentException( + "Discovery filter must not be null if specifying " + "a discovery filter."); + } + discoveryFilter_ = filter; + + return buildDiscovery(); + } + + /** + * Builds the master key provider in Strict Mode. KMS Master Key Providers in Strict Mode will + * only attempt to decrypt using key ARNs listed in {@code keyIds}. KMS Master Key Providers in + * Strict Mode will encrypt data keys using the keys listed in {@code keyIds} + * + *

In Strict Mode, one or more CMKs must be provided. For providers that will only be used + * for encryption, you can use any valid KMS key identifier. For providers that will be used for + * decryption, you must use the key ARN; key ids, alias names, and alias ARNs are not supported. + * + * @param keyIds + * @return + */ + public KmsMasterKeyProvider buildStrict(List keyIds) { + if (keyIds == null) { + throw new IllegalArgumentException( + "Strict mode must be configured with a non-empty " + "list of keyIds."); + } + + final boolean isDiscovery = false; + RegionalClientSupplier supplier = clientFactory(); + + return new KmsMasterKeyProvider( + supplier, defaultRegion_, new ArrayList<>(keyIds), emptyList(), isDiscovery, null); + } + + /** + * Builds the master key provider in strict mode. KMS Master Key Providers in Strict Mode will + * only attempt to decrypt using key ARNs listed in {@code keyIds}. KMS Master Key Providers in + * Strict Mode will encrypt data keys using the keys listed in {@code keyIds} + * + *

In Strict Mode, one or more CMKs must be provided. For providers that will only be used + * for encryption, you can use any valid KMS key identifier. For providers that will be used for + * decryption, you must use the key ARN; key ids, alias names, and alias ARNs are not supported. + * + * @param keyIds + * @return + */ + public KmsMasterKeyProvider buildStrict(String... keyIds) { + return buildStrict(asList(keyIds)); + } + + RegionalClientSupplier clientFactory() { + if (regionalClientSupplier_ != null) { + return regionalClientSupplier_; + } + + ConcurrentHashMap clientCache = new ConcurrentHashMap<>(); + snoopClientCache(clientCache); + + return region -> { + KmsClient client = clientCache.get(region); + + if (client != null) return client; + + KmsClientBuilder builder = + builderSupplier_ != null ? builderSupplier_.get() : KmsClient.builder(); + + // We can't just use computeIfAbsent as we need to avoid leaking KMS clients if we're asked + // to decrypt + // an EDK with a bogus region in its ARN. So we'll install a request handler to identify the + // first + // successful call, and cache it when we see that. + RequestClientCacher cacher = new RequestClientCacher(clientCache, region); + + ClientOverrideConfiguration overrideConfig = + builder.overrideConfiguration().toBuilder().addExecutionInterceptor(cacher).build(); + + client = builder.region(region).overrideConfiguration(overrideConfig).build(); + + return cacher.setClient(client); + }; + } + + protected void snoopClientCache(ConcurrentHashMap map) { + // no-op - this is a test hook + } + } + + public static Builder builder() { + return new Builder(); + } + + KmsMasterKeyProvider( + RegionalClientSupplier supplier, + Region defaultRegion, + List keyIds, + List grantTokens, + boolean isDiscovery, + DiscoveryFilter discoveryFilter) { + if (!isDiscovery && (keyIds == null || keyIds.isEmpty())) { + throw new IllegalArgumentException( + "Strict mode must be configured with a non-empty " + "list of keyIds."); + } + if (!isDiscovery && keyIds.contains(null)) { + throw new IllegalArgumentException( + "Strict mode cannot be configured with a " + "null key identifier."); + } + if (!isDiscovery && discoveryFilter != null) { + throw new IllegalArgumentException( + "Strict mode cannot be configured with a " + "discovery filter."); + } + // If we don't have a default region, we need to check that all key IDs will be usable + if (!isDiscovery && defaultRegion == null) { + for (String keyId : keyIds) { + final AwsKmsCmkArnInfo arnInfo = parseInfoFromKeyArn(keyId); + if (arnInfo == null) { + throw new AwsCryptoException( + "Can't use non-ARN key identifiers or aliases when " + "no default region is set"); + } + } + } + + this.regionalClientSupplier_ = supplier; + this.defaultRegion_ = defaultRegion; + this.keyIds_ = Collections.unmodifiableList(new ArrayList<>(keyIds)); + + this.isDiscovery_ = isDiscovery; + this.discoveryFilter_ = discoveryFilter; + this.grantTokens_ = grantTokens; + } + + /** Returns "aws-kms" */ + @Override + public String getDefaultProviderId() { + return PROVIDER_NAME; + } + + @Override + public KmsMasterKey getMasterKey(final String provider, final String keyId) + throws UnsupportedProviderException, NoSuchMasterKeyException { + if (!canProvide(provider)) { + throw new UnsupportedProviderException(); + } + + if (!isDiscovery_ && !keyIds_.contains(keyId)) { + throw new NoSuchMasterKeyException("Key must be in supplied list of keyIds."); + } + + final AwsKmsCmkArnInfo arnInfo = parseInfoFromKeyArn(keyId); + + if (isDiscovery_ && discoveryFilter_ != null && (arnInfo == null)) { + throw new NoSuchMasterKeyException( + "Cannot use non-ARN key identifiers or aliases if " + "discovery filter is configured."); + } else if (isDiscovery_ + && discoveryFilter_ != null + && !discoveryFilter_.allowsPartitionAndAccount( + arnInfo.getPartition(), arnInfo.getAccountId())) { + throw new NoSuchMasterKeyException( + "Cannot use key in partition " + + arnInfo.getPartition() + + " with account id " + + arnInfo.getAccountId() + + " with configured discovery filter."); + } + + Region region = defaultRegion_; + if (arnInfo != null) { + region = Region.of(arnInfo.getRegion()); + } + + final Region region_ = region; + + Supplier kmsSupplier = + () -> { + KmsClient client = regionalClientSupplier_.getClient(region_); + if (client == null) { + throw new AwsCryptoException("Can't use keys from region " + region_.id()); + } + return client; + }; + + final KmsMasterKey result = KmsMasterKey.getInstance(kmsSupplier, keyId, this); + result.setGrantTokens(grantTokens_); + return result; + } + + /** Returns all CMKs provided to the constructor of this object. */ + @Override + public List getMasterKeysForEncryption(final MasterKeyRequest request) { + if (keyIds_ == null) { + return emptyList(); + } + List result = new ArrayList<>(keyIds_.size()); + for (String id : keyIds_) { + result.add(getMasterKey(id)); + } + return result; + } + + @Override + public DataKey decryptDataKey( + final CryptoAlgorithm algorithm, + final Collection encryptedDataKeys, + final Map encryptionContext) + throws AwsCryptoException { + final List exceptions = new ArrayList<>(); + for (final EncryptedDataKey edk : encryptedDataKeys) { + if (canProvide(edk.getProviderId())) { + try { + final String keyArn = new String(edk.getProviderInformation(), StandardCharsets.UTF_8); + // This will throw if we can't use this key for whatever reason + return getMasterKey(keyArn) + .decryptDataKey(algorithm, singletonList(edk), encryptionContext); + } catch (final Exception ex) { + exceptions.add(ex); + } + } + } + throw buildCannotDecryptDksException(exceptions); + } + + /** + * @deprecated This method is inherently not thread safe. Use {@link + * KmsMasterKey#setGrantTokens(List)} instead. {@link KmsMasterKeyProvider}s constructed using + * the builder will throw an exception on attempts to modify the list of grant tokens. + */ + @Deprecated + @Override + public void setGrantTokens(final List grantTokens) { + try { + this.grantTokens_.clear(); + this.grantTokens_.addAll(grantTokens); + } catch (UnsupportedOperationException e) { + throw grantTokenError(); + } + } + + @Override + public List getGrantTokens() { + return new ArrayList<>(grantTokens_); + } + + /** + * @deprecated This method is inherently not thread safe. Use {@link #withGrantTokens(List)} or + * {@link KmsMasterKey#setGrantTokens(List)} instead. {@link KmsMasterKeyProvider}s + * constructed using the builder will throw an exception on attempts to modify the list of + * grant tokens. + */ + @Deprecated + @Override + public void addGrantToken(final String grantToken) { + try { + grantTokens_.add(grantToken); + } catch (UnsupportedOperationException e) { + throw grantTokenError(); + } + } + + private RuntimeException grantTokenError() { + return new IllegalStateException( + "This master key provider is immutable. Use withGrantTokens instead."); + } + + /** + * Returns a new {@link KmsMasterKeyProvider} that is configured identically to this one, except + * with the given list of grant tokens. The grant token list in the returned provider is immutable + * (but can be further overridden by invoking withGrantTokens again). + * + * @param grantTokens + * @return + */ + public KmsMasterKeyProvider withGrantTokens(List grantTokens) { + grantTokens = Collections.unmodifiableList(new ArrayList<>(grantTokens)); + + return new KmsMasterKeyProvider( + regionalClientSupplier_, + defaultRegion_, + keyIds_, + grantTokens, + isDiscovery_, + discoveryFilter_); + } + + /** + * Returns a new {@link KmsMasterKeyProvider} that is configured identically to this one, except + * with the given list of grant tokens. The grant token list in the returned provider is immutable + * (but can be further overridden by invoking withGrantTokens again). + * + * @param grantTokens + * @return + */ + public KmsMasterKeyProvider withGrantTokens(String... grantTokens) { + return withGrantTokens(asList(grantTokens)); + } +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RegionalClientSupplier.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RegionalClientSupplier.java new file mode 100644 index 000000000..0716aea1e --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RegionalClientSupplier.java @@ -0,0 +1,16 @@ +package com.amazonaws.encryptionsdk.kmssdkv2; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; + +@FunctionalInterface +public interface RegionalClientSupplier { + /** + * Supplies an {@link KmsClient} instance to use for a given {@link Region}. The {@link + * KmsMasterKeyProvider} will not cache the result of this function. + * + * @param region The region to get a client for + * @return The client to use, or null if this region cannot or should not be used. + */ + KmsClient getClient(Region region); +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RequestClientCacher.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RequestClientCacher.java new file mode 100644 index 000000000..9fb7fe57a --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/RequestClientCacher.java @@ -0,0 +1,53 @@ +package com.amazonaws.encryptionsdk.kmssdkv2; + +import java.util.concurrent.ConcurrentHashMap; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; + +class RequestClientCacher implements ExecutionInterceptor { + private final ConcurrentHashMap cache_; + private final Region region_; + private KmsClient client_; + + volatile boolean ranBefore_ = false; + + RequestClientCacher(final ConcurrentHashMap cache, final Region region) { + this.region_ = region; + this.cache_ = cache; + } + + public KmsClient setClient(final KmsClient client) { + client_ = client; + return client; + } + + @Override + public void afterExecution( + Context.AfterExecution context, ExecutionAttributes executionAttributes) { + if (ranBefore_) { + return; + } + ranBefore_ = true; + + cache_.putIfAbsent(region_, client_); + } + + @Override + public void onExecutionFailure( + Context.FailedExecution context, ExecutionAttributes executionAttributes) { + if (ranBefore_) { + return; + } + + if (!(context.exception() instanceof AwsServiceException)) { + return; + } + + ranBefore_ = true; + cache_.putIfAbsent(region_, client_); + } +} diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/package-info.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/package-info.java new file mode 100644 index 000000000..1ee063dac --- /dev/null +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/package-info.java @@ -0,0 +1,18 @@ +/* + * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except + * in compliance with the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +/** + * Contains logic necessary to create {@link com.amazonaws.encryptionsdk.MasterKey}s backed by AWS + * KMS keys. + */ +package com.amazonaws.encryptionsdk.kmssdkv2; diff --git a/src/test/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExampleTest.java index 8ebdae172..77769a2e1 100644 --- a/src/test/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExampleTest.java +++ b/src/test/java/com/amazonaws/crypto/examples/DiscoveryMultiRegionDecryptionExampleTest.java @@ -5,6 +5,7 @@ import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; import org.junit.Test; +import software.amazon.awssdk.regions.Region; public class DiscoveryMultiRegionDecryptionExampleTest { @@ -14,6 +15,6 @@ public void testEncryptAndDecrypt() { KMSTestFixtures.US_EAST_1_MULTI_REGION_KEY_ID, KMSTestFixtures.PARTITION, KMSTestFixtures.ACCOUNT_ID, - KMSTestFixtures.US_WEST_2); + Region.US_WEST_2); } } diff --git a/src/test/java/com/amazonaws/crypto/examples/RestrictRegionExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/RestrictRegionExampleTest.java index 0758378c2..6613b8ea2 100644 --- a/src/test/java/com/amazonaws/crypto/examples/RestrictRegionExampleTest.java +++ b/src/test/java/com/amazonaws/crypto/examples/RestrictRegionExampleTest.java @@ -5,6 +5,7 @@ import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; import org.junit.Test; +import software.amazon.awssdk.regions.Region; public class RestrictRegionExampleTest { @@ -14,6 +15,6 @@ public void testEncryptAndDecrypt() { KMSTestFixtures.US_WEST_2_KEY_ID, KMSTestFixtures.PARTITION, KMSTestFixtures.ACCOUNT_ID, - KMSTestFixtures.US_WEST_2); + Region.US_WEST_2); } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java index e6fd1534b..e72a0b2ed 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java +++ b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java @@ -90,5 +90,9 @@ AwsKmsMrkAwareMasterKeyProviderTest.class, AwsKmsMrkAwareMasterKeyTest.class, VersionInfoTest.class, + com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProviderTest.class, + com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyTest.class, + com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProviderTest.class, + com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyTest.class, }) public class AllTestsSuite {} diff --git a/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java b/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java index aa6ea32ee..55b3e04d3 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java +++ b/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java @@ -11,5 +11,8 @@ XCompatKmsDecryptTest.class, KMSProviderBuilderIntegrationTests.class, MaxEncryptedDataKeysIntegrationTest.class, + com.amazonaws.encryptionsdk.kms.KMSProviderBuilderIntegrationTests.class, + com.amazonaws.encryptionsdk.kms.MaxEncryptedDataKeysIntegrationTest.class, + com.amazonaws.encryptionsdk.kms.XCompatKmsDecryptTest.class }) public class IntegrationTestSuite {} diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java index cc2d9efbd..a89cde8ed 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java @@ -40,6 +40,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import software.amazon.awssdk.regions.Region; @RunWith(Parameterized.class) public class TestVectorRunner { @@ -104,19 +105,28 @@ public static Collection data() throws Exception { final Map keys = parseKeyManifest(readJsonMapFromJar(jar, (String) manifest.get("keys"))); - final KmsMasterKeyProvider kmsProv = + final KmsMasterKeyProvider kmsProvV1 = KmsMasterKeyProvider.builder() .withCredentials(new DefaultAWSCredentialsProviderChain()) .buildDiscovery(); + final com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider kmsProvV2 = + com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider.builder().buildDiscovery(); + List testCases = new ArrayList<>(); for (Map.Entry> testEntry : ((Map>) manifest.get("tests")).entrySet()) { String testName = testEntry.getKey(); - TestCase testCase = parseTest(testEntry.getKey(), testEntry.getValue(), keys, jar, kmsProv); + + TestCase testCaseV1 = + parseTest(testEntry.getKey(), testEntry.getValue(), keys, jar, kmsProvV1); + TestCase testCaseV2 = + parseTest(testEntry.getKey(), testEntry.getValue(), keys, jar, kmsProvV2); + for (DecryptionMethod decryptionMethod : DecryptionMethod.values()) { - if (testCase.signaturePolicy.equals(decryptionMethod.signaturePolicy())) { - testCases.add(new Object[] {testName, testCase, decryptionMethod}); + if (testCaseV1.signaturePolicy.equals(decryptionMethod.signaturePolicy())) { + testCases.add(new Object[] {testName, testCaseV1, decryptionMethod}); + testCases.add(new Object[] {testName + "-V2", testCaseV2, decryptionMethod}); } } } @@ -157,7 +167,7 @@ private static void cacheData(JarFile jar, String url) throws IOException { } @SuppressWarnings("unchecked") - private static TestCase parseTest( + private static TestCase parseTest( String testName, Map data, Map keys, @@ -259,6 +269,110 @@ private static TestCase parseTest( return new TestCase(testName, ciphertextURL, mkpSupplier, matcher, signaturePolicy); } + @SuppressWarnings("unchecked") + private static TestCase parseTest( + String testName, + Map data, + Map keys, + JarFile jar, + com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider kmsProv) + throws IOException { + final String ciphertextURL = (String) data.get("ciphertext"); + cacheData(jar, ciphertextURL); + + Supplier> mkpSupplier = + () -> { + @SuppressWarnings("generic") + final List> mks = new ArrayList<>(); + + for (Map mkEntry : (List>) data.get("master-keys")) { + final String type = (String) mkEntry.get("type"); + final String keyName = (String) mkEntry.get("key"); + final KeyEntry key = keys.get(keyName); + + if ("aws-kms".equals(type)) { + mks.add(kmsProv.getMasterKey(key.keyId)); + } else if ("aws-kms-mrk-aware".equals(type)) { + com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProvider provider = + com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict(key.keyId); + mks.add(provider.getMasterKey(key.keyId)); + } else if ("aws-kms-mrk-aware-discovery".equals(type)) { + final String defaultMrkRegion = (String) mkEntry.get("default-mrk-region"); + final Map discoveryFilterSpec = + (Map) mkEntry.get("aws-kms-discovery-filter"); + final DiscoveryFilter discoveryFilter; + if (discoveryFilterSpec != null) { + discoveryFilter = + new DiscoveryFilter( + (String) discoveryFilterSpec.get("partition"), + (List) discoveryFilterSpec.get("account-ids")); + } else { + discoveryFilter = null; + } + return com.amazonaws.encryptionsdk.kmssdkv2.AwsKmsMrkAwareMasterKeyProvider.builder() + .discoveryMrkRegion(Region.of(defaultMrkRegion)) + .buildDiscovery(discoveryFilter); + } else if ("raw".equals(type)) { + final String provId = (String) mkEntry.get("provider-id"); + final String algorithm = (String) mkEntry.get("encryption-algorithm"); + if ("aes".equals(algorithm)) { + mks.add( + JceMasterKey.getInstance( + (SecretKey) key.key, provId, key.keyId, "AES/GCM/NoPadding")); + } else if ("rsa".equals(algorithm)) { + String transformation = "RSA/ECB/"; + final String padding = (String) mkEntry.get("padding-algorithm"); + if ("pkcs1".equals(padding)) { + transformation += "PKCS1Padding"; + } else if ("oaep-mgf1".equals(padding)) { + final String hashName = + ((String) mkEntry.get("padding-hash")).replace("sha", "sha-").toUpperCase(); + transformation += "OAEPWith" + hashName + "AndMGF1Padding"; + } else { + throw new IllegalArgumentException("Unsupported padding:" + padding); + } + final PublicKey wrappingKey; + final PrivateKey unwrappingKey; + if (key.key instanceof PublicKey) { + wrappingKey = (PublicKey) key.key; + unwrappingKey = null; + } else { + wrappingKey = null; + unwrappingKey = (PrivateKey) key.key; + } + mks.add( + JceMasterKey.getInstance( + wrappingKey, unwrappingKey, provId, key.keyId, transformation)); + } else { + throw new IllegalArgumentException("Unsupported algorithm: " + algorithm); + } + } else { + throw new IllegalArgumentException("Unsupported Key Type: " + type); + } + } + + return MultipleProviderFactory.buildMultiProvider(mks); + }; + + @SuppressWarnings("unchecked") + final Map resultSpec = (Map) data.get("result"); + final ResultMatcher matcher = parseResultMatcher(jar, resultSpec); + + String decryptionMethodSpec = (String) data.get("decryption-method"); + SignaturePolicy signaturePolicy = SignaturePolicy.AllowEncryptAllowDecrypt; + if (decryptionMethodSpec != null) { + if ("streaming-unsigned-only".equals(decryptionMethodSpec)) { + signaturePolicy = SignaturePolicy.AllowEncryptForbidDecrypt; + } else { + throw new IllegalArgumentException( + "Unsupported Decryption Method: " + decryptionMethodSpec); + } + } + + return new TestCase(testName, ciphertextURL, mkpSupplier, matcher, signaturePolicy); + } + private static ResultMatcher parseResultMatcher( final JarFile jar, final Map result) throws IOException { if (result.size() != 1) { diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProviderTest.java b/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProviderTest.java index f896dce35..3bc0e99e2 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProviderTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProviderTest.java @@ -28,7 +28,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.junit.Test; import org.junit.experimental.runners.Enclosed; -import org.junit.jupiter.api.DisplayName; import org.junit.runner.RunWith; @RunWith(Enclosed.class) @@ -36,7 +35,6 @@ public class AwsKmsMrkAwareMasterKeyProviderTest { public static class getResourceForResourceTypeKey { @Test - @DisplayName("Postcondition: Return the key id.") public void basic_use() { assertEquals( "mrk-edb7fe6942894d32ac46dbb1c922d574", @@ -45,7 +43,6 @@ public void basic_use() { } @Test - @DisplayName("Check for early return (Postcondition): Non-ARNs may be raw resources.") public void not_an_arn() { assertEquals( "mrk-edb7fe6942894d32ac46dbb1c922d574", @@ -57,8 +54,6 @@ public void not_an_arn() { } @Test - @DisplayName( - "Check for early return (Postcondition): Return the identifier for non-key resource types.") public void not_a_key() { final String alias = "arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt"; assertEquals(alias, AwsKmsMrkAwareMasterKeyProvider.getResourceForResourceTypeKey(alias)); @@ -102,7 +97,6 @@ public void no_mrks_at_all() { } @Test - @DisplayName("Postcondition: Filter out duplicate resources that are not multi-region keys.") public void non_mrk_duplicates_ok() { AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( Arrays.asList( @@ -230,7 +224,6 @@ public void no_duplicate_mrks() { } @Test - @DisplayName("Precondition: A region is required to contact AWS KMS.") public void always_need_a_region() { assertThrows( AwsCryptoException.class, @@ -498,7 +491,6 @@ public void no_key_id_match() { } @Test - @DisplayName("Precondition: Discovery mode requires requestedKeyArn be an ARN.") // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 // = type=test // # In discovery mode, the requested @@ -786,7 +778,6 @@ public void basic_use() { } @Test - @DisplayName("Check for early return (Postcondition): If a client already exists, use that.") public void use_clients_that_exist() { final String region = "asdf"; final ConcurrentHashMap cache = spy(new ConcurrentHashMap<>()); diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyTest.java b/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyTest.java index 933e375e4..695607932 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyTest.java @@ -28,7 +28,6 @@ import javax.crypto.spec.SecretKeySpec; import org.junit.Test; import org.junit.experimental.runners.Enclosed; -import org.junit.jupiter.api.DisplayName; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -102,7 +101,6 @@ public void requires_valid_client() { } @Test - @DisplayName("Precondition: A provider is required.") public void requires_valid_provider() { AWSKMS client = spy(new MockKMSClient()); @@ -230,8 +228,6 @@ public void length_must_match() { } @Test - @DisplayName( - "Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey.") public void need_an_arn() { final CryptoAlgorithm ALGORITHM_SUITE = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; @@ -342,7 +338,6 @@ public void basic_use() { } @Test - @DisplayName("Precondition: The key format MUST be RAW.") public void secret_key_must_be_raw() { final CryptoAlgorithm ALGORITHM_SUITE = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; @@ -382,7 +377,6 @@ public void secret_key_must_be_raw() { } @Test - @DisplayName("Postcondition: Must have an AWS KMS ARN from AWS KMS encrypt.") public void need_an_arn() { final CryptoAlgorithm ALGORITHM_SUITE = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; @@ -573,7 +567,6 @@ public void basic_use() { } @Test - @DisplayName("Exceptional Postcondition: Must have a CMK ARN from AWS KMS to match.") public void expect_key_arn() { final CryptoAlgorithm ALGORITHM_SUITE = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; @@ -821,7 +814,6 @@ public void edk_match() { } @Test - @DisplayName("Exceptional Postcondition: Master key was unable to decrypt.") // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 // = type=test // # If this attempt diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProviderTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProviderTest.java new file mode 100644 index 000000000..3a238e196 --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProviderTest.java @@ -0,0 +1,945 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.internal.AwsKmsCmkArnInfo.parseInfoFromKeyArn; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.exception.NoSuchMasterKeyException; +import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException; +import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import com.amazonaws.encryptionsdk.model.KeyBlob; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.jupiter.api.DisplayName; +import org.junit.runner.RunWith; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.KmsClientBuilder; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.DecryptResponse; + +@RunWith(Enclosed.class) +public class AwsKmsMrkAwareMasterKeyProviderTest { + + public static class getResourceForResourceTypeKey { + @Test + @DisplayName("Postcondition: Return the key id.") + public void basic_use() { + assertEquals( + "mrk-edb7fe6942894d32ac46dbb1c922d574", + AwsKmsMrkAwareMasterKeyProvider.getResourceForResourceTypeKey( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574")); + } + + @Test + @DisplayName("Check for early return (Postcondition): Non-ARNs may be raw resources.") + public void not_an_arn() { + assertEquals( + "mrk-edb7fe6942894d32ac46dbb1c922d574", + AwsKmsMrkAwareMasterKeyProvider.getResourceForResourceTypeKey( + "mrk-edb7fe6942894d32ac46dbb1c922d574")); + final String malformed = "aws:kms:us-west-2::key/garbage"; + assertEquals( + malformed, AwsKmsMrkAwareMasterKeyProvider.getResourceForResourceTypeKey(malformed)); + } + + @Test + @DisplayName( + "Check for early return (Postcondition): Return the identifier for non-key resource types.") + public void not_a_key() { + final String alias = "arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt"; + assertEquals(alias, AwsKmsMrkAwareMasterKeyProvider.getResourceForResourceTypeKey(alias)); + } + } + + public static class assertMrksAreUnique { + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // = type=test + // # The caller MUST provide: + public void basic_use() { + AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( + Arrays.asList( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574")); + } + + @Test + public void no_duplicates() { + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // = type=test + // # If there are zero duplicate resource ids between the multi-region + // # keys, this function MUST exit successfully + AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( + Arrays.asList( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f")); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // = type=test + // # If the list does not contain any multi-Region keys (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST + // # exit successfully. + public void no_mrks_at_all() { + AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( + Arrays.asList( + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f")); + } + + @Test + @DisplayName("Postcondition: Filter out duplicate resources that are not multi-region keys.") + public void non_mrk_duplicates_ok() { + AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( + Arrays.asList( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + "arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt", + "arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt")); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 + // = type=test + // # If any duplicate multi-region resource ids exist, this function MUST + // # yield an error that includes all identifiers with duplicate resource + // # ids not only the first duplicate found. + public void no_duplicate_mrks() { + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.assertMrksAreUnique( + Arrays.asList( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + "arn:aws:kms:us-east-1:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"))); + } + } + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # On initialization the caller MUST provide: + public static class AwsKmsMrkAwareMasterKeyProviderBuilderTests { + @Test + public void basic_use() { + final AwsKmsMrkAwareMasterKeyProvider strict = + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"); + final AwsKmsMrkAwareMasterKeyProvider discovery = + AwsKmsMrkAwareMasterKeyProvider.builder().buildDiscovery(); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.5 + // = type=test + // # MUST implement the Master Key Provider Interface (../master-key- + // # provider-interface.md#interface) + assertTrue(MasterKeyProvider.class.isInstance(strict)); + assertTrue(MasterKeyProvider.class.isInstance(discovery)); + + // These are not testable because of how the builder is structured. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # A discovery filter MUST NOT be configured in strict mode. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # A default MRK Region MUST NOT be configured in strict mode. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # In + // # discovery mode if a default MRK Region is not configured the AWS SDK + // # Default Region MUST be used. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # The key id list MUST be empty in discovery mode. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # The regional client + // # supplier MUST be defined in discovery mode. + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # The key id list MUST NOT be empty or null in strict mode. + public void no_noop() { + assertThrows( + IllegalArgumentException.class, + () -> AwsKmsMrkAwareMasterKeyProvider.builder().buildStrict()); + assertThrows( + IllegalArgumentException.class, + () -> AwsKmsMrkAwareMasterKeyProvider.builder().buildStrict(new ArrayList())); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # The key id + // # list MUST NOT contain any null or empty string values. + public void no_null_identifiers() { + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + "")); + + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + null)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # All AWS KMS + // # key identifiers are be passed to Assert AWS KMS MRK are unique (aws- + // # kms-mrk-are-unique.md#Implementation) and the function MUST return + // # success. + public void no_duplicate_mrks() { + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + "arn:aws:kms:us-east-1:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574")); + } + + @Test + @DisplayName("Precondition: A region is required to contact AWS KMS.") + public void always_need_a_region() { + assertThrows( + AwsCryptoException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .defaultRegion(null) + .buildStrict("mrk-edb7fe6942894d32ac46dbb1c922d574")); + + AwsKmsMrkAwareMasterKeyProvider.builder() + .defaultRegion(Region.US_EAST_1) + .buildStrict("mrk-edb7fe6942894d32ac46dbb1c922d574"); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 + // = type=test + // # If an AWS SDK Default Region can not be + // # obtained initialization MUST fail. + public void discovery_region_can_not_be_null() { + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + // need to force the default region to `null` + // otherwise it may pick one up from the environment. + .defaultRegion(null) + .discoveryMrkRegion(null) + .buildDiscovery()); + } + + @Test + @DisplayName("Precondition: Discovery filter is only valid in discovery mode.") + public void strict_cannot_have_discovery_filter() { + assertThrows( + IllegalArgumentException.class, + () -> { + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildStrict( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"); + + Field field = mkp.getClass().getDeclaredField("discoveryFilter_"); + field.setAccessible(true); + DiscoveryFilter filter = new DiscoveryFilter("partition", "accountId1"); + field.set(mkp, filter); + field.setAccessible(false); + + mkp.withGrantTokens("token1", "token2"); + }); + } + + @Test + @DisplayName("Precondition: Discovery mode can not have any keys to filter.") + public void discovery_cannot_have_any_keys() { + assertThrows( + IllegalArgumentException.class, + () -> { + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildDiscovery(); + + Field field = mkp.getClass().getDeclaredField("keyIds_"); + field.setAccessible(true); + List keyIds = Arrays.asList("keyId1", "keyId2"); + field.set(mkp, keyIds); + field.setAccessible(false); + + mkp.withGrantTokens("token1", "token2"); + }); + } + + @Test + public void get_grant_tokens() { + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildDiscovery(); + mkp = mkp.withGrantTokens("token1", "token2"); + assert (mkp.getGrantTokens()).contains("token1"); + assert (mkp.getGrantTokens()).contains("token2"); + } + + @Test + public void basic_credentials_and_builder() { + AwsCredentialsProvider credsProvider = + StaticCredentialsProvider.create(AwsBasicCredentials.create("asdf", "qwer")); + AwsKmsMrkAwareMasterKeyProvider.builder() + .builderSupplier(() -> KmsClient.builder().credentialsProvider(credsProvider)) + .buildDiscovery(); + } + } + + public static class extractRegion { + + @Test + public void basic_use() { + final Region test = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.of( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"), + parseInfoFromKeyArn( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"), + false); + + assertEquals(Region.US_WEST_2, test); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # If the requested AWS KMS key identifier is not a well formed ARN the + // # AWS Region MUST be the configured default region this SHOULD be + // # obtained from the AWS SDK. + public void not_an_arn() { + final Region test = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.empty(), + parseInfoFromKeyArn("mrk-edb7fe6942894d32ac46dbb1c922d574"), + false); + + assertEquals(Region.US_EAST_1, test); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # Otherwise if the requested AWS KMS key + // # identifier is identified as a multi-Region key (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key), then AWS Region MUST + // # be the region from the AWS KMS key ARN stored in the provider info + // # from the encrypted data key. + public void not_an_mrk() { + final Region test = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.of( + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"), + parseInfoFromKeyArn( + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"), + false); + + assertEquals(Region.US_WEST_2, test); + + final Region test2 = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.of("arn:aws:kms:us-west-2:658956600833:alias/mrk-nasty"), + parseInfoFromKeyArn("arn:aws:kms:us-west-2:658956600833:alias/mrk-nasty"), + false); + + assertEquals(Region.US_WEST_2, test2); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # Otherwise if the mode is discovery then + // # the AWS Region MUST be the discovery MRK region. + public void mrk_in_discovery() { + final Region test = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.empty(), + parseInfoFromKeyArn( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"), + true); + + assertEquals(Region.US_EAST_2, test); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # Finally if the + // # provider info is identified as a multi-Region key (aws-kms-key- + // # arn.md#identifying-an-aws-kms-multi-region-key) the AWS Region MUST + // # be the region from the AWS KMS key in the configured key ids matched + // # to the requested AWS KMS key by using AWS KMS MRK Match for Decrypt + // # (aws-kms-mrk-match-for-decrypt.md#implementation). + public void fuzzy_match_mrk() { + final Region test = + AwsKmsMrkAwareMasterKeyProvider.extractRegion( + Region.US_EAST_1, + Region.US_EAST_2, + Optional.of( + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"), + parseInfoFromKeyArn( + "arn:aws:kms:us-west-1:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"), + false); + + assertEquals(Region.US_WEST_2, test); + } + } + + public static class getMasterKey { + @Test + public void basic_use() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(identifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # The input MUST be the same as the Master Key Provider Get Master Key + // # (../master-key-provider-interface.md#get-master-key) interface. + AwsKmsMrkAwareMasterKey test = mkp.getMasterKey("aws-kms", identifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # The output MUST be the same as the Master Key Provider Get Master Key + // # (../master-key-provider-interface.md#get-master-key) interface. + assertTrue(AwsKmsMrkAwareMasterKey.class.isInstance((test))); + + assertEquals(identifier, test.getKeyId()); + verify(supplier, times(1)).getClient(Region.US_WEST_2); + } + + @Test + public void basic_mrk_use() { + final String configuredIdentifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String requestedIdentifier = + "arn:aws:kms:us-east-1:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(configuredIdentifier); + + AwsKmsMrkAwareMasterKey test = mkp.getMasterKey("aws-kms", requestedIdentifier); + + assertEquals(configuredIdentifier, test.getKeyId()); + verify(supplier, times(1)).getClient(Region.US_WEST_2); + } + + @Test + public void other_basic_uses() { + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + // A raw alias is a valid configuration for encryption + final String rawAliasIdentifier = "alias/my-alias"; + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(rawAliasIdentifier) + .getMasterKey("aws-kms", rawAliasIdentifier); + + // A raw alias is a valid configuration for encryption + final String rawKeyIdentifier = "mrk-edb7fe6942894d32ac46dbb1c922d574"; + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(rawKeyIdentifier) + .getMasterKey("aws-kms", rawKeyIdentifier); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # The function MUST only provide master keys if the input provider id + // # equals "aws-kms". + public void only_this_provider() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(identifier); + + assertThrows( + UnsupportedProviderException.class, () -> mkp.getMasterKey("not-aws-kms", identifier)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # In strict mode, the requested AWS KMS key ARN MUST + // # match a member of the configured key ids by using AWS KMS MRK Match + // # for Decrypt (aws-kms-mrk-match-for-decrypt.md#implementation) + // # otherwise this function MUST error. + public void no_key_id_match() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + final AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(identifier); + + assertThrows( + NoSuchMasterKeyException.class, + () -> mkp.getMasterKey("aws-kms", "does-not-match-configured")); + } + + @Test + @DisplayName("Precondition: Discovery mode requires requestedKeyArn be an ARN.") + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # In discovery mode, the requested + // # AWS KMS key identifier MUST be a well formed AWS KMS ARN. + public void discovery_request_must_be_arn() { + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildDiscovery(); + + assertThrows( + NoSuchMasterKeyException.class, + () -> mkp.getMasterKey("aws-kms", "mrk-edb7fe6942894d32ac46dbb1c922d574")); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # In + // # discovery mode if a discovery filter is configured the requested AWS + // # KMS key ARN's "partition" MUST match the discovery filter's + // # "partition" and the AWS KMS key ARN's "account" MUST exist in the + // # discovery filter's account id set. + public void discovery_filter_must_match() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + assertThrows( + NoSuchMasterKeyException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildDiscovery(new DiscoveryFilter("aws", Arrays.asList("not-111122223333"))) + .getMasterKey("aws-kms", identifier)); + + assertThrows( + NoSuchMasterKeyException.class, + () -> + AwsKmsMrkAwareMasterKeyProvider.builder() + .buildDiscovery(new DiscoveryFilter("not-aws", Arrays.asList("111122223333"))) + .getMasterKey("aws-kms", identifier)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # In discovery mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware- + // # master-key.md) MUST be returned configured with + public void discovery_magic_to_make_the_region_match() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .discoveryMrkRegion(Region.of("my-region")) + .buildDiscovery(); + + AwsKmsMrkAwareMasterKey test = mkp.getMasterKey("aws-kms", identifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # An AWS KMS client + // # MUST be obtained by calling the regional client supplier with this + // # AWS Region. + assertEquals( + "arn:aws:kms:my-region:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + test.getKeyId()); + verify(supplier, times(1)).getClient(Region.of("my-region")); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 + // = type=test + // # In strict mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware- + // # master-key.md) MUST be returned configured with + public void strict_mrk_region_match() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String configIdentifier = + "arn:aws:kms:us-east-1:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(configIdentifier); + + AwsKmsMrkAwareMasterKey test = mkp.getMasterKey("aws-kms", identifier); + + assertEquals(configIdentifier, test.getKeyId()); + verify(supplier, times(1)).getClient(Region.US_EAST_1); + } + } + + public static class decryptDataKey { + + @Test + public void basic_use() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final byte[] cipherText = new byte[10]; + final EncryptedDataKey edk1 = + new KeyBlob("aws-kms", identifier.getBytes(StandardCharsets.UTF_8), cipherText); + final EncryptedDataKey edk2 = + new KeyBlob("aws-kms", identifier.getBytes(StandardCharsets.UTF_8), cipherText); + + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId(identifier) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build()); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(identifier) + .withGrantTokens(GRANT_TOKENS); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # The input MUST be the same as the Master Key Provider Decrypt Data + // # Key (../master-key-provider-interface.md#decrypt-data-key) interface. + final DataKey test = + mkp.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(edk1, edk2), ENCRYPTION_CONTEXT); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # For each encrypted data key in the filtered set, one at a time, the + // # master key provider MUST call Get Master Key (aws-kms-mrk-aware- + // # master-key-provider.md#get-master-key) with the encrypted data key's + // # provider info as the AWS KMS key ARN. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # It MUST call Decrypt Data Key + // # (aws-kms-mrk-aware-master-key.md#decrypt-data-key) on this master key + // # with the input algorithm, this single encrypted data key, and the + // # input encryption context. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # If the decrypt data key call is + // # successful, then this function MUST return this result and not + // # attempt to decrypt any more encrypted data keys. + verify(client, times((1))) + .decrypt( + DecryptRequest.builder() + .overrideConfiguration( + builder -> builder.addApiName(AwsKmsMrkAwareMasterKey.API_NAME)) + .grantTokens(GRANT_TOKENS) + .encryptionContext(ENCRYPTION_CONTEXT) + .keyId(identifier) + .ciphertextBlob(SdkBytes.fromByteArray(cipherText)) + .build()); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # The output MUST be the same as the Master Key Provider Decrypt Data + // # Key (../master-key-provider-interface.md#decrypt-data-key) interface. + assertTrue(DataKey.class.isInstance(test)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # The set of encrypted data keys MUST first be filtered to match this + // # master key's configuration. + public void only_if_providers_match() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final EncryptedDataKey edk = + new KeyBlob( + "not-aws-kms", "not the identifier".getBytes(StandardCharsets.UTF_8), new byte[10]); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildStrict(identifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # To match the encrypted data key's + // # provider ID MUST exactly match the value "aws-kms". + final CannotUnwrapDataKeyException test = + assertThrows( + "Unable to decrypt any data keys", + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(edk), ENCRYPTION_CONTEXT)); + assertEquals(0, test.getSuppressed().length); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # Additionally + // # each provider info MUST be a valid AWS KMS ARN (aws-kms-key-arn.md#a- + // # valid-aws-kms-arn) with a resource type of "key". + public void provider_info_must_be_arn() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String aliasArn = + "arn:aws:kms:us-west-2:111122223333:alias/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final EncryptedDataKey edk = + new KeyBlob("aws-kms", aliasArn.getBytes(StandardCharsets.UTF_8), new byte[10]); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildStrict(identifier); + + final IllegalStateException test = + assertThrows( + "Invalid provider info in message.", + IllegalStateException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(edk), ENCRYPTION_CONTEXT)); + assertEquals(0, test.getSuppressed().length); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # If this attempt results in an error, then + // # these errors MUST be collected. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.9 + // = type=test + // # If all the input encrypted data keys have been processed then this + // # function MUST yield an error that includes all the collected errors. + public void exception_wrapped() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final EncryptedDataKey edk = + new KeyBlob("aws-kms", identifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + final KmsClient client = mock(KmsClient.class); + final String clientErrMsg = "asdf"; + when(client.decrypt((DecryptRequest) any())) + .thenThrow(AwsServiceException.builder().message(clientErrMsg).build()); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(identifier); + + CannotUnwrapDataKeyException test = + assertThrows( + "Unable to decrypt any data keys", + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(edk), ENCRYPTION_CONTEXT)); + assertEquals(1, test.getSuppressed().length); + Throwable fromMasterKey = Arrays.stream(test.getSuppressed()).findFirst().get(); + assertTrue(fromMasterKey instanceof CannotUnwrapDataKeyException); + assertEquals(1, fromMasterKey.getSuppressed().length); + Throwable fromClient = Arrays.stream(fromMasterKey.getSuppressed()).findFirst().get(); + assertTrue(fromClient instanceof AwsServiceException); + assertTrue(fromClient.getMessage().startsWith(clientErrMsg)); + } + } + + public static class clientFactory { + @Test + public void basic_use() { + final ConcurrentHashMap cache = spy(new ConcurrentHashMap<>()); + final Region region = Region.of("asdf"); + final KmsClient test = + AwsKmsMrkAwareMasterKeyProvider.Builder.clientFactory(cache, null).getClient(region); + assertNotEquals(null, test); + verify(cache, times(1)).containsKey(region); + } + + @Test + @DisplayName("Check for early return (Postcondition): If a client already exists, use that.") + public void use_clients_that_exist() { + final Region region = Region.of("asdf"); + final ConcurrentHashMap cache = spy(new ConcurrentHashMap<>()); + // Add something so we can verify that we get it + final KmsClient client = mock(KmsClient.class); + cache.put(region, client); + + final KmsClient test = + AwsKmsMrkAwareMasterKeyProvider.Builder.clientFactory(cache, null).getClient(region); + + assertEquals(client, test); + } + + @Test + public void uses_builder_supplier() { + final ConcurrentHashMap cache = spy(new ConcurrentHashMap<>()); + final Region region = Region.of("asdf"); + + KmsClientBuilder builder = mock(KmsClientBuilder.class); + KmsClient client = mock(KmsClient.class); + ClientOverrideConfiguration.Builder overrideBuilder = + mock(ClientOverrideConfiguration.Builder.class); + + when(builder.region(any())).thenReturn(builder); + when(builder.build()).thenReturn(client); + doAnswer( + ans -> { + Consumer consumer = ans.getArgument(0); + consumer.accept(overrideBuilder); + return builder; + }) + .when(builder) + .overrideConfiguration((Consumer) any()); + + final KmsClient test = + AwsKmsMrkAwareMasterKeyProvider.Builder.clientFactory(cache, () -> builder) + .getClient(region); + + verify(builder, times(1)).build(); + verify(overrideBuilder, times(1)).addExecutionInterceptor(any()); + assertEquals(client, test); + } + } + + public static class getMasterKeysForEncryption { + @Test + public void basic_use() { + final String identifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final KmsClient client = spy(new MockKmsClient()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(Region.US_WEST_2)).thenReturn(client); + final MasterKeyRequest request = MasterKeyRequest.newBuilder().build(); + + final AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder() + .defaultRegion(Region.US_WEST_2) + .customRegionalClientSupplier(supplier) + .buildStrict(identifier); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // = type=test + // # The input MUST be the same as the Master Key Provider Get Master Keys + // # For Encryption (../master-key-provider-interface.md#get-master-keys- + // # for-encryption) interface. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // = type=test + // # The output MUST be the same as the Master Key Provider Get Master + // # Keys For Encryption (../master-key-provider-interface.md#get-master- + // # keys-for-encryption) interface. + final List test = mkp.getMasterKeysForEncryption(request); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // = type=test + // # If the configured mode is strict this function MUST return a + // # list of master keys obtained by calling Get Master Key (aws-kms-mrk- + // # aware-master-key-provider.md#get-master-key) for each AWS KMS key + // # identifier in the configured key ids + assertEquals(1, test.size()); + assertEquals(identifier, test.get(0).getKeyId()); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.8 + // = type=test + // # If the configured mode is discovery the function MUST return an empty + // # list. + public void no_keys_is_empty_list() { + final AwsKmsMrkAwareMasterKeyProvider mkp = + AwsKmsMrkAwareMasterKeyProvider.builder().buildDiscovery(); + + final List test = + mkp.getMasterKeysForEncryption(MasterKeyRequest.newBuilder().build()); + assertEquals(0, test.size()); + } + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyTest.java new file mode 100644 index 000000000..1d5a3f1b1 --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyTest.java @@ -0,0 +1,924 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.model.KeyBlob; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.jupiter.api.DisplayName; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.*; + +@RunWith(Enclosed.class) +public class AwsKmsMrkAwareMasterKeyTest { + + public static class getInstance { + + @Test + public void basic_use() { + KmsClient client = spy(new MockKmsClient()); + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=test + // # On initialization, the caller MUST provide: + final AwsKmsMrkAwareMasterKey test = + AwsKmsMrkAwareMasterKey.getInstance( + client, + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + mkp); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.5 + // = type=test + // # MUST implement the Master Key Interface (../master-key- + // # interface.md#interface) + assertTrue(MasterKey.class.isInstance(test)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=test + // # The AWS KMS key identifier MUST NOT be null or empty. + public void requires_valid_identifiers() { + KmsClient client = spy(new MockKmsClient()); + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + + assertThrows( + IllegalArgumentException.class, + () -> AwsKmsMrkAwareMasterKey.getInstance(client, "", mkp)); + assertThrows( + IllegalArgumentException.class, + () -> AwsKmsMrkAwareMasterKey.getInstance(client, null, mkp)); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=test + // # The AWS KMS + // # key identifier MUST be a valid identifier (aws-kms-key-arn.md#a- + // # valid-aws-kms-identifier). + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKey.getInstance( + client, "arn:aws:dynamodb:us-east-2:123456789012:table/myDynamoDBTable", mkp)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=test + // # The AWS KMS SDK client MUST not be null. + public void requires_valid_client() { + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKey.getInstance( + null, + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + mkp)); + } + + @Test + @DisplayName("Precondition: A provider is required.") + public void requires_valid_provider() { + KmsClient client = spy(new MockKmsClient()); + + assertThrows( + IllegalArgumentException.class, + () -> + AwsKmsMrkAwareMasterKey.getInstance( + client, + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + null)); + } + } + + public static class generateDataKey { + + @Test + public void basic_use() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + + final KmsClient client = mock(KmsClient.class); + when(client.generateDataKey((GenerateDataKeyRequest) any())) + .thenReturn( + GenerateDataKeyResponse.builder() + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .keyId(keyIdentifier) + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.6 + // = type=test + // # The master key MUST be able to be configured with an optional list of + // # Grant Tokens. + masterKey.setGrantTokens(GRANT_TOKENS); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # The inputs MUST be the same as the Master Key Generate Data Key + // # (../master-key-interface.md#generate-data-key) interface. + DataKey test = + masterKey.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT); + ArgumentCaptor gr = + ArgumentCaptor.forClass(GenerateDataKeyRequest.class); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # This + // # master key MUST use the configured AWS KMS client to make an AWS KMS + // # GenerateDatakey (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_GenerateDataKey.html) request constructed as follows: + verify(client, times(1)).generateDataKey(gr.capture()); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # The output MUST be the same as the Master Key Generate Data Key + // # (../master-key-interface.md#generate-data-key) interface. + assertTrue(DataKey.class.isInstance(test)); + + GenerateDataKeyRequest actualRequest = gr.getValue(); + + assertEquals(keyIdentifier, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertEquals(ALGORITHM_SUITE.getDataKeyLength(), actualRequest.numberOfBytes().longValue()); + assertTrue(actualRequest.overrideConfiguration().isPresent()); + assertTrue( + actualRequest + .overrideConfiguration() + .get() + .apiNames() + .contains(AwsKmsMrkAwareMasterKey.API_NAME)); + + assertNotNull(test.getKey()); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # The response's "Plaintext" MUST be the plaintext in + // # the output. + assertEquals(ALGORITHM_SUITE.getDataKeyLength(), test.getKey().getEncoded().length); + assertEquals(ALGORITHM_SUITE.getDataKeyAlgo(), test.getKey().getAlgorithm()); + assertNotNull(test.getEncryptedDataKey()); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # The response's cipher text blob MUST be used as the + // # returned as the ciphertext for the encrypted data key in the output. + assertEquals(10, test.getEncryptedDataKey().length); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # If the call succeeds the AWS KMS Generate Data Key response's + // # "Plaintext" MUST match the key derivation input length specified by + // # the algorithm suite included in the input. + public void length_must_match() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + // I use more, because less _should_ trigger an underflow... but the condition should _always_ + // fail + final int wrongLength = ALGORITHM_SUITE.getDataKeyLength() + 1; + + final KmsClient client = mock(KmsClient.class); + when(client.generateDataKey((GenerateDataKeyRequest) any())) + .thenReturn( + GenerateDataKeyResponse.builder() + .plaintext(SdkBytes.fromByteArray(new byte[wrongLength])) + .keyId(keyIdentifier) + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + + assertThrows( + IllegalStateException.class, + () -> masterKey.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT)); + } + + @Test + @DisplayName( + "Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey.") + public void need_an_arn() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + + final KmsClient client = mock(KmsClient.class); + when(client.generateDataKey((GenerateDataKeyRequest) any())) + .thenReturn( + GenerateDataKeyResponse.builder() + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10 + // = type=test + // # The response's "KeyId" + // # MUST be valid. + .keyId("b3537ef1-d8dc-4780-9f5a-55776cbb2f7f") + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + + assertThrows( + IllegalStateException.class, + () -> masterKey.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT)); + } + } + + public static class encryptDataKey { + @Test + public void basic_use() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final SecretKey SECRET_KEY = + new SecretKeySpec( + generate(ALGORITHM_SUITE.getDataKeyLength()), ALGORITHM_SUITE.getDataKeyAlgo()); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + + final DataKey dataKey = + new DataKey( + SECRET_KEY, + new byte[0], + "aws-kms".getBytes(StandardCharsets.UTF_8), + mock(MasterKey.class)); + + final KmsClient client = mock(KmsClient.class); + when(client.encrypt((EncryptRequest) any())) + .thenReturn( + EncryptResponse.builder() + .keyId(keyIdentifier) + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // = type=test + // # The inputs MUST be the same as the Master Key Encrypt Data Key + // # (../master-key-interface.md#encrypt-data-key) interface. + DataKey test = + masterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // = type=test + // # The output MUST be the same as the Master Key Encrypt Data Key + // # (../master-key-interface.md#encrypt-data-key) interface. + assertTrue(DataKey.class.isInstance(test)); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // = type=test + // # The master + // # key MUST use the configured AWS KMS client to make an AWS KMS Encrypt + // # (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_Encrypt.html) request constructed as follows: + verify(client, times(1)).encrypt((EncryptRequest) any()); + ArgumentCaptor gr = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(gr.capture()); + + final EncryptRequest actualRequest = gr.getValue(); + + assertEquals(keyIdentifier, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertTrue(actualRequest.overrideConfiguration().isPresent()); + assertTrue( + actualRequest + .overrideConfiguration() + .get() + .apiNames() + .contains(AwsKmsMrkAwareMasterKey.API_NAME)); + + assertNotNull(test.getKey()); + assertEquals(ALGORITHM_SUITE.getDataKeyLength(), test.getKey().getEncoded().length); + assertEquals(ALGORITHM_SUITE.getDataKeyAlgo(), test.getKey().getAlgorithm()); + assertNotNull(test.getEncryptedDataKey()); + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // = type=test + // # The + // # response's cipher text blob MUST be used as the "ciphertext" for the + // # encrypted data key. + assertEquals(10, test.getEncryptedDataKey().length); + } + + @Test + @DisplayName("Precondition: The key format MUST be RAW.") + public void secret_key_must_be_raw() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + + // Test "stuff" here + final SecretKey SECRET_KEY = mock(SecretKeySpec.class); + when(SECRET_KEY.getFormat()).thenReturn("NOT-RAW"); + + final DataKey dataKey = + new DataKey( + SECRET_KEY, + new byte[0], + "aws-kms".getBytes(StandardCharsets.UTF_8), + mock(MasterKey.class)); + + final KmsClient client = mock(KmsClient.class); + when(client.encrypt((EncryptRequest) any())) + .thenReturn( + EncryptResponse.builder() + .keyId(keyIdentifier) + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + assertThrows( + "Only RAW encoded keys are supported", + IllegalArgumentException.class, + () -> masterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey)); + } + + @Test + @DisplayName("Postcondition: Must have an AWS KMS ARN from AWS KMS encrypt.") + public void need_an_arn() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final SecretKey SECRET_KEY = + new SecretKeySpec( + generate(ALGORITHM_SUITE.getDataKeyLength()), ALGORITHM_SUITE.getDataKeyAlgo()); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn("aws-kms"); + + final DataKey dataKey = + new DataKey( + SECRET_KEY, + new byte[0], + "aws-kms".getBytes(StandardCharsets.UTF_8), + mock(MasterKey.class)); + + final KmsClient client = mock(KmsClient.class); + when(client.encrypt((EncryptRequest) any())) + .thenReturn( + EncryptResponse.builder() + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 + // = type=test + // # The AWS KMS Encrypt response MUST contain a valid "KeyId". + .keyId("b3537ef1-d8dc-4780-9f5a-55776cbb2f7f") + .ciphertextBlob(SdkBytes.fromByteArray(new byte[10])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + assertThrows( + IllegalStateException.class, + () -> masterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey)); + } + } + + public static class filterEncryptedDataKeys { + @Test + public void basic_use() { + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + assertTrue(AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys(providerId, keyIdentifier, edk)); + } + + @Test + public void mrk_specific() { + /* This may be overkill, + * but the whole point + * of multi-region optimization + * is this fuzzy match. + */ + final String configuredIdentifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String ekdIdentifier = + "arn:aws:kms:us-east-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, ekdIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + assertTrue( + AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys(providerId, configuredIdentifier, edk)); + } + + @Test + public void provider_info_must_be_arn() { + final String configuredIdentifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String rawKeyId = "mrk-edb7fe6942894d32ac46dbb1c922d574"; + final String alias = + "arn:aws:kms:us-west-2:111122223333:alias/mrk-edb7fe6942894d32ac46dbb1c922d574"; + + final String providerId = "aws-kms"; + final EncryptedDataKey edkNotArn = + new KeyBlob(providerId, rawKeyId.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final EncryptedDataKey edkAliasArn = + new KeyBlob(providerId, rawKeyId.getBytes(StandardCharsets.UTF_8), new byte[10]); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # Additionally each provider info MUST be a valid AWS KMS ARN + // # (aws-kms-key-arn.md#a-valid-aws-kms-arn) with a resource type of + // # "key". + assertThrows( + IllegalStateException.class, + () -> + AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys( + providerId, configuredIdentifier, edkNotArn)); + assertThrows( + IllegalStateException.class, + () -> + AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys( + providerId, configuredIdentifier, edkAliasArn)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # To match the encrypted data key's + // # provider ID MUST exactly match the value "aws-kms" and the the + // # function AWS KMS MRK Match for Decrypt (aws-kms-mrk-match-for- + // # decrypt.md#implementation) called with the configured AWS KMS key + // # identifier and the encrypted data key's provider info MUST return + // # "true". + public void may_not_match() { + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + assertFalse( + AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys("not-aws-kms", keyIdentifier, edk)); + + assertFalse( + AwsKmsMrkAwareMasterKey.filterEncryptedDataKeys( + providerId, + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574", + edk)); + } + } + + public static class decryptSingleEncryptedDataKey { + @Test + public void basic_use() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId(keyIdentifier) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + DataKey test = + AwsKmsMrkAwareMasterKey.decryptSingleEncryptedDataKey( + any(), client, keyIdentifier, GRANT_TOKENS, ALGORITHM_SUITE, edk, ENCRYPTION_CONTEXT); + + verify(client, times(1)).decrypt((DecryptRequest) any()); + ArgumentCaptor gr = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(gr.capture()); + + final DecryptRequest actualRequest = gr.getValue(); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # To decrypt the encrypted data key this master key MUST use the + // # configured AWS KMS client to make an AWS KMS Decrypt + // # (https://docs.aws.amazon.com/kms/latest/APIReference/ + // # API_Decrypt.html) request constructed as follows: + assertEquals(keyIdentifier, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertTrue(actualRequest.overrideConfiguration().isPresent()); + assertTrue( + actualRequest + .overrideConfiguration() + .get() + .apiNames() + .contains(AwsKmsMrkAwareMasterKey.API_NAME)); + + assertNotNull(test.getKey()); + assertEquals(ALGORITHM_SUITE.getDataKeyLength(), test.getKey().getEncoded().length); + assertEquals(ALGORITHM_SUITE.getDataKeyAlgo(), test.getKey().getAlgorithm()); + } + + @Test + @DisplayName("Exceptional Postcondition: Must have a CMK ARN from AWS KMS to match.") + public void expect_key_arn() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId(null) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + assertThrows( + IllegalStateException.class, + () -> + AwsKmsMrkAwareMasterKey.decryptSingleEncryptedDataKey( + any(), + client, + keyIdentifier, + GRANT_TOKENS, + ALGORITHM_SUITE, + edk, + ENCRYPTION_CONTEXT)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # If the call succeeds then the response's "KeyId" MUST be equal to the + // # configured AWS KMS key identifier otherwise the function MUST collect + // # an error. + public void returned_arn_must_match() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId("arn:aws:kms:us-west-2:658956600833:key/something-else") + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + assertThrows( + IllegalStateException.class, + () -> + AwsKmsMrkAwareMasterKey.decryptSingleEncryptedDataKey( + any(), + client, + keyIdentifier, + GRANT_TOKENS, + ALGORITHM_SUITE, + edk, + ENCRYPTION_CONTEXT)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # The response's "Plaintext"'s length MUST equal the length + // # required by the requested algorithm suite otherwise the function MUST + // # collect an error. + public void key_length_must_match() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + // I use more, because less _should_ trigger an underflow... but the condition should _always_ + // fail + final int wrongLength = ALGORITHM_SUITE.getDataKeyLength() + 1; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId(keyIdentifier) + .plaintext(SdkBytes.fromByteArray(new byte[wrongLength])) + .build()); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + assertThrows( + IllegalStateException.class, + () -> + AwsKmsMrkAwareMasterKey.decryptSingleEncryptedDataKey( + any(), + client, + keyIdentifier, + GRANT_TOKENS, + ALGORITHM_SUITE, + edk, + ENCRYPTION_CONTEXT)); + } + } + + public static class decryptDataKey { + + @Test + public void basic_use() { + final String keyIdentifier = + "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"; + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final byte[] cipherText = new byte[10]; + final String providerId = "aws-kms"; + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final EncryptedDataKey edk1 = + new KeyBlob("aws-kms", keyIdentifier.getBytes(StandardCharsets.UTF_8), cipherText); + final EncryptedDataKey edk2 = + new KeyBlob("aws-kms", keyIdentifier.getBytes(StandardCharsets.UTF_8), cipherText); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenReturn( + DecryptResponse.builder() + .keyId(keyIdentifier) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build()); + + final AwsKmsMrkAwareMasterKey mk = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + mk.setGrantTokens(GRANT_TOKENS); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # The inputs MUST be the same as the Master Key Decrypt Data Key + // # (../master-key-interface.md#decrypt-data-key) interface. + final DataKey test = + mk.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(edk1, edk2), ENCRYPTION_CONTEXT); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # For each encrypted data key in the filtered set, one at a time, the + // # master key MUST attempt to decrypt the data key. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # If the AWS KMS response satisfies the requirements then it MUST be + // # use and this function MUST return and not attempt to decrypt any more + // # encrypted data keys. + verify(client, times((1))) + .decrypt( + DecryptRequest.builder() + .overrideConfiguration( + builder -> builder.addApiName(AwsKmsMrkAwareMasterKey.API_NAME)) + .grantTokens(GRANT_TOKENS) + .encryptionContext(ENCRYPTION_CONTEXT) + .keyId(keyIdentifier) + .ciphertextBlob(SdkBytes.fromByteArray(cipherText)) + .build()); + + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # The output MUST be the same as the Master Key Decrypt Data Key + // # (../master-key-interface.md#decrypt-data-key) interface. + assertTrue(DataKey.class.isInstance(test)); + } + + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # The set of encrypted data keys MUST first be filtered to match this + // # master key's configuration. + public void edk_match() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final String clientErrMsg = "asdf"; + final EncryptedDataKey edk1 = + new KeyBlob("not-aws-kms", keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final EncryptedDataKey edk2 = + new KeyBlob( + providerId, "not-key-identifier".getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenThrow(AwsServiceException.builder().message(clientErrMsg).build()); + final RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + final AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + masterKey.setGrantTokens(GRANT_TOKENS); + + final CannotUnwrapDataKeyException testProviderNotMatch = + assertThrows( + "Unable to decrypt any data keys", + CannotUnwrapDataKeyException.class, + () -> + masterKey.decryptDataKey( + ALGORITHM_SUITE, Arrays.asList(edk1), ENCRYPTION_CONTEXT)); + assertEquals(0, testProviderNotMatch.getSuppressed().length); + + final IllegalStateException testArnNotMatch = + assertThrows( + "Unable to decrypt any data keys", + IllegalStateException.class, + () -> + masterKey.decryptDataKey( + ALGORITHM_SUITE, Arrays.asList(edk2), ENCRYPTION_CONTEXT)); + assertEquals(0, testArnNotMatch.getSuppressed().length); + } + + @Test + @DisplayName("Exceptional Postcondition: Master key was unable to decrypt.") + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # If this attempt + // # results in an error, then these errors MUST be collected. + // + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 + // = type=test + // # If all the input encrypted data keys have been processed then this + // # function MUST yield an error that includes all the collected errors. + public void exception_wrapped() { + final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); + final String keyIdentifier = + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; + final String providerId = "aws-kms"; + final String clientErrMsg = "asdf"; + final EncryptedDataKey edk = + new KeyBlob(providerId, keyIdentifier.getBytes(StandardCharsets.UTF_8), new byte[10]); + + final MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(providerId); + + final KmsClient client = mock(KmsClient.class); + when(client.decrypt((DecryptRequest) any())) + .thenThrow(AwsServiceException.builder().message(clientErrMsg).build()); + + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + AwsKmsMrkAwareMasterKey masterKey = + AwsKmsMrkAwareMasterKey.getInstance(client, keyIdentifier, mkp); + + masterKey.setGrantTokens(GRANT_TOKENS); + + final CannotUnwrapDataKeyException test = + assertThrows( + "Unable to decrypt any data keys", + CannotUnwrapDataKeyException.class, + () -> + masterKey.decryptDataKey( + ALGORITHM_SUITE, Arrays.asList(edk), ENCRYPTION_CONTEXT)); + assertEquals(1, test.getSuppressed().length); + Throwable fromClient = Arrays.stream(test.getSuppressed()).findFirst().get(); + assertTrue(fromClient instanceof AwsServiceException); + assertTrue(fromClient.getMessage().startsWith(clientErrMsg)); + } + } + + public static class getMasterKey { + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.7 + // = type=test + // # MUST be unchanged from the Master Key interface. + public void test_get_master_key() throws NoSuchMethodException { + String methodName = "getMasterKey"; + Class[] parameterTypes = new Class[] {String.class, String.class}; + // Make sure the signature is correct by fetching the base method + Method baseMethod = MasterKey.class.getDeclaredMethod(methodName, parameterTypes); + assertNotNull(baseMethod); + // Assert AwsKmsMrkAwareMasterKey does not declare the same method directly + assertThrows( + NoSuchMethodException.class, + () -> AwsKmsMrkAwareMasterKey.class.getDeclaredMethod(methodName, parameterTypes)); + } + } + + public static class getMasterKeysForEncryption { + @Test + // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.8 + // = type=test + // # MUST be unchanged from the Master Key interface. + public void test_getMasterKeysForEncryption() throws NoSuchMethodException { + String methodName = "getMasterKeysForEncryption"; + Class[] parameterTypes = new Class[] {MasterKeyRequest.class}; + + // Make sure the signature is correct by fetching the base method + Method baseMethod = MasterKey.class.getDeclaredMethod(methodName, parameterTypes); + assertNotNull(baseMethod); + // Assert AwsKmsMrkAwareMasterKey does no declare the same method directly + assertThrows( + NoSuchMethodException.class, + () -> AwsKmsMrkAwareMasterKey.class.getDeclaredMethod(methodName, parameterTypes)); + } + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderIntegrationTests.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderIntegrationTests.java new file mode 100644 index 000000000..827c1fe5e --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderIntegrationTests.java @@ -0,0 +1,472 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; +import com.amazonaws.encryptionsdk.model.KeyBlob; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.awscore.AwsRequest; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.core.ApiName; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.exception.ApiCallAttemptTimeoutException; +import software.amazon.awssdk.core.exception.ApiCallTimeoutException; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.EncryptRequest; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyRequest; + +public class KMSProviderBuilderIntegrationTests { + + private static final String AWS_KMS_PROVIDER_ID = "aws-kms"; + + private KmsClient testUSWestClient__; + private KmsClient testEUCentralClient__; + private RegionalClientSupplier testClientSupplier__; + + @Before + public void setup() { + testUSWestClient__ = + spy(new ProxyKmsClient(KmsClient.builder().region(Region.US_WEST_2).build())); + testEUCentralClient__ = + spy(new ProxyKmsClient(KmsClient.builder().region(Region.EU_CENTRAL_1).build())); + testClientSupplier__ = + region -> { + if (region == Region.US_WEST_2) { + return testUSWestClient__; + } else if (region == Region.EU_CENTRAL_1) { + return testEUCentralClient__; + } else { + throw new AwsCryptoException( + "test supplier only configured for us-west-2 and eu-central-1"); + } + }; + } + + @Test + public void whenBogusRegionsDecrypted_doesNotLeakClients() throws Exception { + AtomicReference> kmsCache = new AtomicReference<>(); + + KmsMasterKeyProvider mkp = + (new KmsMasterKeyProvider.Builder() { + @Override + protected void snoopClientCache(final ConcurrentHashMap map) { + kmsCache.set(map); + } + }) + .buildDiscovery(); + + try { + mkp.decryptDataKey( + CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256, + Collections.singleton( + new KeyBlob( + "aws-kms", + "arn:aws:kms:us-bogus-1:123456789010:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + .getBytes(StandardCharsets.UTF_8), + new byte[40])), + new HashMap<>()); + fail("Expected CannotUnwrapDataKeyException"); + } catch (CannotUnwrapDataKeyException e) { + // ok + } + + assertTrue(kmsCache.get().isEmpty()); + } + + @Test + public void whenOperationSuccessful_clientIsCached() { + AtomicReference> kmsCache = new AtomicReference<>(); + + KmsMasterKeyProvider mkp = + (new KmsMasterKeyProvider.Builder() { + @Override + protected void snoopClientCache(final ConcurrentHashMap map) { + kmsCache.set(map); + } + }) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + AwsCrypto.standard().encryptData(mkp, new byte[1]); + + KmsClient kms = kmsCache.get().get(Region.US_WEST_2); + assertNotNull(kms); + + AwsCrypto.standard().encryptData(mkp, new byte[1]); + + // Cache entry should stay the same + assertEquals(kms, kmsCache.get().get(Region.US_WEST_2)); + } + + // ============================================================================== GOOD + + @Test + public void whenConstructedWithoutArguments_canUseMultipleRegions() throws Exception { + KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder().buildDiscovery(); + + for (String key : KMSTestFixtures.TEST_KEY_IDS) { + byte[] ciphertext = + AwsCrypto.standard() + .encryptData(KmsMasterKeyProvider.builder().buildStrict(key), new byte[1]) + .getResult(); + + AwsCrypto.standard().decryptData(mkp, ciphertext); + } + } + + @Test + public void whenConstructedInStrictMode_encryptDecrypt() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + byte[] ciphertext = AwsCrypto.standard().encryptData(mkp, new byte[1]).getResult(); + verify(testUSWestClient__, times(1)).generateDataKey((GenerateDataKeyRequest) any()); + + AwsCrypto.standard().decryptData(mkp, ciphertext); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedInStrictMode_encryptDecryptMultipleCmks() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildStrict(KMSTestFixtures.US_WEST_2_KEY_ID, KMSTestFixtures.EU_CENTRAL_1_KEY_ID); + + byte[] ciphertext = AwsCrypto.standard().encryptData(mkp, new byte[1]).getResult(); + verify(testUSWestClient__, times(1)).generateDataKey((GenerateDataKeyRequest) any()); + verify(testEUCentralClient__, times(1)).encrypt((EncryptRequest) any()); + + AwsCrypto.standard().decryptData(mkp, ciphertext); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedInStrictMode_encryptSingleBadKeyIdFails() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .defaultRegion(Region.US_WEST_2) + .buildStrict(KMSTestFixtures.US_WEST_2_KEY_ID, "badKeyId"); + + assertThrows( + AwsCryptoException.class, + () -> AwsCrypto.standard().encryptData(mkp, new byte[1]).getResult()); + verify(testUSWestClient__, times(1)).generateDataKey((GenerateDataKeyRequest) any()); + verify(testUSWestClient__, times(1)).encrypt((EncryptRequest) any()); + } + + @Test + public void whenConstructedInStrictMode_decryptBadEDKFails() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .defaultRegion(Region.US_WEST_2) + .buildStrict("badKeyId"); + + final CryptoAlgorithm algSuite = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map encCtx = Collections.singletonMap("myKey", "myValue"); + final EncryptedDataKey badEDK = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + "badKeyId".getBytes(StandardCharsets.UTF_8), + new byte[algSuite.getDataKeyLength()]); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(algSuite, Collections.singletonList(badEDK), encCtx)); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedInDiscoveryMode_decrypt() throws Exception { + KmsMasterKeyProvider singleCmkMkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + byte[] singleCmkCiphertext = + AwsCrypto.standard().encryptData(singleCmkMkp, new byte[1]).getResult(); + + KmsMasterKeyProvider mkpToTest = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildDiscovery(); + AwsCrypto.standard().decryptData(mkpToTest, singleCmkCiphertext); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedInDiscoveryMode_decryptBadEDKFails() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .defaultRegion(Region.US_WEST_2) + .buildDiscovery(); + + final CryptoAlgorithm algSuite = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map encCtx = Collections.singletonMap("myKey", "myValue"); + final EncryptedDataKey badEDK = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + "badKeyId".getBytes(StandardCharsets.UTF_8), + new byte[algSuite.getDataKeyLength()]); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(algSuite, Collections.singletonList(badEDK), encCtx)); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedWithDiscoveryFilter_decrypt() throws Exception { + KmsMasterKeyProvider singleCmkMkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + byte[] singleCmkCiphertext = + AwsCrypto.standard().encryptData(singleCmkMkp, new byte[1]).getResult(); + + KmsMasterKeyProvider mkpToTest = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .buildDiscovery( + new DiscoveryFilter( + KMSTestFixtures.PARTITION, Arrays.asList(KMSTestFixtures.ACCOUNT_ID))); + + AwsCrypto.standard().decryptData(mkpToTest, singleCmkCiphertext); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenConstructedWithDiscoveryFilter_decryptBadEDKFails() throws Exception { + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier__) + .defaultRegion(Region.US_WEST_2) + .buildDiscovery( + new DiscoveryFilter( + KMSTestFixtures.PARTITION, Arrays.asList(KMSTestFixtures.ACCOUNT_ID))); + + final CryptoAlgorithm algSuite = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + final Map encCtx = Collections.singletonMap("myKey", "myValue"); + final String badARN = "arn:aws:kms:us-west-2:658956600833:key/badID"; + final EncryptedDataKey badEDK = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + badARN.getBytes(StandardCharsets.UTF_8), + new byte[algSuite.getDataKeyLength()]); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(algSuite, Collections.singletonList(badEDK), encCtx)); + verify(testUSWestClient__, times(1)).decrypt((DecryptRequest) any()); + } + + @Test + public void whenHandlerConfigured_handlerIsInvoked() throws Exception { + ExecutionInterceptor interceptor = + spy( + new ExecutionInterceptor() { + @Override + public void beforeExecution( + Context.BeforeExecution context, ExecutionAttributes executionAttributes) {} + }); + + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .builderSupplier( + () -> + KmsClient.builder() + .overrideConfiguration( + ClientOverrideConfiguration.builder() + .addExecutionInterceptor(interceptor) + .build())) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + AwsCrypto.standard().encryptData(mkp, new byte[1]); + + verify(interceptor).beforeExecution(any(), any()); + } + + @Test + public void whenShortTimeoutSet_timesOut() throws Exception { + // By setting a timeout of 1ms, it's not physically possible to complete both the us-west-2 and + // eu-central-1 + // requests due to speed of light limits. + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .builderSupplier( + () -> + KmsClient.builder() + .overrideConfiguration( + ClientOverrideConfiguration.builder() + .apiCallTimeout(Duration.ofMillis(1)) + .build())) + .buildStrict(Arrays.asList(KMSTestFixtures.TEST_KEY_IDS)); + + try { + AwsCrypto.standard().encryptData(mkp, new byte[1]); + fail("Expected exception"); + } catch (Exception e) { + if (!(e instanceof ApiCallAttemptTimeoutException) + && !(e instanceof ApiCallTimeoutException)) { + throw e; + } + } + } + + // ================================================= BAD + + @Test + public void whenBuilderCloned_configurationIsRetained() throws Exception { + // TODO: remove test of credentials provider since no longer domain of builder supplier + AwsCredentialsProvider customProvider1 = + spy(new ProxyCredentialsProvider(DefaultCredentialsProvider.builder().build())); + AwsCredentialsProvider customProvider2 = + spy(new ProxyCredentialsProvider(DefaultCredentialsProvider.builder().build())); + + KmsMasterKeyProvider.Builder builder = + KmsMasterKeyProvider.builder() + .builderSupplier(() -> KmsClient.builder().credentialsProvider(customProvider1)); + + KmsMasterKeyProvider.Builder builder2 = builder.clone(); + + // This will mutate the first builder to change the creds, but leave the clone unchanged. + MasterKeyProvider mkp2 = + builder + .builderSupplier(() -> KmsClient.builder().credentialsProvider(customProvider2)) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + MasterKeyProvider mkp1 = builder2.buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + CryptoResult result = AwsCrypto.standard().encryptData(mkp1, new byte[0]); + + verify(customProvider1, atLeastOnce()).resolveCredentials(); + verify(customProvider2, never()).resolveCredentials(); + + reset(customProvider1, customProvider2); + + result = AwsCrypto.standard().encryptData(mkp2, new byte[0]); + + verify(customProvider1, never()).resolveCredentials(); + verify(customProvider2, atLeastOnce()).resolveCredentials(); + } + + @Test + public void whenBuilderCloned_clientBuilderCustomizationIsRetained() throws Exception { + ExecutionInterceptor interceptor = + spy( + new ExecutionInterceptor() { + @Override + public void beforeExecution( + Context.BeforeExecution context, ExecutionAttributes executionAttributes) {} + }); + + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .builderSupplier( + () -> + KmsClient.builder() + .overrideConfiguration( + builder -> builder.addExecutionInterceptor(interceptor))) + .clone() + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + AwsCrypto.standard().encryptData(mkp, new byte[0]); + + verify(interceptor, atLeastOnce()).beforeExecution(any(), any()); + } + + @Test + public void whenUserAgentsOverridden_originalUAsPreserved() throws Exception { + ExecutionInterceptor interceptor = + spy( + new ExecutionInterceptor() { + @Override + public SdkRequest modifyRequest( + Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + if (!(context.request() instanceof AwsRequest)) { + return context.request(); + } + + AwsRequest awsRequest = (AwsRequest) context.request(); + AwsRequestOverrideConfiguration.Builder overrideConfiguration; + if (awsRequest.overrideConfiguration().isPresent()) { + overrideConfiguration = awsRequest.overrideConfiguration().get().toBuilder(); + } else { + overrideConfiguration = AwsRequestOverrideConfiguration.builder(); + } + + AwsRequestOverrideConfiguration newConfig = + overrideConfiguration + .addApiName(ApiName.builder().name("NEW_API").version("0.0.1").build()) + .build(); + + awsRequest = awsRequest.toBuilder().overrideConfiguration(newConfig).build(); + return awsRequest; + } + + @Override + public void beforeTransmission( + Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + // Just for spying + } + }); + + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .builderSupplier( + () -> + KmsClient.builder() + .overrideConfiguration( + ClientOverrideConfiguration.builder() + .addExecutionInterceptor(interceptor) + .build())) + .buildStrict(KMSTestFixtures.TEST_KEY_IDS[0]); + + AwsCrypto.standard().encryptData(mkp, new byte[0]); + + verify(interceptor, atLeastOnce()).modifyRequest(any(), any()); + + ArgumentCaptor captor = + ArgumentCaptor.forClass(Context.BeforeTransmission.class); + verify(interceptor, atLeastOnce()).beforeTransmission(captor.capture(), any()); + + String ua = captor.getValue().httpRequest().headers().get("User-Agent").get(0); + + assertTrue(ua.contains("NEW_API/0.0.1")); + assertTrue(ua.contains(VersionInfo.loadUserAgent())); + } + + @Test + public void whenDefaultRegionSet_itIsUsedForBareKeyIds() throws Exception { + // TODO: Need to set up a role to assume as bare key IDs are relative to the caller account + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderMockTests.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderMockTests.java new file mode 100644 index 000000000..e3043719a --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KMSProviderBuilderMockTests.java @@ -0,0 +1,189 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.multi.MultipleProviderFactory.buildMultiProvider; +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.AwsCrypto; +import com.amazonaws.encryptionsdk.MasterKeyProvider; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import java.util.Arrays; +import java.util.Optional; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.awscore.AwsRequest; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.model.CreateAliasRequest; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.EncryptRequest; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyRequest; + +public class KMSProviderBuilderMockTests { + @Test + public void testBareAliasMapping() { + MockKmsClient client = spy(new MockKmsClient()); + + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(notNull())).thenReturn(client); + + String key1 = client.createKey().keyMetadata().keyId(); + client.createAlias(CreateAliasRequest.builder().aliasName("foo").targetKeyId(key1).build()); + + KmsMasterKeyProvider mkp0 = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .defaultRegion(Region.US_WEST_2) + .buildStrict("alias/foo"); + + AwsCrypto.standard().encryptData(mkp0, new byte[0]); + } + + @Test + public void testGrantTokenPassthrough_usingMKsetCall() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + String key1 = client.createKey().keyMetadata().arn(); + String key2 = client.createKey().keyMetadata().arn(); + + KmsMasterKeyProvider mkp0 = + KmsMasterKeyProvider.builder() + .defaultRegion(Region.US_WEST_2) + .customRegionalClientSupplier(supplier) + .buildStrict(key1, key2); + KmsMasterKey mk1 = mkp0.getMasterKey(key1); + KmsMasterKey mk2 = mkp0.getMasterKey(key2); + + mk1.setGrantTokens(singletonList("foo")); + mk2.setGrantTokens(singletonList("foo")); + + MasterKeyProvider mkp = buildMultiProvider(mk1, mk2); + + byte[] ciphertext = AwsCrypto.standard().encryptData(mkp, new byte[0]).getResult(); + + ArgumentCaptor gdkr = + ArgumentCaptor.forClass(GenerateDataKeyRequest.class); + verify(client, times(1)).generateDataKey(gdkr.capture()); + + assertEquals(key1, gdkr.getValue().keyId()); + assertEquals(1, gdkr.getValue().grantTokens().size()); + assertEquals("foo", gdkr.getValue().grantTokens().get(0)); + + ArgumentCaptor er = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(er.capture()); + + assertEquals(key2, er.getValue().keyId()); + assertEquals(1, er.getValue().grantTokens().size()); + assertEquals("foo", er.getValue().grantTokens().get(0)); + + AwsCrypto.standard().decryptData(mkp, ciphertext); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + + assertEquals(1, decrypt.getValue().grantTokens().size()); + assertEquals("foo", decrypt.getValue().grantTokens().get(0)); + + verify(supplier, atLeastOnce()).getClient(Region.US_WEST_2); + verifyNoMoreInteractions(supplier); + } + + @Test + public void testGrantTokenPassthrough_usingMKPWithers() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + String key1 = client.createKey().keyMetadata().arn(); + String key2 = client.createKey().keyMetadata().arn(); + + KmsMasterKeyProvider mkp0 = + KmsMasterKeyProvider.builder() + .defaultRegion(Region.US_WEST_2) + .customRegionalClientSupplier(supplier) + .buildStrict(key1, key2); + + MasterKeyProvider mkp = mkp0.withGrantTokens("foo"); + + byte[] ciphertext = AwsCrypto.standard().encryptData(mkp, new byte[0]).getResult(); + + ArgumentCaptor gdkr = + ArgumentCaptor.forClass(GenerateDataKeyRequest.class); + verify(client, times(1)).generateDataKey(gdkr.capture()); + + assertEquals(key1, gdkr.getValue().keyId()); + assertEquals(1, gdkr.getValue().grantTokens().size()); + assertEquals("foo", gdkr.getValue().grantTokens().get(0)); + + ArgumentCaptor er = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(er.capture()); + + assertEquals(key2, er.getValue().keyId()); + assertEquals(1, er.getValue().grantTokens().size()); + assertEquals("foo", er.getValue().grantTokens().get(0)); + + mkp = mkp0.withGrantTokens(Arrays.asList("bar")); + + AwsCrypto.standard().decryptData(mkp, ciphertext); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + + assertEquals(1, decrypt.getValue().grantTokens().size()); + assertEquals("bar", decrypt.getValue().grantTokens().get(0)); + + verify(supplier, atLeastOnce()).getClient(Region.US_WEST_2); + verifyNoMoreInteractions(supplier); + } + + @Test + public void testUserAgentPassthrough() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + + String key1 = client.createKey().keyMetadata().arn(); + String key2 = client.createKey().keyMetadata().arn(); + + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(ignored -> client) + .buildStrict(key1, key2); + + AwsCrypto.standard() + .decryptData(mkp, AwsCrypto.standard().encryptData(mkp, new byte[0]).getResult()); + + ArgumentCaptor gdkr = + ArgumentCaptor.forClass(GenerateDataKeyRequest.class); + verify(client, times(1)).generateDataKey(gdkr.capture()); + assertApiName(gdkr.getValue()); + + ArgumentCaptor encr = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(encr.capture()); + assertApiName(encr.getValue()); + + ArgumentCaptor decr = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decr.capture()); + assertApiName(decr.getValue()); + } + + private void assertApiName(AwsRequest request) { + Optional overrideConfig = request.overrideConfiguration(); + assertTrue(overrideConfig.isPresent()); + assertTrue( + overrideConfig.get().apiNames().stream() + .anyMatch( + api -> + api.name().equals(VersionInfo.apiName()) + && api.version().equals(VersionInfo.versionNumber()))); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProviderTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProviderTest.java new file mode 100644 index 000000000..6d89a55df --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProviderTest.java @@ -0,0 +1,521 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; +import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.DataKey; +import com.amazonaws.encryptionsdk.EncryptedDataKey; +import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import com.amazonaws.encryptionsdk.model.KeyBlob; +import java.nio.charset.StandardCharsets; +import java.util.*; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.awscore.AwsRequest; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.DecryptResponse; + +@RunWith(Enclosed.class) +public class KmsMasterKeyProviderTest { + + private static final String AWS_PARTITION = "aws"; + private static final String AWS_KMS_PROVIDER_ID = "aws-kms"; + private static final String OTHER_PARTITION = "not-aws"; + private static final String OTHER_PROVIDER_ID = "not-aws-kms"; + private static final String ACCOUNT_ID = "999999999999"; + private static final String OTHER_ACCOUNT_ID = "000000000000"; + + private static final String KEY_ID_1 = + "arn:" + + AWS_PARTITION + + ":kms:us-east-1:" + + ACCOUNT_ID + + ":key/01234567-89ab-cdef-fedc-ba9876543210"; + private static final String KEY_ID_2 = + "arn:" + + AWS_PARTITION + + ":kms:us-east-1:" + + ACCOUNT_ID + + ":key/01234567-89ab-cdef-fedc-ba9876543211"; + private static final String KEY_ID_3 = + "arn:" + + AWS_PARTITION + + ":kms:us-east-1:" + + ACCOUNT_ID + + ":key/01234567-89ab-cdef-fedc-ba9876543212"; + private static final String KEY_ID_4 = + "arn:" + + AWS_PARTITION + + ":kms:us-east-1:" + + OTHER_ACCOUNT_ID + + ":key/01234567-89ab-cdef-fedc-ba9876543210"; + private static final String KEY_ID_5 = + "arn:" + + OTHER_PARTITION + + ":kms:us-east-1:" + + ACCOUNT_ID + + ":key/01234567-89ab-cdef-fedc-ba9876543210"; + + private static final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + private static final Map ENCRYPTION_CONTEXT = + Collections.singletonMap("myKey", "myValue"); + + private static final EncryptedDataKey EDK_ID_1 = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_1.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_ID_1_OTHER_CIPHERTEXT = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_1.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_ID_2 = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_2.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_ID_3 = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_3.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_NON_ARN = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + "someAlias".getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_EMPTY_PROVIDER = + new KeyBlob( + "", + "someId".getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_OTHER_PROVIDER = + new KeyBlob( + OTHER_PROVIDER_ID, + "someId".getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_OTHER_ACCOUNT = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_4.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + private static final EncryptedDataKey EDK_OTHER_PARTITION = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + KEY_ID_5.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + + @RunWith(Parameterized.class) + public static class ParameterizedDecryptTest { + MKPTestConfiguration mkpConfig; + List inputEDKs; + List decryptableEDKs; + + private static class MKPTestConfiguration { + // instance vars are public for easier access during testing + public boolean isDiscovery; + public DiscoveryFilter discoveryFilter; + public List keyIds; + + public MKPTestConfiguration( + boolean isDiscovery, DiscoveryFilter discoveryFilter, List keyIds) { + this.isDiscovery = isDiscovery; + this.discoveryFilter = discoveryFilter; + this.keyIds = keyIds; + } + } + + public ParameterizedDecryptTest( + MKPTestConfiguration mkpConfig, + List inputEDKs, + List decryptableEDKs) { + this.mkpConfig = mkpConfig; + this.inputEDKs = inputEDKs; + this.decryptableEDKs = decryptableEDKs; + } + + @Parameterized.Parameters(name = "{index}: mkpConfig={0}, inputEDKs={1}, decryptableEDKs={2}") + public static Collection testCases() { + // Create MKP configuration options to test against + MKPTestConfiguration strict_oneCMK = + new MKPTestConfiguration(false, null, Arrays.asList(KEY_ID_1)); + MKPTestConfiguration strict_twoCMKs = + new MKPTestConfiguration(false, null, Arrays.asList(KEY_ID_1, KEY_ID_2)); + MKPTestConfiguration explicitDiscovery = new MKPTestConfiguration(true, null, null); + MKPTestConfiguration explicitDiscovery_filter = + new MKPTestConfiguration( + true, new DiscoveryFilter(AWS_PARTITION, Arrays.asList(ACCOUNT_ID)), null); + + // Define all test cases + Collection testCases = + Arrays.asList( + new Object[][] { + // Test cases where no EDKs are expected to be decrypted + {strict_oneCMK, Collections.emptyList(), Collections.emptyList()}, + {strict_oneCMK, Arrays.asList(EDK_ID_2), Collections.emptyList()}, + {strict_oneCMK, Arrays.asList(EDK_ID_2, EDK_ID_3), Collections.emptyList()}, + {strict_twoCMKs, Collections.emptyList(), Collections.emptyList()}, + {strict_twoCMKs, Arrays.asList(EDK_ID_3), Collections.emptyList()}, + { + strict_twoCMKs, + Arrays.asList(EDK_ID_3, EDK_OTHER_PROVIDER), + Collections.emptyList() + }, + {explicitDiscovery, Collections.emptyList(), Collections.emptyList()}, + {explicitDiscovery, Arrays.asList(EDK_OTHER_PROVIDER), Collections.emptyList()}, + {explicitDiscovery, Arrays.asList(EDK_EMPTY_PROVIDER), Collections.emptyList()}, + { + explicitDiscovery, + Arrays.asList(EDK_OTHER_PROVIDER, EDK_EMPTY_PROVIDER), + Collections.emptyList() + }, + {explicitDiscovery_filter, Collections.emptyList(), Collections.emptyList()}, + { + explicitDiscovery_filter, + Arrays.asList(EDK_OTHER_PROVIDER), + Collections.emptyList() + }, + { + explicitDiscovery_filter, + Arrays.asList(EDK_EMPTY_PROVIDER), + Collections.emptyList() + }, + {explicitDiscovery_filter, Arrays.asList(EDK_NON_ARN), Collections.emptyList()}, + { + explicitDiscovery_filter, + Arrays.asList(EDK_OTHER_PARTITION), + Collections.emptyList() + }, + { + explicitDiscovery_filter, + Arrays.asList(EDK_OTHER_ACCOUNT), + Collections.emptyList() + }, + { + explicitDiscovery_filter, + Arrays.asList(EDK_OTHER_PROVIDER, EDK_EMPTY_PROVIDER), + Collections.emptyList() + }, + + // Test cases where one EDK is expected to be decryptable + {strict_oneCMK, Arrays.asList(EDK_ID_1), Arrays.asList(EDK_ID_1)}, + {strict_oneCMK, Arrays.asList(EDK_ID_2, EDK_ID_1), Arrays.asList(EDK_ID_1)}, + {strict_oneCMK, Arrays.asList(EDK_ID_1, EDK_ID_2), Arrays.asList(EDK_ID_1)}, + {strict_twoCMKs, Arrays.asList(EDK_ID_1), Arrays.asList(EDK_ID_1)}, + {strict_twoCMKs, Arrays.asList(EDK_ID_2), Arrays.asList(EDK_ID_2)}, + {strict_twoCMKs, Arrays.asList(EDK_ID_3, EDK_ID_1), Arrays.asList(EDK_ID_1)}, + {strict_twoCMKs, Arrays.asList(EDK_ID_1, EDK_ID_3), Arrays.asList(EDK_ID_1)}, + {explicitDiscovery, Arrays.asList(EDK_ID_1), Arrays.asList(EDK_ID_1)}, + { + explicitDiscovery, + Arrays.asList(EDK_OTHER_PROVIDER, EDK_ID_1), + Arrays.asList(EDK_ID_1) + }, + { + explicitDiscovery, + Arrays.asList(EDK_ID_1, EDK_OTHER_PROVIDER), + Arrays.asList(EDK_ID_1) + }, + {explicitDiscovery_filter, Arrays.asList(EDK_ID_1), Arrays.asList(EDK_ID_1)}, + { + explicitDiscovery_filter, + Arrays.asList(EDK_OTHER_ACCOUNT, EDK_ID_1), + Arrays.asList(EDK_ID_1) + }, + { + explicitDiscovery_filter, + Arrays.asList(EDK_ID_1, EDK_OTHER_ACCOUNT), + Arrays.asList(EDK_ID_1) + }, + + // Test cases where multiple EDKs are expected to be decryptable + { + strict_oneCMK, + Arrays.asList(EDK_ID_1, EDK_ID_1_OTHER_CIPHERTEXT), + Arrays.asList(EDK_ID_1, EDK_ID_1_OTHER_CIPHERTEXT) + }, + { + strict_twoCMKs, + Arrays.asList(EDK_ID_1, EDK_ID_2), + Arrays.asList(EDK_ID_1, EDK_ID_2) + }, + { + explicitDiscovery, + Arrays.asList(EDK_ID_1, EDK_ID_2), + Arrays.asList(EDK_ID_1, EDK_ID_2) + }, + { + explicitDiscovery_filter, + Arrays.asList(EDK_ID_1, EDK_ID_2), + Arrays.asList(EDK_ID_1, EDK_ID_2) + }, + }); + return testCases; + } + + @SuppressWarnings("deprecation") + private KmsMasterKeyProvider constructMKPForTest( + MKPTestConfiguration mkpConfig, RegionalClientSupplier supplier) { + KmsMasterKeyProvider.Builder builder = + KmsMasterKeyProvider.builder().customRegionalClientSupplier(supplier); + + KmsMasterKeyProvider mkp; + if (mkpConfig.isDiscovery && mkpConfig.discoveryFilter == null) { + mkp = builder.buildDiscovery(); + } else if (mkpConfig.isDiscovery) { + mkp = builder.buildDiscovery(mkpConfig.discoveryFilter); + } else { + mkp = builder.buildStrict(mkpConfig.keyIds); + } + + return mkp; + } + + @Test + public void testDecrypt() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + // create MKP to test + KmsMasterKeyProvider mkp = constructMKPForTest(mkpConfig, supplier); + + // if we expect none of them to decrypt, just test that we get the correct + // failure and KMS was not called + if (decryptableEDKs.size() <= 0) { + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, inputEDKs, ENCRYPTION_CONTEXT)); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verifyNoInteractions(client); + return; + } + + // Test that the mkp calls KMS for the first expected EDK + EncryptedDataKey expectedEDK = decryptableEDKs.get(0); + + // mock KMS to return the KeyId for the expected EDK, + // we verify that we call KMS with this KeyId, so this is ok + DecryptResponse decryptResponse = + DecryptResponse.builder() + .keyId(new String(expectedEDK.getProviderInformation(), StandardCharsets.UTF_8)) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + doReturn(decryptResponse).when(client).decrypt(isA(DecryptRequest.class)); + + DataKey dataKeyResult = + mkp.decryptDataKey(ALGORITHM_SUITE, inputEDKs, ENCRYPTION_CONTEXT); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + verifyNoMoreInteractions(client); + + DecryptRequest actualRequest = decrypt.getValue(); + assertArrayEquals( + expectedEDK.getProviderInformation(), + actualRequest.keyId().getBytes(StandardCharsets.UTF_8)); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertArrayEquals( + expectedEDK.getEncryptedDataKey(), actualRequest.ciphertextBlob().asByteArray()); + assertApiName(actualRequest); + + assertArrayEquals( + expectedEDK.getProviderInformation(), dataKeyResult.getProviderInformation()); + assertArrayEquals(expectedEDK.getEncryptedDataKey(), dataKeyResult.getEncryptedDataKey()); + } + + @Test + public void testDecryptKMSFailsOnce() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + // create MKP to test + KmsMasterKeyProvider mkp = constructMKPForTest(mkpConfig, supplier); + + // if we expect one or less KMS call, just test that we get the correct + // failure and KMS was called the expected number of times + if (decryptableEDKs.size() <= 1) { + // Mock KMS to fail + doThrow(AwsServiceException.builder().message("fail").build()) + .when(client) + .decrypt(isA(DecryptRequest.class)); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, inputEDKs, ENCRYPTION_CONTEXT)); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(decryptableEDKs.size())).decrypt(decrypt.capture()); + return; + } + + EncryptedDataKey expectedFailedEDK = decryptableEDKs.get(0); + EncryptedDataKey expectedSuccessfulEDK = decryptableEDKs.get(1); + + // Mock KMS to fail the first call then succeed for the second call + DecryptResponse decryptResponse = + DecryptResponse.builder() + .keyId( + new String( + expectedSuccessfulEDK.getProviderInformation(), StandardCharsets.UTF_8)) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + doThrow(AwsServiceException.builder().message("fail").build()) + .doReturn(decryptResponse) + .when(client) + .decrypt(isA(DecryptRequest.class)); + + DataKey dataKeyResult = + mkp.decryptDataKey(ALGORITHM_SUITE, inputEDKs, ENCRYPTION_CONTEXT); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(2)).decrypt(decrypt.capture()); + verifyNoMoreInteractions(client); + + List actualRequests = decrypt.getAllValues(); + DecryptRequest failedRequest = actualRequests.get(0); + assertArrayEquals( + expectedFailedEDK.getProviderInformation(), + failedRequest.keyId().getBytes(StandardCharsets.UTF_8)); + assertEquals(ENCRYPTION_CONTEXT, failedRequest.encryptionContext()); + assertArrayEquals( + expectedFailedEDK.getEncryptedDataKey(), failedRequest.ciphertextBlob().asByteArray()); + assertApiName(failedRequest); + + DecryptRequest successfulRequest = actualRequests.get(1); + assertArrayEquals( + expectedSuccessfulEDK.getProviderInformation(), + successfulRequest.keyId().getBytes(StandardCharsets.UTF_8)); + assertEquals(ENCRYPTION_CONTEXT, successfulRequest.encryptionContext()); + assertArrayEquals( + expectedSuccessfulEDK.getEncryptedDataKey(), + successfulRequest.ciphertextBlob().asByteArray()); + assertApiName(successfulRequest); + + assertArrayEquals( + expectedSuccessfulEDK.getProviderInformation(), dataKeyResult.getProviderInformation()); + assertArrayEquals( + expectedSuccessfulEDK.getEncryptedDataKey(), dataKeyResult.getEncryptedDataKey()); + } + + private void assertApiName(AwsRequest request) { + Optional overrideConfig = request.overrideConfiguration(); + assertTrue(overrideConfig.isPresent()); + assertTrue( + overrideConfig.get().apiNames().stream() + .anyMatch( + api -> + api.name().equals(VersionInfo.apiName()) + && api.version().equals(VersionInfo.versionNumber()))); + } + } + + public static class NonParameterized { + @Test + public void testBuildStrictWithNoCMKs() throws Exception { + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder().customRegionalClientSupplier(supplier).buildStrict()); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(Collections.emptyList())); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict((List) null)); + } + + @Test + public void testBuildStrictWithNullCMK() throws Exception { + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict((String) null)); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildStrict(Arrays.asList((String) null))); + } + + @Test + public void testBuildDiscoveryWithFilter() throws Exception { + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + + KmsMasterKeyProvider mkp1 = + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildDiscovery(new DiscoveryFilter("aws", Arrays.asList("accountId"))); + assertNotNull(mkp1); + } + + @Test + public void testBuildDiscoveryWithNullFilter() throws Exception { + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + + assertThrows( + IllegalArgumentException.class, + () -> + KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(supplier) + .buildDiscovery(null)); + } + + @Test + public void testDecryptMismatchedKMSKeyIdResponse() throws Exception { + MockKmsClient client = spy(new MockKmsClient()); + RegionalClientSupplier supplier = mock(RegionalClientSupplier.class); + when(supplier.getClient(any())).thenReturn(client); + + DecryptResponse badResponse = + DecryptResponse.builder() + .keyId(KEY_ID_2) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + + doReturn(badResponse).when(client).decrypt(isA(DecryptRequest.class)); + + KmsMasterKeyProvider mkp = + KmsMasterKeyProvider.builder().customRegionalClientSupplier(supplier).buildDiscovery(); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> mkp.decryptDataKey(ALGORITHM_SUITE, Arrays.asList(EDK_ID_1), ENCRYPTION_CONTEXT)); + } + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyTest.java new file mode 100644 index 000000000..f34526925 --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyTest.java @@ -0,0 +1,408 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; +import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.*; +import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.internal.VersionInfo; +import com.amazonaws.encryptionsdk.model.KeyBlob; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.Supplier; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.awscore.AwsRequest; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.*; + +public class KmsMasterKeyTest { + + private static final String AWS_KMS_PROVIDER_ID = "aws-kms"; + private static final String OTHER_PROVIDER_ID = "not-aws-kms"; + + private static final CryptoAlgorithm ALGORITHM_SUITE = + CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; + private static final SecretKey DATA_KEY = + new SecretKeySpec( + generate(ALGORITHM_SUITE.getDataKeyLength()), ALGORITHM_SUITE.getDataKeyAlgo()); + private static final List GRANT_TOKENS = Collections.singletonList("testGrantToken"); + private static final Map ENCRYPTION_CONTEXT = + Collections.singletonMap("myKey", "myValue"); + + @Test + public void testEncryptAndDecrypt() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKey otherMasterKey = mock(MasterKey.class); + when(otherMasterKey.getProviderId()).thenReturn(OTHER_PROVIDER_ID); + when(otherMasterKey.getKeyId()).thenReturn("someOtherId"); + DataKey dataKey = + new DataKey( + DATA_KEY, + new byte[0], + OTHER_PROVIDER_ID.getBytes(StandardCharsets.UTF_8), + otherMasterKey); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + kmsMasterKey.setGrantTokens(GRANT_TOKENS); + + DataKey encryptDataKeyResponse = + kmsMasterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey); + + ArgumentCaptor er = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(er.capture()); + + EncryptRequest actualRequest = er.getValue(); + assertEquals(keyId, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertArrayEquals(DATA_KEY.getEncoded(), actualRequest.plaintext().asByteArray()); + assertApiName(actualRequest); + + assertEquals(encryptDataKeyResponse.getMasterKey(), kmsMasterKey); + assertEquals(AWS_KMS_PROVIDER_ID, encryptDataKeyResponse.getProviderId()); + assertArrayEquals( + keyId.getBytes(StandardCharsets.UTF_8), encryptDataKeyResponse.getProviderInformation()); + assertNotNull(encryptDataKeyResponse.getEncryptedDataKey()); + + DataKey decryptDataKeyResponse = + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, Collections.singletonList(encryptDataKeyResponse), ENCRYPTION_CONTEXT); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + + DecryptRequest actualDecryptRequest = decrypt.getValue(); + assertArrayEquals( + encryptDataKeyResponse.getProviderInformation(), + actualDecryptRequest.keyId().getBytes(StandardCharsets.UTF_8)); + assertEquals(GRANT_TOKENS, actualDecryptRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualDecryptRequest.encryptionContext()); + assertArrayEquals( + encryptDataKeyResponse.getEncryptedDataKey(), + actualDecryptRequest.ciphertextBlob().asByteArray()); + assertApiName(actualDecryptRequest); + + assertEquals(DATA_KEY, decryptDataKeyResponse.getKey()); + assertArrayEquals( + keyId.getBytes(StandardCharsets.UTF_8), decryptDataKeyResponse.getProviderInformation()); + } + + @Test + public void testGenerateAndDecrypt() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + kmsMasterKey.setGrantTokens(GRANT_TOKENS); + + DataKey generateDataKeyResponse = + kmsMasterKey.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT); + + ArgumentCaptor gr = + ArgumentCaptor.forClass(GenerateDataKeyRequest.class); + verify(client, times(1)).generateDataKey(gr.capture()); + + GenerateDataKeyRequest actualRequest = gr.getValue(); + + assertEquals(keyId, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertEquals(ALGORITHM_SUITE.getDataKeyLength(), actualRequest.numberOfBytes().longValue()); + assertApiName(actualRequest); + + assertNotNull(generateDataKeyResponse.getKey()); + assertEquals( + ALGORITHM_SUITE.getDataKeyLength(), generateDataKeyResponse.getKey().getEncoded().length); + assertEquals(ALGORITHM_SUITE.getDataKeyAlgo(), generateDataKeyResponse.getKey().getAlgorithm()); + assertNotNull(generateDataKeyResponse.getEncryptedDataKey()); + + DataKey decryptDataKeyResponse = + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, + Collections.singletonList(generateDataKeyResponse), + ENCRYPTION_CONTEXT); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + + DecryptRequest actualDecryptRequest = decrypt.getValue(); + assertArrayEquals( + generateDataKeyResponse.getProviderInformation(), + actualDecryptRequest.keyId().getBytes(StandardCharsets.UTF_8)); + assertEquals(GRANT_TOKENS, actualDecryptRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualDecryptRequest.encryptionContext()); + assertArrayEquals( + generateDataKeyResponse.getEncryptedDataKey(), + actualDecryptRequest.ciphertextBlob().asByteArray()); + assertApiName(actualDecryptRequest); + + assertEquals(generateDataKeyResponse.getKey(), decryptDataKeyResponse.getKey()); + assertArrayEquals( + keyId.getBytes(StandardCharsets.UTF_8), decryptDataKeyResponse.getProviderInformation()); + } + + @Test + public void testEncryptWithRawKeyId() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKey otherMasterKey = mock(MasterKey.class); + when(otherMasterKey.getProviderId()).thenReturn(OTHER_PROVIDER_ID); + when(otherMasterKey.getKeyId()).thenReturn("someOtherId"); + DataKey dataKey = + new DataKey( + DATA_KEY, + new byte[0], + OTHER_PROVIDER_ID.getBytes(StandardCharsets.UTF_8), + otherMasterKey); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + String rawKeyId = keyId.split("/")[1]; + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, rawKeyId, mkp); + kmsMasterKey.setGrantTokens(GRANT_TOKENS); + + DataKey encryptDataKeyResponse = + kmsMasterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey); + + ArgumentCaptor er = ArgumentCaptor.forClass(EncryptRequest.class); + verify(client, times(1)).encrypt(er.capture()); + + EncryptRequest actualRequest = er.getValue(); + + assertEquals(rawKeyId, actualRequest.keyId()); + assertEquals(GRANT_TOKENS, actualRequest.grantTokens()); + assertEquals(ENCRYPTION_CONTEXT, actualRequest.encryptionContext()); + assertArrayEquals(DATA_KEY.getEncoded(), actualRequest.plaintext().asByteArray()); + assertApiName(actualRequest); + + assertEquals(AWS_KMS_PROVIDER_ID, encryptDataKeyResponse.getProviderId()); + assertArrayEquals( + keyId.getBytes(StandardCharsets.UTF_8), encryptDataKeyResponse.getProviderInformation()); + assertNotNull(encryptDataKeyResponse.getEncryptedDataKey()); + } + + @Test + public void testEncryptWrongKeyFormat() { + SecretKey key = mock(SecretKey.class); + when(key.getFormat()).thenReturn("BadFormat"); + + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKey otherMasterKey = mock(MasterKey.class); + when(otherMasterKey.getProviderId()).thenReturn(OTHER_PROVIDER_ID); + when(otherMasterKey.getKeyId()).thenReturn("someOtherId"); + DataKey dataKey = + new DataKey( + key, new byte[0], OTHER_PROVIDER_ID.getBytes(StandardCharsets.UTF_8), otherMasterKey); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + assertThrows( + IllegalArgumentException.class, + () -> kmsMasterKey.encryptDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT, dataKey)); + } + + @Test + public void testGenerateBadKmsKeyLength() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + GenerateDataKeyResponse badResponse = + GenerateDataKeyResponse.builder() + .keyId(keyId) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength() + 1])) + .build(); + + doReturn(badResponse).when(client).generateDataKey(isA(GenerateDataKeyRequest.class)); + + assertThrows( + IllegalStateException.class, + () -> kmsMasterKey.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT)); + } + + @Test + public void testDecryptBadKmsKeyLength() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + DecryptResponse badResponse = + DecryptResponse.builder() + .keyId(keyId) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength() + 1])) + .build(); + + doReturn(badResponse).when(client).decrypt(isA(DecryptRequest.class)); + + EncryptedDataKey edk = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + keyId.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + + assertThrows( + IllegalStateException.class, + () -> + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, Collections.singletonList(edk), ENCRYPTION_CONTEXT)); + } + + @Test + public void testDecryptMissingKmsKeyId() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + DecryptResponse badResponse = + DecryptResponse.builder() + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + + doReturn(badResponse).when(client).decrypt(isA(DecryptRequest.class)); + + EncryptedDataKey edk = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + keyId.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + + assertThrows( + IllegalStateException.class, + "Received an empty keyId from KMS", + () -> + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, Collections.singletonList(edk), ENCRYPTION_CONTEXT)); + } + + @Test + public void testDecryptMismatchedKmsKeyId() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + DecryptResponse badResponse = + DecryptResponse.builder() + .keyId("mismatchedID") + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + + doReturn(badResponse).when(client).decrypt(isA(DecryptRequest.class)); + + EncryptedDataKey edk = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + keyId.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + + assertThrows( + CannotUnwrapDataKeyException.class, + () -> + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, Collections.singletonList(edk), ENCRYPTION_CONTEXT)); + } + + @Test + public void testDecryptSkipsMismatchedIdEDK() { + KmsClient client = spy(new MockKmsClient()); + Supplier supplier = mock(Supplier.class); + when(supplier.get()).thenReturn(client); + + MasterKeyProvider mkp = mock(MasterKeyProvider.class); + when(mkp.getDefaultProviderId()).thenReturn(AWS_KMS_PROVIDER_ID); + String keyId = client.createKey().keyMetadata().arn(); + KmsMasterKey kmsMasterKey = KmsMasterKey.getInstance(supplier, keyId, mkp); + + // Mock expected KMS response to verify success if second EDK is ok, + // and the mismatched EDK is skipped vs failing outright + DecryptResponse kmsResponse = + DecryptResponse.builder() + .keyId(keyId) + .plaintext(SdkBytes.fromByteArray(new byte[ALGORITHM_SUITE.getDataKeyLength()])) + .build(); + doReturn(kmsResponse).when(client).decrypt(isA(DecryptRequest.class)); + + EncryptedDataKey edk = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + keyId.getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + EncryptedDataKey mismatchedEDK = + new KeyBlob( + AWS_KMS_PROVIDER_ID, + "mismatchedID".getBytes(StandardCharsets.UTF_8), + generate(ALGORITHM_SUITE.getDataKeyLength())); + + DataKey decryptDataKeyResponse = + kmsMasterKey.decryptDataKey( + ALGORITHM_SUITE, Arrays.asList(mismatchedEDK, edk), ENCRYPTION_CONTEXT); + + ArgumentCaptor decrypt = ArgumentCaptor.forClass(DecryptRequest.class); + verify(client, times(1)).decrypt(decrypt.capture()); + + DecryptRequest actualDecryptRequest = decrypt.getValue(); + assertArrayEquals( + edk.getProviderInformation(), + actualDecryptRequest.keyId().getBytes(StandardCharsets.UTF_8)); + } + + private void assertApiName(AwsRequest request) { + Optional overrideConfig = request.overrideConfiguration(); + assertTrue(overrideConfig.isPresent()); + assertTrue( + overrideConfig.get().apiNames().stream() + .anyMatch( + api -> + api.name().equals(VersionInfo.apiName()) + && api.version().equals(VersionInfo.versionNumber()))); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MaxEncryptedDataKeysIntegrationTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MaxEncryptedDataKeysIntegrationTest.java new file mode 100644 index 000000000..4709d21ba --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MaxEncryptedDataKeysIntegrationTest.java @@ -0,0 +1,88 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static org.junit.Assert.assertArrayEquals; +import static org.mockito.Mockito.*; + +import com.amazonaws.encryptionsdk.AwsCrypto; +import com.amazonaws.encryptionsdk.TestUtils; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.DecryptRequest; + +public class MaxEncryptedDataKeysIntegrationTest { + private static final byte[] PLAINTEXT = {1, 2, 3, 4}; + private static final int MAX_EDKS = 3; + + private KmsClient testClient_; + private RegionalClientSupplier testClientSupplier_; + private AwsCrypto testCryptoClient_; + + @Before + public void setup() { + testClient_ = spy(new ProxyKmsClient(KmsClient.builder().region(Region.US_WEST_2).build())); + testClientSupplier_ = + region -> { + if (region == Region.US_WEST_2) { + return testClient_; + } + throw new AwsCryptoException( + "test supplier only configured for us-west-2 and eu-central-1"); + }; + testCryptoClient_ = AwsCrypto.standard().toBuilder().withMaxEncryptedDataKeys(MAX_EDKS).build(); + } + + private KmsMasterKeyProvider providerWithEdks(int numKeys) { + List keyIds = new ArrayList<>(numKeys); + for (int i = 0; i < numKeys; i++) { + keyIds.add(KMSTestFixtures.US_WEST_2_KEY_ID); + } + return KmsMasterKeyProvider.builder() + .customRegionalClientSupplier(testClientSupplier_) + .buildStrict(keyIds); + } + + @Test + public void encryptDecryptWithLessThanMaxEdks() { + KmsMasterKeyProvider provider = providerWithEdks(MAX_EDKS - 1); + byte[] ciphertext = testCryptoClient_.encryptData(provider, PLAINTEXT).getResult(); + byte[] decrypted = testCryptoClient_.decryptData(provider, ciphertext).getResult(); + assertArrayEquals(decrypted, PLAINTEXT); + } + + @Test + public void encryptDecryptWithMaxEdks() { + KmsMasterKeyProvider provider = providerWithEdks(MAX_EDKS); + byte[] ciphertext = testCryptoClient_.encryptData(provider, PLAINTEXT).getResult(); + byte[] decrypted = testCryptoClient_.decryptData(provider, ciphertext).getResult(); + assertArrayEquals(decrypted, PLAINTEXT); + } + + @Test + public void noEncryptWithMoreThanMaxEdks() { + KmsMasterKeyProvider provider = providerWithEdks(MAX_EDKS + 1); + TestUtils.assertThrows( + AwsCryptoException.class, + "Encrypted data keys exceed maxEncryptedDataKeys", + () -> testCryptoClient_.encryptData(provider, PLAINTEXT)); + } + + @Test + public void noDecryptWithMoreThanMaxEdks() { + KmsMasterKeyProvider provider = providerWithEdks(MAX_EDKS + 1); + byte[] ciphertext = AwsCrypto.standard().encryptData(provider, PLAINTEXT).getResult(); + TestUtils.assertThrows( + AwsCryptoException.class, + "Ciphertext encrypted data keys exceed maxEncryptedDataKeys", + () -> testCryptoClient_.decryptData(provider, ciphertext)); + verify(testClient_, never()).decrypt((DecryptRequest) any()); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MockKmsClient.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MockKmsClient.java new file mode 100644 index 000000000..62ae7f26c --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/MockKmsClient.java @@ -0,0 +1,254 @@ +/* + * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except + * in compliance with the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import java.nio.ByteBuffer; +import java.security.SecureRandom; +import java.time.Instant; +import java.util.*; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.*; +import software.amazon.awssdk.services.kms.model.UnsupportedOperationException; + +public class MockKmsClient implements KmsClient { + private static final SecureRandom rnd = new SecureRandom(); + private static final String ACCOUNT_ID = "01234567890"; + private final Map responses_ = new HashMap<>(); + private final Set activeKeys = new HashSet<>(); + private final Map keyAliases = new HashMap<>(); + private Region region_ = Region.US_WEST_2; + + @Override + public final String serviceName() { + return SERVICE_NAME; + } + + @Override + public void close() {} + + @Override + public CreateAliasResponse createAlias(CreateAliasRequest req) { + assertExists(req.targetKeyId()); + + keyAliases.put("alias/" + req.aliasName(), keyAliases.get(req.targetKeyId())); + + return CreateAliasResponse.builder().build(); + } + + @Override + public CreateKeyResponse createKey() { + return createKey(CreateKeyRequest.builder().build()); + } + + @Override + public CreateKeyResponse createKey(CreateKeyRequest req) { + String keyId = UUID.randomUUID().toString(); + String arn = "arn:aws:kms:" + region_.id() + ":" + ACCOUNT_ID + ":key/" + keyId; + activeKeys.add(arn); + keyAliases.put(keyId, arn); + keyAliases.put(arn, arn); + return CreateKeyResponse.builder() + .keyMetadata( + KeyMetadata.builder() + .awsAccountId(ACCOUNT_ID) + .creationDate(Instant.now()) + .description(req.description()) + .enabled(true) + .keyId(keyId) + .keyUsage(KeyUsageType.ENCRYPT_DECRYPT) + .arn(arn) + .build()) + .build(); + } + + @Override + public DecryptResponse decrypt(DecryptRequest req) { + DecryptResponse response = responses_.get(new DecryptMapKey(req)); + if (response != null) { + // Copy it to avoid external modification + return DecryptResponse.builder() + .keyId(retrieveArn(response.keyId())) + .plaintext(SdkBytes.fromByteArray(response.plaintext().asByteArray())) + .build(); + } else { + throw InvalidCiphertextException.builder().message("Invalid Ciphertext").build(); + } + } + + @Override + public DescribeKeyResponse describeKey(DescribeKeyRequest req) { + final String arn = retrieveArn(req.keyId()); + + return DescribeKeyResponse.builder() + .keyMetadata(KeyMetadata.builder().arn(arn).keyId(arn).build()) + .build(); + } + + @Override + public EncryptResponse encrypt(EncryptRequest req) { + // We internally delegate to encrypt, so as to avoid mockito detecting extra calls to encrypt + // when spying on the + // MockKMSClient, we put the real logic into a separate function. + return encrypt0(req); + } + + private EncryptResponse encrypt0(EncryptRequest req) { + String arn = retrieveArn(req.keyId()); + + final byte[] cipherText = new byte[512]; + rnd.nextBytes(cipherText); + DecryptResponse dec = + DecryptResponse.builder() + .keyId(retrieveArn(arn)) + .plaintext(SdkBytes.fromByteArray(req.plaintext().asByteArray())) + .build(); + ByteBuffer ctBuff = ByteBuffer.wrap(cipherText); + responses_.put(new DecryptMapKey(ctBuff, req.encryptionContext()), dec); + + return EncryptResponse.builder() + .ciphertextBlob(SdkBytes.fromByteBuffer(ctBuff)) + .keyId(arn) + .build(); + } + + @Override + public GenerateDataKeyResponse generateDataKey(GenerateDataKeyRequest req) { + byte[] pt; + DataKeySpec keySpec = req.keySpec(); + if (keySpec == null) { + pt = new byte[req.numberOfBytes()]; + } else { + switch (keySpec) { + case AES_256: + pt = new byte[32]; + break; + case AES_128: + pt = new byte[16]; + break; + default: + throw UnsupportedOperationException.builder().build(); + } + } + rnd.nextBytes(pt); + + String arn = retrieveArn(req.keyId()); + EncryptResponse encryptResponse = + encrypt0( + EncryptRequest.builder() + .keyId(arn) + .plaintext(SdkBytes.fromByteArray(pt)) + .encryptionContext(req.encryptionContext()) + .build()); + + return GenerateDataKeyResponse.builder() + .keyId(arn) + .ciphertextBlob(encryptResponse.ciphertextBlob()) + .plaintext(SdkBytes.fromByteArray(pt)) + .build(); + } + + public GenerateDataKeyWithoutPlaintextResponse generateDataKeyWithoutPlaintext( + GenerateDataKeyWithoutPlaintextRequest req) { + String arn = retrieveArn(req.keyId()); + GenerateDataKeyRequest generateDataKeyRequest = + GenerateDataKeyRequest.builder() + .encryptionContext(req.encryptionContext()) + .grantTokens(req.grantTokens()) + .keyId(arn) + .keySpec(req.keySpec()) + .numberOfBytes(req.numberOfBytes()) + .build(); + GenerateDataKeyResponse generateDataKey = generateDataKey(generateDataKeyRequest); + + return GenerateDataKeyWithoutPlaintextResponse.builder() + .ciphertextBlob(generateDataKey.ciphertextBlob()) + .keyId(arn) + .build(); + } + + public void setRegion(Region req) { + region_ = req; + } + + public void deleteKey(final String keyId) { + final String arn = retrieveArn(keyId); + activeKeys.remove(arn); + } + + private String retrieveArn(final String keyId) { + String arn = keyAliases.get(keyId); + assertExists(arn); + return arn; + } + + private void assertExists(String keyId) { + if (keyAliases.containsKey(keyId)) { + keyId = keyAliases.get(keyId); + } + if (keyId == null || !activeKeys.contains(keyId)) { + throw NotFoundException.builder().message("Key doesn't exist: " + keyId).build(); + } + } + + private static class DecryptMapKey { + private final ByteBuffer cipherText; + private final Map ec; + + public DecryptMapKey(DecryptRequest req) { + cipherText = req.ciphertextBlob().asByteBuffer(); + if (req.encryptionContext() != null) { + ec = Collections.unmodifiableMap(new HashMap<>(req.encryptionContext())); + } else { + ec = Collections.emptyMap(); + } + } + + public DecryptMapKey(ByteBuffer ctBuff, Map ec) { + cipherText = ctBuff.asReadOnlyBuffer(); + if (ec != null) { + this.ec = Collections.unmodifiableMap(new HashMap<>(ec)); + } else { + this.ec = Collections.emptyMap(); + } + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((cipherText == null) ? 0 : cipherText.hashCode()); + result = prime * result + ((ec == null) ? 0 : ec.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + DecryptMapKey other = (DecryptMapKey) obj; + if (cipherText == null) { + if (other.cipherText != null) return false; + } else if (!cipherText.equals(other.cipherText)) return false; + if (ec == null) { + if (other.ec != null) return false; + } else if (!ec.equals(other.ec)) return false; + return true; + } + + public String toString() { + return "DecryptMapKey [cipherText=" + cipherText + ", ec=" + ec + "]"; + } + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyCredentialsProvider.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyCredentialsProvider.java new file mode 100644 index 000000000..fb8766054 --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyCredentialsProvider.java @@ -0,0 +1,17 @@ +package com.amazonaws.encryptionsdk.kmssdkv2; + +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +class ProxyCredentialsProvider implements AwsCredentialsProvider { + private final AwsCredentialsProvider proxiedProvider_; + + ProxyCredentialsProvider(AwsCredentialsProvider credentialsProvider) { + proxiedProvider_ = credentialsProvider; + } + + @Override + public AwsCredentials resolveCredentials() { + return proxiedProvider_.resolveCredentials(); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyKmsClient.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyKmsClient.java new file mode 100644 index 000000000..996ee202c --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/ProxyKmsClient.java @@ -0,0 +1,68 @@ +package com.amazonaws.encryptionsdk.kmssdkv2; + +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.DecryptResponse; +import software.amazon.awssdk.services.kms.model.DependencyTimeoutException; +import software.amazon.awssdk.services.kms.model.DisabledException; +import software.amazon.awssdk.services.kms.model.EncryptRequest; +import software.amazon.awssdk.services.kms.model.EncryptResponse; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyRequest; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyResponse; +import software.amazon.awssdk.services.kms.model.IncorrectKeyException; +import software.amazon.awssdk.services.kms.model.InvalidCiphertextException; +import software.amazon.awssdk.services.kms.model.InvalidGrantTokenException; +import software.amazon.awssdk.services.kms.model.InvalidKeyUsageException; +import software.amazon.awssdk.services.kms.model.KeyUnavailableException; +import software.amazon.awssdk.services.kms.model.KmsException; +import software.amazon.awssdk.services.kms.model.KmsInternalException; +import software.amazon.awssdk.services.kms.model.KmsInvalidStateException; +import software.amazon.awssdk.services.kms.model.NotFoundException; + +/** This wraps KmsClient since the default implementation is final. */ +class ProxyKmsClient implements KmsClient { + private final KmsClient proxiedClient_; + + ProxyKmsClient(KmsClient kmsClient) { + proxiedClient_ = kmsClient; + } + + @Override + public String serviceName() { + return proxiedClient_.serviceName(); + } + + @Override + public void close() { + proxiedClient_.close(); + } + + @Override + public DecryptResponse decrypt(DecryptRequest decryptRequest) + throws NotFoundException, DisabledException, InvalidCiphertextException, + KeyUnavailableException, IncorrectKeyException, InvalidKeyUsageException, + DependencyTimeoutException, InvalidGrantTokenException, KmsInternalException, + KmsInvalidStateException, AwsServiceException, SdkClientException, KmsException { + return proxiedClient_.decrypt(decryptRequest); + } + + @Override + public EncryptResponse encrypt(EncryptRequest encryptRequest) + throws NotFoundException, DisabledException, KeyUnavailableException, + DependencyTimeoutException, InvalidKeyUsageException, InvalidGrantTokenException, + KmsInternalException, KmsInvalidStateException, AwsServiceException, SdkClientException, + KmsException { + return proxiedClient_.encrypt(encryptRequest); + } + + @Override + public GenerateDataKeyResponse generateDataKey(GenerateDataKeyRequest generateDataKeyRequest) + throws NotFoundException, DisabledException, KeyUnavailableException, + DependencyTimeoutException, InvalidKeyUsageException, InvalidGrantTokenException, + KmsInternalException, KmsInvalidStateException, AwsServiceException, SdkClientException, + KmsException { + return proxiedClient_.generateDataKey(generateDataKeyRequest); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/XCompatKmsDecryptTest.java b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/XCompatKmsDecryptTest.java new file mode 100644 index 000000000..e2929271b --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/kmssdkv2/XCompatKmsDecryptTest.java @@ -0,0 +1,96 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.encryptionsdk.kmssdkv2; + +import static org.junit.Assert.assertArrayEquals; + +import com.amazonaws.encryptionsdk.AwsCrypto; +import com.amazonaws.encryptionsdk.CryptoResult; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class XCompatKmsDecryptTest { + private final String plaintextFileName; + private final String ciphertextFileName; + private final String kmsKeyId; + + public XCompatKmsDecryptTest( + String plaintextFileName, String ciphertextFileName, String kmsKeyId) { + this.plaintextFileName = plaintextFileName; + this.ciphertextFileName = ciphertextFileName; + this.kmsKeyId = kmsKeyId; + } + + @Parameters(name = "{index}: testDecryptFromFile({0}, {1}, {2})") + public static Collection data() throws Exception { + String baseDirName; + baseDirName = System.getProperty("staticCompatibilityResourcesDir"); + if (baseDirName == null) { + baseDirName = + XCompatKmsDecryptTest.class.getProtectionDomain().getCodeSource().getLocation().getPath() + + "aws_encryption_sdk_resources"; + } + + List testCases_ = new ArrayList<>(); + + String ciphertextManifestName = + StringUtils.join( + new String[] {baseDirName, "manifests", "ciphertext.manifest"}, File.separator); + File ciphertextManifestFile = new File(ciphertextManifestName); + + if (!ciphertextManifestFile.exists()) { + return Collections.emptyList(); + } + + ObjectMapper ciphertextManifestMapper = new ObjectMapper(); + Map ciphertextManifest = + ciphertextManifestMapper.readValue( + ciphertextManifestFile, new TypeReference>() {}); + + List> testCases = + (List>) ciphertextManifest.get("test_cases"); + for (Map testCase : testCases) { + Map plaintext = (Map) testCase.get("plaintext"); + Map ciphertext = (Map) testCase.get("ciphertext"); + + List> masterKeys = + (List>) testCase.get("master_keys"); + for (Map masterKey : masterKeys) { + String providerId = (String) masterKey.get("provider_id"); + if (providerId.equals("aws-kms") && (boolean) masterKey.get("decryptable")) { + testCases_.add( + new Object[] { + baseDirName + File.separator + plaintext.get("filename"), + baseDirName + File.separator + ciphertext.get("filename"), + (String) masterKey.get("key_id") + }); + break; + } + } + } + return testCases_; + } + + @Test + public void testDecryptFromFile() throws Exception { + AwsCrypto crypto = AwsCrypto.standard(); + final KmsMasterKeyProvider masterKeyProvider = + KmsMasterKeyProvider.builder().buildStrict(kmsKeyId); + byte[] ciphertextBytes = Files.readAllBytes(Paths.get(ciphertextFileName)); + byte[] plaintextBytes = Files.readAllBytes(Paths.get(plaintextFileName)); + final CryptoResult decryptResult = + crypto.decryptData(masterKeyProvider, ciphertextBytes); + assertArrayEquals(plaintextBytes, decryptResult.getResult()); + } +} From c49f4a34e01a8ef304ec2c0f70dd586401aeed86 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 9 Mar 2022 19:33:21 +0000 Subject: [PATCH 49/55] AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d) ## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) ### Features * AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) ### Maintenance * Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) * add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) * Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) * add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) * Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) * **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) * **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) * **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) * **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) * **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) * **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) * **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) * **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) * **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) * **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) * **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) * **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) * **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) * **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) * **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) * **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) * **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) * **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) * **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) * **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) * **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) * **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) * **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) * **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) * **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) * **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) * **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) * **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) * **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) * **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) * **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) * **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) * moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) * release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) * source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) * update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) * update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) * update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) * update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) * update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) * updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) * Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- pom.xml | 2 +- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9678bf084..eae9aeab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,63 @@ # Changelog +## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) + + +### Features + +* AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) + + +### Maintenance + +* Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) +* add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) +* Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) +* add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) +* Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) +* **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) +* **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) +* **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) +* **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) +* **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) +* **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) +* **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) +* **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) +* **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) +* **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) +* **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) +* **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) +* **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) +* **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) +* **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) +* **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) +* **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) +* **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) +* **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) +* **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) +* **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) +* **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) +* **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) +* **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) +* **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) +* **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) +* **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) +* **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) +* **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) +* **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) +* **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) +* **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) +* moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) +* release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) +* source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) +* update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) +* update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) +* update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) +* update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) +* update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) +* updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) +* Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) + ### 2.3.3 -- 2021-08-26 ### Maintenance diff --git a/README.md b/README.md index bed34b071..587099702 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 ``` diff --git a/pom.xml b/pom.xml index df905b0e5..a0e35ae8f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 jar aws-encryption-sdk-java From 7563a9536fdd0a637777df7659f15bfbb56f31cb Mon Sep 17 00:00:00 2001 From: Sean Swezey Date: Wed, 9 Mar 2022 13:55:52 -0600 Subject: [PATCH 50/55] Revert "AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d)" This reverts commit c49f4a34e01a8ef304ec2c0f70dd586401aeed86. --- CHANGELOG.md | 58 ---------------------------------------------------- README.md | 2 +- pom.xml | 2 +- 3 files changed, 2 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eae9aeab4..9678bf084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,63 +1,5 @@ # Changelog -## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) - - -### Features - -* AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) - - -### Maintenance - -* Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) -* add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) -* Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) -* add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) -* Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) -* **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) -* **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) -* **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) -* **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) -* **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) -* **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) -* **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) -* **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) -* **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) -* **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) -* **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) -* **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) -* **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) -* **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) -* **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) -* **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) -* **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) -* **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) -* **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) -* **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) -* **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) -* **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) -* **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) -* **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) -* **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) -* **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) -* **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) -* **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) -* **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) -* **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) -* **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) -* **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) -* moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) -* release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) -* source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) -* update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) -* update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) -* update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) -* update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) -* update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) -* updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) -* Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) - ### 2.3.3 -- 2021-08-26 ### Maintenance diff --git a/README.md b/README.md index 587099702..bed34b071 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 2.4.0 + 2.3.3 ``` diff --git a/pom.xml b/pom.xml index a0e35ae8f..df905b0e5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.amazonaws aws-encryption-sdk-java - 2.4.0 + 2.3.3 jar aws-encryption-sdk-java From 6fa782bb830273bf09cf80e0f14fc3be774ea276 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:01:40 -0600 Subject: [PATCH 51/55] chore(deps): bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 (#546) Bumps nexus-staging-maven-plugin from 1.6.11 to 1.6.12. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df905b0e5..9be1f51b6 100644 --- a/pom.xml +++ b/pom.xml @@ -317,7 +317,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.11 + 1.6.12 true sonatype-nexus-staging From b1d902da90c7c5945e9443e26985004911232112 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 9 Mar 2022 21:12:35 +0000 Subject: [PATCH 52/55] AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d) ## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) ### Features * AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) ### Maintenance * Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) * add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) * Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) * add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) * Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) * **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) * **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) * **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) * **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) * **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) * **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) * **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) * **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) * **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) * **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) * **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) * **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) * **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) * **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) * **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) * **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) * **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) * **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) * **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) * **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) * **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) * **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) * **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) * **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) * **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) * **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) * **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) * **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) * **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) * **deps:** bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 ([#546](https://github.com/aws/aws-encryption-sdk-java/issues/546)) ([6fa782b](https://github.com/aws/aws-encryption-sdk-java/commit/6fa782bb830273bf09cf80e0f14fc3be774ea276)) * **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) * **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) * **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) * moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) * release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) * source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) * update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) * update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) * update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) * update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) * update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) * updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) * Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) --- CHANGELOG.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- pom.xml | 2 +- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9678bf084..75836610a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,64 @@ # Changelog +## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) + + +### Features + +* AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) + + +### Maintenance + +* Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) +* add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) +* Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) +* add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) +* Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) +* **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) +* **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) +* **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) +* **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) +* **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) +* **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) +* **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) +* **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) +* **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) +* **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) +* **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) +* **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) +* **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) +* **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) +* **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) +* **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) +* **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) +* **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) +* **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) +* **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) +* **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) +* **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) +* **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) +* **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) +* **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) +* **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) +* **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) +* **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) +* **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) +* **deps:** bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 ([#546](https://github.com/aws/aws-encryption-sdk-java/issues/546)) ([6fa782b](https://github.com/aws/aws-encryption-sdk-java/commit/6fa782bb830273bf09cf80e0f14fc3be774ea276)) +* **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) +* **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) +* **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) +* moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) +* release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) +* source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) +* update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) +* update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) +* update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) +* update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) +* update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) +* updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) +* Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) + ### 2.3.3 -- 2021-08-26 ### Maintenance diff --git a/README.md b/README.md index bed34b071..587099702 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 ``` diff --git a/pom.xml b/pom.xml index 9be1f51b6..d36709c88 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 jar aws-encryption-sdk-java From 65bc24d4751c6f56d5d6be9a11e7c9171dfeb4ef Mon Sep 17 00:00:00 2001 From: Sean Swezey Date: Wed, 9 Mar 2022 16:09:31 -0600 Subject: [PATCH 53/55] Revert "AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d)" This reverts commit b1d902da90c7c5945e9443e26985004911232112. --- CHANGELOG.md | 59 ---------------------------------------------------- README.md | 2 +- pom.xml | 2 +- 3 files changed, 2 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75836610a..9678bf084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,64 +1,5 @@ # Changelog -## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) - - -### Features - -* AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) - - -### Maintenance - -* Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) -* add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) -* Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) -* add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) -* Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) -* **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) -* **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) -* **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) -* **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) -* **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) -* **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) -* **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) -* **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) -* **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) -* **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) -* **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) -* **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) -* **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) -* **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) -* **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) -* **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) -* **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) -* **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) -* **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) -* **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) -* **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) -* **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) -* **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) -* **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) -* **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) -* **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) -* **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) -* **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) -* **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) -* **deps:** bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 ([#546](https://github.com/aws/aws-encryption-sdk-java/issues/546)) ([6fa782b](https://github.com/aws/aws-encryption-sdk-java/commit/6fa782bb830273bf09cf80e0f14fc3be774ea276)) -* **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) -* **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) -* **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) -* moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) -* release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) -* source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) -* update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) -* update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) -* update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) -* update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) -* update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) -* updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) -* Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) - ### 2.3.3 -- 2021-08-26 ### Maintenance diff --git a/README.md b/README.md index 587099702..bed34b071 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 2.4.0 + 2.3.3 ``` diff --git a/pom.xml b/pom.xml index d36709c88..9be1f51b6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.amazonaws aws-encryption-sdk-java - 2.4.0 + 2.3.3 jar aws-encryption-sdk-java From de99b563d1cd63551e284a0b9c71dad8dec53444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Corella?= <39066999+josecorella@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:12:01 -0800 Subject: [PATCH 54/55] chore(ci): change release vars (#578) --- codebuild/release/release-prod.yml | 3 +++ codebuild/release/upload_artifacts.yml | 2 +- codebuild/release/validate-prod.yml | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/codebuild/release/release-prod.yml b/codebuild/release/release-prod.yml index 6d5e9d835..ec22a30a0 100644 --- a/codebuild/release/release-prod.yml +++ b/codebuild/release/release-prod.yml @@ -4,6 +4,8 @@ version: 0.2 env: + variables: + BRANCH: "master" secrets-manager: GPG_KEY: Maven-GPG-Keys-Credentials:Keyname GPG_PASS: Maven-GPG-Keys-Credentials:Passphrase @@ -16,6 +18,7 @@ phases: java: corretto11 pre_build: commands: + - git checkout $BRANCH - export SETTINGS_FILE=$(pwd)/codebuild/release/settings.xml - aws secretsmanager get-secret-value --region us-west-2 --secret-id Maven-GPG-Keys --query SecretBinary --output text | base64 -d > ~/mvn_gpg.tgz - tar -xvf ~/mvn_gpg.tgz -C ~ diff --git a/codebuild/release/upload_artifacts.yml b/codebuild/release/upload_artifacts.yml index 0712e2d65..178ffcb61 100644 --- a/codebuild/release/upload_artifacts.yml +++ b/codebuild/release/upload_artifacts.yml @@ -14,6 +14,7 @@ phases: pre_build: commands: # get new project version + - git checkout $BRANCH - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - git config --global user.name "aws-crypto-tools-ci-bot" - git config --global user.email "no-reply@noemail.local" @@ -24,7 +25,6 @@ phases: - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null - apt update - apt install gh - - git checkout $BRANCH build: commands: - gh version diff --git a/codebuild/release/validate-prod.yml b/codebuild/release/validate-prod.yml index dc8809eec..c61229c17 100644 --- a/codebuild/release/validate-prod.yml +++ b/codebuild/release/validate-prod.yml @@ -3,12 +3,18 @@ version: 0.2 +env: + variables: + BRANCH: "master" + phases: install: runtime-versions: java: $JAVA_ENV_VERSION pre_build: commands: + - git checkout $BRANCH + - export VERSION=$(grep version pom.xml | head -n 1 | sed -n 's/[ \t]*\(.*\)<\/version>/\1/p') - git clone https://github.com/aws-samples/busy-engineers-document-bucket.git - cd busy-engineers-document-bucket/exercises/java/encryption-context-complete build: From e9869f8cb35452071103651dff6d8918adcca9e1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 9 Mar 2022 23:23:03 +0000 Subject: [PATCH 55/55] AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d) ## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) ### Features * AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) ### Fixes * Revert "AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d)" ([7563a95](https://github.com/aws/aws-encryption-sdk-java/commit/7563a9536fdd0a637777df7659f15bfbb56f31cb)) ### Maintenance * Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) * add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) * Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) * add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) * Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) * **ci:** change release vars ([#578](https://github.com/aws/aws-encryption-sdk-java/issues/578)) ([de99b56](https://github.com/aws/aws-encryption-sdk-java/commit/de99b563d1cd63551e284a0b9c71dad8dec53444)) * **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) * **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) * **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) * **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) * **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) * **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) * **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) * **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) * **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) * **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) * **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) * **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) * **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) * **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) * **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) * **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) * **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) * **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) * **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) * **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) * **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) * **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) * **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) * **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) * **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) * **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) * **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) * **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) * **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) * **deps:** bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 ([#546](https://github.com/aws/aws-encryption-sdk-java/issues/546)) ([6fa782b](https://github.com/aws/aws-encryption-sdk-java/commit/6fa782bb830273bf09cf80e0f14fc3be774ea276)) * **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) * **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) * **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) * moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) * release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) * source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) * update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) * update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) * update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) * update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) * update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) * updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) * Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) --- CHANGELOG.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- pom.xml | 2 +- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9678bf084..06bc7ddfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,70 @@ # Changelog +## [2.4.0](https://github.com/aws/aws-encryption-sdk-java/compare/v2.3.3...v2.4.0) (2022-03-09) + + +### Features + +* AWS SDK v2 support ([006cdc4](https://github.com/aws/aws-encryption-sdk-java/commit/006cdc4b6395536c8c1b317d85c252f4892d6172)) + + +### Fixes + +* Revert "AWS Encryption SDK 2.4.0 Release -- $(date +%Y-%m-%d)" ([7563a95](https://github.com/aws/aws-encryption-sdk-java/commit/7563a9536fdd0a637777df7659f15bfbb56f31cb)) + + +### Maintenance + +* Add back removed CiphertextHeaders.deserialize method ([#382](https://github.com/aws/aws-encryption-sdk-java/issues/382)) ([c1f3e63](https://github.com/aws/aws-encryption-sdk-java/commit/c1f3e637421c7d5d71a092fd4812aa435639c3da)) +* add build to support uploading artifacts ([#379](https://github.com/aws/aws-encryption-sdk-java/issues/379)) ([69e7914](https://github.com/aws/aws-encryption-sdk-java/commit/69e7914d30e8c0ecea11aed7a924f77210677991)) +* Add CODEOWNERS file ([#406](https://github.com/aws/aws-encryption-sdk-java/issues/406)) ([b9adf9f](https://github.com/aws/aws-encryption-sdk-java/commit/b9adf9fdb3177d80bd7c2ec5ddad86230f2b13f4)) +* add javadoc update to batch build ([#376](https://github.com/aws/aws-encryption-sdk-java/issues/376)) ([d88190b](https://github.com/aws/aws-encryption-sdk-java/commit/d88190b810452c29c9e48892806bc7063a75800a)) +* Adding semantic release config file ([#346](https://github.com/aws/aws-encryption-sdk-java/issues/346)) ([6201c1a](https://github.com/aws/aws-encryption-sdk-java/commit/6201c1accccd3dea2d991a1d579234842865540d)) +* **ci:** change release vars ([#578](https://github.com/aws/aws-encryption-sdk-java/issues/578)) ([de99b56](https://github.com/aws/aws-encryption-sdk-java/commit/de99b563d1cd63551e284a0b9c71dad8dec53444)) +* **deps-dev:** bump junit-jupiter-api from 5.7.2 to 5.8.0 ([#339](https://github.com/aws/aws-encryption-sdk-java/issues/339)) ([6dfaef9](https://github.com/aws/aws-encryption-sdk-java/commit/6dfaef907b5ec5a3ed0c8bb4e774792f683ef03d)) +* **deps-dev:** bump junit-jupiter-api from 5.8.0 to 5.8.1 ([#347](https://github.com/aws/aws-encryption-sdk-java/issues/347)) ([7d3bb0a](https://github.com/aws/aws-encryption-sdk-java/commit/7d3bb0a976746bfb56c13136e876234ea64da581)) +* **deps-dev:** bump junit-jupiter-api from 5.8.1 to 5.8.2 ([#427](https://github.com/aws/aws-encryption-sdk-java/issues/427)) ([7de569a](https://github.com/aws/aws-encryption-sdk-java/commit/7de569aa3766e2339a2c7bbf0bb3c474f75f99cd)) +* **deps-dev:** bump junit-vintage-engine from 5.7.2 to 5.8.0 ([#337](https://github.com/aws/aws-encryption-sdk-java/issues/337)) ([2338b92](https://github.com/aws/aws-encryption-sdk-java/commit/2338b92358b655ee057ba15b4a6b4282988f8875)) +* **deps-dev:** bump junit-vintage-engine from 5.8.0 to 5.8.1 ([#348](https://github.com/aws/aws-encryption-sdk-java/issues/348)) ([d0221cf](https://github.com/aws/aws-encryption-sdk-java/commit/d0221cf8367d7cf2e03ef94dc55f09e48ef9fa07)) +* **deps-dev:** bump junit-vintage-engine from 5.8.1 to 5.8.2 ([#426](https://github.com/aws/aws-encryption-sdk-java/issues/426)) ([065ab94](https://github.com/aws/aws-encryption-sdk-java/commit/065ab94d7ca57d33fac8217cdcba4f046d7e910c)) +* **deps-dev:** bump mockito-core from 3.12.3 to 3.12.4 ([#323](https://github.com/aws/aws-encryption-sdk-java/issues/323)) ([0208d0d](https://github.com/aws/aws-encryption-sdk-java/commit/0208d0d1a2309a26277f3793dc3e7ba6c13c1141)) +* **deps-dev:** bump mockito-core from 4.0.0 to 4.1.0 ([#441](https://github.com/aws/aws-encryption-sdk-java/issues/441)) ([8dfda1a](https://github.com/aws/aws-encryption-sdk-java/commit/8dfda1ac4d28d82e069a91891743a524965a16e8)) +* **deps-dev:** bump mockito-core from 4.1.0 to 4.2.0 ([#458](https://github.com/aws/aws-encryption-sdk-java/issues/458)) ([a1b1885](https://github.com/aws/aws-encryption-sdk-java/commit/a1b18851328a310deff388b11f0fbf691a4cfd2b)) +* **deps-dev:** bump mockito-core from 4.2.0 to 4.3.1 ([#500](https://github.com/aws/aws-encryption-sdk-java/issues/500)) ([a709e69](https://github.com/aws/aws-encryption-sdk-java/commit/a709e69c3beca2824bc5f6c6529b30417df4bbaf)) +* **deps:** bump aws-java-sdk from 1.12.102 to 1.12.105 ([#404](https://github.com/aws/aws-encryption-sdk-java/issues/404)) ([b87d8c6](https://github.com/aws/aws-encryption-sdk-java/commit/b87d8c6716ba98e1b4e1bb08c841f849aa31ebc2)) +* **deps:** bump aws-java-sdk from 1.12.105 to 1.12.106 ([#405](https://github.com/aws/aws-encryption-sdk-java/issues/405)) ([dd633c0](https://github.com/aws/aws-encryption-sdk-java/commit/dd633c037caa0c7ca373cd59f554d49b5cb80448)) +* **deps:** bump aws-java-sdk from 1.12.106 to 1.12.127 ([#436](https://github.com/aws/aws-encryption-sdk-java/issues/436)) ([91f6ffc](https://github.com/aws/aws-encryption-sdk-java/commit/91f6ffca2ce0499d08b6ce3259459fbb7cce890d)) +* **deps:** bump aws-java-sdk from 1.12.127 to 1.12.128 ([#437](https://github.com/aws/aws-encryption-sdk-java/issues/437)) ([37078ec](https://github.com/aws/aws-encryption-sdk-java/commit/37078ec29805ae23ce7c21e440890d68a9b0956c)) +* **deps:** bump aws-java-sdk from 1.12.128 to 1.12.129 ([#447](https://github.com/aws/aws-encryption-sdk-java/issues/447)) ([6872c63](https://github.com/aws/aws-encryption-sdk-java/commit/6872c637b199b3df16104ce3b3b644b90f308c1c)) +* **deps:** bump aws-java-sdk from 1.12.129 to 1.12.131 ([#463](https://github.com/aws/aws-encryption-sdk-java/issues/463)) ([a98a321](https://github.com/aws/aws-encryption-sdk-java/commit/a98a321c046ef1af0343ee3c4753c5e1c361bb62)) +* **deps:** bump aws-java-sdk from 1.12.131 to 1.12.150 ([#508](https://github.com/aws/aws-encryption-sdk-java/issues/508)) ([433dc1b](https://github.com/aws/aws-encryption-sdk-java/commit/433dc1b809a62f7e3bc011b62a55ec4a5e7e90ae)) +* **deps:** bump aws-java-sdk from 1.12.150 to 1.12.151 ([#510](https://github.com/aws/aws-encryption-sdk-java/issues/510)) ([70257a5](https://github.com/aws/aws-encryption-sdk-java/commit/70257a5e0d7244682ce8a72c72ea20101113dd48)) +* **deps:** bump aws-java-sdk from 1.12.151 to 1.12.162 ([#541](https://github.com/aws/aws-encryption-sdk-java/issues/541)) ([22abc6c](https://github.com/aws/aws-encryption-sdk-java/commit/22abc6c14714ecd164fbb08936d996fd34610b05)) +* **deps:** bump aws-java-sdk from 1.12.54 to 1.12.68 ([#341](https://github.com/aws/aws-encryption-sdk-java/issues/341)) ([291be0a](https://github.com/aws/aws-encryption-sdk-java/commit/291be0a722567697cb2fe5174837c83276d626bd)) +* **deps:** bump aws-java-sdk from 1.12.68 to 1.12.73 ([#350](https://github.com/aws/aws-encryption-sdk-java/issues/350)) ([153a0b3](https://github.com/aws/aws-encryption-sdk-java/commit/153a0b3ec3e99c3d878ac9f97176138277a35d8b)) +* **deps:** bump aws-java-sdk from 1.12.73 to 1.12.74 ([#351](https://github.com/aws/aws-encryption-sdk-java/issues/351)) ([e5f3962](https://github.com/aws/aws-encryption-sdk-java/commit/e5f3962f74da9b4197e37d98e68e722ee0d10e8f)) +* **deps:** bump aws-java-sdk from 1.12.74 to 1.12.75 ([#353](https://github.com/aws/aws-encryption-sdk-java/issues/353)) ([3339c20](https://github.com/aws/aws-encryption-sdk-java/commit/3339c20b05e9cbb65317785cf72c3d46087c82c6)) +* **deps:** bump aws-java-sdk from 1.12.75 to 1.12.102 ([#400](https://github.com/aws/aws-encryption-sdk-java/issues/400)) ([98b079c](https://github.com/aws/aws-encryption-sdk-java/commit/98b079cb61417f3ee36035d74772f8913ef09518)) +* **deps:** bump bcprov-ext-jdk15on from 1.69 to 1.70 ([#439](https://github.com/aws/aws-encryption-sdk-java/issues/439)) ([969852a](https://github.com/aws/aws-encryption-sdk-java/commit/969852a4bd934f1a50d05b256e6aae82ed8832fe)) +* **deps:** bump build-helper-maven-plugin from 3.2.0 to 3.3.0 ([#473](https://github.com/aws/aws-encryption-sdk-java/issues/473)) ([4f7d08c](https://github.com/aws/aws-encryption-sdk-java/commit/4f7d08ca31c09dc6ddbd22bd1d4d4c8629614ea0)) +* **deps:** bump fmt-maven-plugin from 2.12 to 2.13 ([#429](https://github.com/aws/aws-encryption-sdk-java/issues/429)) ([e5d8c32](https://github.com/aws/aws-encryption-sdk-java/commit/e5d8c3227ae027105e0195e006dd5a9a2f2fa0d6)) +* **deps:** bump maven-compiler-plugin from 3.8.1 to 3.9.0 ([#481](https://github.com/aws/aws-encryption-sdk-java/issues/481)) ([369a049](https://github.com/aws/aws-encryption-sdk-java/commit/369a0498127377ae3b4cdfa3649c612f18a4582a)) +* **deps:** bump maven-javadoc-plugin from 3.3.0 to 3.3.1 ([#333](https://github.com/aws/aws-encryption-sdk-java/issues/333)) ([693e43f](https://github.com/aws/aws-encryption-sdk-java/commit/693e43fb9606824e8b4f5336ef8d06cf454338de)) +* **deps:** bump nexus-staging-maven-plugin from 1.6.11 to 1.6.12 ([#546](https://github.com/aws/aws-encryption-sdk-java/issues/546)) ([6fa782b](https://github.com/aws/aws-encryption-sdk-java/commit/6fa782bb830273bf09cf80e0f14fc3be774ea276)) +* **deps:** bump nexus-staging-maven-plugin from 1.6.8 to 1.6.11 ([#535](https://github.com/aws/aws-encryption-sdk-java/issues/535)) ([0ab1db0](https://github.com/aws/aws-encryption-sdk-java/commit/0ab1db09d10c9477167dd0545747e1391090727b)) +* **docs:** update README get started example ([#423](https://github.com/aws/aws-encryption-sdk-java/issues/423)) ([da0fe89](https://github.com/aws/aws-encryption-sdk-java/commit/da0fe89836c40e33f201b792052f02abe44af92b)) +* **docs:** updating broken javadoc link ([#366](https://github.com/aws/aws-encryption-sdk-java/issues/366)) ([487be4b](https://github.com/aws/aws-encryption-sdk-java/commit/487be4b8765e92b4b5b8d840133955573e8710da)) +* moving and renaming buildspec.yml ([#360](https://github.com/aws/aws-encryption-sdk-java/issues/360)) ([e259caf](https://github.com/aws/aws-encryption-sdk-java/commit/e259caf3c50ab4c3346ca8e203cc6d6878482aa7)) +* release updates ([#369](https://github.com/aws/aws-encryption-sdk-java/issues/369)) ([4b9d932](https://github.com/aws/aws-encryption-sdk-java/commit/4b9d932a6d8f5085db34b0f8a693f9cfc0d04b49)) +* source controlling cfn templates that will be used for our release process ([#345](https://github.com/aws/aws-encryption-sdk-java/issues/345)) ([456dda0](https://github.com/aws/aws-encryption-sdk-java/commit/456dda0a8d6a2b3ce67024cc0b52edd24ec2816b)) +* update dependabot to update mainline-1.x ([#440](https://github.com/aws/aws-encryption-sdk-java/issues/440)) ([960f3e5](https://github.com/aws/aws-encryption-sdk-java/commit/960f3e5459d196b1d623d61d9d780fa519b106ad)) +* update gh token ([#412](https://github.com/aws/aws-encryption-sdk-java/issues/412)) ([f8ada9b](https://github.com/aws/aws-encryption-sdk-java/commit/f8ada9bcd3c804abcf1747ffb1cefbdff8c1e576)) +* update release process ([#396](https://github.com/aws/aws-encryption-sdk-java/issues/396)) ([c0ff093](https://github.com/aws/aws-encryption-sdk-java/commit/c0ff093c633cabc21d537ff8e27d6a41d08a772c)) +* update releaserc to include pom.xml file ([#357](https://github.com/aws/aws-encryption-sdk-java/issues/357)) ([63e2f05](https://github.com/aws/aws-encryption-sdk-java/commit/63e2f054929b056bdd74328b94c5f96577626113)) +* update token name and timeout ([#411](https://github.com/aws/aws-encryption-sdk-java/issues/411)) ([c0d5a0e](https://github.com/aws/aws-encryption-sdk-java/commit/c0d5a0e8c8564ece51f4c43c99ae7bfcc4ab71d5)) +* updating prod template to remove resources and abstract ones ([#354](https://github.com/aws/aws-encryption-sdk-java/issues/354)) ([ecc17a6](https://github.com/aws/aws-encryption-sdk-java/commit/ecc17a6789a204fdc9bded0fa335b7087f0b371b)) +* Upgrade mockito to 4.0.0 ([#438](https://github.com/aws/aws-encryption-sdk-java/issues/438)) ([629dbfd](https://github.com/aws/aws-encryption-sdk-java/commit/629dbfdaa91b6023034f808f5e4865fd7048c963)) + ### 2.3.3 -- 2021-08-26 ### Maintenance diff --git a/README.md b/README.md index bed34b071..587099702 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 ``` diff --git a/pom.xml b/pom.xml index 9be1f51b6..d36709c88 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.amazonaws aws-encryption-sdk-java - 2.3.3 + 2.4.0 jar aws-encryption-sdk-java