18
18
import static java .time .temporal .ChronoUnit .MINUTES ;
19
19
import static software .amazon .awssdk .utils .ComparableUtils .maximum ;
20
20
import static software .amazon .awssdk .utils .FunctionalUtils .invokeSafely ;
21
+ import static software .amazon .awssdk .utils .StringUtils .isBlank ;
21
22
import static software .amazon .awssdk .utils .cache .CachedSupplier .StaleValueBehavior .ALLOW ;
22
23
23
24
import java .net .URI ;
@@ -103,6 +104,8 @@ private enum ApiVersion {
103
104
private final Supplier <ProfileFile > profileFile ;
104
105
105
106
private final String profileName ;
107
+
108
+ private final String ec2InstanceProfileName ;
106
109
107
110
private final Duration staleTime ;
108
111
@@ -118,6 +121,13 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
118
121
.orElseGet (() -> ProfileFileSupplier .fixedProfileFile (ProfileFile .defaultProfileFile ()));
119
122
this .profileName = Optional .ofNullable (builder .profileName )
120
123
.orElseGet (ProfileFileSystemSetting .AWS_PROFILE ::getStringValueOrThrow );
124
+ this .ec2InstanceProfileName = builder .ec2InstanceProfileName ;
125
+
126
+ if (isBlank (ec2InstanceProfileName ) && ec2InstanceProfileName != null ) {
127
+ throw SdkClientException .builder ()
128
+ .message ("ec2InstanceProfileName cannot be blank" )
129
+ .build ();
130
+ }
121
131
122
132
this .httpCredentialsLoader = HttpCredentialsLoader .create (PROVIDER_NAME );
123
133
this .configProvider =
@@ -173,6 +183,11 @@ private RefreshResult<AwsCredentials> refreshCredentials() {
173
183
174
184
try {
175
185
LoadedCredentials credentials = httpCredentialsLoader .loadCredentials (createEndpointProvider ());
186
+
187
+ if (apiVersion == ApiVersion .UNKNOWN ) {
188
+ apiVersion = ApiVersion .EXTENDED ;
189
+ }
190
+
176
191
Instant expiration = credentials .getExpiration ().orElse (null );
177
192
log .debug (() -> "Loaded credentials from IMDS with expiration time of " + expiration );
178
193
@@ -186,19 +201,25 @@ private RefreshResult<AwsCredentials> refreshCredentials() {
186
201
} catch (Ec2MetadataClientException e ) {
187
202
if (e .statusCode () == 404 ) {
188
203
log .debug (() -> "Resolved profile is no longer available. Resetting it and trying again." );
189
- resolvedProfile = null ;
190
204
191
205
if (apiVersion == ApiVersion .UNKNOWN ) {
192
206
apiVersion = ApiVersion .LEGACY ;
193
207
return refreshCredentials ();
208
+ } else if (ec2InstanceProfileName == null && configProvider .ec2InstanceProfileName () == null ) {
209
+ // Resolved profile name is invalid, reset it and try again
210
+ resolvedProfile = null ;
211
+
212
+ profileRetryCount ++;
213
+ if (profileRetryCount <= MAX_PROFILE_RETRIES ) {
214
+ log .debug (() -> "Profile name not found, retrying fetching the profile name again." );
215
+ return refreshCredentials ();
216
+ }
217
+ } else {
218
+ throw SdkClientException .builder ()
219
+ .message ("Invalid profile name" )
220
+ .cause (e )
221
+ .build ();
194
222
}
195
-
196
- profileRetryCount ++;
197
- if (profileRetryCount <= MAX_PROFILE_RETRIES ) {
198
- log .debug (() -> "Profile name not found, retrying fetching the profile name again." );
199
- return refreshCredentials ();
200
- }
201
- throw SdkClientException .create (FAILED_TO_LOAD_CREDENTIALS_ERROR , e );
202
223
}
203
224
throw SdkClientException .create (FAILED_TO_LOAD_CREDENTIALS_ERROR , e );
204
225
} catch (RuntimeException e ) {
@@ -328,6 +349,15 @@ private boolean isInsecureFallbackDisabled() {
328
349
}
329
350
330
351
private String [] getSecurityCredentials (String imdsHostname , String metadataToken ) {
352
+ if (ec2InstanceProfileName != null ) {
353
+ return new String []{ec2InstanceProfileName };
354
+ }
355
+
356
+ String configuredProfileName = this .configProvider .ec2InstanceProfileName ();
357
+ if (configuredProfileName != null ) {
358
+ return new String []{configuredProfileName };
359
+ }
360
+
331
361
if (resolvedProfile != null ) {
332
362
return new String []{resolvedProfile };
333
363
}
@@ -383,6 +413,19 @@ public Builder toBuilder() {
383
413
*/
384
414
public interface Builder extends HttpCredentialsProvider .Builder <InstanceProfileCredentialsProvider , Builder >,
385
415
CopyableBuilder <Builder , InstanceProfileCredentialsProvider > {
416
+ /**
417
+ * Configure the EC2 instance profile name to use for retrieving credentials.
418
+ *
419
+ * <p>When this is set, the provider will skip fetching the list of available instance profiles
420
+ * and use this name directly. This can improve performance by reducing the number of calls to IMDS.
421
+ *
422
+ * <p>By default, this is not set and the provider will discover the instance profile name from IMDS.
423
+ *
424
+ * @param ec2InstanceProfileName The EC2 instance profile name to use
425
+ * @return This builder for method chaining
426
+ */
427
+ Builder ec2InstanceProfileName (String ec2InstanceProfileName );
428
+
386
429
/**
387
430
* Configure the profile file used for loading IMDS-related configuration, like the endpoint mode (IPv4 vs IPv6).
388
431
*
@@ -434,6 +477,7 @@ static final class BuilderImpl implements Builder {
434
477
private String asyncThreadName ;
435
478
private Supplier <ProfileFile > profileFile ;
436
479
private String profileName ;
480
+ private String ec2InstanceProfileName ;
437
481
private Duration staleTime ;
438
482
439
483
private BuilderImpl () {
@@ -447,6 +491,7 @@ private BuilderImpl(InstanceProfileCredentialsProvider provider) {
447
491
this .asyncThreadName = provider .asyncThreadName ;
448
492
this .profileFile = provider .profileFile ;
449
493
this .profileName = provider .profileName ;
494
+ this .ec2InstanceProfileName = provider .ec2InstanceProfileName ;
450
495
this .staleTime = provider .staleTime ;
451
496
}
452
497
@@ -515,6 +560,17 @@ public Builder profileName(String profileName) {
515
560
public void setProfileName (String profileName ) {
516
561
profileName (profileName );
517
562
}
563
+
564
+ @ Override
565
+ public Builder ec2InstanceProfileName (String ec2InstanceProfileName ) {
566
+ this .ec2InstanceProfileName = ec2InstanceProfileName ;
567
+ return this ;
568
+ }
569
+
570
+ public void setEc2InstanceProfileName (String ec2InstanceProfileName ) {
571
+ ec2InstanceProfileName (ec2InstanceProfileName );
572
+ }
573
+
518
574
519
575
@ Override
520
576
public Builder staleTime (Duration duration ) {
0 commit comments