All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.services.sts.internal.StsProfileCredentialsProviderFactory Maven / Gradle / Ivy

/*
 * Copyright 2010-2019 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 software.amazon.awssdk.services.sts.internal;

import java.net.URI;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ChildProfileCredentialsProviderFactory;
import software.amazon.awssdk.profiles.Profile;
import software.amazon.awssdk.profiles.ProfileProperty;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.StsClientBuilder;
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.SdkAutoCloseable;

/**
 * An implementation of {@link ChildProfileCredentialsProviderFactory} that uses configuration in a profile to create a
 * {@link StsAssumeRoleCredentialsProvider}.
 */
@SdkInternalApi
public final class StsProfileCredentialsProviderFactory implements ChildProfileCredentialsProviderFactory {
    private static final String MISSING_PROPERTY_ERROR_FORMAT = "'%s' must be set to use role-based credential loading in the "
                                                                + "'%s' profile.";

    @Override
    public AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile) {
        return new StsProfileCredentialsProvider(sourceCredentialsProvider, profile);
    }

    /**
     * A wrapper for a {@link StsAssumeRoleCredentialsProvider} that is returned by this factory when
     * {@link #create(AwsCredentialsProvider, Profile)} is invoked. This wrapper is important because it ensures the parent
     * credentials provider is closed when the assume-role credentials provider is no longer needed.
     */
    private static final class StsProfileCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
        private final StsClient stsClient;
        private final AwsCredentialsProvider parentCredentialsProvider;
        private final StsAssumeRoleCredentialsProvider credentialsProvider;

        private StsProfileCredentialsProvider(AwsCredentialsProvider parentCredentialsProvider, Profile profile) {
            String roleArn = requireProperty(profile, ProfileProperty.ROLE_ARN);
            String roleSessionName = profile.property(ProfileProperty.ROLE_SESSION_NAME)
                                            .orElseGet(() -> "aws-sdk-java-" + System.currentTimeMillis());
            String externalId = profile.property(ProfileProperty.EXTERNAL_ID).orElse(null);

            AssumeRoleRequest assumeRoleRequest = AssumeRoleRequest.builder()
                                                                   .roleArn(roleArn)
                                                                   .roleSessionName(roleSessionName)
                                                                   .externalId(externalId)
                                                                   .build();

            this.stsClient = StsClient.builder()
                                      .applyMutation(client -> configureEndpoint(client, profile))
                                      .credentialsProvider(parentCredentialsProvider)
                                      .build();

            this.parentCredentialsProvider = parentCredentialsProvider;
            this.credentialsProvider = StsAssumeRoleCredentialsProvider.builder()
                                                                       .stsClient(stsClient)
                                                                       .refreshRequest(assumeRoleRequest)
                                                                       .build();
        }

        private void configureEndpoint(StsClientBuilder stsClientBuilder, Profile profile) {
            Region stsRegion = profile.property(ProfileProperty.REGION)
                                      .map(Region::of)
                                      .orElseGet(() -> {
                                          try {
                                              return new DefaultAwsRegionProviderChain().getRegion();
                                          } catch (RuntimeException e) {
                                              return null;
                                          }
                                      });

            if (stsRegion != null) {
                stsClientBuilder.region(stsRegion);
            } else {
                stsClientBuilder.region(Region.US_EAST_1);
                stsClientBuilder.endpointOverride(URI.create("https://sts.amazonaws.com"));
            }
        }

        private String requireProperty(Profile profile, String requiredProperty) {
            return profile.property(requiredProperty)
                          .orElseThrow(() -> new IllegalArgumentException(String.format(MISSING_PROPERTY_ERROR_FORMAT,
                                                                                        requiredProperty, profile.name())));
        }

        @Override
        public AwsCredentials resolveCredentials() {
            return this.credentialsProvider.resolveCredentials();
        }

        @Override
        public void close() {
            IoUtils.closeIfCloseable(parentCredentialsProvider, null);
            IoUtils.closeQuietly(credentialsProvider, null);
            IoUtils.closeQuietly(stsClient, null);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy