1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.auth.credentials; 17 18 import java.util.Optional; 19 import java.util.function.Supplier; 20 import software.amazon.awssdk.annotations.SdkPublicApi; 21 import software.amazon.awssdk.auth.credentials.internal.LazyAwsCredentialsProvider; 22 import software.amazon.awssdk.profiles.ProfileFile; 23 import software.amazon.awssdk.profiles.ProfileFileSupplier; 24 import software.amazon.awssdk.utils.SdkAutoCloseable; 25 import software.amazon.awssdk.utils.ToString; 26 import software.amazon.awssdk.utils.builder.CopyableBuilder; 27 import software.amazon.awssdk.utils.builder.ToCopyableBuilder; 28 29 /** 30 * AWS credentials provider chain that looks for credentials in this order: 31 * <ol> 32 * <li>Java System Properties - {@code aws.accessKeyId} and {@code aws.secretAccessKey}</li> 33 * <li>Environment Variables - {@code AWS_ACCESS_KEY_ID} and {@code AWS_SECRET_ACCESS_KEY}</li> 34 * <li>Web Identity Token credentials from system properties or environment variables</li> 35 * <li>Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI</li> 36 * <li>Credentials delivered through the Amazon EC2 container service if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment 37 * variable is set and security manager has permission to access the variable,</li> 38 * <li>Instance profile credentials delivered through the Amazon EC2 metadata service</li> 39 * </ol> 40 * 41 * @see SystemPropertyCredentialsProvider 42 * @see EnvironmentVariableCredentialsProvider 43 * @see ProfileCredentialsProvider 44 * @see WebIdentityTokenFileCredentialsProvider 45 * @see ContainerCredentialsProvider 46 * @see InstanceProfileCredentialsProvider 47 */ 48 @SdkPublicApi 49 public final class DefaultCredentialsProvider 50 implements AwsCredentialsProvider, SdkAutoCloseable, 51 ToCopyableBuilder<DefaultCredentialsProvider.Builder, DefaultCredentialsProvider> { 52 53 private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER = new DefaultCredentialsProvider(builder()); 54 55 private final LazyAwsCredentialsProvider providerChain; 56 57 private final Supplier<ProfileFile> profileFile; 58 59 private final String profileName; 60 61 private final Boolean reuseLastProviderEnabled; 62 63 private final Boolean asyncCredentialUpdateEnabled; 64 65 /** 66 * @see #builder() 67 */ DefaultCredentialsProvider(Builder builder)68 private DefaultCredentialsProvider(Builder builder) { 69 this.profileFile = builder.profileFile; 70 this.profileName = builder.profileName; 71 this.reuseLastProviderEnabled = builder.reuseLastProviderEnabled; 72 this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled; 73 this.providerChain = createChain(builder); 74 } 75 76 /** 77 * Create an instance of the {@link DefaultCredentialsProvider} using the default configuration. Configuration can be 78 * specified by creating an instance using the {@link #builder()}. 79 */ create()80 public static DefaultCredentialsProvider create() { 81 return DEFAULT_CREDENTIALS_PROVIDER; 82 } 83 84 /** 85 * Create the default credential chain using the configuration in the provided builder. 86 */ createChain(Builder builder)87 private static LazyAwsCredentialsProvider createChain(Builder builder) { 88 boolean asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled; 89 boolean reuseLastProviderEnabled = builder.reuseLastProviderEnabled; 90 91 return LazyAwsCredentialsProvider.create(() -> { 92 AwsCredentialsProvider[] credentialsProviders = new AwsCredentialsProvider[] { 93 SystemPropertyCredentialsProvider.create(), 94 EnvironmentVariableCredentialsProvider.create(), 95 WebIdentityTokenFileCredentialsProvider.builder() 96 .asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled) 97 .build(), 98 ProfileCredentialsProvider.builder() 99 .profileFile(builder.profileFile) 100 .profileName(builder.profileName) 101 .build(), 102 ContainerCredentialsProvider.builder() 103 .asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled) 104 .build(), 105 InstanceProfileCredentialsProvider.builder() 106 .asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled) 107 .profileFile(builder.profileFile) 108 .profileName(builder.profileName) 109 .build() 110 }; 111 112 return AwsCredentialsProviderChain.builder() 113 .reuseLastProviderEnabled(reuseLastProviderEnabled) 114 .credentialsProviders(credentialsProviders) 115 .build(); 116 }); 117 } 118 119 /** 120 * Get a builder for defining a {@link DefaultCredentialsProvider} with custom configuration. 121 */ builder()122 public static Builder builder() { 123 return new Builder(); 124 } 125 126 @Override resolveCredentials()127 public AwsCredentials resolveCredentials() { 128 return providerChain.resolveCredentials(); 129 } 130 131 @Override close()132 public void close() { 133 providerChain.close(); 134 } 135 136 @Override toString()137 public String toString() { 138 return ToString.builder("DefaultCredentialsProvider") 139 .add("providerChain", providerChain) 140 .build(); 141 } 142 143 @Override toBuilder()144 public Builder toBuilder() { 145 return new Builder(this); 146 } 147 148 /** 149 * Configuration that defines the {@link DefaultCredentialsProvider}'s behavior. 150 */ 151 public static final class Builder implements CopyableBuilder<Builder, DefaultCredentialsProvider> { 152 private Supplier<ProfileFile> profileFile; 153 private String profileName; 154 private Boolean reuseLastProviderEnabled = true; 155 private Boolean asyncCredentialUpdateEnabled = false; 156 157 /** 158 * Created with {@link #builder()}. 159 */ Builder()160 private Builder() { 161 } 162 Builder(DefaultCredentialsProvider credentialsProvider)163 private Builder(DefaultCredentialsProvider credentialsProvider) { 164 this.profileFile = credentialsProvider.profileFile; 165 this.profileName = credentialsProvider.profileName; 166 this.reuseLastProviderEnabled = credentialsProvider.reuseLastProviderEnabled; 167 this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled; 168 } 169 profileFile(ProfileFile profileFile)170 public Builder profileFile(ProfileFile profileFile) { 171 return profileFile(Optional.ofNullable(profileFile) 172 .map(ProfileFileSupplier::fixedProfileFile) 173 .orElse(null)); 174 } 175 profileFile(Supplier<ProfileFile> profileFileSupplier)176 public Builder profileFile(Supplier<ProfileFile> profileFileSupplier) { 177 this.profileFile = profileFileSupplier; 178 return this; 179 } 180 profileName(String profileName)181 public Builder profileName(String profileName) { 182 this.profileName = profileName; 183 return this; 184 } 185 186 /** 187 * Controls whether the provider should reuse the last successful credentials provider in the chain. Reusing the last 188 * successful credentials provider will typically return credentials faster than searching through the chain. 189 * 190 * <p>By default, this is enabled.</p> 191 */ reuseLastProviderEnabled(Boolean reuseLastProviderEnabled)192 public Builder reuseLastProviderEnabled(Boolean reuseLastProviderEnabled) { 193 this.reuseLastProviderEnabled = reuseLastProviderEnabled; 194 return this; 195 } 196 197 /** 198 * Configure whether this provider should fetch credentials asynchronously in the background. If this is true, threads are 199 * less likely to block when {@link #resolveCredentials()} is called, but additional resources are used to maintain the 200 * provider. 201 * 202 * <p>By default, this is disabled.</p> 203 */ asyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled)204 public Builder asyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled) { 205 this.asyncCredentialUpdateEnabled = asyncCredentialUpdateEnabled; 206 return this; 207 } 208 209 /** 210 * Create a {@link DefaultCredentialsProvider} using the configuration defined in this builder. 211 */ 212 @Override build()213 public DefaultCredentialsProvider build() { 214 return new DefaultCredentialsProvider(this); 215 } 216 } 217 } 218