Skip to content

Signed URLs Commands

The site signed-urls command group provides functionality to create and verify cryptographically signed URLs for secure, time-limited file access.

Overview

Signed URLs allow you to: - Grant temporary access to specific files without authentication - Control access duration and permissions - Share files securely via simple URLs - Revoke access by changing the master token - Invalidate all existing signed URLs if the master token is rotated or revoked

What are Signed URLs?

A signed URL is a regular URL with cryptographic signature parameters added: - Contains file path, expiration time, and permissions - Signed with the site's master token - Can be shared freely and accessed without further authentication - Automatically expires after specified duration - Cannot be modified without invalidating the signature

Example:

https://sites.ecmwf.int/myspace/mysite/data/report.pdf?signature=abc123...&expires=1234567890

Global Flags

  • --debug, -d, --verbose - Show debug information
  • --insecure, -k - Skip TLS certificate verification
  • --force, -f, -y, --yes - Force operations without prompting
  • --output, -o - Output format: json, yaml, or table

Commands

sitesctl site signed-urls create

Create a signed URL for a file or directory.

Usage:

sitesctl site --space <space> --name <name> signed-urls create --url <full-url> [flags]

Flags:

  • --url (required) - Full URL to sign
  • Must be complete URL including protocol and domain
  • Should point to a file or directory on your site

  • --duration - Token lifetime in seconds

  • Default: 86400 (24 hours)
  • After this period, the URL becomes invalid

  • --permission - Access permission level

  • Values: r (read-only) or rw (read/write)
  • Default: r
  • Note: Write permission via signed URL depends on server configuration

Examples:

# Create read-only signed URL (24 hour default)
sitesctl site --space myspace --name mysite \
  signed-urls create \
  --url https://sites.ecmwf.int/myspace/mysite/data/file.txt

# Create signed URL for 1 hour
sitesctl site --space myspace --name mysite \
  signed-urls create \
  --url https://sites.ecmwf.int/myspace/mysite/reports/report.pdf \
  --duration 3600

# Create signed URL for 7 days
sitesctl site --space myspace --name mysite \
  signed-urls create \
  --url https://sites.ecmwf.int/myspace/mysite/archive/ \
  --duration 604800

# Create with read/write permission
sitesctl site --space myspace --name mysite \
  signed-urls create \
  --url https://sites.ecmwf.int/myspace/mysite/upload/data.csv \
  --permission rw \
  --duration 3600

# Save signed URL to variable
signed_url=$(sitesctl site --space myspace --name mysite \
  signed-urls create \
  --url https://sites.ecmwf.int/myspace/mysite/file.txt \
  --output json | jq -r '.signed_url')

Common Duration Values:

Duration Seconds Use Case
1 hour 3600 Quick file sharing
6 hours 21600 Work session
24 hours 86400 Daily access (default)
7 days 604800 Weekly sharing
30 days 2592000 Long-term access

Output: - Original URL - Signed URL (with signature and expiration parameters) - Expiration timestamp - Permission level

Use Cases: - Share files with external users - Embed in emails or documents - Temporary public access - Time-limited downloads - Integration with external systems


sitesctl site signed-urls verify

Verify a signed URL and check its validity.

Usage:

sitesctl site --space <space> --name <name> signed-urls verify --url <signed-url>

Flags: - --url (required) - Signed URL to verify

Examples:

# Verify a signed URL
sitesctl site --space myspace --name mysite \
  signed-urls verify \
  --url "https://sites.ecmwf.int/myspace/mysite/file.txt?signature=abc&expires=123"

# Verify with JSON output
sitesctl site --space myspace --name mysite \
  signed-urls verify \
  --url "https://sites.ecmwf.int/myspace/mysite/file.txt?signature=abc&expires=123" \
  --output json

What it does: - Validates the signature - Checks expiration time - Confirms the URL hasn't been tampered with - Returns validity status

Output: - Validity status (valid/invalid) - Expiration date/time (if valid) - Error message (if invalid) - Permission level

Use Cases: - Check URL before sharing - Verify URL hasn't expired - Debug access issues - Audit URL validity


How Signed URLs Work

Creation Process

  1. Input: Original URL + duration + permissions
  2. Calculation:
  3. Expiration timestamp = current time + duration
  4. Signature = HMAC(URL + expires + permission, master_token)
  5. Output: URL + signature + expiration parameters

Verification Process

  1. Parse: Extract URL, signature, expiration from signed URL
  2. Check Expiration: Compare expiration timestamp with current time
  3. Verify Signature: Recalculate signature and compare with provided signature
  4. Result: Valid if signature matches and not expired

