1 /*
2 * Copyright 2014-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15 package com.amazonaws.auth.internal;
16
17 import com.amazonaws.SignableRequest;
18 import com.amazonaws.auth.SdkClock;
19 import com.amazonaws.util.endpoint.DefaultRegionFromEndpointResolver;
20 import com.amazonaws.util.endpoint.RegionFromEndpointResolver;
21 import java.util.Date;
22
23 /**
24 * Parameters that are used for computing a AWS 4 signature for a request.
25 */
26 public final class AWS4SignerRequestParams {
27
28 /**
29 * The request for which the signature needs to be computed.
30 */
31 private final SignableRequest<?> request;
32
33 /**
34 * The datetime in milliseconds for which the signature needs to be
35 * computed.
36 */
37 private final long signingDateTimeMilli;
38
39 /**
40 * The scope of the signature.
41 */
42 private final String scope;
43
44 /**
45 * The AWS region to be used for computing the signature.
46 */
47 private final String regionName;
48
49 /**
50 * The name of the AWS service.
51 */
52 private final String serviceName;
53
54 /**
55 * UTC formatted version of the signing time stamp.
56 */
57 private final String formattedSigningDateTime;
58
59 /**
60 * UTC Formatted Signing date with time stamp stripped
61 */
62 private final String formattedSigningDate;
63
64 /**
65 * The signing algorithm to be used for computing the signature.
66 */
67 private final String signingAlgorithm;
68
69 /**
70 * Generates an instance of AWS4signerRequestParams that holds the
71 * parameters used for computing a AWS 4 signature for a request
72 */
73 public AWS4SignerRequestParams(SignableRequest<?> request,
74 Date signingDateOverride, String regionNameOverride,
75 String serviceName, String signingAlgorithm) {
76 this(request, signingDateOverride, regionNameOverride,
77 serviceName, signingAlgorithm, null);
78 }
79
80 /**
81 * Generates an instance of AWS4signerRequestParams that holds the
82 * parameters used for computing a AWS 4 signature for a request
83 */
84 public AWS4SignerRequestParams(SignableRequest<?> request,
85 Date signingDateOverride, String regionNameOverride,
86 String serviceName, String signingAlgorithm,
87 String endpointPrefix) {
88 this(request, signingDateOverride, regionNameOverride, serviceName, signingAlgorithm, endpointPrefix, null);
89 }
90
91 /**
92 * Generates an instance of AWS4signerRequestParams that holds the
93 * parameters used for computing a AWS 4 signature for a request
94 */
95 public AWS4SignerRequestParams(SignableRequest<?> request,
96 Date signingDateOverride, String regionNameOverride,
97 String serviceName, String signingAlgorithm,
98 String endpointPrefix,
99 RegionFromEndpointResolver regionFromEndpointResolver) {
100 if (request == null) {
101 throw new IllegalArgumentException("Request cannot be null");
102 }
103 if (signingAlgorithm == null) {
104 throw new IllegalArgumentException(
105 "Signing Algorithm cannot be null");
106 }
107
108 this.request = request;
109 this.signingDateTimeMilli = signingDateOverride != null ? signingDateOverride
110 .getTime() : getSigningDate(request);
111 this.formattedSigningDate = AWS4SignerUtils
112 .formatDateStamp(signingDateTimeMilli);
113 this.serviceName = serviceName;
114
115 this.regionName = regionNameOverride != null
116 ? regionNameOverride : resolveRegion(regionFromEndpointResolver, endpointPrefix, this.serviceName);
117
118 this.scope = generateScope(request, formattedSigningDate, this.serviceName,
119 regionName);
120 this.formattedSigningDateTime = AWS4SignerUtils
121 .formatTimestamp(signingDateTimeMilli);
122 this.signingAlgorithm = signingAlgorithm;
123 }
124
125 /*
126 * Ideally, we should be using endpoint prefix to parse the region from host.
127 *
128 * Previously we were using service signing name to parse region. It is possible that
129 * endpoint prefix is null if customers are still using older clients. So using
130 * service signing name as alternative will prevent any behavior breaking change.
131 */
132 private String resolveRegion(RegionFromEndpointResolver resolver, String endpointPrefix, String serviceSigningName) {
133 if (resolver == null) {
134 resolver = new DefaultRegionFromEndpointResolver();
135 }
136 String host = request.getEndpoint().getHost();
137 String region = resolver.guessRegionFromEndpoint(host, endpointPrefix != null ? endpointPrefix : serviceSigningName);
138 return region != null ? region : "us-east-1";
139 }
140
141 /**
142 * Returns the signing date from the request.
143 */
144 private final long getSigningDate(SignableRequest<?> request) {
145 return SdkClock.Instance.get().currentTimeMillis() - request.getTimeOffset() * 1000L;
146 }
147
148 /**
149 * Returns the scope to be used for the signing.
150 */
151 private String generateScope(SignableRequest<?> request, String dateStamp,
152 String serviceName, String regionName) {
153 final StringBuilder scopeBuilder = new StringBuilder();
154 return scopeBuilder.append(dateStamp).append("/").append(regionName)
155 .append("/").append(serviceName).append("/")
156 .append(SignerConstants.AWS4_TERMINATOR).toString();
157 }
158
159 /**
160 * Returns the request for which the signing needs to be done.
161 */
162 public SignableRequest<?> getRequest() {
163 return request;
164 }
165
166 /**
167 * Returns the scope of the signing.
168 */
169 public String getScope() {
170 return scope;
171 }
172
173 /**
174 * Returns the formatted date and time of the signing date in UTC zone.
175 */
176 public String getFormattedSigningDateTime() {
177 return formattedSigningDateTime;
178 }
179
180 /**
181 * Returns the signing date time in millis for which the signature needs to
182 * be computed.
183 */
184 public long getSigningDateTimeMilli() {
185 return signingDateTimeMilli;
186 }
187
188 /**
189 * Returns the AWS region name to be used while computing the signature.
190 */
191 public String getRegionName() {
192 return regionName;
193 }
194
195 /**
196 * Returns the AWS Service name to be used while computing the signature.
197 */
198 public String getServiceName() {
199 return serviceName;
200 }
201
202 /**
203 * Returns the formatted date in UTC zone of the signing date.
204 */
205 public String getFormattedSigningDate() {
206 return formattedSigningDate;
207 }
208
209 /**
210 * Returns the signing algorithm used for computing the signature.
211 */
212 public String getSigningAlgorithm() {
213 return signingAlgorithm;
214 }
215 }
216