diff --git a/.gitignore b/.gitignore index 0bdd78e..cc34d89 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ -*.iml \ No newline at end of file +*.iml +.idea/* diff --git a/pom.xml b/pom.xml index 787c81e..1c6719a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ com.amazonaws amazon-neptune-sigv4-signer jar - 1.0.3 + 1.0.4 amazon-neptune-sigv4-signer diff --git a/src/main/java/com/amazonaws/neptune/auth/NeptuneApacheHttpSigV4Signer.java b/src/main/java/com/amazonaws/neptune/auth/NeptuneApacheHttpSigV4Signer.java index 578138b..5a85fd0 100644 --- a/src/main/java/com/amazonaws/neptune/auth/NeptuneApacheHttpSigV4Signer.java +++ b/src/main/java/com/amazonaws/neptune/auth/NeptuneApacheHttpSigV4Signer.java @@ -36,6 +36,7 @@ import static com.amazonaws.auth.internal.SignerConstants.AUTHORIZATION; import static com.amazonaws.auth.internal.SignerConstants.HOST; import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_DATE; +import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_SECURITY_TOKEN; /** * Signer for HTTP requests made via Apache Commons {@link HttpUriRequest}s. @@ -173,6 +174,14 @@ protected void attachSignature(final HttpUriRequest request, final NeptuneSigV4S request.setHeader(HOST, signature.getHostHeader()); request.setHeader(X_AMZ_DATE, signature.getXAmzDateHeader()); request.setHeader(AUTHORIZATION, signature.getAuthorizationHeader()); + + // https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html + // For temporary security credentials, it requires an additional HTTP header + // or query string parameter for the security token. The name of the header + // or query string parameter is X-Amz-Security-Token, and the value is the session token. + if (!signature.getSessionToken().isEmpty()) { + request.setHeader(X_AMZ_SECURITY_TOKEN, signature.getSessionToken()); + } } } diff --git a/src/main/java/com/amazonaws/neptune/auth/NeptuneNettyHttpSigV4Signer.java b/src/main/java/com/amazonaws/neptune/auth/NeptuneNettyHttpSigV4Signer.java index 85cd4e0..afac3fe 100644 --- a/src/main/java/com/amazonaws/neptune/auth/NeptuneNettyHttpSigV4Signer.java +++ b/src/main/java/com/amazonaws/neptune/auth/NeptuneNettyHttpSigV4Signer.java @@ -36,6 +36,7 @@ import static com.amazonaws.auth.internal.SignerConstants.AUTHORIZATION; import static com.amazonaws.auth.internal.SignerConstants.HOST; import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_DATE; +import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_SECURITY_TOKEN; /** * Signer for HTTP requests made via Netty clients {@link FullHttpRequest}s. @@ -52,7 +53,6 @@ public class NeptuneNettyHttpSigV4Signer extends NeptuneSigV4SignerBase generic, using the AWS SDK signer aws4Signer.sign(awsSignableRequest, awsCredentialsProvider.getCredentials()); + + // extract session token if temporary credentials are provided + String sessionToken = ""; + if ((awsCredentialsProvider.getCredentials() instanceof BasicSessionCredentials)) { + sessionToken = ((BasicSessionCredentials) awsCredentialsProvider.getCredentials()).getSessionToken(); + } + final NeptuneSigV4Signature signature = new NeptuneSigV4Signature( awsSignableRequest.getHeaders().get(HOST), awsSignableRequest.getHeaders().get(X_AMZ_DATE), - awsSignableRequest.getHeaders().get(AUTHORIZATION)); + awsSignableRequest.getHeaders().get(AUTHORIZATION), + sessionToken); // 3. Copy over the Signature V4 headers to the original request // => to be implemented in subclass @@ -306,6 +313,11 @@ public static class NeptuneSigV4Signature { */ private final String authorizationHeader; + /** + * Value of the Temporary credential session token. + */ + private final String sessionToken; + /** * Constructor. @@ -315,10 +327,12 @@ public static class NeptuneSigV4Signature { * @param authorizationHeader string value of the authorization header used for signing the request */ public NeptuneSigV4Signature( - final String hostHeader, final String xAmzDateHeader, final String authorizationHeader) { + final String hostHeader, final String xAmzDateHeader, final String authorizationHeader, + final String sessionToken) { this.hostHeader = hostHeader; this.xAmzDateHeader = xAmzDateHeader; this.authorizationHeader = authorizationHeader; + this.sessionToken = sessionToken; } /** @@ -341,5 +355,12 @@ public String getXAmzDateHeader() { public String getAuthorizationHeader() { return authorizationHeader; } + + /** + * @return the Session Token value + */ + public String getSessionToken() { + return sessionToken; + } } } diff --git a/src/test/java/com/amazonaws/neptune/auth/NeptuneSigV4SignerAbstractTest.java b/src/test/java/com/amazonaws/neptune/auth/NeptuneSigV4SignerAbstractTest.java index 325ca42..b61149d 100644 --- a/src/test/java/com/amazonaws/neptune/auth/NeptuneSigV4SignerAbstractTest.java +++ b/src/test/java/com/amazonaws/neptune/auth/NeptuneSigV4SignerAbstractTest.java @@ -60,6 +60,7 @@ public abstract class NeptuneSigV4SignerAbstractTest { protected static final String TEST_QUERY_PARAM_NAME = "query"; protected static final String TEST_DATE_HEADER_VALUE = "2020/10/04"; protected static final String TEST_AUTHORIZATION_HEADER_VALUE = "Authorization Header"; + protected static final String TEST_SESSION_TOKEN_VALUE = "Session Token"; protected final AWSCredentialsProvider awsCredentialsProvider = mock(AWSCredentialsProvider.class); @@ -215,9 +216,7 @@ public void toSignableRequestGetNoHost() throws NeptuneSigV4SignerException { signer.toSignableRequest(request); } - @Test - public void attachSignatureHeaders() throws Exception { - + private void testAttachSignatureHeaders(final String sessionToken) throws Exception { // prep final String uri = TEST_FULL_URI_WITH_SLASH; final Map requestHeaders = new HashMap<>(); @@ -230,7 +229,8 @@ public void attachSignatureHeaders() throws Exception { final String dateHeader = TEST_DATE_HEADER_VALUE; final String authHeader = TEST_AUTHORIZATION_HEADER_VALUE; - final NeptuneSigV4SignerBase.NeptuneSigV4Signature signature = new NeptuneSigV4SignerBase.NeptuneSigV4Signature(hostname, dateHeader, authHeader); + final NeptuneSigV4SignerBase.NeptuneSigV4Signature signature = + new NeptuneSigV4SignerBase.NeptuneSigV4Signature(hostname, dateHeader, authHeader, sessionToken); signer.attachSignature(request, signature); final Map attachedHeaders = getRequestHeaders(request); @@ -240,4 +240,16 @@ public void attachSignatureHeaders() throws Exception { assertEquals(HEADER_TWO_VALUE, attachedHeaders.get(HEADER_TWO_NAME)); assertEquals(authHeader, attachedHeaders.get(SignerConstants.AUTHORIZATION)); } + + @Test + public void attachSignatureHeadersWithSessionToken() throws Exception { + final String sessionToken = TEST_SESSION_TOKEN_VALUE; + testAttachSignatureHeaders(sessionToken); + } + + @Test + public void attachSignatureHeadersWithEmptySessionToken() throws Exception { + final String sessionToken = ""; + testAttachSignatureHeaders(sessionToken); + } }