🦉
Programming Notes
  • My Programming Notes
  • CKA Exam Preparation
    • Certified Kubernetes Administrator
    • Setup Minikube
    • Network Design Principles
    • Role-Based Access Control (RBAC)
    • Namespace
    • Resource Quota
    • Pod
    • Deployment
    • Deployment: Rollout
    • ConfigMap
    • Service
    • Service: kubectl expose
    • Pod: Resources Management
    • Pod & Container: Quality of Service Class
    • Pod & Container: Probes
    • Limit Range
    • Scaling: Manual
    • Scaling: Horizontal Pod Autoscaler
    • Persistent Volume & Claim
    • Secret
    • Ingress: Routing
    • Ingress: TLS
    • Ingress: Rate Limit
    • Ingress: Basic Auth
    • Ingress: CRD (Custom Resource Definition)
    • Job
    • CronJob
    • Mutli-Node Cluster
  • Golang
    • Generics
    • Context
    • Goroutines and Channels in Go
    • Goroutine: Concurrency vs Parallelism
    • Goroutine: Performance & Tradeoffs
    • JSON: omitzero
  • Rust
    • Arrays & Slices
    • Closures
    • Generics & Traits
    • Iterators
    • Run Code Simultaneously
    • String vs &str
    • Tests
    • Rustlings Exercises
      • Variables
      • Functions
      • If
      • Primitive Types
      • Vectors
      • Move Semantics
      • Structs
      • Enums and Matching Pattern
      • Strings
      • Modules
      • Hashmaps
      • Options
      • Error Handling
      • Generics
      • Traits
      • Lifetimes
      • Tests
      • Iterators
      • Smart Pointers
      • Threads
      • Macros
      • Quiz 1
      • Quiz 2
      • Quiz 3
  • Software Engineering
    • CAP Theorem
    • Circuit Breaker
    • Decoupling
    • GraphQL: Query Caching
    • HMAC Signature
    • Idempotency
    • Monolith VS Microservice
    • OWASP Top 10 2021
    • PCI DSS
    • PostgreSQL: Partitioning
    • PostgreSQL: Replication
    • Protobuf & gRPC
    • Redis: Streams
    • Resource Scaling
    • Signed URL
    • SOLID
    • Stack VS Heap
    • Stateful VS Stateless
  • Site Reliability Engineering
    • Chaos Engineering
    • Distributed Tracing
    • Kubernetes (k8s)
    • SLA, SLO, and SLI Metrics
    • Site Reliability Engineer
  • Others
    • FFMPEG Cheat sheet
Powered by GitBook
On this page
  • How it Works
  • Common Use Cases of Signed URLs
  • Share AWS S3 Object using Signed URL
  • Start Localstack
  • Create Bucket
  • Pre-Sign with AWS CLI
  • Pre-Sign with AWS SDK Golang
  • Other Cloud Providers
  • References
  1. Software Engineering

Signed URL

PreviousResource ScalingNextSOLID

Last updated 3 months ago

A signed URL is a time-limited, pre-authorized URL that allows users to access a protected resource (such as an image, video, or document) without exposing the underlying storage system or requiring direct authentication.

These URLs contain a cryptographic signature and optional metadata (like expiration time and access permissions). Only users with a valid signed URL can access the resource.

How it Works

  • A user (or client) requests access to a protected resource.

  • The server/service generates a signed URL using a private key or a secret.

  • The user can upload, download, or view (can be protected to only download) the resource by using the URL until it expires.

  • Once the URL expires, access is revoked.

Common Use Cases of Signed URLs

  • Secure File Uploads: Allow clients to upload files directly to storage without exposing backend systems.

  • Secure File Downloads: Allow users to download resources securely without making them public.

  • Access Control: Grant temporary access to internal or confidential resources.

Share AWS S3 Object using Signed URL

Lets try to share image using signed URL in AWS S3.

Here we will use localstack, a cloud service simulator that works locally in our machine to simulate AWS S3 stack. To install localstack you can follow the guide in .

