software.amazon.awssdk.services.cloudfront.CloudFrontUtilities Maven / Gradle / Ivy
Show all versions of cloudfront Show documentation
/*
* Copyright Amazon.com, Inc. or its affiliates. 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.services.cloudfront;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.net.URI;
import java.security.InvalidKeyException;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Immutable;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.services.cloudfront.cookie.CookiesForCannedPolicy;
import software.amazon.awssdk.services.cloudfront.cookie.CookiesForCustomPolicy;
import software.amazon.awssdk.services.cloudfront.internal.cookie.DefaultCookiesForCannedPolicy;
import software.amazon.awssdk.services.cloudfront.internal.cookie.DefaultCookiesForCustomPolicy;
import software.amazon.awssdk.services.cloudfront.internal.url.DefaultSignedUrl;
import software.amazon.awssdk.services.cloudfront.internal.utils.SigningUtils;
import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest;
import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest;
import software.amazon.awssdk.services.cloudfront.url.SignedUrl;
/**
*
* Utilities for working with CloudFront distributions
*
* To securely serve private content by using CloudFront, you can require that users access your private content by using
* special CloudFront signed URLs or signed cookies. You then develop your application either to create and distribute signed
* URLs to authenticated users or to send Set-Cookie headers that set signed cookies for authenticated users.
*
* Signed URLs take precedence over signed cookies. If you use both signed URLs and signed cookies to control access to the
* same files and a viewer uses a signed URL to request a file, CloudFront determines whether to return the file to the
* viewer based only on the signed URL.
*
*/
@Immutable
@ThreadSafe
@SdkPublicApi
public final class CloudFrontUtilities {
private static final String KEY_PAIR_ID_KEY = "CloudFront-Key-Pair-Id";
private static final String SIGNATURE_KEY = "CloudFront-Signature";
private static final String EXPIRES_KEY = "CloudFront-Expires";
private static final String POLICY_KEY = "CloudFront-Policy";
private CloudFrontUtilities() {
}
public static CloudFrontUtilities create() {
return new CloudFrontUtilities();
}
/**
* Returns a signed URL with a canned policy that grants universal access to
* private content until a given date.
* For more information, see Creating a signed URL using a canned policy.
*
*
* This is a convenience which creates an instance of the {@link CannedSignerRequest.Builder} avoiding the need to
* create one manually via {@link CannedSignerRequest#builder()}
*
* @param request
* A {@link Consumer} that will call methods on {@link CannedSignerRequest.Builder} to create a request.
* @return A signed URL that will permit access to a specific distribution
* and S3 object.
*
*
Example Usage
*
* {@snippet :
* //Generates signed URL String with canned policy, valid for 7 days
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* PrivateKey privateKey = myPrivateKey;
*
* SignedUrl signedUrl = utilities.getSignedUrlWithCannedPolicy(r -> r.resourceUrl(resourceUrl)
* .privateKey(privateKey)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate));
* String url = signedUrl.url();
* }
*/
public SignedUrl getSignedUrlWithCannedPolicy(Consumer request) {
return getSignedUrlWithCannedPolicy(CannedSignerRequest.builder().applyMutation(request).build());
}
/**
* Returns a signed URL with a canned policy that grants universal access to
* private content until a given date.
* For more information, see Creating a signed URL using a canned policy.
*
* @param request
* A {@link CannedSignerRequest} configured with the following values:
* resourceUrl, privateKey, keyPairId, expirationDate
* @return A signed URL that will permit access to a specific distribution
* and S3 object.
*
* Example Usage
*
* {@snippet :
* //Generates signed URL String with canned policy, valid for 7 days
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* Path keyFile = myKeyFile;
*
* CannedSignerRequest cannedRequest = CannedSignerRequest.builder()
* .resourceUrl(resourceUrl)
* .privateKey(keyFile)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate)
* .build();
* SignedUrl signedUrl = utilities.getSignedUrlWithCannedPolicy(cannedRequest);
* String url = signedUrl.url();
* }
*/
public SignedUrl getSignedUrlWithCannedPolicy(CannedSignerRequest request) {
try {
String resourceUrl = request.resourceUrl();
String cannedPolicy = SigningUtils.buildCannedPolicy(resourceUrl, request.expirationDate());
byte[] signatureBytes = SigningUtils.signWithSha1Rsa(cannedPolicy.getBytes(UTF_8), request.privateKey());
String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes);
URI uri = URI.create(resourceUrl);
String protocol = uri.getScheme();
String encodedPath = uri.getRawPath()
+ (uri.getQuery() != null ? "?" + uri.getRawQuery() + "&" : "?")
+ "Expires=" + request.expirationDate().getEpochSecond()
+ "&Signature=" + urlSafeSignature
+ "&Key-Pair-Id=" + request.keyPairId();
return DefaultSignedUrl.builder()
.protocol(protocol)
.domain(uri.getHost())
.encodedPath(encodedPath)
.url(protocol + "://" + uri.getAuthority() + encodedPath)
.build();
} catch (InvalidKeyException e) {
throw SdkClientException.create("Could not sign url", e);
}
}
/**
* Returns a signed URL that provides tailored access to private content
* based on an access time window and an ip range. The custom policy itself
* is included as part of the signed URL (For a signed URL with canned
* policy, there is no policy included in the signed URL).
* For more information, see Creating a signed URL using a custom policy.
*
*
* This is a convenience which creates an instance of the {@link CustomSignerRequest.Builder} avoiding the need to
* create one manually via {@link CustomSignerRequest#builder()}
*
* @param request
* A {@link Consumer} that will call methods on {@link CustomSignerRequest.Builder} to create a request.
* @return A signed URL that will permit access to distribution and S3
* objects as specified in the policy document.
*
*
Example Usage
*
* {@snippet :
* //Generates signed URL String with custom policy, with an access window that begins in 2 days and ends in 7 days,
* //for a specified IP range
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* PrivateKey privateKey = myPrivateKey;
* Instant activeDate = Instant.now().plus(Duration.ofDays(2));
* String ipRange = "192.168.0.1/24";
*
* SignedUrl signedUrl = utilities.getSignedUrlWithCustomPolicy(r -> r.resourceUrl(resourceUrl)
* .privateKey(privateKey)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate)
* .activeDate(activeDate)
* .ipRange(ipRange));
* String url = signedUrl.url();
* }
*/
public SignedUrl getSignedUrlWithCustomPolicy(Consumer request) {
return getSignedUrlWithCustomPolicy(CustomSignerRequest.builder().applyMutation(request).build());
}
/**
* Returns a signed URL that provides tailored access to private content
* based on an access time window and an ip range. The custom policy itself
* is included as part of the signed URL (For a signed URL with canned
* policy, there is no policy included in the signed URL).
* For more information, see Creating a signed URL using a custom policy.
*
* @param request
* A {@link CustomSignerRequest} configured with the following values:
* resourceUrl, privateKey, keyPairId, expirationDate, activeDate (optional), ipRange (optional)
* @return A signed URL that will permit access to distribution and S3
* objects as specified in the policy document.
*
* Example Usage
*
* {@snippet :
* //Generates signed URL String with custom policy, with an access window that begins in 2 days and ends in 7 days,
* //for a specified IP range
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* Path keyFile = myKeyFile;
* Instant activeDate = Instant.now().plus(Duration.ofDays(2));
* String ipRange = "192.168.0.1/24";
*
* CustomSignerRequest customRequest = CustomSignerRequest.builder()
* .resourceUrl(resourceUrl)
* .privateKey(keyFile)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate)
* .activeDate(activeDate)
* .ipRange(ipRange)
* .build();
* SignedUrl signedUrl = utilities.getSignedUrlWithCustomPolicy(customRequest);
* String url = signedUrl.url();
* }
*/
public SignedUrl getSignedUrlWithCustomPolicy(CustomSignerRequest request) {
try {
String resourceUrl = request.resourceUrl();
String policy = SigningUtils.buildCustomPolicyForSignedUrl(request.resourceUrl(), request.activeDate(),
request.expirationDate(), request.ipRange());
byte[] signatureBytes = SigningUtils.signWithSha1Rsa(policy.getBytes(UTF_8), request.privateKey());
String urlSafePolicy = SigningUtils.makeStringUrlSafe(policy);
String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes);
URI uri = URI.create(resourceUrl);
String protocol = uri.getScheme();
String encodedPath = uri.getRawPath()
+ (uri.getQuery() != null ? "?" + uri.getRawQuery() + "&" : "?")
+ "Policy=" + urlSafePolicy
+ "&Signature=" + urlSafeSignature
+ "&Key-Pair-Id=" + request.keyPairId();
return DefaultSignedUrl.builder()
.protocol(protocol)
.domain(uri.getHost())
.encodedPath(encodedPath)
.url(protocol + "://" + uri.getAuthority() + encodedPath)
.build();
} catch (InvalidKeyException e) {
throw SdkClientException.create("Could not sign url", e);
}
}
/**
* Generate signed cookies that allows access to a specific distribution and
* resource path by applying access restrictions from a "canned" (simplified)
* policy document.
* For more information, see Setting signed cookies using a canned policy.
*
*
* This is a convenience which creates an instance of the {@link CannedSignerRequest.Builder} avoiding the need to
* create one manually via {@link CannedSignerRequest#builder()}
*
* @param request
* A {@link Consumer} that will call methods on {@link CannedSignerRequest.Builder} to create a request.
* @return The signed cookies with canned policy.
*
*
Example Usage
*
* {@snippet :
* //Generates signed Cookie for canned policy, valid for 7 days
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* PrivateKey privateKey = myPrivateKey;
*
* CookiesForCannedPolicy cookies = utilities.getSignedCookiesForCannedPolicy(r -> r.resourceUrl(resourceUrl)
* .privateKey(privateKey)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate));
* // Generates Set-Cookie header values to send to the viewer to allow access
* String signatureHeaderValue = cookies.signatureHeaderValue();
* String keyPairIdHeaderValue = cookies.keyPairIdHeaderValue();
* String expiresHeaderValue = cookies.expiresHeaderValue();
* }
*/
public CookiesForCannedPolicy getCookiesForCannedPolicy(Consumer request) {
return getCookiesForCannedPolicy(CannedSignerRequest.builder().applyMutation(request).build());
}
/**
* Generate signed cookies that allows access to a specific distribution and
* resource path by applying access restrictions from a "canned" (simplified)
* policy document.
* For more information, see Setting signed cookies using a canned policy.
*
* @param request
* A {@link CannedSignerRequest} configured with the following values:
* resourceUrl, privateKey, keyPairId, expirationDate
* @return The signed cookies with canned policy.
*
* Example Usage
*
* {@snippet :
* //Generates signed Cookie for canned policy, valid for 7 days
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* Path keyFile = myKeyFile;
*
* CannedSignerRequest cannedRequest = CannedSignerRequest.builder()
* .resourceUrl(resourceUrl)
* .privateKey(keyFile)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate)
* .build();
* CookiesForCannedPolicy cookies = utilities.getCookiesForCannedPolicy(cannedRequest);
* // Generates Set-Cookie header values to send to the viewer to allow access
* String signatureHeaderValue = cookies.signatureHeaderValue();
* String keyPairIdHeaderValue = cookies.keyPairIdHeaderValue();
* String expiresHeaderValue = cookies.expiresHeaderValue();
* }
*/
public CookiesForCannedPolicy getCookiesForCannedPolicy(CannedSignerRequest request) {
try {
String cannedPolicy = SigningUtils.buildCannedPolicy(request.resourceUrl(), request.expirationDate());
byte[] signatureBytes = SigningUtils.signWithSha1Rsa(cannedPolicy.getBytes(UTF_8), request.privateKey());
String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes);
String expiry = String.valueOf(request.expirationDate().getEpochSecond());
return DefaultCookiesForCannedPolicy.builder()
.resourceUrl(request.resourceUrl())
.keyPairIdHeaderValue(KEY_PAIR_ID_KEY + "=" + request.keyPairId())
.signatureHeaderValue(SIGNATURE_KEY + "=" + urlSafeSignature)
.expiresHeaderValue(EXPIRES_KEY + "=" + expiry).build();
} catch (InvalidKeyException e) {
throw SdkClientException.create("Could not sign canned policy cookie", e);
}
}
/**
* Returns signed cookies that provides tailored access to private content based on an access time window and an ip range.
* For more information, see Setting signed cookies using a custom policy.
*
*
* This is a convenience which creates an instance of the {@link CustomSignerRequest.Builder} avoiding the need to
* create one manually via {@link CustomSignerRequest#builder()}
*
* @param request
* A {@link Consumer} that will call methods on {@link CustomSignerRequest.Builder} to create a request.
* @return The signed cookies with custom policy.
*
*
Example Usage
*
* {@snippet :
* //Generates signed Cookie for custom policy, with an access window that begins in 2 days and ends in 7 days,
* //for a specified IP range
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* PrivateKey privateKey = myPrivateKey;
* Instant activeDate = Instant.now().plus(Duration.ofDays(2));
* String ipRange = "192.168.0.1/24";
*
* CookiesForCustomPolicy cookies = utilities.getCookiesForCustomPolicy(r -> r.resourceUrl(resourceUrl)
* .privateKey(privateKey)
* .keyPairId(keyPairId)
* .expirationDate(expirationDate)
* .activeDate(activeDate)
* .ipRange(ipRange));
* // Generates Set-Cookie header values to send to the viewer to allow access
* String signatureHeaderValue = cookies.signatureHeaderValue();
* String keyPairIdHeaderValue = cookies.keyPairIdHeaderValue();
* String policyHeaderValue = cookies.policyHeaderValue();
* }
*/
public CookiesForCustomPolicy getCookiesForCustomPolicy(Consumer request) {
return getCookiesForCustomPolicy(CustomSignerRequest.builder().applyMutation(request).build());
}
/**
* Returns signed cookies that provides tailored access to private content based on an access time window and an ip range.
* For more information, see Setting signed cookies using a custom policy.
*
* @param request
* A {@link CustomSignerRequest} configured with the following values:
* resourceUrl, privateKey, keyPairId, expirationDate, activeDate (optional), ipRange (optional)
* @return The signed cookies with custom policy.
*
* Example Usage
*
* {@snippet :
* //Generates signed Cookie for custom policy, with an access window that begins in 2 days and ends in 7 days,
* //for a specified IP range
* CloudFrontUtilities utilities = CloudFrontUtilities.create();
*
* Instant expirationDate = Instant.now().plus(Duration.ofDays(7));
* String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
* String keyPairId = "myKeyPairId";
* Path keyFile = myKeyFile;
* Instant activeDate = Instant.now().plus(Duration.ofDays(2));
* String ipRange = "192.168.0.1/24";
*
* CustomSignerRequest customRequest = CustomSignerRequest.builder()
* .resourceUrl(resourceUrl)
* .privateKey(keyFile)
* .keyPairId(keyFile)
* .expirationDate(expirationDate)
* .activeDate(activeDate)
* .ipRange(ipRange)
* .build();
* CookiesForCustomPolicy cookies = utilities.getCookiesForCustomPolicy(customRequest);
* // Generates Set-Cookie header values to send to the viewer to allow access
* String signatureHeaderValue = cookies.signatureHeaderValue();
* String keyPairIdHeaderValue = cookies.keyPairIdHeaderValue();
* String policyHeaderValue = cookies.policyHeaderValue();
* }
*/
public CookiesForCustomPolicy getCookiesForCustomPolicy(CustomSignerRequest request) {
try {
String policy = SigningUtils.buildCustomPolicy(request.resourceUrl(), request.activeDate(), request.expirationDate(),
request.ipRange());
byte[] signatureBytes = SigningUtils.signWithSha1Rsa(policy.getBytes(UTF_8), request.privateKey());
String urlSafePolicy = SigningUtils.makeStringUrlSafe(policy);
String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes);
return DefaultCookiesForCustomPolicy.builder()
.resourceUrl(request.resourceUrl())
.keyPairIdHeaderValue(KEY_PAIR_ID_KEY + "=" + request.keyPairId())
.signatureHeaderValue(SIGNATURE_KEY + "=" + urlSafeSignature)
.policyHeaderValue(POLICY_KEY + "=" + urlSafePolicy).build();
} catch (InvalidKeyException e) {
throw SdkClientException.create("Could not sign custom policy cookie", e);
}
}
}