@@ -41,9 +41,15 @@ internal class DefaultInstanceProfileAWSCredentials : AWSCredentials, IDisposabl
41
41
private const string FailedToGetCredentialsMessage = "Failed to retrieve credentials from EC2 Instance Metadata Service." ;
42
42
private static readonly TimeSpan _credentialsLockTimeout = TimeSpan . FromSeconds ( 5 ) ;
43
43
44
+ /// <summary>
45
+ /// Control flag: in the event IMDS returns an expired credential, a refresh must be immediately
46
+ /// retried, if it continues to fail, then retry every 5-10 minutes.
47
+ /// </summary>
48
+ private static volatile bool _imdsRefreshFailed = false ;
49
+
44
50
private const string _usingExpiredCredentialsFromIMDS =
45
51
"Attempting credential expiration extension due to a credential service availability issue. " +
46
- "A refresh of these credentials will be attempted again in 5-15 minutes." ;
52
+ "A refresh of these credentials will be attempted again in 5-10 minutes." ;
47
53
48
54
private static DefaultInstanceProfileAWSCredentials _instance ;
49
55
@@ -94,12 +100,24 @@ public override ImmutableCredentials GetCredentials()
94
100
{
95
101
if ( null != _lastRetrievedCredentials )
96
102
{
103
+ if ( _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) &&
104
+ ! _imdsRefreshFailed )
105
+ {
106
+ // this is the first failure - immediately try to renew
107
+ _imdsRefreshFailed = true ;
108
+ _lastRetrievedCredentials = FetchCredentials ( ) ;
109
+ }
110
+
97
111
// if credentials are expired, we'll still return them, but log a message about
98
112
// them being expired.
99
113
if ( _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) )
100
114
{
101
115
_logger . InfoFormat ( _usingExpiredCredentialsFromIMDS ) ;
102
116
}
117
+ else
118
+ {
119
+ _imdsRefreshFailed = false ;
120
+ }
103
121
104
122
return _lastRetrievedCredentials ? . Credentials . Copy ( ) ;
105
123
}
@@ -121,12 +139,24 @@ public override ImmutableCredentials GetCredentials()
121
139
_lastRetrievedCredentials = FetchCredentials ( ) ;
122
140
}
123
141
142
+ if ( _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) &&
143
+ ! _imdsRefreshFailed )
144
+ {
145
+ // this is the first failure - immediately try to renew
146
+ _imdsRefreshFailed = true ;
147
+ _lastRetrievedCredentials = FetchCredentials ( ) ;
148
+ }
149
+
124
150
// if credentials are expired, we'll still return them, but log a message about
125
151
// them being expired.
126
152
if ( _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) )
127
153
{
128
154
_logger . InfoFormat ( _usingExpiredCredentialsFromIMDS ) ;
129
155
}
156
+ else
157
+ {
158
+ _imdsRefreshFailed = false ;
159
+ }
130
160
131
161
credentials = _lastRetrievedCredentials . Credentials ? . Copy ( ) ;
132
162
}
@@ -169,10 +199,24 @@ private void RenewCredentials(object unused)
169
199
// would remain unchanged and would continue to be returned in GetCredentials()
170
200
_lastRetrievedCredentials = FetchCredentials ( ) ;
171
201
202
+ // check for a first time failure
203
+ if ( ! _imdsRefreshFailed &&
204
+ _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) )
205
+ {
206
+ // this is the first failure - immediately try to renew
207
+ _imdsRefreshFailed = true ;
208
+ _lastRetrievedCredentials = FetchCredentials ( ) ;
209
+ }
210
+
211
+ // first failure refresh failed OR subsequent refresh failed.
172
212
if ( _lastRetrievedCredentials . IsExpiredWithin ( TimeSpan . Zero ) )
173
213
{
174
214
// relax the refresh rate to at least 5 minutes
175
- refreshRate = TimeSpan . FromMinutes ( new Random ( ) . Next ( 5 , 16 ) ) ;
215
+ refreshRate = TimeSpan . FromMinutes ( new Random ( ) . Next ( 5 , 11 ) ) ;
216
+ }
217
+ else
218
+ {
219
+ _imdsRefreshFailed = false ;
176
220
}
177
221
}
178
222
catch ( OperationCanceledException e )
0 commit comments