com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider Maven / Gradle / Ivy
Show all versions of aws-java-sdk-sts Show documentation
/*
* Copyright 2011-2024 Amazon Technologies, 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://aws.amazon.com/apache2.0
*
* 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.auth;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.annotation.ThreadSafe;
import com.amazonaws.internal.StaticCredentialsProvider;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Tag;
import com.amazonaws.util.ValidationUtils;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
/**
* AWSCredentialsProvider implementation that uses the AWS Security Token Service to assume a Role
* and create temporary, short-lived sessions to use for authentication.
*
* This credentials provider uses a background thread to refresh credentials. This background thread can be shut down via the
* {@link #close()} method when the credentials provider is no longer used. You can also specify a custom {@link ExecutorService}
* to refresh the credentials. See {@link Builder#withAsyncRefreshExecutor}. Note that the custom executor service must be shut
* down when it is ready to be disposed. The SDK will not close it when the credential provider is closed.
*/
@ThreadSafe
public class STSAssumeRoleSessionCredentialsProvider implements AWSSessionCredentialsProvider, Closeable {
private static final String PROVIDER_NAME = "STSAssumeRoleCredentialsProvider";
/**
* Default duration for started sessions.
*/
public static final int DEFAULT_DURATION_SECONDS = 900;
/**
* The client for starting STS sessions.
*/
private final AWSSecurityTokenService securityTokenService;
/**
* The arn of the role to be assumed.
*/
private final String roleArn;
/**
* An identifier for the assumed role session.
*/
private final String roleSessionName;
/**
* An external Id parameter for the assumed role session
*/
private final String roleExternalId;
/**
* The Duration for assume role sessions.
*/
private final int roleSessionDurationSeconds;
/**
* Scope down policy to limit permissions from the assumed role.
*/
private final String scopeDownPolicy;
/**
* Tags for the assume role session
*/
private final Collection sessionTags;
/**
* Transitive tag keys for the assume role session
*/
private final Collection transitiveTagKeys;
/**
* Source Identity for the assume role session
*/
private final String sourceIdentity;
private final Callable refreshCallable = new Callable() {
@Override
public SessionCredentialsHolder call() throws Exception {
return newSession();
}
};
/**
* Handles the refreshing of sessions. Ideally this should be final but #setSTSClientEndpoint
* forces us to create a new one.
*/
private volatile RefreshableTask refreshableTask;
/**
* Constructs a new STSAssumeRoleSessionCredentialsProvider, which makes a request to the AWS
* Security Token Service (STS), uses the provided {@link #roleArn} to assume a role and then
* request short lived session credentials, which will then be returned by this class's {@link
* #getCredentials()} method.
*
* @param roleArn The ARN of the Role to be assumed.
* @param roleSessionName An identifier for the assumed role session.
* @deprecated Use the {@link Builder} instead.
*/
@Deprecated
public STSAssumeRoleSessionCredentialsProvider(String roleArn, String roleSessionName) {
this(new Builder(roleArn, roleSessionName));
}
/**
* Constructs a new STSAssumeRoleSessionCredentialsProvider, which will use the specified long
* lived AWS credentials to make a request to the AWS Security Token Service (STS), uses the
* provided {@link #roleArn} to assume a role and then request short lived session credentials,
* which will then be returned by this class's {@link #getCredentials()} method.
*
* @param longLivedCredentials The main AWS credentials for a user's account.
* @param roleArn The ARN of the Role to be assumed.
* @param roleSessionName An identifier for the assumed role session.
* @deprecated Use the {@link Builder} instead.
*/
@Deprecated
public STSAssumeRoleSessionCredentialsProvider(AWSCredentials longLivedCredentials,
String roleArn, String roleSessionName) {
this(longLivedCredentials, roleArn, roleSessionName, new ClientConfiguration());
}
/**
* Constructs a new STSAssumeRoleSessionCredentialsProvider, which will use the specified long
* lived AWS credentials to make a request to the AWS Security Token Service (STS), uses the
* provided {@link #roleArn} to assume a role and then request short lived session credentials,
* which will then be returned by this class's {@link #getCredentials()} method.
*
* @param longLivedCredentials The main AWS credentials for a user's account.
* @param roleArn The ARN of the Role to be assumed.
* @param roleSessionName An identifier for the assumed role session.
* @param clientConfiguration Client configuration connection parameters.
* @deprecated Use the {@link Builder} instead.
*/
@Deprecated
public STSAssumeRoleSessionCredentialsProvider(AWSCredentials longLivedCredentials,
String roleArn, String roleSessionName,
ClientConfiguration clientConfiguration) {
this(new Builder(roleArn, roleSessionName).withLongLivedCredentials(longLivedCredentials)
.withClientConfiguration(clientConfiguration));
}
/**
* Constructs a new STSAssumeRoleSessionCredentialsProvider, which will use the specified
* credentials provider (which vends long lived AWS credentials) to make a request to the AWS
* Security Token Service (STS), usess the provided {@link #roleArn} to assume a role and then
* request short lived session credentials, which will then be returned by this class's {@link
* #getCredentials()} method.
*
* @param longLivedCredentialsProvider Credentials provider for the main AWS credentials for a
* user's account.
* @param roleArn The ARN of the Role to be assumed.
* @param roleSessionName An identifier for the assumed role session.
* @deprecated Use the {@link Builder} instead.
*/
@Deprecated
public STSAssumeRoleSessionCredentialsProvider(
AWSCredentialsProvider longLivedCredentialsProvider, String roleArn,
String roleSessionName) {
this(new Builder(roleArn, roleSessionName)
.withLongLivedCredentialsProvider(longLivedCredentialsProvider));
}
/**
* Constructs a new STSAssumeRoleSessionCredentialsProvider, which will use the specified
* credentials provider (which vends long lived AWS credentials) to make a request to the AWS
* Security Token Service (STS), uses the provided {@link #roleArn} to assume a role and then
* request short lived session credentials, which will then be returned by this class's {@link
* #getCredentials()} method.
*
* @param longLivedCredentialsProvider Credentials provider for the main AWS credentials for a
* user's account.
* @param roleArn The ARN of the Role to be assumed.
* @param roleSessionName An identifier for the assumed role session.
* @param clientConfiguration Client configuration connection parameters.
* @deprecated Use the {@link Builder} instead.
*/
@Deprecated
public STSAssumeRoleSessionCredentialsProvider(
AWSCredentialsProvider longLivedCredentialsProvider, String roleArn,
String roleSessionName, ClientConfiguration clientConfiguration) {
this(new Builder(roleArn, roleSessionName)
.withLongLivedCredentialsProvider(longLivedCredentialsProvider)
.withClientConfiguration(clientConfiguration));
}
private RefreshableTask createRefreshableTask(ExecutorService asyncRefeshExecutor) {
return new RefreshableTask.Builder()
.withRefreshCallable(refreshCallable)
.withExecutorService(asyncRefeshExecutor)
.withBlockingRefreshPredicate(new ShouldDoBlockingSessionRefresh())
.withAsyncRefreshPredicate(new ShouldDoAsyncSessionRefresh()).build();
}
/**
* The following private constructor reads state from the builder and sets the appropriate
* parameters accordingly
*
* When public constructors are called, this constructors is deferred to with a null value for
* roleExternalId and endpoint The inner Builder class can be used to construct an object that
* actually has a value for roleExternalId and endpoint
*
* @throws IllegalArgumentException if both an AWSCredentials and AWSCredentialsProvider have
* been set on the builder
*/
private STSAssumeRoleSessionCredentialsProvider(Builder builder) {
if (builder.sts != null) {
ValidationUtils.assertAllAreNull(
"If a custom STS client is set you must not set any other client related fields (ClientConfiguration, AWSCredentials, Endpoint, etc",
builder.longLivedCredentials, builder.longLivedCredentialsProvider,
builder.clientConfiguration, builder.serviceEndpoint);
this.securityTokenService = builder.sts;
} else {
this.securityTokenService = buildStsClient(builder);
if (builder.serviceEndpoint != null) {
securityTokenService.setEndpoint(builder.serviceEndpoint);
}
}
//required parameters are null checked in the builder constructor
this.roleArn = builder.roleArn;
this.roleSessionName = builder.roleSessionName;
//roleExternalId may be null
this.roleExternalId = builder.roleExternalId;
//Assume Role Session duration may not be provided, in which case we fall back to default value of 15min
if (builder.roleSessionDurationSeconds != 0) {
this.roleSessionDurationSeconds = builder.roleSessionDurationSeconds;
} else {
this.roleSessionDurationSeconds = DEFAULT_DURATION_SECONDS;
}
this.refreshableTask = createRefreshableTask(builder.asyncRefreshExecutor);
this.scopeDownPolicy = builder.scopeDownPolicy;
this.sessionTags = builder.sessionTags;
this.transitiveTagKeys = builder.transitiveTagKeys;
this.sourceIdentity = builder.sourceIdentity;
}
/**
* Construct a new STS client from the settings in the builder.
*
* @param builder Configured builder
* @return New instance of AWSSecurityTokenService
* @throws IllegalArgumentException if builder configuration is inconsistent
*/
private static AWSSecurityTokenService buildStsClient(Builder builder) throws
IllegalArgumentException {
/**
* Passing two types of credential interfaces is not permitted
*/
if (builder.longLivedCredentials != null && builder.longLivedCredentialsProvider != null) {
throw new IllegalArgumentException(
"It is illegal to set both an AWSCredentials and an AWSCredentialsProvider for an " +
STSAssumeRoleSessionCredentialsProvider.class.getName());
}
AWSCredentialsProvider longLivedCredentialsProvider = null;
if (builder.longLivedCredentials != null) {
longLivedCredentialsProvider = new StaticCredentialsProvider(
builder.longLivedCredentials);
} else if (builder.longLivedCredentialsProvider != null) {
longLivedCredentialsProvider = builder.longLivedCredentialsProvider;
}
// Depending on which options are explicitly provided we have to call the right overloaded constructor so
// defaults are properly applied.
if (longLivedCredentialsProvider == null) {
if (builder.clientConfiguration == null) {
return new AWSSecurityTokenServiceClient();
} else {
return new AWSSecurityTokenServiceClient(builder.clientConfiguration);
}
} else {
if (builder.clientConfiguration == null) {
return new AWSSecurityTokenServiceClient(longLivedCredentialsProvider);
} else {
return new AWSSecurityTokenServiceClient(longLivedCredentialsProvider,
builder.clientConfiguration);
}
}
}
/**
* Sets the AWS Security Token Service (STS) endpoint where session credentials are retrieved
* from. The default AWS Security Token Service (STS) endpoint ("sts.amazonaws.com")
* works for all accounts that are not for China (Beijing) region or GovCloud. You only need to
* change the endpoint to "sts.cn-north-1.amazonaws.com.cn" when you are requesting session
* credentials for services in China(Beijing) region or "sts.us-gov-west-1.amazonaws.com" for
* GovCloud. Setting this invalidates existing session credentials.
*
* @deprecated This method may be removed in a future major version. Create multiple providers
* if you need to work with multiple STS endpoints.
*/
@Deprecated
public synchronized void setSTSClientEndpoint(String endpoint) {
securityTokenService.setEndpoint(endpoint);
this.refreshableTask = createRefreshableTask(null);
}
@Override
public AWSSessionCredentials getCredentials() {
return refreshableTask.getValue().getSessionCredentials();
}
@Override
public void refresh() {
refreshableTask.forceGetValue();
}
/**
* Starts a new session by sending a request to the AWS Security Token Service (STS) to assume a
* Role using the long lived AWS credentials. This class then vends the short lived session
* credentials for the assumed Role sent back from STS.
*/
private SessionCredentialsHolder newSession() {
AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest().withRoleArn(roleArn)
.withDurationSeconds(roleSessionDurationSeconds)
.withRoleSessionName(roleSessionName)
.withPolicy(scopeDownPolicy);
if (roleExternalId != null) {
assumeRoleRequest = assumeRoleRequest.withExternalId(roleExternalId);
}
if(sessionTags != null) {
assumeRoleRequest = assumeRoleRequest.withTags(sessionTags);
}
if(transitiveTagKeys != null) {
assumeRoleRequest = assumeRoleRequest.withTransitiveTagKeys(transitiveTagKeys);
}
if (sourceIdentity != null) {
assumeRoleRequest = assumeRoleRequest.withSourceIdentity(sourceIdentity);
}
AssumeRoleResult assumeRoleResult = securityTokenService.assumeRole(assumeRoleRequest);
return new SessionCredentialsHolder(assumeRoleResult.getCredentials(), PROVIDER_NAME);
}
/**
* Shut down this credentials provider, shutting down the thread that performs asynchronous credential refreshing. This
* should not be invoked if the credentials provider is still in use by an AWS client.
*/
@Override
public void close() {
refreshableTask.close();
}
/**
* Provides a builder pattern to avoid combinatorial explosion of the number of parameters that
* are passed to constructors. The builder introspects which parameters have been set and calls
* the appropriate constructor.
*/
public static final class Builder {
private final String roleArn;
private final String roleSessionName;
private AWSCredentialsProvider longLivedCredentialsProvider;
private AWSCredentials longLivedCredentials;
private ClientConfiguration clientConfiguration;
private String roleExternalId;
private String serviceEndpoint;
private int roleSessionDurationSeconds;
private String scopeDownPolicy;
private AWSSecurityTokenService sts;
private Collection sessionTags;
private Collection transitiveTagKeys;
private String sourceIdentity;
private ExecutorService asyncRefreshExecutor;
/**
* @param roleArn Required roleArn parameter used when starting a session
* @param roleSessionName Required roleSessionName parameter used when starting a session
*/
public Builder(String roleArn, String roleSessionName) {
if (roleArn == null || roleSessionName == null) {
throw new NullPointerException(
"You must specify a value for roleArn and roleSessionName");
}
this.roleArn = roleArn;
this.roleSessionName = roleSessionName;
}
/**
* Set credentials to use when retrieving session credentials This is not the recommended
* approach. Instead, consider using the CredentialsProvider field.
*
* @param longLivedCredentials Credentials used to generate sessions in the assumed role
* @return the builder itself for chained calls
* @deprecated Supply a configured STS client via the {@link #withStsClient(AWSSecurityTokenService)}
* setter. Use {@link com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder}
* to create an STS client.
*/
@Deprecated
public Builder withLongLivedCredentials(AWSCredentials longLivedCredentials) {
this.longLivedCredentials = longLivedCredentials;
return this;
}
/**
* Set credentials provider to use when retrieving session credentials
*
* @param longLivedCredentialsProvider A credentials provider used to generate sessions in
* the assumed role
* @return the builder itself for chained calls
* @deprecated Supply a configured STS client via the {@link #withStsClient(AWSSecurityTokenService)}
* setter. Use {@link com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder}
* to create an STS client.
*/
@Deprecated
public Builder withLongLivedCredentialsProvider(
AWSCredentialsProvider longLivedCredentialsProvider) {
this.longLivedCredentialsProvider = longLivedCredentialsProvider;
return this;
}
/**
* Set the client configuration used to create the AWSSecurityTokenService
*
* @param clientConfiguration ClientConfiguration for the AWSSecurityTokenService client
* @return the builder itself for chained calls
* @deprecated Supply a configured STS client via the {@link #withStsClient(AWSSecurityTokenService)}
* setter. Use {@link com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder}
* to create an STS client.
*/
@Deprecated
public Builder withClientConfiguration(ClientConfiguration clientConfiguration) {
this.clientConfiguration = clientConfiguration;
return this;
}
/**
* Set the roleExternalId parameter that is used when retrieving session credentials under
* an assumed role.
*
* @param roleExternalId An external id used in the service call used to retrieve session
* credentials
* @return the builder itself for chained calls
*/
public Builder withExternalId(String roleExternalId) {
this.roleExternalId = roleExternalId;
return this;
}
/**
* Set the {@link ExecutorService} used for background credential refreshing.
* This executor service must be shut down by the user when it is ready to be disposed.
* The SDK will not close the executor service when the credential provider is closed.
* @param asyncRefreshExecetor the {@link ExecutorService} used for background credential refreshing.
* @return the builder itself for chained calls
*/
public Builder withAsyncRefreshExecutor(ExecutorService asyncRefreshExecetor) {
this.asyncRefreshExecutor = asyncRefreshExecetor;
return this;
}
/**
* Set the roleSessionDurationSeconds that is used when creating a new assumed role
* session.
*
* @param roleSessionDurationSeconds The duration for which we want to have an assumed role
* session to be active.
* @return the itself for chained calls
*/
public Builder withRoleSessionDurationSeconds(int roleSessionDurationSeconds) {
this.roleSessionDurationSeconds = roleSessionDurationSeconds;
return this;
}
/**
* Set the tags that is used when creating a new assumed role
* session.
* @param sessionTags the collection of tags which we want to pass to the assume role request.
* @return the itself for chained calls
*/
public Builder withSessionTags(Collection sessionTags) {
if (sessionTags == null) {
this.sessionTags = null;
return this;
}
this.sessionTags = Collections.unmodifiableCollection(new ArrayList(sessionTags));
return this;
}
/**
* Set the transitive tags keys when creating a new assume role session
* @param transitiveTagKeys collection of tags transitive tag keys we want to pass to the assume role request.
* @return the itself for chained calls
*/
public Builder withTransitiveTagKeys(Collection transitiveTagKeys) {
if (transitiveTagKeys == null) {
this.transitiveTagKeys = null;
return this;
}
this.transitiveTagKeys = Collections.unmodifiableCollection(new ArrayList(transitiveTagKeys));
return this;
}
/**
* Set the source identity when creating a new assume role session
* @param sourceIdentity a string represent an identity we want to pass to the assume role request.
* @return the itself for chained calls
*/
public Builder withSourceIdentity(String sourceIdentity) {
this.sourceIdentity = sourceIdentity;
return this;
}
/**
* Sets the AWS Security Token Service (STS) endpoint where session credentials are
* retrieved from. The default AWS Security Token Service (STS) endpoint
* ("sts.amazonaws.com") works for all accounts that are not for China (Beijing) region or
* GovCloud. You only need to change the endpoint to "sts.cn-north-1.amazonaws.com.cn" when
* you are requesting session credentials for services in China(Beijing) region or
* "sts.us-gov-west-1.amazonaws.com" for GovCloud.
* @deprecated Supply a configured STS client via the {@link #withStsClient(AWSSecurityTokenService)}
* setter. Use {@link com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder}
* to create an STS client.
*/
@Deprecated
public Builder withServiceEndpoint(String serviceEndpoint) {
this.serviceEndpoint = serviceEndpoint;
return this;
}
/**
*
* An IAM policy in JSON format to scope down permissions granted from the assume role.
*
*
* This parameter is optional. If you pass a policy, the temporary security
* credentials that are returned by the operation have the permissions that
* are allowed by both (the intersection of) the access policy of the role
* that is being assumed, and the policy that you pass. This gives
* you a way to further restrict the permissions for the resulting temporary
* security credentials. You cannot use the passed policy to grant
* permissions that are in excess of those allowed by the access policy of
* the role that is being assumed. For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, and
* AssumeRoleWithWebIdentity in the IAM User Guide.
*
*
* The format for this parameter, as described by its regex pattern, is a
* string of characters up to 2048 characters in length. The characters can
* be any ASCII character from the space character to the end of the valid
* character list ( -\u00FF). It can also include the tab ( ), linefeed ( ),
* and carriage return ( ) characters.
*
*
*
* The policy plain text must be 2048 bytes or shorter. However, an internal
* conversion compresses it into a packed binary format with a separate
* limit. The PackedPolicySize response element indicates by percentage how
* close to the upper size limit the policy is, with 100% equaling the
* maximum allowed size.
*
*
*
* @param scopeDownPolicy
* An IAM policy in JSON format.
*
* This parameter is optional. If you pass a policy, the temporary
* security credentials that are returned by the operation have the
* permissions that are allowed by both (the intersection of) the
* access policy of the role that is being assumed, and the
* policy that you pass. This gives you a way to further restrict the
* permissions for the resulting temporary security credentials. You
* cannot use the passed policy to grant permissions that are in
* excess of those allowed by the access policy of the role that is
* being assumed. For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, and
* AssumeRoleWithWebIdentity in the IAM User Guide.
*
*
* The format for this parameter, as described by its regex pattern,
* is a string of characters up to 2048 characters in length. The
* characters can be any ASCII character from the space character to
* the end of the valid character list ( -\u00FF). It can also
* include the tab ( ), linefeed ( ), and carriage return ( )
* characters.
*
*
*
* The policy plain text must be 2048 bytes or shorter. However, an
* internal conversion compresses it into a packed binary format with
* a separate limit. The PackedPolicySize response element indicates
* by percentage how close to the upper size limit the policy is,
* with 100% equaling the maximum allowed size.
*
* @return Returns a reference to this object so that method calls can be
* chained together.
*/
public Builder withScopeDownPolicy(String scopeDownPolicy) {
this.scopeDownPolicy = scopeDownPolicy;
return this;
}
/**
* Sets a preconfigured STS client to use for the credentials provider. See {@link
* com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder} for an easy
* way to configure and create an STS client.
*
* Note: This setter is mutually exclusive to the deprecated {@link
* #withClientConfiguration(ClientConfiguration)}, {@link #withLongLivedCredentials(AWSCredentials)},
* {@link #withLongLivedCredentialsProvider(AWSCredentialsProvider)}, and {@link
* #withServiceEndpoint(String)} setters. Construct a fully configured STS client via the
* {@link com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder} and
* pass it to this setter.
*
* @param sts Custom STS client to use.
* @return This object for chained calls.
*/
public Builder withStsClient(AWSSecurityTokenService sts) {
this.sts = sts;
return this;
}
/**
* Build the configured provider
*
* @return the configured STSAssumeRoleSessionCredentialsProvider
*/
public STSAssumeRoleSessionCredentialsProvider build() {
return new STSAssumeRoleSessionCredentialsProvider(this);
}
}
}