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