Start Localstack

Start your localstack using optional LOCALSTACK_S3_SKIP_SIGNATURE_VALIDATION=0 to enable validation of S3 pre-signed URL request signature.

➜ LOCALSTACK_S3_SKIP_SIGNATURE_VALIDATION=0 localstack start

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

- LocalStack CLI: 4.2.0
- Profile: default
- App: https://app.localstack.cloud

[13:29:01] starting LocalStack in Docker mode 🐳
───────────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────────

LocalStack version: 4.2.1.dev7
LocalStack build date: 2025-02-28
LocalStack build git hash: 4285fb18c

Ready.

Create Bucket

Create bucket and add some image to the bucket.

➜ awslocal s3api create-bucket --bucket my-bucket
{
    "Location": "/my-bucket"
}
➜ awslocal s3api put-object --bucket my-bucket --key image.png --body bc-logo.png
{
    "ETag": "\"0c8c0a48b20dc18c7645de633daf165a\"",
    "ChecksumCRC32": "6+7i7g==",
    "ChecksumType": "FULL_OBJECT",
    "ServerSideEncryption": "AES256"
}

Pre-Sign with AWS CLI

Now you can create and share a signed URL for your image using this command below.

➜ awslocal s3 presign s3://my-bucket/image.png
http://localhost:4566/my-bucket/image.png?AWSAccessKeyId=test&Signature=XsnJh3uvtdcKlmUHQoVcibO9LD4%3D&Expires=1740985783

Open the URL in your browser and it should start download the image. The URL will expired in 3600s or ypu can override it by adding --expires-in options.

When you try to access the URL after expired it will return an error AccessDenied: Request has expired.

<Error>
  <Code>AccessDenied</Code>
  <Message>Request has expired</Message>
  <RequestId>bf512477-206d-43dc-9bb8-baaee642db8f</RequestId>
  <Expires>2025-03-03T07:37:10.000Z</Expires>
  <ServerTime>2025-03-03T07:38:04.000Z</ServerTime>
  <X-Amz-Expires>300</X-Amz-Expires>
  <HostId>9Gjjt1m+cjU4OPvX9O9/8RuvnG41MRb/18Oux2o5H5MY7ISNTlXN+Dz9IG62/ILVxhAGI0qyPfg=</HostId>
</Error>

Pre-Sign with AWS SDK Golang

Most of the time you will not use the AWS CLI to generate a signed URL. Here are example on how to create a signed URL using AWS SDK connected to localstack in Golang.

package main

import (
  "context"
  "fmt"
  "log"
  "time"

  "github.com/aws/aws-sdk-go-v2/aws"
  "github.com/aws/aws-sdk-go-v2/credentials"
  "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
  cfg := aws.Config{
    Region:      "ap-southeast-1", // any region will work for localstack
    Credentials: credentials.NewStaticCredentialsProvider("test", "test", "test"),
  }

  s3client := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.BaseEndpoint = aws.String("http://localhost:4566")
    o.UsePathStyle = true
  })

  psClient := s3.NewPresignClient(s3client)
  req, err := psClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{
    Bucket: aws.String("my-bucket"),
    Key:    aws.String("image.png"),
  }, s3.WithPresignExpires(5*time.Minute))
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println(req.URL)
}
➜ go run main.go
http://localhost:4566/my-bucket/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test%2F20250303%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20250303T073210Z&X-Amz-Expires=300&X-Amz-Security-Token=test&X-Amz-SignedHeaders=host&x-id=GetObject&X-Amz-Signature=07782ba9ccc584bc5f85fd6b41c19cf79024626ce96830eaf4c12783d23455dd

Other Cloud Providers

References

GCP:

here
https://cloud.google.com/storage/docs/access-control/signed-urls
https://docs.localstack.cloud/user-guide/aws/s3/
https://docs.aws.amazon.com/cli/latest/reference/s3/presign.html
https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html