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