/* * Copyright 2014-2017 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 com.amazonaws.auth.profile; import com.amazonaws.SdkClientException; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.profile.internal.AllProfiles; import com.amazonaws.auth.profile.internal.AwsProfileNameLoader; import com.amazonaws.auth.profile.internal.BasicProfile; import com.amazonaws.auth.profile.internal.BasicProfileConfigLoader; import com.amazonaws.auth.profile.internal.Profile; import com.amazonaws.auth.profile.internal.ProfileAssumeRoleCredentialsProvider; import com.amazonaws.auth.profile.internal.ProfileStaticCredentialsProvider; import com.amazonaws.auth.profile.internal.securitytoken.ProfileCredentialsService; import com.amazonaws.auth.profile.internal.securitytoken.STSProfileCredentialsServiceLoader; import com.amazonaws.internal.StaticCredentialsProvider; import com.amazonaws.profile.path.AwsProfileFileLocationProvider; import com.amazonaws.util.ValidationUtils; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Loads the local AWS credential profiles from the standard location (~/.aws/credentials), which * can be easily overridden through the <code>AWS_CREDENTIAL_PROFILES_FILE</code> environment * variable or by specifying an alternate credentials file location through this class' constructor. * <p> The AWS credentials file format allows you to specify multiple profiles, each with their own * set of AWS security credentials: * <pre> * [default] * aws_access_key_id=testAccessKey * aws_secret_access_key=testSecretKey * aws_session_token=testSessionToken * * [test-user] * aws_access_key_id=testAccessKey * aws_secret_access_key=testSecretKey * aws_session_token=testSessionToken * </pre> * * <p> These credential profiles allow you to share multiple sets of AWS security credentails * between different tools such as the AWS SDK for Java and the AWS CLI. * * <p> For more information on setting up AWS credential profiles, see: * http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html * * @see ProfileCredentialsProvider */ public class ProfilesConfigFile { /** * Environment variable name for overriding the default AWS profile */ @Deprecated public static final String AWS_PROFILE_ENVIRONMENT_VARIABLE = AwsProfileNameLoader.AWS_PROFILE_ENVIRONMENT_VARIABLE; /** * System property name for overriding the default AWS profile */ @Deprecated public static final String AWS_PROFILE_SYSTEM_PROPERTY = AwsProfileNameLoader.AWS_PROFILE_SYSTEM_PROPERTY; /** * Name of the default profile as specified in the configuration file. */ @Deprecated public static final String DEFAULT_PROFILE_NAME = AwsProfileNameLoader.DEFAULT_PROFILE_NAME; private final File profileFile; private final ProfileCredentialsService profileCredentialsService; /** * Cache credential providers as credentials from profiles are requested. Doesn't really make a * difference for basic credentials but for assume role it's more efficient as each assume role * provider has it's own async refresh logic. */ private final ConcurrentHashMap<String, AWSCredentialsProvider> credentialProviderCache = new ConcurrentHashMap<String, AWSCredentialsProvider>(); private volatile AllProfiles allProfiles; private volatile long profileFileLastModified; /** * Loads the AWS credential profiles file from the default location (~/.aws/credentials) or from * an alternate location if <code>AWS_CREDENTIAL_PROFILES_FILE</code> is set. */ public ProfilesConfigFile() throws SdkClientException { this(getCredentialProfilesFile()); } /** * Loads the AWS credential profiles from the file. The path of the file is specified as a * parameter to the constructor. */ public ProfilesConfigFile(String filePath) { this(new File(validateFilePath(filePath))); } /** * Loads the AWS credential profiles from the file. The path of the file is specified as a * parameter to the constructor. */ public ProfilesConfigFile(String filePath, ProfileCredentialsService credentialsService) throws SdkClientException { this(new File(validateFilePath(filePath)), credentialsService); } private static String validateFilePath(String filePath) { if (filePath == null) { throw new IllegalArgumentException( "Unable to load AWS profiles: specified file path is null."); } return filePath; } /** * Loads the AWS credential profiles from the file. The reference to the file is specified as a * parameter to the constructor. */ public ProfilesConfigFile(File file) throws SdkClientException { this(file, STSProfileCredentialsServiceLoader.getInstance()); } /** * Loads the AWS credential profiles from the file. The reference to the file is specified as a * parameter to the constructor. */ public ProfilesConfigFile(File file, ProfileCredentialsService credentialsService) throws SdkClientException { profileFile = ValidationUtils.assertNotNull(file, "profile file"); profileCredentialsService = credentialsService; profileFileLastModified = file.lastModified(); allProfiles = loadProfiles(profileFile); } /** * Returns the AWS credentials for the specified profile. */ public AWSCredentials getCredentials(String profileName) { final AWSCredentialsProvider provider = credentialProviderCache.get(profileName); if (provider != null) { return provider.getCredentials(); } else { BasicProfile profile = allProfiles.getProfile(profileName); if (profile == null) { throw new IllegalArgumentException("No AWS profile named '" + profileName + "'"); } final AWSCredentialsProvider newProvider = fromProfile(profile); credentialProviderCache.put(profileName, newProvider); return newProvider.getCredentials(); } } /** * Reread data from disk. */ public void refresh() { if (profileFile.lastModified() > profileFileLastModified) { profileFileLastModified = profileFile.lastModified(); allProfiles = loadProfiles(profileFile); } credentialProviderCache.clear(); } public Map<String, BasicProfile> getAllBasicProfiles() { return allProfiles.getProfiles(); } @Deprecated public Map<String, Profile> getAllProfiles() { Map<String, Profile> legacyProfiles = new HashMap<String, Profile>(); for (Map.Entry<String, BasicProfile> entry : getAllBasicProfiles().entrySet()) { final String profileName = entry.getKey(); legacyProfiles.put(profileName, new Profile(profileName, entry.getValue().getProperties(), new StaticCredentialsProvider( getCredentials(profileName)))); } return legacyProfiles; } private static File getCredentialProfilesFile() { return AwsProfileFileLocationProvider.DEFAULT_CREDENTIALS_LOCATION_PROVIDER.getLocation(); } private static AllProfiles loadProfiles(File file) { return BasicProfileConfigLoader.INSTANCE.loadProfiles(file); } private AWSCredentialsProvider fromProfile(BasicProfile profile) { if (profile.isRoleBasedProfile()) { return new ProfileAssumeRoleCredentialsProvider(profileCredentialsService, allProfiles, profile); } else { return new ProfileStaticCredentialsProvider(profile); } } }