Crate aws_sdk_cloudfront_url_signer

Source
Expand description

§aws-sdk-cloudfront-url-signer

A library for generating signed URLs and cookies for Amazon CloudFront private content.

This crate provides utilities to create cryptographically signed URLs and cookies that grant time-limited access to private CloudFront distributions. It supports both RSA-SHA1 and ECDSA-SHA1 signing algorithms with canned (simple) and custom (advanced) policies.

§Key Features

  • Signed URLs: Generate URLs with embedded signatures for single-resource access
  • Signed Cookies: Generate cookies for multi-resource access without URL modification
  • Canned Policies: Simple time-based expiration
  • Custom Policies: Advanced access control with activation dates, IP restrictions, and wildcards
  • Multiple Key Formats: RSA (PKCS#1/PKCS#8) and ECDSA P-256 (PKCS#8) private keys

§When to Use Signed URLs vs Cookies

Use signed URLs when:

  • Restricting access to individual files (e.g., a download link)
  • Users are accessing content through a client that doesn’t support cookies
  • You want to share a link that works without additional setup

Use signed cookies when:

  • Providing access to multiple restricted files (e.g., all files in a subscriber area)
  • You don’t want to change your existing URLs
  • You’re building a web application where cookies are naturally handled

§Feature Flags

FeatureDescription
rt-tokioEnables async file loading with PrivateKey::from_pem_file()
http-1xEnables conversion to http::Request types

§CloudFront Setup

Before using this library, you need to:

  1. Create a CloudFront key pair in the AWS Console or via CLI
  2. Upload the public key to CloudFront
  3. Create a key group containing your public key
  4. Configure your CloudFront distribution to use the key group for restricted content
  5. Keep the private key secure for use with this library

See the CloudFront Developer Guide for detailed setup instructions.

§Basic Usage

§Signing a URL with Canned Policy

Canned policies provide simple time-based access control with just an expiration time:

use aws_sdk_cloudfront_url_signer::{sign_url, SigningRequest, PrivateKey};
use aws_smithy_types::DateTime;

// Load your CloudFront private key
let private_key = PrivateKey::from_pem(include_bytes!("private_key.pem"))?;

// Create a signing request
let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/image.jpg")
    .key_pair_id("APKAEIBAERJR2EXAMPLE")
    .private_key(private_key)
    .expires_at(DateTime::from_secs(1767290400))  // Absolute expiration
    .build()?;

// Generate the signed URL
let signed_url = sign_url(&request)?;
println!("Signed URL: {}", signed_url);

The resulting URL will include Expires, Signature, and Key-Pair-Id query parameters.

§Using Relative Expiration

Instead of an absolute timestamp, you can specify a duration from now:

use std::time::Duration;

let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/video.mp4")
    .key_pair_id("APKAEIBAERJR2EXAMPLE")
    .private_key(private_key)
    .expires_in(Duration::from_secs(3600))  // Valid for 1 hour
    .build()?;

§Signing a URL with Custom Policy

Custom policies enable advanced access control with activation dates, IP restrictions, and wildcard patterns:

use aws_sdk_cloudfront_url_signer::{sign_url, SigningRequest, PrivateKey};
use aws_smithy_types::DateTime;

let private_key = PrivateKey::from_pem(include_bytes!("private_key.pem"))?;

let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/videos/*")
    .key_pair_id("APKAEIBAERJR2EXAMPLE")
    .private_key(private_key)
    .expires_at(DateTime::from_secs(1767290400))
    .active_at(DateTime::from_secs(1767200000))  // Not valid before this time
    .ip_range("192.0.2.0/24")                    // Restrict to IP range
    .build()?;

let signed_url = sign_url(&request)?;

Custom policy URLs include a Policy parameter (base64-encoded JSON) instead of Expires.

§Generating Signed Cookies

Signed cookies work similarly but return cookie name-value pairs:

use aws_sdk_cloudfront_url_signer::{sign_cookies, SigningRequest, PrivateKey};
use aws_smithy_types::DateTime;

let private_key = PrivateKey::from_pem(include_bytes!("private_key.pem"))?;

let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/*")
    .key_pair_id("APKAEIBAERJR2EXAMPLE")
    .private_key(private_key)
    .expires_at(DateTime::from_secs(1767290400))
    .build()?;

let cookies = sign_cookies(&request)?;

// Set cookies in your HTTP response
for (name, value) in cookies.iter() {
    println!("Set-Cookie: {}={}; Domain=d111111abcdef8.cloudfront.net; Secure; HttpOnly", name, value);
}

For canned policies, cookies include:

  • CloudFront-Expires
  • CloudFront-Signature
  • CloudFront-Key-Pair-Id

For custom policies, cookies include:

  • CloudFront-Policy
  • CloudFront-Signature
  • CloudFront-Key-Pair-Id

§Private Key Loading

§From PEM Bytes

Load a key from bytes (useful when loading from AWS Secrets Manager or environment variables):

use aws_sdk_cloudfront_url_signer::PrivateKey;

// From a byte slice
let key = PrivateKey::from_pem(include_bytes!("private_key.pem"))?;

// From a string
let pem_string = std::fs::read_to_string("private_key.pem")?;
let key = PrivateKey::from_pem(pem_string.as_bytes())?;

§From File (Async)

With the rt-tokio feature enabled, you can load keys directly from files:

use aws_sdk_cloudfront_url_signer::PrivateKey;

let key = PrivateKey::from_pem_file("private_key.pem").await?;

§Supported Key Formats

FormatHeaderKey Type
PKCS#1-----BEGIN RSA PRIVATE KEY-----RSA only
PKCS#8-----BEGIN PRIVATE KEY-----RSA or ECDSA P-256

Both RSA and ECDSA keys use SHA-1 signatures (required by CloudFront).

§Policy Types

§Canned Policy

A canned policy is automatically used when you only specify an expiration time. It’s simpler and produces shorter URLs:

let request = SigningRequest::builder()
    .resource_url("https://example.cloudfront.net/file.pdf")
    .key_pair_id("APKAEXAMPLE")
    .private_key(key)
    .expires_at(DateTime::from_secs(1767290400))
    .build()?;

§Custom Policy

A custom policy is used when you specify any of:

  • resource_pattern() - Wildcard pattern for the policy (different from the signed URL)
  • active_at() - URL becomes valid at this time (not-before)
  • ip_range() - Restrict access to an IPv4 CIDR range
let request = SigningRequest::builder()
    .resource_url("https://example.cloudfront.net/premium/video.mp4")
    .key_pair_id("APKAEXAMPLE")
    .private_key(key)
    .expires_at(DateTime::from_secs(1767290400))
    .active_at(DateTime::from_secs(1767200000))  // Triggers custom policy
    .ip_range("10.0.0.0/8")                      // Also triggers custom policy
    .build()?;

§Wildcard Patterns

Custom policies support wildcards in the resource pattern. Use resource_pattern() to specify a wildcard pattern that grants access to multiple resources, while resource_url() specifies the actual URL being signed:

  • * matches zero or more characters
  • ? matches exactly one character
// Sign a specific URL but grant access to all files under /videos/
let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/videos/intro.mp4")
    .resource_pattern("https://d111111abcdef8.cloudfront.net/videos/*")
    .key_pair_id("APKAEXAMPLE")
    .private_key(key)
    .expires_at(DateTime::from_secs(1767290400))
    .build()?;

// The signed URL points to intro.mp4, but the policy grants access to all /videos/*

Common wildcard patterns:

  • https://example.cloudfront.net/videos/* - All files under /videos/
  • https://example.cloudfront.net/*.mp4 - All .mp4 files
  • https://example.cloudfront.net/video-?.mp4 - video-1.mp4, video-2.mp4, etc.
  • * - All resources (use with caution)

§Using Signed URLs with HTTP Clients

The SignedUrl type provides multiple ways to access the signed URL for use with HTTP clients:

let signed_url = sign_url(&request)?;

// As a string slice
let url_str: &str = signed_url.as_str();

// As a parsed url::Url
let url: &url::Url = signed_url.as_url();

// Convert to owned url::Url
let url: url::Url = signed_url.into_url();

// Use with reqwest (reqwest re-exports url::Url)
let response = reqwest::get(signed_url.as_url()).await?;

// Display trait
println!("Signed URL: {}", signed_url);

§HTTP 1.x Integration

With the http-1x feature enabled, you can convert signed URLs directly to http::Request:

use http::Request;

let signed_url = sign_url(&request)?;

// Convert to http::Request
let http_request: Request<()> = signed_url.try_into()?;

// Or from a reference
let http_request: Request<()> = (&signed_url).try_into()?;

This is useful when working with HTTP clients that use the http crate types.

§Error Handling

All operations return Result<T, SigningError>:

use aws_sdk_cloudfront_url_signer::{sign_url, SigningRequest, PrivateKey, error::SigningError};

let result = sign_url(&request);
match result {
    Ok(signed_url) => println!("Success: {}", signed_url),
    Err(e) => {
        eprintln!("Signing failed: {}", e);
        if let Some(source) = e.source() {
            eprintln!("Caused by: {}", source);
        }
    }
}

Common error scenarios:

  • Invalid private key format
  • Missing required fields (resource_url, key_pair_id, private_key, expiration)
  • Cryptographic signing failures

§URLs with Existing Query Parameters

The library correctly handles URLs that already have query parameters:

let request = SigningRequest::builder()
    .resource_url("https://d111111abcdef8.cloudfront.net/video.mp4?quality=hd")
    .key_pair_id("APKAEXAMPLE")
    .private_key(key)
    .expires_at(DateTime::from_secs(1767290400))
    .build()?;

let signed_url = sign_url(&request)?;
// Result: https://...?quality=hd&Expires=...&Signature=...&Key-Pair-Id=...

This crate is part of the AWS SDK for Rust and the smithy-rs code generator.

Modules§

error
Error types for CloudFront signing operations.

Structs§

SignedCookies
Signed cookies for CloudFront.
SignedUrl
A signed CloudFront URL.
SigningRequest
Request to sign a CloudFront URL or generate signed cookies.
SigningRequestBuilder
Builder for SigningRequest.

Enums§

PrivateKey
Private key for signing CloudFront URLs and cookies.

Functions§

sign_cookies
Generate signed cookies with canned or custom policy
sign_url
Sign a CloudFront URL with canned or custom policy