1 /*
2  * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights
3  * Reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License").
6  * You may not use this file except in compliance with the License.
7  * A copy of the License is located at
8  *
9  *  http://aws.amazon.com/apache2.0
10  *
11  * or in the "license" file accompanying this file. This file is distributed
12  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */

16 package com.amazonaws.services.s3.internal.auth;
17
18 import com.amazonaws.AmazonWebServiceClient;
19 import com.amazonaws.auth.RegionAwareSigner;
20 import com.amazonaws.auth.Signer;
21 import com.amazonaws.internal.auth.SignerProviderContext;
22 import com.amazonaws.internal.auth.SignerProvider;
23 import com.amazonaws.regions.EndpointToRegion;
24 import com.amazonaws.services.s3.internal.ServiceUtils;
25 import com.amazonaws.util.AwsHostNameUtils;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import java.net.URI;
30
31 public class S3SignerProvider extends SignerProvider {
32
33     private static Log log = LogFactory.getLog(S3SignerProvider.class);
34
35     private final AmazonWebServiceClient awsClient;
36     private Signer signer;
37
38     public S3SignerProvider(final AmazonWebServiceClient awsClient,
39                             final Signer defaultSigner) {
40         this.awsClient = awsClient;
41         this.signer = defaultSigner;
42     }
43
44     @Override
45     public Signer getSigner(SignerProviderContext signerProviderContext) {
46         URI uri = signerProviderContext.getUri();
47
48         // Return the default signer if no URI is passed, the client is configured with region override,
49         // or if we are hitting an accelerate endpoint.
50         if (uri == null || ServiceUtils.isS3AccelerateEndpoint(uri.getHost()) || isSignerRegionOverrideSet()) {
51             return signer;
52         }
53
54         if (signer instanceof RegionAwareSigner && !isAccessPointUri(uri)) {
55             // Parse region name from the host component of the URL and
56             // assign it to the signer
57             RegionAwareSigner regionSigner = (RegionAwareSigner) signer;
58
59             try {
60                 regionSigner.setRegionName(EndpointToRegion.guessRegionNameForEndpoint(uri.getHost(), "s3"));
61
62             } catch (RuntimeException e) {
63                 log.warn("Failed to parse the endpoint " + uri +
64                         ", and skip re-assigning the signer region", e);
65             }
66         }
67
68         return signer;
69     }
70
71     private boolean isAccessPointUri(URI uri) {
72         return uri.toASCIIString().contains(".s3-accesspoint.");
73     }
74
75     private boolean isSignerRegionOverrideSet() {
76         return awsClient != null && awsClient.getSignerRegionOverride() != null;
77     }
78
79     /**
80      * This is necessary for S3 since we update the signer during request processing dependent on
81      * which region the bucket exists in.
82      */

83     public void setSigner(Signer signer) {
84         this.signer = signer;
85     }
86
87 }
88