Reputation: 5563
I use Java 11. As AWS Java SDK2 supports for Java 11 I use SDK2. How to create cloud front url for s3 key. I'm able to get many examples for SDK 1.x version but not for SDK2. This is how the url is been generated in 1.x
CloudFrontUrlSigner.getSignedURLWithCannedPolicy(url, keyPairId, privateKey, expires)
Is there any alternative way or replacement in SDK 2.x version
Upvotes: 3
Views: 1489
Reputation: 141
This is available now in AWS Java SDK v2. You can use CloudFrontUtilities
and CannedSignerRequest
.
CloudFrontUtilities cloudFrontUtilities = CloudFrontUtilities.create();
Instant expirationDate = Instant.now().plus(7, ChronoUnit.DAYS);
String resourceUrl = "https://d1npcfkc2mojrf.cloudfront.net/s3ObjectKey";
String keyPairId = "myKeyPairId";
PrivateKey privateKey = myPrivateKey; // Either PrivateKey or Path can be passed in
CannedSignerRequest cannedRequest = CannedSignerRequest.builder()
.resourceUrl(resourceUrl)
.privateKey(privateKey)
.keyPairId(keyPairId)
.expirationDate(expirationDate)
.build();
Refer to https://aws.amazon.com/blogs/developer/amazon-cloudfront-signed-urls-and-cookies-are-now-supported-in-aws-sdk-for-java-2-x/ for more information.
Upvotes: 1
Reputation: 2055
I don't think it's been implemented yet. In the meantime, it was fairly easy to rip code from the old version to do the same thing.
and
import software.amazon.awssdk.core.exception.SdkException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Date;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class AwsUtils {
private static final SecureRandom srand = new SecureRandom();
/**
* Generates a signed url that expires after given date.
* @param resourceUrlOrPath The url.
* @param keyPairId The keypair id used to sign.
* @param privateKey The private key.
* @param dateLessThan The expire date/time.
* @return A valid cloudwatch url.
* @throws SdkException If any errors occur during the signing process.
*/
public static String getSignedUrlWithCannedPolicy(String resourceUrlOrPath,
String keyPairId,
PrivateKey privateKey,
Date dateLessThan) throws SdkException {
try {
String cannedPolicy = buildCannedPolicy(resourceUrlOrPath, dateLessThan);
byte[] signatureBytes = signWithSha1Rsa(cannedPolicy.getBytes(StandardCharsets.UTF_8), privateKey);
String urlSafeSignature = makeBytesUrlSafe(signatureBytes);
return resourceUrlOrPath
+ (resourceUrlOrPath.indexOf('?') >= 0 ? "&" : "?")
+ "Expires=" + MILLISECONDS.toSeconds(dateLessThan.getTime())
+ "&Signature=" + urlSafeSignature
+ "&Key-Pair-Id=" + keyPairId;
} catch (InvalidKeyException e) {
throw SdkException.create("Couldn't sign url", e);
}
}
/**
* Returns a "canned" policy for the given parameters.
* For more information, see <a href=
* "http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls-overview.html"
* >Overview of Signed URLs</a>.
* @param resourceUrlOrPath The resource to grant access.
* @param dateLessThan The expiration time.
* @return the aws policy as a string.
*/
public static String buildCannedPolicy(String resourceUrlOrPath,
Date dateLessThan) {
return "{\"Statement\":[{\"Resource\":\""
+ resourceUrlOrPath
+ "\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":"
+ MILLISECONDS.toSeconds(dateLessThan.getTime())
+ "}}}]}";
}
/**
* Signs the data given with the private key given, using the SHA1withRSA
* algorithm provided by bouncy castle.
* @param dataToSign The data to sign.
* @param privateKey The private key.
* @return A signature.
* @throws InvalidKeyException if an invalid key was provided.
*/
public static byte[] signWithSha1Rsa(byte[] dataToSign,
PrivateKey privateKey) throws InvalidKeyException {
Signature signature;
try {
signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey, srand);
signature.update(dataToSign);
return signature.sign();
} catch (NoSuchAlgorithmException | SignatureException e) {
throw new IllegalStateException(e);
}
}
/**
* Converts the given data to be safe for use in signed URLs for a private
* distribution by using specialized Base64 encoding.
* @param bytes The bytes
*/
public static String makeBytesUrlSafe(byte[] bytes) {
byte[] encoded = java.util.Base64.getEncoder().encode(bytes);
for (int i = 0; i < encoded.length; i++) {
switch (encoded[i]) {
case '+':
encoded[i] = '-';
continue;
case '=':
encoded[i] = '_';
continue;
case '/':
encoded[i] = '~';
continue;
default:
continue;
}
}
return new String(encoded, StandardCharsets.UTF_8);
}
}
Upvotes: 1