Skip to content

Commit

Permalink
added CloudCDN url signing samples (#1020)
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-sanche authored and lesv committed Mar 5, 2018
1 parent 1dcc8c0 commit edb1883
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 0 deletions.
9 changes: 9 additions & 0 deletions cdn/signed-urls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Google Cloud CDN - Signing URLs
Java implementation of [`gcloud alpha compute sign-url`](https://cloud.google.com/sdk/gcloud/reference/alpha/compute/sign-url)
- uses a private key to create a time-sensitive URL that can be used to access a private Cloud CDN endpoint
- requires [random 128-bit key](https://cloud.google.com/cdn/docs/signed-urls#creatingkeys) encoded as base64 and [uploaded to a backend bucket](https://cloud.google.com/sdk/gcloud/reference/alpha/compute/backend-buckets/add-signed-url-key)

## Getting Started

1. [Download](https://maven.apache.org/download.cgi) and [install](https://maven.apache.org/install.html) maven to handle the project's dependencies
2. run `mvn clean verify` to build the project and run the tests
37 changes: 37 additions & 0 deletions cdn/signed-urls/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.google.cdn</groupId>
<artifactId>signedurls</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<!--
The parent pom defines common style checks and testing strategies for our samples.
Removing or replacing it should not affect the execution of the samples in anyway.
-->
<parent>
<groupId>com.google.cloud.samples</groupId>
<artifactId>shared-configuration</artifactId>
<version>1.0.8</version>
</parent>

<name>signedurls</name>
<url>http://maven.apache.org</url>

<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
91 changes: 91 additions & 0 deletions cdn/signed-urls/src/main/java/com/google/cdn/SignedUrls.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2018 Google Inc.
*
* 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.google.cdn;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
* Samples to create a signed URL for a Cloud CDN endpoint
*/
public class SignedUrls {

// [START signUrl]
/**
* Creates a signed URL for a Cloud CDN endpoint with the given key
* URL must start with http:// or https://, and must contain a forward
* slash (/) after the hostname.
* @param url the Cloud CDN endpoint to sign
* @param key url signing key uploaded to the backend service/bucket, as a 16-byte array
* @param keyName the name of the signing key added to the back end bucket or service
* @param expirationTime the date that the signed URL expires
* @return a properly formatted signed URL
* @throws InvalidKeyException when there is an error generating the signature for the input key
* @throws NoSuchAlgorithmException when HmacSHA1 algorithm is not available in the environment
*/
public static String signUrl(String url,
byte[] key,
String keyName,
Date expirationTime)
throws InvalidKeyException, NoSuchAlgorithmException {

final long unixTime = expirationTime.getTime() / 1000;

String urlToSign = url
+ (url.contains("?") ? "&" : "?")
+ "Expires=" + unixTime
+ "&KeyName=" + keyName;

String encoded = SignedUrls.getSignature(key, urlToSign);
return urlToSign + "&Signature=" + encoded;
}

public static String getSignature(byte[] privateKey, String input)
throws InvalidKeyException, NoSuchAlgorithmException {

final String algorithm = "HmacSHA1";
final int offset = 0;
Key key = new SecretKeySpec(privateKey, offset, privateKey.length, algorithm);
Mac mac = Mac.getInstance(algorithm);
mac.init(key);
return Base64.getUrlEncoder().encodeToString(mac.doFinal(input.getBytes()));
}
// [END signUrl]

public static void main(String[] args) throws Exception {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, 1);
Date tomorrow = cal.getTime();

//read the key as a base 64 url-safe encoded string, then convert to byte array
final String keyPath = "/path/to/key";
String base64String = new String(Files.readAllBytes(Paths.get(keyPath)));
byte[] keyBytes = Base64.getUrlDecoder().decode(base64String);

String result = signUrl("http://example.com/", keyBytes, "YOUR-KEY-NAME", tomorrow);
System.out.println(result);
}
}
62 changes: 62 additions & 0 deletions cdn/signed-urls/src/test/java/com/google/cdn/SignedUrlsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2018 Google Inc.
*
* 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.google.cdn;

import static com.google.cdn.SignedUrls.signUrl;
import static junit.framework.TestCase.assertEquals;

import java.util.Base64;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
* Test SignedUrls samples
*/
@RunWith(JUnit4.class)
@SuppressWarnings("checkstyle:abbreviationaswordinname")
public class SignedUrlsTest {
private static long TIMESTAMP = 1518135754;
private static Date EXPIRATION = new Date(TIMESTAMP * 1000);
private static byte[] KEY_BYTES = Base64.getUrlDecoder().decode("aaaaaaaaaaaaaaaaaaaaaa==");
private static String KEY_NAME = "my-key";
private static String BASE_URL = "https://www.example.com/";

@Test
public void testUrlPath() throws Exception {
String result = signUrl(BASE_URL + "foo", KEY_BYTES, KEY_NAME, EXPIRATION);
final String expected = "https://www.example.com/foo?Expires=1518135754&KeyName=my-key&Signature=vUfG4yv47dyns1j9e_OI6_5meuA=";
assertEquals(result, expected);
}

@Test
public void testUrlParams() throws Exception {
String result = signUrl(BASE_URL + "?param=true", KEY_BYTES, KEY_NAME, EXPIRATION);
final String expected = "https://www.example.com/?param=true&Expires=1518135754&KeyName=my-key&Signature=6TijW8OMX3gcMI5Kqs8ESiPY97c=";
assertEquals(result, expected);
}


@Test
public void testStandard() throws Exception {
String result = signUrl(BASE_URL, KEY_BYTES, KEY_NAME, EXPIRATION);
final String expected = "https://www.example.com/?Expires=1518135754&KeyName=my-key&Signature=4D0AbT4y0O7ZCzCUcAtPOJDkl2g=";
assertEquals(result, expected);
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<module>bigquery/datatransfer/cloud-client</module>
<module>bigquery/rest</module>

<module>cdn/signed-urls</module>
<module>cloud-tasks</module>
<module>compute</module>
<module>container-registry/container-analysis</module>
Expand Down

0 comments on commit edb1883

Please sign in to comment.