44
44
import java .security .NoSuchAlgorithmException ;
45
45
import java .util .*;
46
46
47
- public final class S3AuthUtil {
47
+ public final class S3SignerV2 {
48
+ private static final Logger log = LoggerFactory .getLogger (S3SignerV2 .class );
48
49
49
- private static final Logger log = LoggerFactory .getLogger (S3AuthUtil .class );
50
+ private S3Config s3Config ;
51
+ private SortedSet <String > signedParameters ;
50
52
51
- public static SortedSet <String > SIGNED_PARAMETERS ;
52
-
53
- static {
54
- SIGNED_PARAMETERS = new TreeSet <String >(Arrays .asList (
53
+ public S3SignerV2 (S3Config s3Config ) {
54
+ this .s3Config = s3Config ;
55
+ signedParameters = new TreeSet <String >(Arrays .asList (
55
56
"acl" , "torrent" , "logging" , "location" , "policy" , "requestPayment" , "versioning" ,
56
57
"versions" , "versionId" , "notification" , "uploadId" , "uploads" , "partNumber" , "website" ,
57
58
"delete" , "lifecycle" , "tagging" , "cors" , "restore" ,
@@ -63,16 +64,19 @@ public final class S3AuthUtil {
63
64
S3Constants .PARAM_RESPONSE_HEADER_EXPIRES ,
64
65
S3Constants .PARAM_ENDPOINT ,
65
66
S3Constants .PARAM_IS_STALE_ALLOWED ));
67
+ if (s3Config .isSignMetadataSearch ()) {
68
+ signedParameters .add (S3Constants .PARAM_QUERY );
69
+ signedParameters .add (S3Constants .PARAM_SEARCH_METADATA );
70
+ }
66
71
}
67
72
68
- public static void sign (String method , String resource , Map <String , String > parameters , Map <String , List <Object >> headers ,
69
- String accessKey , String secretKey , long clockSkew ) {
70
- String stringToSign = getStringToSign (method , resource , parameters , headers , clockSkew );
71
- String signature = getSignature (stringToSign , secretKey );
72
- RestUtil .putSingle (headers , "Authorization" , "AWS " + accessKey + ":" + signature );
73
+ public void sign (String method , String resource , Map <String , String > parameters , Map <String , List <Object >> headers ) {
74
+ String stringToSign = getStringToSign (method , resource , parameters , headers );
75
+ String signature = getSignature (stringToSign );
76
+ RestUtil .putSingle (headers , "Authorization" , "AWS " + s3Config .getIdentity () + ":" + signature );
73
77
}
74
78
75
- public static URL generatePresignedUrl (PresignedUrlRequest request , S3Config s3Config ) {
79
+ public URL generatePresignedUrl (PresignedUrlRequest request ) {
76
80
String namespace = request .getNamespace () != null ? request .getNamespace () : s3Config .getNamespace ();
77
81
78
82
URI uri = s3Config .resolvePath (request .getPath (), null ); // don't care about the query string yet
@@ -100,9 +104,8 @@ public static URL generatePresignedUrl(PresignedUrlRequest request, S3Config s3C
100
104
queryParams .put (S3Constants .PARAM_ACCESS_KEY , s3Config .getIdentity ());
101
105
102
106
// sign the request
103
- String stringToSign = S3AuthUtil .getStringToSign (request .getMethod ().toString (), resource ,
104
- queryParams , request .getHeaders (), s3Config .getServerClockSkew ());
105
- String signature = S3AuthUtil .getSignature (stringToSign , s3Config .getSecretKey ());
107
+ String stringToSign = getStringToSign (request .getMethod ().toString (), resource , queryParams , request .getHeaders ());
108
+ String signature = getSignature (stringToSign );
106
109
107
110
// add signature to query string
108
111
queryParams .put (S3Constants .PARAM_SIGNATURE , signature );
@@ -118,8 +121,8 @@ public static URL generatePresignedUrl(PresignedUrlRequest request, S3Config s3C
118
121
}
119
122
}
120
123
121
- public static String getStringToSign (String method , String resource , Map <String , String > parameters ,
122
- Map <String , List <Object >> headers , long clockSkew ) {
124
+ public String getStringToSign (String method , String resource , Map <String , String > parameters ,
125
+ Map <String , List <Object >> headers ) {
123
126
StringBuilder stringToSign = new StringBuilder ();
124
127
125
128
// method line
@@ -140,7 +143,7 @@ public static String getStringToSign(String method, String resource, Map<String,
140
143
String date = RestUtil .getFirstAsString (headers , RestUtil .HEADER_DATE );
141
144
if (date == null ) {
142
145
// must have a date in the headers
143
- date = RestUtil .getRequestDate (clockSkew );
146
+ date = RestUtil .getRequestDate (s3Config . getServerClockSkew () );
144
147
RestUtil .putSingle (headers , RestUtil .HEADER_DATE , date );
145
148
}
146
149
// if x-amz-date is specified, date line should be blank
@@ -162,7 +165,7 @@ public static String getStringToSign(String method, String resource, Map<String,
162
165
// resource path (includes signed parameters)
163
166
stringToSign .append (resource );
164
167
boolean firstParameter = true ;
165
- for (String parameter : SIGNED_PARAMETERS ) {
168
+ for (String parameter : signedParameters ) {
166
169
if (parameters .containsKey (parameter )) {
167
170
stringToSign .append (firstParameter ? "?" : "&" ).append (parameter );
168
171
String value = parameters .get (parameter );
@@ -176,7 +179,7 @@ public static String getStringToSign(String method, String resource, Map<String,
176
179
return stringToSignStr ;
177
180
}
178
181
179
- public static SortedMap <String , String > getCanonicalizedHeaders (Map <String , List <Object >> headers , Map <String , String > parameters ) {
182
+ private SortedMap <String , String > getCanonicalizedHeaders (Map <String , List <Object >> headers , Map <String , String > parameters ) {
180
183
SortedMap <String , String > canonicalizedHeaders = new TreeMap <String , String >();
181
184
182
185
// add x-emc- and x-amz- headers
@@ -198,7 +201,7 @@ public static SortedMap<String, String> getCanonicalizedHeaders(Map<String, List
198
201
return canonicalizedHeaders ;
199
202
}
200
203
201
- public static String trimAndJoin (List <Object > values , String delimiter ) {
204
+ private String trimAndJoin (List <Object > values , String delimiter ) {
202
205
if (values == null || values .isEmpty ()) return null ;
203
206
StringBuilder delimited = new StringBuilder ();
204
207
Iterator <Object > valuesI = values .iterator ();
@@ -209,10 +212,10 @@ public static String trimAndJoin(List<Object> values, String delimiter) {
209
212
return delimited .toString ();
210
213
}
211
214
212
- public static String getSignature (String stringToSign , String secretKey ) {
215
+ public String getSignature (String stringToSign ) {
213
216
try {
214
217
Mac mac = Mac .getInstance ("HmacSHA1" );
215
- mac .init (new SecretKeySpec (secretKey .getBytes ("UTF-8" ), "HmacSHA1" )); // AWS does not B64-decode the secret key!
218
+ mac .init (new SecretKeySpec (s3Config . getSecretKey () .getBytes ("UTF-8" ), "HmacSHA1" )); // AWS does not B64-decode the secret key!
216
219
String signature = new String (Base64 .encodeBase64 (mac .doFinal (stringToSign .getBytes ("UTF-8" ))));
217
220
log .debug ("signature:\n " + signature );
218
221
return signature ;
@@ -221,10 +224,7 @@ public static String getSignature(String stringToSign, String secretKey) {
221
224
} catch (UnsupportedEncodingException e ) {
222
225
throw new RuntimeException ("UTF-8 encoding is not supported on this platform" , e );
223
226
} catch (InvalidKeyException e ) {
224
- throw new RuntimeException ("The secret key \" " + secretKey + "\" is not valid" , e );
227
+ throw new RuntimeException ("The secret key \" " + s3Config . getSecretKey () + "\" is not valid" , e );
225
228
}
226
229
}
227
-
228
- private S3AuthUtil () {
229
- }
230
230
}
0 commit comments