diff options
-rw-r--r-- | parent/pom.xml | 6 | ||||
-rw-r--r-- | vespa-athenz/pom.xml | 5 | ||||
-rw-r--r-- | vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/aws/AwsCredentialsProvider.java | 79 |
3 files changed, 89 insertions, 1 deletions
diff --git a/parent/pom.xml b/parent/pom.xml index 7d7dfc1dc08..1cececbd8e8 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -708,6 +708,11 @@ <artifactId>assertj-core</artifactId> <version>3.11.1</version> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-core</artifactId> + <version>${aws.sdk.version}</version> + </dependency> </dependencies> </dependencyManagement> @@ -717,6 +722,7 @@ <apache.httpclient.version>4.4.1</apache.httpclient.version> <apache.httpcore.version>4.4.1</apache.httpcore.version> <asm.version>7.0</asm.version> + <aws.sdk.version>1.11.357</aws.sdk.version> <jna.version>4.5.2</jna.version> <tensorflow.version>1.12.0</tensorflow.version> <!-- Athenz dependencies. Make sure these dependencies matches those in Vespa's internal repositories --> diff --git a/vespa-athenz/pom.xml b/vespa-athenz/pom.xml index 27b68fbf360..f30aed1af5f 100644 --- a/vespa-athenz/pom.xml +++ b/vespa-athenz/pom.xml @@ -114,7 +114,10 @@ <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> - + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-core</artifactId> + </dependency> </dependencies> <build> diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/aws/AwsCredentialsProvider.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/aws/AwsCredentialsProvider.java new file mode 100644 index 00000000000..28f028832b4 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/aws/AwsCredentialsProvider.java @@ -0,0 +1,79 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.client.aws; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.BasicSessionCredentials; +import com.yahoo.vespa.athenz.api.AthenzDomain; +import com.yahoo.vespa.athenz.api.AwsRole; +import com.yahoo.vespa.athenz.api.AwsTemporaryCredentials; +import com.yahoo.vespa.athenz.client.zts.DefaultZtsClient; +import com.yahoo.vespa.athenz.client.zts.ZtsClient; +import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider; + +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.time.Duration; +import java.time.Instant; +import java.util.Objects; +import java.util.logging.Logger; + +/** + * Implementation of AWSCredentialsProvider using com.yahoo.vespa.athenz.client.zts.ZtsClient + * + * @author mortent + */ +public class AwsCredentialsProvider implements AWSCredentialsProvider { + + private static final Logger logger = Logger.getLogger(AwsCredentialsProvider.class.getName()); + + private final static Duration MIN_EXPIRY = Duration.ofMinutes(5); + private final AthenzDomain athenzDomain; + private final AwsRole awsRole; + private final ZtsClient ztsClient; + private volatile AwsTemporaryCredentials credentials; + + public AwsCredentialsProvider(ZtsClient ztsClient, AthenzDomain athenzDomain, AwsRole awsRole) { + this.ztsClient = ztsClient; + this.athenzDomain = athenzDomain; + this.awsRole = awsRole; + this.credentials = getAthenzTempCredentials(); + } + + public AwsCredentialsProvider(URI ztsUrl, ServiceIdentityProvider identityProvider, AthenzDomain athenzDomain, AwsRole awsRole) { + this(new DefaultZtsClient(ztsUrl, identityProvider), athenzDomain, awsRole); + } + + public AwsCredentialsProvider(URI ztsUrl, SSLContext sslContext, AthenzDomain athenzDomain, AwsRole awsRole) { + this(new DefaultZtsClient(ztsUrl, null, sslContext), athenzDomain, awsRole); + } + + /** + * Requests temporary credentials from ZTS or return cached credentials + */ + private AwsTemporaryCredentials getAthenzTempCredentials() { + if(shouldRefresh(credentials)) { + this.credentials = ztsClient.getAwsTemporaryCredentials(athenzDomain, awsRole); + } + return credentials; + } + + @Override + public AWSCredentials getCredentials() { + AwsTemporaryCredentials creds = getAthenzTempCredentials(); + return new BasicSessionCredentials(creds.accessKeyId(), creds.secretAccessKey(), creds.sessionToken()); + } + + @Override + public void refresh() { + getAthenzTempCredentials(); + } + + /* + * Checks credential expiration, returns true if it will expipre in the next MIN_EXPIRY minutes + */ + private static boolean shouldRefresh(AwsTemporaryCredentials credentials) { + Instant expiration = credentials.expiration(); + return Objects.isNull(expiration) || expiration.minus(MIN_EXPIRY).isAfter(Instant.now()); + } +} |