diff --git a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/AbstractEdgeGridRequestSigner.java b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/AbstractEdgeGridRequestSigner.java
index 2cfb512..801643d 100644
--- a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/AbstractEdgeGridRequestSigner.java
+++ b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/AbstractEdgeGridRequestSigner.java
@@ -62,7 +62,16 @@ public AbstractEdgeGridRequestSigner(ClientCredential clientCredential) {
*/
public AbstractEdgeGridRequestSigner(ClientCredentialProvider clientCredentialProvider) {
this.clientCredentialProvider = clientCredentialProvider;
- this.edgeGridSigner = new EdgeGridV1Signer();
+ this.edgeGridSigner = createEdgeGridSigner();
+ }
+
+ /**
+ * Returns new instance of EdgeGridV1Signer.
+ *
+ * @return a {@link EdgeGridV1Signer} new instance
+ */
+ protected EdgeGridV1Signer createEdgeGridSigner() {
+ return new EdgeGridV1Signer();
}
/**
diff --git a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/EdgeGridV1Signer.java b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/EdgeGridV1Signer.java
index 2fe2e7f..3ad1967 100644
--- a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/EdgeGridV1Signer.java
+++ b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/EdgeGridV1Signer.java
@@ -110,7 +110,23 @@ public EdgeGridV1Signer() {
*/
public String getSignature(Request request, ClientCredential credential)
throws RequestSigningException {
- return getSignature(request, credential, System.currentTimeMillis(), generateNonce());
+ return getSignature(request, credential, getTimestamp(), getNonce());
+ }
+
+ /**
+ * Returns timestamp needed for signing
+ * @return returns current time stamp
+ */
+ protected long getTimestamp() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * Returns nonce needed for signing
+ * @return returns generated nonce
+ */
+ protected String getNonce() {
+ return generateNonce();
}
private static String generateNonce() {
diff --git a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/Request.java b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/Request.java
index eb19656..ae5d85c 100644
--- a/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/Request.java
+++ b/edgegrid-signer-core/src/main/java/com/akamai/edgegrid/signer/Request.java
@@ -286,6 +286,21 @@ public RequestBuilder uri(URI uri) {
return this;
}
+ /**
+ *
+ * Sets the URI of the HTTP request without any processing it, which is important when URI contains
+ * path parameters which consists of encoded URLs.
+ * This URI MUST have the correct path and query segments set. Scheme is assumed to be "HTTPS" for the purpose of this library. Host is
+ * actually taken from a {@link ClientCredential} at signing time; any value in this URI is
+ * discarded. Fragments are not removed from signing process.
+ *
+ *
+ * A path and/or query string is required.
+ *
+ *
+ * @param uri a {@link URI}
+ * @return reference back to this builder instance
+ */
public RequestBuilder rawUri(URI uri) {
Objects.requireNonNull(uri, "uri cannot be empty");
this.uri = uri;
diff --git a/edgegrid-signer-rest-assured/src/main/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilter.java b/edgegrid-signer-rest-assured/src/main/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilter.java
index b77ca70..cfe1a25 100644
--- a/edgegrid-signer-rest-assured/src/main/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilter.java
+++ b/edgegrid-signer-rest-assured/src/main/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilter.java
@@ -40,7 +40,7 @@
*/
public class RestAssuredEdgeGridFilter implements Filter {
- private final RestAssuredEdgeGridRequestSigner binding;
+ protected RestAssuredEdgeGridRequestSigner binding;
/**
* Creates an EdgeGrid signing interceptor using the same {@link ClientCredential} for each
diff --git a/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterIntegrationTest.java b/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterIntegrationTest.java
index 6b0ee5f..8da26ba 100644
--- a/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterIntegrationTest.java
+++ b/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterIntegrationTest.java
@@ -17,6 +17,7 @@
import com.akamai.edgegrid.signer.ClientCredential;
+import com.akamai.edgegrid.signer.EdgeGridV1Signer;
import com.akamai.edgegrid.signer.exceptions.RequestSigningException;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.matching.RequestPattern;
@@ -261,6 +262,61 @@ public void dontSignRequestWithMultipartContent() throws URISyntaxException, IOE
.then().statusCode(200);
}
+ class MockedEdgeGridV1Signer extends EdgeGridV1Signer {
+ String fixedNonce = "ec9d20ee-1e9b-4c1f-925a-f0017754f86c";
+ // Fixed timestamp corresponds to 2016-08-04T07:00:00+0000.
+ long fixedTimestamp = 1470294000000L;
+
+ protected long getTimestamp() {
+ return fixedTimestamp;
+ }
+
+ protected String getNonce() {
+ return fixedNonce;
+ }
+
+ }
+
+ class MockedRestAssuredEdgeGridRequestSigner extends RestAssuredEdgeGridRequestSigner {
+
+ public MockedRestAssuredEdgeGridRequestSigner(ClientCredential clientCredential) {
+ super(clientCredential);
+ }
+
+ @Override
+ protected EdgeGridV1Signer createEdgeGridSigner() {
+ return new MockedEdgeGridV1Signer();
+ }
+ }
+
+ class MockedRestAssuredEdgeGridFilter extends RestAssuredEdgeGridFilter {
+
+ public MockedRestAssuredEdgeGridFilter(ClientCredential credential) {
+ super(credential);
+ this.binding = new MockedRestAssuredEdgeGridRequestSigner(credential);
+ }
+ }
+ @Test
+ public void signRequestWithPathParamContainingURL() throws URISyntaxException, IOException {
+
+ wireMockServer.stubFor(get(urlPathMatching("/sso-config/v1/idps/https%3A%2F%2Ffdef2ea8-64b1-4b78-ad36-bacae87af167/certificates"))
+ .withHeader("Authorization", equalTo("EG1-HMAC-SHA256 client_token=akaa-k7glklzuxkkh2ycw-oadjphopvpn6yjoj;access_token=akaa-dm5g2bfwoodqnc6k-ju7vlao2wz6oz2rp;timestamp=20160804T07:00:00+0000;nonce=ec9d20ee-1e9b-4c1f-925a-f0017754f86c;signature=2KunLDWST5ZgrbL8CuTF2Gxp7UfsIy/DxELcajvziTo="))
+ .withHeader("Host", equalTo(SERVICE_MOCK))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "text/xml")
+ .withBody("Some content")));
+
+ RestAssuredEdgeGridFilter filter = new MockedRestAssuredEdgeGridFilter(credential);
+ RestAssured.given()
+ .relaxedHTTPSValidation()
+ .filter(filter)
+ .get("/sso-config/v1/idps/{id}/certificates", "https://fdef2ea8-64b1-4b78-ad36-bacae87af167")
+ .then().statusCode(200);
+
+ assertThat(wireMockServer.findAllUnmatchedRequests().size(), CoreMatchers.equalTo(0));
+ }
+
@AfterClass
public void tearDownAll() {
wireMockServer.stop();
diff --git a/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterTest.java b/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterTest.java
deleted file mode 100644
index 240f659..0000000
--- a/edgegrid-signer-rest-assured/src/test/java/com/akamai/edgegrid/signer/restassured/RestAssuredEdgeGridFilterTest.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2018 Akamai Technologies, Inc. All Rights Reserved.
- *
- * 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 com.akamai.edgegrid.signer.restassured;
-
-import com.akamai.edgegrid.signer.ClientCredential;
-import com.akamai.edgegrid.signer.exceptions.RequestSigningException;
-import com.github.tomakehurst.wiremock.WireMockServer;
-import com.github.tomakehurst.wiremock.matching.RequestPattern;
-import com.github.tomakehurst.wiremock.verification.LoggedRequest;
-
-import io.restassured.RestAssured;
-import io.restassured.filter.Filter;
-import io.restassured.filter.FilterContext;
-import io.restassured.response.Response;
-import io.restassured.specification.FilterableRequestSpecification;
-import io.restassured.specification.FilterableResponseSpecification;
-import io.restassured.specification.RequestSpecification;
-
-import org.hamcrest.CoreMatchers;
-import org.hamcrest.MatcherAssert;
-import org.hamcrest.Matchers;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.*;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-
-/**
- * Unit tests for {@link RestAssuredEdgeGridFilterTest}.
- *
- * @author mgawinec@akamai.com
- */
-public class RestAssuredEdgeGridFilterTest {
-
- static final String SERVICE_MOCK_HOST = "localhost";
- static final int SERVICE_MOCK_PORT = 9089;
- static final String SERVICE_MOCK = SERVICE_MOCK_HOST + ":" + SERVICE_MOCK_PORT;
-
- ClientCredential credential = ClientCredential.builder()
- .accessToken("akaa-dm5g2bfwoodqnc6k-ju7vlao2wz6oz2rp")
- .clientToken("akaa-k7glklzuxkkh2ycw-oadjphopvpn6yjoj")
- .clientSecret("SOMESECRET")
- .host(SERVICE_MOCK)
- .build();
-
- WireMockServer wireMockServer = new WireMockServer(wireMockConfig().httpsPort(SERVICE_MOCK_PORT));
-
-
-
- @BeforeClass
- public void setUp() {
- wireMockServer.start();
- }
-
- @BeforeMethod
- public void reset() {
- wireMockServer.resetMappings();
- wireMockServer.resetRequests();
- }
-
- @Test
- // Due to limitations of REST-assured we cannot sign again followed redirects
- // https://github.com/akamai-open/AkamaiOPEN-edgegrid-java/issues/21
- public void cannotSignAgainFollowedRedirects() throws URISyntaxException, IOException {
-
- wireMockServer.stubFor(get(urlPathEqualTo("/billing-usage/v1/reportSources"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .willReturn(aResponse()
- .withStatus(302)
- .withHeader("Location", "/billing-usage/v1/reportSources/alternative")));
-
- wireMockServer.stubFor(get(urlPathEqualTo("/billing-usage/v1/reportSources/alternative"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .willReturn(aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "text/xml")
- .withBody("Some content")));
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .get("/billing-usage/v1/reportSources")
- .then().statusCode(200);
-
- List loggedRequests = wireMockServer.findRequestsMatching(RequestPattern
- .everything()).getRequests();
- MatcherAssert.assertThat(loggedRequests.get(0).getHeader("Authorization"),
- CoreMatchers.equalTo(loggedRequests.get(1).getHeader("Authorization")));
- }
-
- @Test
- public void signEachRequest() throws URISyntaxException, IOException {
-
- wireMockServer.stubFor(get(urlPathEqualTo("/billing-usage/v1/reportSources"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .willReturn(aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "text/xml")
- .withBody("Some content")));
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .get("/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @Test
- public void signEachRequestWithPathParams() throws URISyntaxException, IOException {
-
- wireMockServer.stubFor(get(urlPathMatching("/config-gtm/v1/domains/.*"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .willReturn(aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "text/xml")
- .withBody("Some content")));
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .get("/config-gtm/v1/domains/{domain}", "storage1.akadns.net")
- .then().statusCode(200);
- }
-
- @Test
- public void signEachRequestWithPathParamsAndQueryString() throws URISyntaxException,
- IOException {
-
- wireMockServer.stubFor(get(urlPathMatching("/config-gtm/v1/domains/.*"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .withQueryParam("param1", equalTo("value1"))
- .willReturn(aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "text/xml")
- .withBody("Some content")));
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .queryParam("param1", "value1")
- .get("/config-gtm/v1/domains/{domain}", "storage1.akadns.net")
- .then().statusCode(200);
- }
-
- @Test
- public void signWithHostHeader() throws URISyntaxException, IOException {
-
- wireMockServer.stubFor(get(urlPathEqualTo("/billing-usage/v1/reportSources"))
- .withHeader("Authorization", matching(".*"))
- .withHeader("Host", equalTo(SERVICE_MOCK))
- .willReturn(aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "text/xml")
- .withBody("Some content")));
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .header("Host", "ignored-hostname.com")
- .get("/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @Test
- public void replacesProvidedHostHeader() throws URISyntaxException, IOException,
- RequestSigningException {
-
-
- RestAssured.given()
- .relaxedHTTPSValidation()
- .header("Host", "ignored-hostname.com")
- .filter(new RestAssuredEdgeGridFilter(credential))
- .filter(new Filter() {
- @Override
- public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, FilterContext ctx) {
- MatcherAssert.assertThat(requestSpec.getHeaders().getList("Host").size(),
- CoreMatchers.equalTo(1));
- MatcherAssert.assertThat(requestSpec.getHeaders().get("Host").getValue(),
- CoreMatchers.equalTo(credential.getHost()));
-
- return ctx.next(requestSpec, responseSpec);
- }
- })
- .get();
-
-
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void dontSignEachRequestWithAbsolutePath() throws URISyntaxException, IOException {
-
- RestAssured.given()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .get("https://ignored-hostname.com/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void dontSignRequestWithFileContent() throws URISyntaxException, IOException {
-
- RestAssured.given()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .body(new File("/home/johan/some_large_file.bin"))
- .post("/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void dontSignRequestWithInputStreamContent() throws URISyntaxException, IOException {
-
- RestAssured.given()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .body(new ByteArrayInputStream("exampleString".getBytes(StandardCharsets.UTF_8)))
- .post("/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void dontSignRequestWithMultipartContent() throws URISyntaxException, IOException {
-
- RestAssured.given()
- .filter(new RestAssuredEdgeGridFilter(credential))
- .multiPart("file", new File("/home/johan/some_large_file.bin"))
- .post("/billing-usage/v1/reportSources")
- .then().statusCode(200);
- }
-
- @AfterClass
- public void tearDownAll() {
- wireMockServer.stop();
- }
-
-}