-
Notifications
You must be signed in to change notification settings - Fork 864
/
Copy pathECSTaskCredentials.cs
128 lines (115 loc) · 5.41 KB
/
ECSTaskCredentials.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* Copyright 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.
*/
using Amazon.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
namespace Amazon.Runtime
{
/// <summary>
/// When running in an ECS container and AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set,
/// use the given end point to retrieve the credentials.
/// </summary>
public class ECSTaskCredentials : URIBasedRefreshingCredentialHelper
{
/// <summary>
/// These constants should not be consumed by client code. They are only relevant
/// in the context of ECS container and, especially, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, AWS_CONTAINER_CREDENTIALS_FULL_URI & AWS_CONTAINER_AUTHORIZATION_TOKEN
/// environment variable should not be overriden by the client code.
/// </summary>
public const string ContainerCredentialsURIEnvVariable = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
public const string ContainerCredentialsFullURIEnvVariable = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
public const string ContainerCredentialsAuthorizationTokenEnvVariable = "AWS_CONTAINER_AUTHORIZATION_TOKEN";
public const string EndpointAddress = "http://169.254.170.2";
private Uri Uri {
get
{
var relativeUri = Environment.GetEnvironmentVariable(ContainerCredentialsURIEnvVariable);
var fullUri = Environment.GetEnvironmentVariable(ContainerCredentialsFullURIEnvVariable);
// AWS_CONTAINER_CREDENTIALS_FULL_URI variable is not compatible with AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, and will not be used if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set.
if (!string.IsNullOrEmpty(relativeUri))
{
var uriBuilder = new UriBuilder(Server);
uriBuilder.Path = relativeUri;
return uriBuilder.Uri;
}
else if (!string.IsNullOrEmpty(fullUri))
{
return new Uri(fullUri);
}
else
{
throw new ArgumentException($"Cannot fetch credentials from container - neither {ContainerCredentialsURIEnvVariable} or {ContainerCredentialsFullURIEnvVariable}" +
$" environment variables are set.");
}
}
}
private string Server = null;
private static int MaxRetries = 5;
private IWebProxy Proxy;
public ECSTaskCredentials() : this(null) { }
public ECSTaskCredentials(IWebProxy proxy)
{
Server = EndpointAddress;
Proxy = proxy;
}
protected override CredentialsRefreshState GenerateNewCredentials()
{
SecurityCredentials credentials = null;
Uri ecsEndpointUri = Uri;
JitteredDelay retry = new JitteredDelay(new TimeSpan(0, 0, 0, 0, 200), new TimeSpan(0, 0, 0, 0, 50));
// Attempt to get the credentials 4 times ignoring null return/exceptions and on the 5th try, escalate the exception if there is one.
for (int i = 1; ; i++)
{
try
{
// AWS_CONTAINER_AUTHORIZATION_TOKEN is optional environment variable
// If this variable is set the SDK will set the Authorization header on the HTTP request with the environment variable's value.
var headers = CreateAuthorizationHeader();
credentials = GetObjectFromResponse<SecurityCredentials>(ecsEndpointUri, Proxy, headers);
if (credentials != null)
{
break;
}
}
catch (Exception e)
{
if (i == MaxRetries)
{
throw new AmazonServiceException(string.Format(CultureInfo.InvariantCulture,
"Unable to retrieve credentials. Message = \"{0}\".",
e.Message));
}
};
Util.AWSSDKUtils.Sleep(retry.Next());
}
return new CredentialsRefreshState(new ImmutableCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.Token), credentials.Expiration);
}
private static Dictionary<string, string> CreateAuthorizationHeader()
{
Dictionary<string, string> headers = null;
var authorizationToken = Environment.GetEnvironmentVariable(ContainerCredentialsAuthorizationTokenEnvVariable);
if (!string.IsNullOrEmpty(authorizationToken))
{
headers = new Dictionary<string, string>
{
{HeaderKeys.AuthorizationHeader, authorizationToken}
};
}
return headers;
}
}
}