Security Properties

  • Integrity: URL cannot be modified without invalidating signature
  • Expiration: Automatically becomes invalid after duration
  • Non-transferable: Tied to specific file path
  • Revocable: Rotating master token invalidates all signed URLs
  • Master token dependency: Rotating or revoking the master token invalidates all existing signed URLs

Comparison: Signed URLs vs HTTP Access Tokens

Feature Signed URLs HTTP Access Tokens
Scope Single file/directory Entire site
Authentication No (embedded in URL) Yes (in headers/params)
Sharing Very easy (just share URL) Moderate (share token + instructions)
Expiration Per-URL Per-token
Use in Browser Direct access Requires parameter or extension
Granularity Per-file Site-wide
Best For File sharing, embeddings API access, automation

When to use Signed URLs: - Sharing specific files with non-technical users - Embedding files in web pages or documents - Temporary public access to specific resources - Simple click-to-download scenarios

When to use HTTP Access Tokens: - API integrations - Automated content management - Multiple file operations - Complex workflows


Common Workflows

Share File via Email

#!/bin/bash
# Create signed URL and send via email

space="myspace"
name="mysite"
file_path="reports/monthly-report.pdf"
recipient="colleague@example.com"

# Create 7-day signed URL
signed_url=$(sitesctl site --space "$space" --name "$name" \
  signed-urls create \
  --url "https://sites.ecmwf.int/${space}/${name}/${file_path}" \
  --duration 604800 \
  --output json | jq -r '.signed_url')

# Send email
cat <<EOF | mail -s "Monthly Report" "$recipient"
Hi,

Please find the monthly report here:
$signed_url

This link expires in 7 days.

Best regards
EOF

echo "Signed URL sent to $recipient"

Embed in Web Page

#!/bin/bash
# Generate HTML with signed URL

space="myspace"
name="mysite"
image_path="images/chart.png"

# Create 30-day signed URL
signed_url=$(sitesctl site --space "$space" --name "$name" \
  signed-urls create \
  --url "https://sites.ecmwf.int/${space}/${name}/${image_path}" \
  --duration 2592000 \
  --output json | jq -r '.signed_url')

# Generate HTML
cat <<EOF > chart.html
<!DOCTYPE html>
<html>
<head><title>Chart</title></head>
<body>
  <h1>Data Chart</h1>
  <img src="$signed_url" alt="Chart">
</body>
</html>
EOF

echo "HTML file generated with signed URL"

Batch Generate Signed URLs

#!/bin/bash
# Create signed URLs for multiple files

space="myspace"
name="mysite"
base_url="https://sites.ecmwf.int/${space}/${name}"
files=(
  "data/file1.csv"
  "data/file2.csv"
  "data/file3.csv"
)

echo "Generating signed URLs..."

for file in "${files[@]}"; do
  signed_url=$(sitesctl site --space "$space" --name "$name" \
    signed-urls create \
    --url "${base_url}/${file}" \
    --duration 86400 \
    --output json | jq -r '.signed_url')

  echo "$file -> $signed_url"
done > signed_urls.txt

echo "Signed URLs saved to signed_urls.txt"

Verify Before Sharing

#!/bin/bash
# Create and verify signed URL before sharing

space="myspace"
name="mysite"
file_url="https://sites.ecmwf.int/${space}/${name}/data/report.pdf"

# Create signed URL
signed_url=$(sitesctl site --space "$space" --name "$name" \
  signed-urls create \
  --url "$file_url" \
  --duration 604800 \
  --output json | jq -r '.signed_url')

echo "Signed URL created: $signed_url"

# Verify it
echo "Verifying..."
sitesctl site --space "$space" --name "$name" \
  signed-urls verify --url "$signed_url"

if [ $? -eq 0 ]; then
  echo "URL verified successfully!"
  echo "Safe to share: $signed_url"
else
  echo "URL verification failed!"
  exit 1
fi
#!/bin/bash
# Create gallery of images with signed URLs

space="myspace"
name="mysite"
base_url="https://sites.ecmwf.int/${space}/${name}"
duration=604800  # 7 days

# Get list of images
images=$(sitesctl site --space "$space" --name "$name" \
  content list --path /gallery --match "*.jpg" --output json | \
  jq -r '.[].name')

# Generate HTML gallery
cat <<EOF > gallery.html
<!DOCTYPE html>
<html>
<head>
  <title>Image Gallery</title>
  <style>
    .gallery { display: flex; flex-wrap: wrap; gap: 10px; }
    .gallery img { width: 300px; height: auto; }
  </style>
</head>
<body>
  <h1>Image Gallery (Links expire in 7 days)</h1>
  <div class="gallery">
EOF

