-
Notifications
You must be signed in to change notification settings - Fork 756
/
Copy pathAWSSigV4Signer.cs
138 lines (110 loc) · 5.97 KB
/
AWSSigV4Signer.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
129
130
131
132
133
134
135
136
137
138
using System;
using System.Text;
using RestSharp;
using Amazon.Runtime;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using System.Threading;
namespace Amazon.SellingPartnerAPIAA
{
public class AWSSigV4Signer
{
public virtual AWSSignerHelper AwsSignerHelper { get; set; }
private AWSAuthenticationCredentials awsCredentials;
private AssumeRoleResponse assumeRole;
public const string SecurityTokenHeaderName = "X-Amz-Security-Token";
/// <summary>
/// Constructor for AWSSigV4Signer
/// </summary>
/// <param name="awsAuthenticationCredentials">AWS Developer Account Credentials</param>
public AWSSigV4Signer(AWSAuthenticationCredentials awsAuthenticationCredentials)
{
awsCredentials = awsAuthenticationCredentials;
AwsSignerHelper = new AWSSignerHelper();
}
/// <summary>
/// Overloaded Constructor for AWSSigV4Signer using IAM Role
/// </summary>
/// <param name="awsAuthenticationCredentials">AWS Developer Account Credentials</param>
/// <param name="awsAuthenticationCredentialsProvider">AWS IAM Role and Session Name container</param>
public AWSSigV4Signer(AWSAuthenticationCredentials awsAuthenticationCredentials,
AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider)
{
awsCredentials = awsAuthenticationCredentials;
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(
awsAuthenticationCredentials.AccessKeyId, awsAuthenticationCredentials.SecretKey);
AmazonSecurityTokenServiceClient sts = new AmazonSecurityTokenServiceClient(basicAWSCredentials);
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken cancellationToken = source.Token;
assumeRole = sts.AssumeRoleAsync(new AssumeRoleRequest{
RoleArn = awsAuthenticationCredentialsProvider.RoleArn,
RoleSessionName = awsAuthenticationCredentialsProvider.RoleSessionName
}).Result;
AwsSignerHelper = new AWSSignerHelper();
}
/// <summary>
/// Signs a Request with AWS Signature Version 4
/// </summary>
/// <param name="request">RestRequest which needs to be signed</param>
/// <param name="host">Request endpoint</param>
/// <returns>RestRequest with AWS Signature</returns>
public IRestRequest Sign(IRestRequest request, string host)
{
DateTime signingDate = AwsSignerHelper.SetDateAndHostHeaders(request, host);
string signedHeaders = AwsSignerHelper.ExtractSignedHeaders(request);
string hashedCanonicalRequest = CreateCanonicalRequest(request, signedHeaders);
string stringToSign = AwsSignerHelper.BuildStringToSign(signingDate,
hashedCanonicalRequest,
awsCredentials.Region);
if (assumeRole != null)
{
Credentials credentials = assumeRole.Credentials;
AwsSignerHelper.SetSessionTokenHeader(request, credentials.SessionToken);
string signature = AwsSignerHelper.CalculateSignature(stringToSign,
signingDate,
credentials.SecretAccessKey,
awsCredentials.Region);
AwsSignerHelper.AddSignature(request,
credentials.AccessKeyId,
signedHeaders,
signature,
awsCredentials.Region,
signingDate);
return request;
}
else
{
string signature = AwsSignerHelper.CalculateSignature(stringToSign,
signingDate,
awsCredentials.SecretKey,
awsCredentials.Region);
AwsSignerHelper.AddSignature(request,
awsCredentials.AccessKeyId,
signedHeaders,
signature,
awsCredentials.Region,
signingDate);
return request;
}
}
private string CreateCanonicalRequest(IRestRequest restRequest, string signedHeaders)
{
var canonicalizedRequest = new StringBuilder();
//Request Method
canonicalizedRequest.AppendFormat("{0}\n", restRequest.Method);
//CanonicalURI
canonicalizedRequest.AppendFormat("{0}\n", AwsSignerHelper.ExtractCanonicalURIParameters(restRequest.Resource));
//CanonicalQueryString
canonicalizedRequest.AppendFormat("{0}\n", AwsSignerHelper.ExtractCanonicalQueryString(restRequest));
//CanonicalHeaders
canonicalizedRequest.AppendFormat("{0}\n", AwsSignerHelper.ExtractCanonicalHeaders(restRequest));
//SignedHeaders
canonicalizedRequest.AppendFormat("{0}\n", signedHeaders);
// Hash(digest) the payload in the body
canonicalizedRequest.AppendFormat(AwsSignerHelper.HashRequestBody(restRequest));
string canonicalRequest = canonicalizedRequest.ToString();
//Create a digest(hash) of the canonical request
return Utils.ToHex(Utils.Hash(canonicalRequest));
}
}
}