• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 
16 package software.amazon.awssdk.auth.signer;
17 
18 import static software.amazon.awssdk.utils.CompletableFutureUtils.joinLikeSync;
19 
20 import java.time.Clock;
21 import java.time.Instant;
22 import java.util.concurrent.CompletableFuture;
23 import software.amazon.awssdk.annotations.SdkProtectedApi;
24 import software.amazon.awssdk.auth.credentials.AwsCredentials;
25 import software.amazon.awssdk.auth.credentials.CredentialUtils;
26 import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
27 import software.amazon.awssdk.core.SelectedAuthScheme;
28 import software.amazon.awssdk.core.interceptor.ExecutionAttribute;
29 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
30 import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
31 import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
32 import software.amazon.awssdk.core.signer.Signer;
33 import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
34 import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner;
35 import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
36 import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
37 import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
38 import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
39 import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest;
40 import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest;
41 import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
42 import software.amazon.awssdk.http.auth.spi.signer.SignRequest;
43 import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
44 import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
45 import software.amazon.awssdk.identity.spi.Identity;
46 import software.amazon.awssdk.regions.Region;
47 import software.amazon.awssdk.regions.RegionScope;
48 import software.amazon.awssdk.utils.CompletableFutureUtils;
49 
50 /**
51  * AWS-specific signing attributes attached to the execution. This information is available to {@link ExecutionInterceptor}s and
52  * {@link Signer}s.
53  *
54  * @deprecated Signer execution attributes have been deprecated in favor of signer properties, set on the auth scheme's signer
55  * option.
56  */
57 @Deprecated
58 @SdkProtectedApi
59 public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
60     /**
61      * The key under which the request credentials are set.
62      *
63      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
64      * from execution interceptors, you should instead be overriding the credential provider via the {@code SdkRequest}'s
65      * {@code overrideConfiguration.credentialsProvider}. If you're using it to call the SDK's signers, you should migrate to a
66      * subtype of {@code HttpSigner}.
67      */
68     @Deprecated
69     public static final ExecutionAttribute<AwsCredentials> AWS_CREDENTIALS =
70         ExecutionAttribute.derivedBuilder("AwsCredentials",
71                                           AwsCredentials.class,
72                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
73                           .readMapping(AwsSignerExecutionAttribute::awsCredentialsReadMapping)
74                           .writeMapping(AwsSignerExecutionAttribute::awsCredentialsWriteMapping)
75                           .build();
76 
77     /**
78      * The AWS {@link Region} that is used for signing a request. This is not always same as the region configured on the client
79      * for global services like IAM.
80      *
81      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
82      * from execution interceptors, you should instead be overriding the signing region via the {@code AuthSchemeProvider} that
83      * is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
84      * subtype of {@code HttpSigner}.
85      */
86     @Deprecated
87     public static final ExecutionAttribute<Region> SIGNING_REGION =
88         ExecutionAttribute.derivedBuilder("SigningRegion",
89                                           Region.class,
90                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
91                           .readMapping(AwsSignerExecutionAttribute::signingRegionReadMapping)
92                           .writeMapping(AwsSignerExecutionAttribute::signingRegionWriteMapping)
93                           .build();
94 
95     /**
96      * The AWS {@link Region} that is used for signing a request. This is not always same as the region configured on the client
97      * for global services like IAM.
98      *
99      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
100      * from execution interceptors, you should instead be overriding the signing region scope via the {@code AuthSchemeProvider}
101      * that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
102      * subtype of {@code HttpSigner}.
103      */
104     @Deprecated
105     public static final ExecutionAttribute<RegionScope> SIGNING_REGION_SCOPE =
106         ExecutionAttribute.derivedBuilder("SigningRegionScope",
107                                           RegionScope.class,
108                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
109                           .readMapping(AwsSignerExecutionAttribute::signingRegionScopeReadMapping)
110                           .writeMapping(AwsSignerExecutionAttribute::signingRegionScopeWriteMapping)
111                           .build();
112 
113     /**
114      * The signing name of the service to be using in SigV4 signing
115      *
116      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
117      * from execution interceptors, you should instead be overriding the signing region name via the {@code AuthSchemeProvider}
118      * that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
119      * subtype of {@code HttpSigner}.
120      */
121     @Deprecated
122     public static final ExecutionAttribute<String> SERVICE_SIGNING_NAME =
123             ExecutionAttribute.derivedBuilder("ServiceSigningName",
124                                               String.class,
125                                               SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
126                               .readMapping(AwsSignerExecutionAttribute::serviceSigningNameReadMapping)
127                               .writeMapping(AwsSignerExecutionAttribute::serviceSigningNameWriteMapping)
128                               .build();
129 
130     /**
131      * The key to specify whether to use double url encoding during signing.
132      *
133      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
134      * from execution interceptors, you should instead be overriding the double-url-encode setting via the {@code
135      * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
136      * should migrate to a subtype of {@code HttpSigner}.
137      */
138     @Deprecated
139     public static final ExecutionAttribute<Boolean> SIGNER_DOUBLE_URL_ENCODE =
140         ExecutionAttribute.derivedBuilder("DoubleUrlEncode",
141                                           Boolean.class,
142                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
143                           .readMapping(AwsSignerExecutionAttribute::signerDoubleUrlEncodeReadMapping)
144                           .writeMapping(AwsSignerExecutionAttribute::signerDoubleUrlEncodeWriteMapping)
145                           .build();
146 
147     /**
148      * The key to specify whether to normalize the resource path during signing.
149      *
150      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
151      * from execution interceptors, you should instead be overriding the normalize-path setting via the {@code
152      * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
153      * should migrate to a subtype of {@code HttpSigner}.
154      */
155     @Deprecated
156     public static final ExecutionAttribute<Boolean> SIGNER_NORMALIZE_PATH =
157         ExecutionAttribute.derivedBuilder("NormalizePath",
158                                           Boolean.class,
159                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
160                           .readMapping(AwsSignerExecutionAttribute::signerNormalizePathReadMapping)
161                           .writeMapping(AwsSignerExecutionAttribute::signerNormalizePathWriteMapping)
162                           .build();
163 
164 
165     /**
166      * An override clock to use during signing.
167      * @see Aws4SignerParams.Builder#signingClockOverride(Clock)
168      *
169      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
170      * from execution interceptors, you should instead be overriding the clock setting via the {@code
171      * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
172      * should migrate to a subtype of {@code HttpSigner}.
173      */
174     @Deprecated
175     public static final ExecutionAttribute<Clock> SIGNING_CLOCK =
176         ExecutionAttribute.derivedBuilder("Clock",
177                                           Clock.class,
178                                           SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
179                           .readMapping(AwsSignerExecutionAttribute::signingClockReadMapping)
180                           .writeMapping(AwsSignerExecutionAttribute::signingClockWriteMapping)
181                           .build();
182 
183     /**
184      * The key to specify the expiration time when pre-signing aws requests.
185      *
186      * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
187      * from execution interceptors, you should instead be overriding the expiration via the {@code AuthSchemeProvider} that is
188      * configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a subtype of
189      * {@code HttpSigner}.
190      */
191     @Deprecated
192     public static final ExecutionAttribute<Instant> PRESIGNER_EXPIRATION = new ExecutionAttribute("PresignerExpiration");
193 
AwsSignerExecutionAttribute()194     private AwsSignerExecutionAttribute() {
195     }
196 
awsCredentialsReadMapping(SelectedAuthScheme<?> authScheme)197     private static AwsCredentials awsCredentialsReadMapping(SelectedAuthScheme<?> authScheme) {
198         if (authScheme == null) {
199             return null;
200         }
201         Identity identity = joinLikeSync(authScheme.identity());
202         if (!(identity instanceof AwsCredentialsIdentity)) {
203             return null;
204         }
205         return CredentialUtils.toCredentials((AwsCredentialsIdentity) identity);
206     }
207 
awsCredentialsWriteMapping(SelectedAuthScheme<T> authScheme, AwsCredentials awsCredentials)208     private static <T extends Identity> SelectedAuthScheme<?> awsCredentialsWriteMapping(SelectedAuthScheme<T> authScheme,
209                                                                                          AwsCredentials awsCredentials) {
210         if (authScheme == null) {
211             // This is an unusual use-case.
212             // Let's assume they're setting the credentials so that they can call the signer directly. If that's true, then it
213             // doesn't really matter what we store other than the credentials.
214             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(awsCredentials),
215                                             AwsV4HttpSigner.create(),
216                                             AuthSchemeOption.builder()
217                                                             .schemeId(AwsV4AuthScheme.SCHEME_ID)
218                                                             .build());
219         }
220 
221         return new SelectedAuthScheme<>(CompletableFuture.completedFuture((T) awsCredentials),
222                                         authScheme.signer(),
223                                         authScheme.authSchemeOption());
224     }
225 
signingRegionReadMapping(SelectedAuthScheme<?> authScheme)226     private static Region signingRegionReadMapping(SelectedAuthScheme<?> authScheme) {
227         if (authScheme == null) {
228             return null;
229         }
230         String regionName = authScheme.authSchemeOption().signerProperty(AwsV4HttpSigner.REGION_NAME);
231         if (regionName == null) {
232             return null;
233         }
234         return Region.of(regionName);
235     }
236 
signingRegionWriteMapping(SelectedAuthScheme<T> authScheme, Region region)237     private static <T extends Identity> SelectedAuthScheme<?> signingRegionWriteMapping(SelectedAuthScheme<T> authScheme,
238                                                                                         Region region) {
239         String regionString = region == null ? null : region.id();
240 
241         if (authScheme == null) {
242             // This is an unusual use-case.
243             // Let's assume they're setting the region so that they can call the signer directly. If that's true, then it
244             // doesn't really matter what we store other than the region.
245             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
246                                             new UnsetHttpSigner(),
247                                             AuthSchemeOption.builder()
248                                                             .schemeId("unset")
249                                                             .putSignerProperty(AwsV4HttpSigner.REGION_NAME,
250                                                                                regionString)
251                                                             .build());
252         }
253 
254         return new SelectedAuthScheme<>(authScheme.identity(),
255                                         authScheme.signer(),
256                                         authScheme.authSchemeOption().copy(o -> o.putSignerProperty(AwsV4HttpSigner.REGION_NAME,
257                                                                                                     regionString)));
258     }
259 
signingRegionScopeReadMapping(SelectedAuthScheme<?> authScheme)260     private static RegionScope signingRegionScopeReadMapping(SelectedAuthScheme<?> authScheme) {
261         if (authScheme == null) {
262             return null;
263         }
264         RegionSet regionSet = authScheme.authSchemeOption().signerProperty(AwsV4aHttpSigner.REGION_SET);
265         if (regionSet == null || regionSet.asString().isEmpty()) {
266             return null;
267         }
268 
269         return RegionScope.create(regionSet.asString());
270     }
271 
signingRegionScopeWriteMapping(SelectedAuthScheme<T> authScheme, RegionScope regionScope)272     private static <T extends Identity> SelectedAuthScheme<?> signingRegionScopeWriteMapping(SelectedAuthScheme<T> authScheme,
273                                                                                              RegionScope regionScope) {
274         RegionSet regionSet = regionScope != null ? RegionSet.create(regionScope.id()) : null;
275 
276         if (authScheme == null) {
277             // This is an unusual use-case.
278             // Let's assume they're setting the region scope so that they can call the signer directly. If that's true, then it
279             // doesn't really matter what we store other than the region scope.
280             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
281                                             new UnsetHttpSigner(),
282                                             AuthSchemeOption.builder()
283                                                             .schemeId("unset")
284                                                             .putSignerProperty(AwsV4aHttpSigner.REGION_SET, regionSet)
285                                                             .build());
286         }
287 
288         return new SelectedAuthScheme<>(authScheme.identity(),
289                                         authScheme.signer(),
290                                         authScheme.authSchemeOption().copy(o -> o.putSignerProperty(AwsV4aHttpSigner.REGION_SET,
291                                                                                                     regionSet)));
292     }
293 
serviceSigningNameReadMapping(SelectedAuthScheme<?> authScheme)294     private static String serviceSigningNameReadMapping(SelectedAuthScheme<?> authScheme) {
295         if (authScheme == null) {
296             return null;
297         }
298         return authScheme.authSchemeOption().signerProperty(AwsV4FamilyHttpSigner.SERVICE_SIGNING_NAME);
299     }
300 
serviceSigningNameWriteMapping(SelectedAuthScheme<T> authScheme, String signingName)301     private static <T extends Identity> SelectedAuthScheme<?> serviceSigningNameWriteMapping(SelectedAuthScheme<T> authScheme,
302                                                                                              String signingName) {
303         if (authScheme == null) {
304             // This is an unusual use-case.
305             // Let's assume they're setting the signing name so that they can call the signer directly. If that's true, then it
306             // doesn't really matter what we store other than the signing name.
307             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
308                                             new UnsetHttpSigner(),
309                                             AuthSchemeOption.builder()
310                                                             .schemeId("unset")
311                                                             .putSignerProperty(AwsV4FamilyHttpSigner.SERVICE_SIGNING_NAME,
312                                                                                signingName)
313                                                             .build());
314         }
315 
316         return new SelectedAuthScheme<>(authScheme.identity(),
317                                         authScheme.signer(),
318                                         authScheme.authSchemeOption()
319                                                   .copy(o -> o.putSignerProperty(AwsV4FamilyHttpSigner.SERVICE_SIGNING_NAME,
320                                                                                  signingName)));
321     }
322 
signerDoubleUrlEncodeReadMapping(SelectedAuthScheme<?> authScheme)323     private static Boolean signerDoubleUrlEncodeReadMapping(SelectedAuthScheme<?> authScheme) {
324         if (authScheme == null) {
325             return null;
326         }
327         AuthSchemeOption authOption = authScheme.authSchemeOption();
328         return authOption.signerProperty(AwsV4FamilyHttpSigner.DOUBLE_URL_ENCODE);
329     }
330 
signerDoubleUrlEncodeWriteMapping(SelectedAuthScheme<T> authScheme, Boolean doubleUrlEncode)331     private static <T extends Identity> SelectedAuthScheme<?> signerDoubleUrlEncodeWriteMapping(SelectedAuthScheme<T> authScheme,
332                                                                                                 Boolean doubleUrlEncode) {
333         if (authScheme == null) {
334             // This is an unusual use-case.
335             // Let's assume they're setting double-url-encode so that they can call the signer directly. If that's true, then it
336             // doesn't really matter what we store other than double-url-encode.
337             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
338                                             new UnsetHttpSigner(),
339                                             AuthSchemeOption.builder()
340                                                             .schemeId("unset")
341                                                             .putSignerProperty(AwsV4FamilyHttpSigner.DOUBLE_URL_ENCODE,
342                                                                                doubleUrlEncode)
343                                                             .build());
344         }
345 
346         return new SelectedAuthScheme<>(authScheme.identity(),
347                                         authScheme.signer(),
348                                         authScheme.authSchemeOption()
349                                                   .copy(o -> o.putSignerProperty(AwsV4FamilyHttpSigner.DOUBLE_URL_ENCODE,
350                                                                                  doubleUrlEncode)));
351     }
352 
signerNormalizePathReadMapping(SelectedAuthScheme<?> authScheme)353     private static Boolean signerNormalizePathReadMapping(SelectedAuthScheme<?> authScheme) {
354         if (authScheme == null) {
355             return null;
356         }
357         AuthSchemeOption authOption = authScheme.authSchemeOption();
358         return authOption.signerProperty(AwsV4FamilyHttpSigner.NORMALIZE_PATH);
359     }
360 
signerNormalizePathWriteMapping(SelectedAuthScheme<T> authScheme, Boolean normalizePath)361     private static <T extends Identity> SelectedAuthScheme<?> signerNormalizePathWriteMapping(SelectedAuthScheme<T> authScheme,
362                                                                                               Boolean normalizePath) {
363         if (authScheme == null) {
364             // This is an unusual use-case.
365             // Let's assume they're setting normalize-path so that they can call the signer directly. If that's true, then it
366             // doesn't really matter what we store other than normalize-path.
367             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
368                                             new UnsetHttpSigner(),
369                                             AuthSchemeOption.builder()
370                                                             .schemeId("unset")
371                                                             .putSignerProperty(AwsV4FamilyHttpSigner.NORMALIZE_PATH,
372                                                                                normalizePath)
373                                                             .build());
374         }
375 
376         return new SelectedAuthScheme<>(authScheme.identity(),
377                                         authScheme.signer(),
378                                         authScheme.authSchemeOption()
379                                                   .copy(o -> o.putSignerProperty(AwsV4FamilyHttpSigner.NORMALIZE_PATH,
380                                                                                  normalizePath)));
381     }
382 
signingClockReadMapping(SelectedAuthScheme<?> authScheme)383     private static Clock signingClockReadMapping(SelectedAuthScheme<?> authScheme) {
384         if (authScheme == null) {
385             return null;
386         }
387         return authScheme.authSchemeOption().signerProperty(HttpSigner.SIGNING_CLOCK);
388     }
389 
signingClockWriteMapping(SelectedAuthScheme<T> authScheme, Clock clock)390     private static <T extends Identity> SelectedAuthScheme<?> signingClockWriteMapping(SelectedAuthScheme<T> authScheme,
391                                                                                        Clock clock) {
392         if (authScheme == null) {
393             // This is an unusual use-case.
394             // Let's assume they're setting signing clock so that they can call the signer directly. If that's true, then it
395             // doesn't really matter what we store other than the signing clock.
396             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
397                                             new UnsetHttpSigner(),
398                                             AuthSchemeOption.builder()
399                                                             .schemeId("unset")
400                                                             .putSignerProperty(HttpSigner.SIGNING_CLOCK, clock)
401                                                             .build());
402         }
403 
404         return new SelectedAuthScheme<>(authScheme.identity(),
405                                         authScheme.signer(),
406                                         authScheme.authSchemeOption()
407                                                   .copy(o -> o.putSignerProperty(HttpSigner.SIGNING_CLOCK, clock)));
408     }
409 
410     private static class UnsetIdentity implements Identity {
411     }
412 
413     private static class UnsetHttpSigner implements HttpSigner<UnsetIdentity> {
414         @Override
sign(SignRequest<? extends UnsetIdentity> request)415         public SignedRequest sign(SignRequest<? extends UnsetIdentity> request) {
416             throw new IllegalStateException("A signer was not configured.");
417         }
418 
419         @Override
signAsync(AsyncSignRequest<? extends UnsetIdentity> request)420         public CompletableFuture<AsyncSignedRequest> signAsync(AsyncSignRequest<? extends UnsetIdentity> request) {
421             return CompletableFutureUtils.failedFuture(new IllegalStateException("A signer was not configured."));
422         }
423     }
424 }
425