# Add each image with signed URL
for image in $images; do
  signed_url=$(sitesctl site --space "$space" --name "$name" \
    signed-urls create \
    --url "${base_url}/gallery/${image}" \
    --duration "$duration" \
    --output json | jq -r '.signed_url')

  echo "    <img src=\"$signed_url\" alt=\"$image\">" >> gallery.html
done

cat <<EOF >> gallery.html
  </div>
</body>
</html>
EOF

echo "Gallery generated: gallery.html"

Security Considerations

Best Practices

  1. Minimize Duration
  2. Use shortest practical duration
  3. Default to 24 hours unless longer needed
  4. Regenerate for extended access

  5. Use Read-Only Permission

  6. Default to r permission
  7. Only use rw when absolutely necessary
  8. Understand write implications

  9. Monitor Access

  10. Track which URLs you create
  11. Log URL generation with identifiers
  12. Review access logs regularly

  13. Rotate Master Token

  14. Rotating master token invalidates all signed URLs
  15. Use as emergency revocation mechanism
  16. Plan URL regeneration strategy

Security Risks

URL Exposure: - Signed URLs contain authentication in the URL itself - Can be logged by proxies, browsers, servers - Can be shared further by recipients - Consider for sensitive data

No Usage Limits: - Valid signed URL can be used repeatedly - No download count limit - Consider for high-value content

URL Sharing: - Recipient can share the URL - No way to track secondary sharing - URL remains valid until expiration

Mitigation Strategies

  1. Short Durations: Minimize window of exposure
  2. File Sensitivity: Use for less sensitive content
  3. Access Logging: Monitor who accesses URLs
  4. Token Rotation: Emergency revocation via master token rotation
  5. Alternative Methods: Consider HTTP access tokens for sensitive operations

Troubleshooting

URL Expired

Problem: Signed URL no longer works

Solutions: - Check expiration with signed-urls verify - Generate new signed URL with appropriate duration - Consider longer duration if frequently needed

Invalid Signature

Problem: URL reports invalid signature

Solutions: - Verify URL wasn't modified - Check if master token was rotated - Regenerate the signed URL

Access Denied

Problem: Valid signed URL but access denied

Solutions: - Verify the file exists: sitesctl site ... content list - Check file permissions on server - Ensure site is not archived - Verify site health

URL Not Working in Browser

Problem: URL doesn't load in web browser

Solutions: - URL-encode special characters - Verify URL is complete (includes signature params) - Check if site is accessible - Test with curl first


curl Examples

Download with Signed URL

# Simple download
curl -O "https://sites.ecmwf.int/space/site/file.txt?signature=...&expires=..."

# Download with custom filename
curl -o myfile.txt "https://sites.ecmwf.int/space/site/file.txt?signature=...&expires=..."

# Follow redirects
curl -L -O "https://sites.ecmwf.int/space/site/file.txt?signature=...&expires=..."

Upload with Signed URL (rw permission)

# Upload file
curl -X PUT \
  --data-binary @localfile.txt \
  "https://sites.ecmwf.int/space/site/path/file.txt?signature=...&expires=..."

Check URL Validity with curl

# HEAD request to check accessibility
curl -I "https://sites.ecmwf.int/space/site/file.txt?signature=...&expires=..."

# Should return 200 OK if valid

Integration Examples

Python Script

import subprocess
import json
import requests

def create_signed_url(space, name, file_path, duration=86400):
    """Create a signed URL using sitesctl"""
    url = f"https://sites.ecmwf.int/{space}/{name}/{file_path}"

    cmd = [
        "sitesctl", "site",
        "--space", space,
        "--name", name,
        "signed-urls", "create",
        "--url", url,
        "--duration", str(duration),
        "--output", "json"
    ]

    result = subprocess.run(cmd, capture_output=True, text=True)
    data = json.loads(result.stdout)
    return data['signed_url']

# Usage
signed_url = create_signed_url("myspace", "mysite", "data/file.csv")
print(f"Signed URL: {signed_url}")

# Download the file
response = requests.get(signed_url)
with open("downloaded.csv", "wb") as f:
    f.write(response.content)

Node.js Script

const { exec } = require('child_process');
const util = require('util');
const execPromise = util.promisify(exec);

async function createSignedUrl(space, name, filePath, duration = 86400) {
  const url = `https://sites.ecmwf.int/${space}/${name}/${filePath}`;

  const cmd = `sitesctl site --space ${space} --name ${name} ` +
    `signed-urls create --url ${url} --duration ${duration} --output json`;

  const { stdout } = await execPromise(cmd);
  const data = JSON.parse(stdout);
  return data.signed_url;
}

// Usage
createSignedUrl('myspace', 'mysite', 'data/file.csv')
  .then(signedUrl => console.log(`Signed URL: ${signedUrl}`))
  .catch(err => console.error('Error:', err));

See Also