Java tutorial
// Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.google.crypto.tink.integration.awskms; import com.amazonaws.AmazonServiceException; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.auth.PropertiesFileCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.google.auto.service.AutoService; import com.google.crypto.tink.Aead; import com.google.crypto.tink.KmsClient; import com.google.crypto.tink.subtle.Validators; import java.security.GeneralSecurityException; /** * An implementation of {@link KmsClient} for <a href="https://aws.amazon.com/kms/">AWS KMS</a>. * * @since 1.0.0 */ @AutoService(KmsClient.class) public final class AwsKmsClient implements KmsClient { /** The prefix of all keys stored in AWS KMS. */ public static final String PREFIX = "aws-kms://"; private AWSKMS client; private String keyUri; /** Constructs a generic AwsKmsClient that is not bound to any specific key. */ public AwsKmsClient() { } /** Constructs a specific AwsKmsClient that is bound to a single key identified by {@code uri}. */ public AwsKmsClient(String uri) { if (!uri.toLowerCase().startsWith(PREFIX)) { throw new IllegalArgumentException("key URI must starts with " + PREFIX); } this.keyUri = uri; } /** * @return @return true either if this client is a generic one and uri starts with {@link * AwsKmsClient#PREFIX}, or the client is a specific one that is bound to the key identified * by {@code uri}. */ @Override public boolean doesSupport(String uri) { if (this.keyUri != null && this.keyUri.equals(uri)) { return true; } return this.keyUri == null && uri.toLowerCase().startsWith(PREFIX); } /** * Loads AWS credentials from a properties file. * * <p>The AWS access key ID is expected to be in the <code>accessKey</code> property and the AWS * secret key is expected to be in the <code>secretKey</code> property. * * @throws GeneralSecurityException if the client initialization fails */ @Override public KmsClient withCredentials(String credentialPath) throws GeneralSecurityException { try { if (credentialPath == null) { return withDefaultCredentials(); } return withCredentialsProvider(new PropertiesFileCredentialsProvider(credentialPath)); } catch (AmazonServiceException e) { throw new GeneralSecurityException("cannot load credentials", e); } } /** * Loads default AWS credentials. * * <p>AWS credentials provider chain that looks for credentials in this order: * * <ul> * <li>Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_KEY * <li>Java System Properties - aws.accessKeyId and aws.secretKey * <li>Credential profiles file at the default location (~/.aws/credentials) * <li>Instance profile credentials delivered through the Amazon EC2 metadata service * </ul> * * @throws GeneralSecurityException if the client initialization fails */ @Override public KmsClient withDefaultCredentials() throws GeneralSecurityException { try { return withCredentialsProvider(new DefaultAWSCredentialsProviderChain()); } catch (AmazonServiceException e) { throw new GeneralSecurityException("cannot load default credentials", e); } } /** Loads AWS credentials from a provider. */ public KmsClient withCredentialsProvider(AWSCredentialsProvider provider) throws GeneralSecurityException { try { String[] tokens = this.keyUri.split(":"); this.client = AWSKMSClientBuilder.standard().withCredentials(provider) .withRegion(Regions.fromName(tokens[4])).build(); return this; } catch (AmazonServiceException e) { throw new GeneralSecurityException("cannot load credentials from provider", e); } } @Override public Aead getAead(String uri) throws GeneralSecurityException { if (this.keyUri != null && !this.keyUri.equals(uri)) { throw new GeneralSecurityException( String.format("this client is bound to %s, cannot load keys bound to %s", this.keyUri, uri)); } return new AwsKmsAead(client, Validators.validateKmsKeyUriAndRemovePrefix(PREFIX, uri)); } }