kopia lustrzana https://github.com/gaul/s3proxy
Add configuration for AWS authentication V4
Supports aws-v2, aws-v4, aws-v2-or-v4, and none. Fixes #156.pull/176/merge
rodzic
80e256435e
commit
04657867b8
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014-2016 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
|
||||
public enum AuthenticationType {
|
||||
AWS_V2,
|
||||
AWS_V4,
|
||||
AWS_V2_OR_V4,
|
||||
NONE;
|
||||
|
||||
static AuthenticationType fromString(String string) {
|
||||
return AuthenticationType.valueOf(CaseFormat.LOWER_HYPHEN.to(
|
||||
CaseFormat.UPPER_UNDERSCORE, string));
|
||||
}
|
||||
}
|
|
@ -84,10 +84,10 @@ public final class Main {
|
|||
S3ProxyConstants.PROPERTY_ENDPOINT);
|
||||
String secureEndpoint = properties.getProperty(
|
||||
S3ProxyConstants.PROPERTY_SECURE_ENDPOINT);
|
||||
String s3ProxyAuthorization = properties.getProperty(
|
||||
String s3ProxyAuthorizationString = properties.getProperty(
|
||||
S3ProxyConstants.PROPERTY_AUTHORIZATION);
|
||||
if ((s3ProxyEndpointString == null && secureEndpoint == null) ||
|
||||
s3ProxyAuthorization == null) {
|
||||
s3ProxyAuthorizationString == null) {
|
||||
System.err.println("Properties file must contain:\n" +
|
||||
S3ProxyConstants.PROPERTY_AUTHORIZATION + "\n" +
|
||||
"and one of\n" +
|
||||
|
@ -96,9 +96,14 @@ public final class Main {
|
|||
System.exit(1);
|
||||
}
|
||||
|
||||
AuthenticationType s3ProxyAuthorization =
|
||||
AuthenticationType.fromString(s3ProxyAuthorizationString);
|
||||
String localIdentity = null;
|
||||
String localCredential = null;
|
||||
if (s3ProxyAuthorization.equalsIgnoreCase("aws-v2")) {
|
||||
switch (s3ProxyAuthorization) {
|
||||
case AWS_V2:
|
||||
case AWS_V4:
|
||||
case AWS_V2_OR_V4:
|
||||
localIdentity = properties.getProperty(
|
||||
S3ProxyConstants.PROPERTY_IDENTITY);
|
||||
localCredential = properties.getProperty(
|
||||
|
@ -107,12 +112,15 @@ public final class Main {
|
|||
System.err.println("Must specify both " +
|
||||
S3ProxyConstants.PROPERTY_IDENTITY + " and " +
|
||||
S3ProxyConstants.PROPERTY_CREDENTIAL +
|
||||
" when using aws-v2 authentication");
|
||||
" when using authentication");
|
||||
System.exit(1);
|
||||
}
|
||||
} else if (!s3ProxyAuthorization.equalsIgnoreCase("none")) {
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
System.err.println(S3ProxyConstants.PROPERTY_AUTHORIZATION +
|
||||
" must be aws-v2 or none, was: " + s3ProxyAuthorization);
|
||||
" invalid value, was: " + s3ProxyAuthorization);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
@ -171,7 +179,8 @@ public final class Main {
|
|||
s3ProxyBuilder.secureEndpoint(new URI(secureEndpoint));
|
||||
}
|
||||
if (localIdentity != null || localCredential != null) {
|
||||
s3ProxyBuilder.awsAuthentication(localIdentity,
|
||||
s3ProxyBuilder.awsAuthentication(
|
||||
s3ProxyAuthorization, localIdentity,
|
||||
localCredential);
|
||||
}
|
||||
if (keyStorePath != null || keyStorePassword != null) {
|
||||
|
|
|
@ -30,6 +30,7 @@ final class S3AuthorizationHeader {
|
|||
|
||||
// TODO: these fields should have accessors
|
||||
// CHECKSTYLE:OFF
|
||||
final AuthenticationType authenticationType;
|
||||
final String hmacAlgorithm;
|
||||
final String hashAlgorithm;
|
||||
final String region;
|
||||
|
@ -41,7 +42,7 @@ final class S3AuthorizationHeader {
|
|||
|
||||
S3AuthorizationHeader(String header) {
|
||||
if (header.startsWith("AWS ")) {
|
||||
// AWS v2 header
|
||||
authenticationType = AuthenticationType.AWS_V2;
|
||||
hmacAlgorithm = null;
|
||||
hashAlgorithm = null;
|
||||
region = null;
|
||||
|
@ -58,7 +59,7 @@ final class S3AuthorizationHeader {
|
|||
identity = identityTuple[0];
|
||||
signature = identityTuple[1];
|
||||
} else if (header.startsWith("AWS4-HMAC")) {
|
||||
// AWS v4 header
|
||||
authenticationType = AuthenticationType.AWS_V4;
|
||||
signature = extractSignature(header);
|
||||
|
||||
int credentialIndex = header.indexOf(CREDENTIAL_FIELD);
|
||||
|
|
|
@ -101,7 +101,8 @@ public final class S3Proxy {
|
|||
} else {
|
||||
listenHTTPS = false;
|
||||
}
|
||||
handler = new S3ProxyHandlerJetty(builder.blobStore, builder.identity,
|
||||
handler = new S3ProxyHandlerJetty(builder.blobStore,
|
||||
builder.authenticationType, builder.identity,
|
||||
builder.credential, Optional.fromNullable(builder.virtualHost),
|
||||
builder.v4MaxNonChunkedRequestSize,
|
||||
builder.ignoreUnknownHeaders, builder.corsAllowAll);
|
||||
|
@ -112,6 +113,8 @@ public final class S3Proxy {
|
|||
private BlobStore blobStore;
|
||||
private URI endpoint;
|
||||
private URI secureEndpoint;
|
||||
private AuthenticationType authenticationType =
|
||||
AuthenticationType.NONE;
|
||||
private String identity;
|
||||
private String credential;
|
||||
private String keyStorePath;
|
||||
|
@ -143,7 +146,9 @@ public final class S3Proxy {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder awsAuthentication(String identity, String credential) {
|
||||
public Builder awsAuthentication(AuthenticationType authenticationType,
|
||||
String identity, String credential) {
|
||||
this.authenticationType = authenticationType;
|
||||
this.identity = requireNonNull(identity);
|
||||
this.credential = requireNonNull(credential);
|
||||
return this;
|
||||
|
@ -223,5 +228,4 @@ public final class S3Proxy {
|
|||
public void setBlobStoreLocator(BlobStoreLocator lookup) {
|
||||
handler.getHandler().setBlobStoreLocator(lookup);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ public class S3ProxyHandler {
|
|||
private static final int B2_PUT_BLOB_BUFFER_SIZE = 1024 * 1024;
|
||||
|
||||
private final boolean anonymousIdentity;
|
||||
private final AuthenticationType authenticationType;
|
||||
private final Optional<String> virtualHost;
|
||||
private final long v4MaxNonChunkedRequestSize;
|
||||
private final boolean ignoreUnknownHeaders;
|
||||
|
@ -216,7 +217,8 @@ public class S3ProxyHandler {
|
|||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
public S3ProxyHandler(final BlobStore blobStore, final String identity,
|
||||
public S3ProxyHandler(final BlobStore blobStore,
|
||||
AuthenticationType authenticationType, final String identity,
|
||||
final String credential, Optional<String> virtualHost,
|
||||
long v4MaxNonChunkedRequestSize, boolean ignoreUnknownHeaders,
|
||||
boolean corsAllowAll) {
|
||||
|
@ -244,6 +246,7 @@ public class S3ProxyHandler {
|
|||
}
|
||||
};
|
||||
}
|
||||
this.authenticationType = authenticationType;
|
||||
this.virtualHost = requireNonNull(virtualHost);
|
||||
this.v4MaxNonChunkedRequestSize = v4MaxNonChunkedRequestSize;
|
||||
this.ignoreUnknownHeaders = ignoreUnknownHeaders;
|
||||
|
@ -385,6 +388,30 @@ public class S3ProxyHandler {
|
|||
}
|
||||
}
|
||||
|
||||
switch (authHeader.authenticationType) {
|
||||
case AWS_V2:
|
||||
switch (authenticationType) {
|
||||
case AWS_V2:
|
||||
case AWS_V2_OR_V4:
|
||||
break;
|
||||
default:
|
||||
throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT);
|
||||
}
|
||||
break;
|
||||
case AWS_V4:
|
||||
switch (authenticationType) {
|
||||
case AWS_V4:
|
||||
case AWS_V2_OR_V4:
|
||||
break;
|
||||
default:
|
||||
throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unhandled type: " +
|
||||
authHeader.authenticationType);
|
||||
}
|
||||
|
||||
String expectedSignature = null;
|
||||
if (authHeader.hmacAlgorithm == null) {
|
||||
expectedSignature = createAuthorizationSignature(request,
|
||||
|
|
|
@ -40,13 +40,14 @@ import org.jclouds.util.Throwables2;
|
|||
final class S3ProxyHandlerJetty extends AbstractHandler {
|
||||
private final S3ProxyHandler handler;
|
||||
|
||||
S3ProxyHandlerJetty(final BlobStore blobStore, final String identity,
|
||||
S3ProxyHandlerJetty(final BlobStore blobStore,
|
||||
AuthenticationType authenticationType, final String identity,
|
||||
final String credential, Optional<String> virtualHost,
|
||||
long v4MaxNonChunkedRequestSize, boolean ignoreUnknownHeaders,
|
||||
boolean corsAllowAll) {
|
||||
handler = new S3ProxyHandler(blobStore, identity, credential,
|
||||
virtualHost, v4MaxNonChunkedRequestSize, ignoreUnknownHeaders,
|
||||
corsAllowAll);
|
||||
handler = new S3ProxyHandler(blobStore, authenticationType, identity,
|
||||
credential, virtualHost, v4MaxNonChunkedRequestSize,
|
||||
ignoreUnknownHeaders, corsAllowAll);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -160,6 +160,10 @@ final class TestUtils {
|
|||
}
|
||||
String endpoint = info.getProperties().getProperty(
|
||||
Constants.PROPERTY_ENDPOINT);
|
||||
String s3ProxyAuthorizationString = info.getProperties().getProperty(
|
||||
S3ProxyConstants.PROPERTY_AUTHORIZATION);
|
||||
AuthenticationType s3ProxyAuthorization =
|
||||
AuthenticationType.fromString(s3ProxyAuthorizationString);
|
||||
info.s3Identity = info.getProperties().getProperty(
|
||||
S3ProxyConstants.PROPERTY_IDENTITY);
|
||||
info.s3Credential = info.getProperties().getProperty(
|
||||
|
@ -193,8 +197,8 @@ final class TestUtils {
|
|||
s3ProxyBuilder.secureEndpoint(new URI(secureEndpoint));
|
||||
}
|
||||
if (info.getS3Identity() != null || info.getS3Credential() != null) {
|
||||
s3ProxyBuilder.awsAuthentication(info.getS3Identity(),
|
||||
info.getS3Credential());
|
||||
s3ProxyBuilder.awsAuthentication(s3ProxyAuthorization,
|
||||
info.getS3Identity(), info.getS3Credential());
|
||||
}
|
||||
if (keyStorePath != null || keyStorePassword != null) {
|
||||
s3ProxyBuilder.keyStore(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
s3proxy.endpoint=http://127.0.0.1:0
|
||||
s3proxy.secure-endpoint=https://127.0.0.1:0
|
||||
# authorization must be aws-v2 or none
|
||||
s3proxy.authorization=aws-v2
|
||||
# authorization must be aws-v2, aws-v4, aws-v2-or-v4, or none
|
||||
s3proxy.authorization=aws-v2-or-v4
|
||||
s3proxy.identity=local-identity
|
||||
s3proxy.credential=local-credential
|
||||
s3proxy.keystore-path=keystore.jks
|
||||
|
|
Ładowanie…
Reference in New Issue