Created
June 15, 2020 15:07
-
-
Save DTTerastar/f373bb6dbfc8d1437665f7b23e0a2cbb to your computer and use it in GitHub Desktop.
Fixed implementation of InstanceProfileAwsCredentials
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal class FixedInstanceProfileAwsCredentials : AWSCredentials, IDisposable | |
{ | |
private static readonly Lazy<FixedInstanceProfileAwsCredentials> InstanceLazy = new Lazy<FixedInstanceProfileAwsCredentials>(() => new FixedInstanceProfileAwsCredentials()); | |
private readonly Task _credentialsRetrieverTimer; | |
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1); | |
private bool _disposed; | |
private ImmutableCredentials _lastRetrievedCredentials; | |
private FixedInstanceProfileAwsCredentials() | |
{ | |
_credentialsRetrieverTimer = Task.Run(async () => | |
{ | |
while (!_disposed) | |
try | |
{ | |
_lastRetrievedCredentials = FetchCredentials(); | |
await Task.Delay(RefreshRate); | |
} | |
catch (Exception ex) | |
{ | |
Log.Error(ex, "Error in RenewCredentials"); | |
await Task.Delay(ErrorRefreshRate); | |
} | |
}); | |
} | |
private static TimeSpan ErrorRefreshRate { get; } = TimeSpan.FromSeconds(5); | |
private static TimeSpan RefreshRate { get; } = TimeSpan.FromMinutes(15); | |
public static FixedInstanceProfileAwsCredentials Instance => InstanceLazy.Value; | |
public void Dispose() | |
{ | |
_disposed = true; | |
_credentialsRetrieverTimer.GetAwaiter().GetResult(); | |
} | |
/// <summary> | |
/// Returns a copy of the most recent instance profile credentials. | |
/// </summary> | |
public override ImmutableCredentials GetCredentials() | |
{ | |
return GetCredentialsAsync().GetAwaiter().GetResult(); | |
} | |
/// <summary> | |
/// Returns a copy of the most recent instance profile credentials. | |
/// </summary> | |
public override async Task<ImmutableCredentials> GetCredentialsAsync() | |
{ | |
if (!EC2InstanceMetadata.IsIMDSEnabled) throw new AmazonServiceException("Unable to retrieve credentials."); | |
var immutableCredentials = _lastRetrievedCredentials?.Copy(); | |
if (immutableCredentials != null) return immutableCredentials; | |
await _semaphore.WaitAsync(); | |
try | |
{ | |
immutableCredentials = _lastRetrievedCredentials?.Copy(); | |
if (immutableCredentials != null) return immutableCredentials; | |
return _lastRetrievedCredentials = FetchCredentials(); | |
} | |
finally | |
{ | |
_semaphore.Release(); | |
} | |
} | |
private ImmutableCredentials FetchCredentials() | |
{ | |
Log.Debug("Fetching Credentials"); | |
var securityCredentials = EC2InstanceMetadata.IAMSecurityCredentials; | |
if (securityCredentials == null) | |
throw new AmazonServiceException("Unable to get IAM security credentials from EC2 Instance Metadata Service."); | |
var index = securityCredentials.Keys.FirstOrDefault(); | |
if (string.IsNullOrEmpty(index)) | |
throw new AmazonServiceException("Unable to get EC2 instance role from EC2 Instance Metadata Service."); | |
var credentialMetadata = securityCredentials[index]; | |
if (credentialMetadata == null) throw new AmazonServiceException("Unable to get credentials for role \"" + index + "\" from EC2 Instance Metadata Service."); | |
return new ImmutableCredentials(credentialMetadata.AccessKeyId, credentialMetadata.SecretAccessKey, credentialMetadata.Token); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment