• 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.core.interceptor;
17 
18 import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32;
19 import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32C;
20 import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA1;
21 import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA256;
22 import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName;
23 
24 import java.net.URI;
25 import java.util.concurrent.CompletableFuture;
26 import java.util.function.Supplier;
27 import software.amazon.awssdk.annotations.SdkPublicApi;
28 import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm;
29 import software.amazon.awssdk.core.ClientType;
30 import software.amazon.awssdk.core.SelectedAuthScheme;
31 import software.amazon.awssdk.core.ServiceConfiguration;
32 import software.amazon.awssdk.core.checksums.Algorithm;
33 import software.amazon.awssdk.core.checksums.ChecksumSpecs;
34 import software.amazon.awssdk.core.checksums.ChecksumValidation;
35 import software.amazon.awssdk.core.signer.Signer;
36 import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner;
37 import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
38 import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest;
39 import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest;
40 import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
41 import software.amazon.awssdk.http.auth.spi.signer.SignRequest;
42 import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
43 import software.amazon.awssdk.identity.spi.Identity;
44 import software.amazon.awssdk.metrics.MetricCollector;
45 import software.amazon.awssdk.profiles.ProfileFile;
46 import software.amazon.awssdk.utils.CompletableFutureUtils;
47 import software.amazon.awssdk.utils.ImmutableMap;
48 
49 /**
50  * Contains attributes attached to the execution. This information is available to {@link ExecutionInterceptor}s and
51  * {@link Signer}s.
52  */
53 @SdkPublicApi
54 public class SdkExecutionAttribute {
55 
56     /**
57      * Handler context key for advanced configuration.
58      */
59     public static final ExecutionAttribute<ServiceConfiguration> SERVICE_CONFIG = new ExecutionAttribute<>("ServiceConfig");
60 
61     /**
62      * The key under which the service name is stored.
63      */
64     public static final ExecutionAttribute<String> SERVICE_NAME = new ExecutionAttribute<>("ServiceName");
65 
66     /**
67      * The key under which the time offset (for clock skew correction) is stored.
68      */
69     public static final ExecutionAttribute<Integer> TIME_OFFSET = new ExecutionAttribute<>("TimeOffset");
70 
71     public static final ExecutionAttribute<ClientType> CLIENT_TYPE = new ExecutionAttribute<>("ClientType");
72 
73     public static final ExecutionAttribute<String> OPERATION_NAME = new ExecutionAttribute<>("OperationName");
74 
75     /**
76      * The {@link MetricCollector} associated with the overall API call.
77      */
78     public static final ExecutionAttribute<MetricCollector> API_CALL_METRIC_COLLECTOR = new ExecutionAttribute<>(
79         "ApiCallMetricCollector");
80 
81     /**
82      * The {@link MetricCollector} associated with the current, ongoing API call attempt. This is not set until the actual
83      * internal API call attempt starts.
84      */
85     public static final ExecutionAttribute<MetricCollector> API_CALL_ATTEMPT_METRIC_COLLECTOR =
86         new ExecutionAttribute<>("ApiCallAttemptMetricCollector");
87 
88     /**
89      * If true indicates that the configured endpoint of the client is a value that was supplied as an override and not
90      * generated from regional metadata.
91      */
92     public static final ExecutionAttribute<Boolean> ENDPOINT_OVERRIDDEN = new ExecutionAttribute<>("EndpointOverridden");
93 
94     /**
95      * This is the endpointOverride (if {@link #ENDPOINT_OVERRIDDEN} is true), otherwise the endpoint generated from regional
96      * metadata.
97      */
98     public static final ExecutionAttribute<URI> CLIENT_ENDPOINT = new ExecutionAttribute<>("EndpointOverride");
99 
100     /**
101      * If the client signer value has been overridden.
102      */
103     public static final ExecutionAttribute<Boolean> SIGNER_OVERRIDDEN = new ExecutionAttribute<>("SignerOverridden");
104 
105     /**
106      * @deprecated This attribute is used for:
107      *             - Set profile file of service endpoint builder docdb, nepture, rds
108      * This has been replaced with {@code PROFILE_FILE_SUPPLIER.get()}.
109      */
110     @Deprecated
111     public static final ExecutionAttribute<ProfileFile> PROFILE_FILE = new ExecutionAttribute<>("ProfileFile");
112 
113     public static final ExecutionAttribute<Supplier<ProfileFile>> PROFILE_FILE_SUPPLIER =
114         new ExecutionAttribute<>("ProfileFileSupplier");
115 
116     public static final ExecutionAttribute<String> PROFILE_NAME = new ExecutionAttribute<>("ProfileName");
117 
118     /**
119      * The checksum algorithm is resolved based on the Request member.
120      * The RESOLVED_CHECKSUM_SPECS holds the final checksum which will be used for checksum computation.
121      */
122     public static final ExecutionAttribute<ChecksumSpecs> RESOLVED_CHECKSUM_SPECS =
123         ExecutionAttribute.mappedBuilder("ResolvedChecksumSpecs",
124                                          () -> SdkInternalExecutionAttribute.INTERNAL_RESOLVED_CHECKSUM_SPECS,
125                                          () -> SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)
126                           .readMapping(SdkExecutionAttribute::signerChecksumReadMapping)
127                           .writeMapping(SdkExecutionAttribute::signerChecksumWriteMapping)
128                           .build();
129 
130     /**
131      * The Algorithm used for checksum validation of a response.
132      */
133     public static final ExecutionAttribute<Algorithm> HTTP_CHECKSUM_VALIDATION_ALGORITHM = new ExecutionAttribute<>(
134         "HttpChecksumValidationAlgorithm");
135 
136     /**
137      * Provides the status of {@link ChecksumValidation} performed on the  response.
138      */
139     public static final ExecutionAttribute<ChecksumValidation> HTTP_RESPONSE_CHECKSUM_VALIDATION = new ExecutionAttribute<>(
140         "HttpResponseChecksumValidation");
141 
142     private static final ImmutableMap<ChecksumAlgorithm, Algorithm> ALGORITHM_MAP = ImmutableMap.of(
143         SHA256, Algorithm.SHA256,
144         SHA1, Algorithm.SHA1,
145         CRC32, Algorithm.CRC32,
146         CRC32C, Algorithm.CRC32C
147     );
148 
149     private static final ImmutableMap<Algorithm, ChecksumAlgorithm> CHECKSUM_ALGORITHM_MAP = ImmutableMap.of(
150         Algorithm.SHA256, SHA256,
151         Algorithm.SHA1, SHA1,
152         Algorithm.CRC32, CRC32,
153         Algorithm.CRC32C, CRC32C
154     );
155 
SdkExecutionAttribute()156     protected SdkExecutionAttribute() {
157     }
158 
159     /**
160      * Map from the SelectedAuthScheme and the backing ChecksumSpecs value to a new value for ChecksumSpecs.
161      */
signerChecksumReadMapping(ChecksumSpecs checksumSpecs, SelectedAuthScheme<T> authScheme)162     private static <T extends Identity> ChecksumSpecs signerChecksumReadMapping(ChecksumSpecs checksumSpecs,
163                                                                                 SelectedAuthScheme<T> authScheme) {
164         if (checksumSpecs == null || authScheme == null) {
165             return checksumSpecs;
166         }
167 
168         ChecksumAlgorithm checksumAlgorithm =
169             authScheme.authSchemeOption().signerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM);
170 
171         return ChecksumSpecs.builder()
172                             .algorithm(checksumAlgorithm != null ? ALGORITHM_MAP.get(checksumAlgorithm) : null)
173                             .isRequestStreaming(checksumSpecs.isRequestStreaming())
174                             .isRequestChecksumRequired(checksumSpecs.isRequestChecksumRequired())
175                             .isValidationEnabled(checksumSpecs.isValidationEnabled())
176                             .headerName(checksumAlgorithm != null ? checksumHeaderName(checksumAlgorithm) : null)
177                             .responseValidationAlgorithms(checksumSpecs.responseValidationAlgorithms())
178                             .build();
179     }
180 
181     /**
182      * Map from ChecksumSpecs to a SelectedAuthScheme with the CHECKSUM_ALGORITHM signer property set.
183      */
signerChecksumWriteMapping(SelectedAuthScheme<T> authScheme, ChecksumSpecs checksumSpecs)184     private static <T extends Identity> SelectedAuthScheme<?> signerChecksumWriteMapping(SelectedAuthScheme<T> authScheme,
185                                                                                          ChecksumSpecs checksumSpecs) {
186         ChecksumAlgorithm checksumAlgorithm = checksumSpecs == null ? null :
187                                               CHECKSUM_ALGORITHM_MAP.get(checksumSpecs.algorithm());
188 
189         if (authScheme == null) {
190             // This is an unusual use-case.
191             // Let's assume they're setting the checksum-algorithm so that they can call the signer directly. If that's true,
192             // then it doesn't really matter what we store other than the checksum-algorithm.
193             return new SelectedAuthScheme<>(CompletableFuture.completedFuture(new UnsetIdentity()),
194                                             new UnsetHttpSigner(),
195                                             AuthSchemeOption.builder()
196                                                             .schemeId("unset")
197                                                             .putSignerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM,
198                                                                                checksumAlgorithm)
199                                                             .build());
200         }
201 
202         return new SelectedAuthScheme<>(authScheme.identity(),
203                                         authScheme.signer(),
204                                         authScheme.authSchemeOption()
205                                                   .copy(o -> o.putSignerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM,
206                                                                                  checksumAlgorithm)));
207     }
208 
209     private static class UnsetIdentity implements Identity {
210     }
211 
212     private static class UnsetHttpSigner implements HttpSigner<UnsetIdentity> {
213         @Override
sign(SignRequest<? extends UnsetIdentity> request)214         public SignedRequest sign(SignRequest<? extends UnsetIdentity> request) {
215             throw new IllegalStateException("A signer was not configured.");
216         }
217 
218         @Override
signAsync(AsyncSignRequest<? extends UnsetIdentity> request)219         public CompletableFuture<AsyncSignedRequest> signAsync(AsyncSignRequest<? extends UnsetIdentity> request) {
220             return CompletableFutureUtils.failedFuture(new IllegalStateException("A signer was not configured."));
221         }
222     }
223 }
224