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

software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider Maven / Gradle / Ivy

Go to download

The AWS SDK for Java - Auth module holds the classes that are used for authentication with services

There is a newer version: 2.29.15
Show newest version
/*
 * Copyright 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.auth.credentials;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.SdkTestInternalApi;
import software.amazon.awssdk.auth.credentials.internal.ProfileCredentialsUtils;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.profiles.ProfileFileSupplier;
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.SdkAutoCloseable;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
 * Credentials provider based on AWS configuration profiles. This loads credentials from a {@link ProfileFile}, allowing you to
 * share multiple sets of AWS security credentials between different tools like the AWS SDK for Java and the AWS CLI.
 *
 * 

See http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html

* *

If this credentials provider is loading assume-role credentials from STS, it should be cleaned up with {@link #close()} if * it is no longer being used.

* * @see ProfileFile */ @SdkPublicApi public final class ProfileCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable, ToCopyableBuilder { private volatile AwsCredentialsProvider credentialsProvider; private final RuntimeException loadException; private final Supplier profileFile; private volatile ProfileFile currentProfileFile; private final String profileName; private final Supplier defaultProfileFileLoader; private final Object credentialsProviderLock = new Object(); /** * @see #builder() */ private ProfileCredentialsProvider(BuilderImpl builder) { this.defaultProfileFileLoader = builder.defaultProfileFileLoader; RuntimeException thrownException = null; String selectedProfileName = null; Supplier selectedProfileSupplier = null; try { selectedProfileName = Optional.ofNullable(builder.profileName) .orElseGet(ProfileFileSystemSetting.AWS_PROFILE::getStringValueOrThrow); selectedProfileSupplier = Optional.ofNullable(builder.profileFile) .orElseGet(() -> ProfileFileSupplier.fixedProfileFile(builder.defaultProfileFileLoader.get())); } catch (RuntimeException e) { // If we couldn't load the credentials provider for some reason, save an exception describing why. This exception // will only be raised on calls to resolveCredentials. We don't want to raise an exception here because it may be // expected (eg. in the default credential chain). thrownException = e; } this.loadException = thrownException; this.profileName = selectedProfileName; this.profileFile = selectedProfileSupplier; } /** * Create a {@link ProfileCredentialsProvider} using the {@link ProfileFile#defaultProfileFile()} and default profile name. * Use {@link #builder()} for defining a custom {@link ProfileCredentialsProvider}. */ public static ProfileCredentialsProvider create() { return builder().build(); } /** * Create a {@link ProfileCredentialsProvider} using the given profile name and {@link ProfileFile#defaultProfileFile()}. Use * {@link #builder()} for defining a custom {@link ProfileCredentialsProvider}. * * @param profileName the name of the profile to use from the {@link ProfileFile#defaultProfileFile()} */ public static ProfileCredentialsProvider create(String profileName) { return builder().profileName(profileName).build(); } /** * Get a builder for creating a custom {@link ProfileCredentialsProvider}. */ public static Builder builder() { return new BuilderImpl(); } @Override public AwsCredentials resolveCredentials() { if (loadException != null) { throw loadException; } ProfileFile cachedOrRefreshedProfileFile = refreshProfileFile(); if (shouldUpdateCredentialsProvider(cachedOrRefreshedProfileFile)) { synchronized (credentialsProviderLock) { if (shouldUpdateCredentialsProvider(cachedOrRefreshedProfileFile)) { currentProfileFile = cachedOrRefreshedProfileFile; handleProfileFileReload(cachedOrRefreshedProfileFile); } } } return credentialsProvider.resolveCredentials(); } private void handleProfileFileReload(ProfileFile profileFile) { credentialsProvider = createCredentialsProvider(profileFile, profileName); } private ProfileFile refreshProfileFile() { return profileFile.get(); } private boolean shouldUpdateCredentialsProvider(ProfileFile profileFile) { return credentialsProvider == null || !Objects.equals(currentProfileFile, profileFile); } @Override public String toString() { return ToString.builder("ProfileCredentialsProvider") .add("profileName", profileName) .add("profileFile", currentProfileFile) .build(); } @Override public void close() { // The delegate credentials provider may be closeable (eg. if it's an STS credentials provider). In this case, we should // clean it up when this credentials provider is closed. IoUtils.closeIfCloseable(credentialsProvider, null); } @Override public Builder toBuilder() { return new BuilderImpl(this); } private AwsCredentialsProvider createCredentialsProvider(ProfileFile profileFile, String profileName) { // Load the profile and credentials provider return profileFile.profile(profileName) .flatMap(p -> new ProfileCredentialsUtils(profileFile, p, profileFile::profile).credentialsProvider()) .orElseThrow(() -> { String errorMessage = String.format("Profile file contained no credentials for " + "profile '%s': %s", profileName, profileFile); return SdkClientException.builder().message(errorMessage).build(); }); } /** * A builder for creating a custom {@link ProfileCredentialsProvider}. */ public interface Builder extends CopyableBuilder { /** * Define the profile file that should be used by this credentials provider. By default, the * {@link ProfileFile#defaultProfileFile()} is used. * @see #profileFile(Supplier) */ Builder profileFile(ProfileFile profileFile); /** * Similar to {@link #profileFile(ProfileFile)}, but takes a lambda to configure a new {@link ProfileFile.Builder}. This * removes the need to called {@link ProfileFile#builder()} and {@link ProfileFile.Builder#build()}. */ Builder profileFile(Consumer profileFile); /** * Define the mechanism for loading profile files. * * @param profileFileSupplier Supplier interface for generating a ProfileFile instance. * @see #profileFile(ProfileFile) */ Builder profileFile(Supplier profileFileSupplier); /** * Define the name of the profile that should be used by this credentials provider. By default, the value in * {@link ProfileFileSystemSetting#AWS_PROFILE} is used. */ Builder profileName(String profileName); /** * Create a {@link ProfileCredentialsProvider} using the configuration applied to this builder. */ @Override ProfileCredentialsProvider build(); } static final class BuilderImpl implements Builder { private Supplier profileFile; private String profileName; private Supplier defaultProfileFileLoader = ProfileFile::defaultProfileFile; BuilderImpl() { } BuilderImpl(ProfileCredentialsProvider provider) { this.profileName = provider.profileName; this.defaultProfileFileLoader = provider.defaultProfileFileLoader; this.profileFile = provider.profileFile; } @Override public Builder profileFile(ProfileFile profileFile) { return profileFile(Optional.ofNullable(profileFile) .map(ProfileFileSupplier::fixedProfileFile) .orElse(null)); } public void setProfileFile(ProfileFile profileFile) { profileFile(profileFile); } @Override public Builder profileFile(Consumer profileFile) { return profileFile(ProfileFile.builder().applyMutation(profileFile).build()); } @Override public Builder profileFile(Supplier profileFileSupplier) { this.profileFile = profileFileSupplier; return this; } public void setProfileFile(Supplier supplier) { profileFile(supplier); } @Override public Builder profileName(String profileName) { this.profileName = profileName; return this; } public void setProfileName(String profileName) { profileName(profileName); } @Override public ProfileCredentialsProvider build() { return new ProfileCredentialsProvider(this); } /** * Override the default configuration file to be used when the customer does not explicitly set * profileFile(ProfileFile) or profileFileSupplier(supplier); * {@link #profileFile(ProfileFile)}. Use of this method is * only useful for testing the default behavior. */ @SdkTestInternalApi Builder defaultProfileFileLoader(Supplier defaultProfileFileLoader) { this.defaultProfileFileLoader = defaultProfileFileLoader; return this; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy