Skip to content

Latest commit

 

History

History
276 lines (201 loc) · 8.52 KB

File metadata and controls

276 lines (201 loc) · 8.52 KB

WebAssembly Component OCI Publishing Example

This example demonstrates the complete workflow for publishing WebAssembly components to OCI registries with optional cryptographic signing using wasmsign2.

Features Demonstrated

  • Component Preparation: Building Rust WebAssembly components
  • Cryptographic Signing: Using wasmsign2 with OpenSSH keys (embedded and detached signatures)
  • OCI Image Creation: Preparing components for OCI registry publishing
  • Registry Publishing: Publishing to local and remote OCI registries
  • Registry Authentication: Supporting multiple registry types with authentication
  • Metadata Handling: OCI annotations and component metadata
  • Workflow Automation: Single-step publishing with convenience macros
  • Security Policies: Enterprise-grade security policy enforcement
  • Automated Security: Policy-driven signing and validation workflows
  • Multi-Registry Publishing: Synchronized publishing to multiple registries

Example Components

1. Basic OCI Image Preparation

# Prepare unsigned OCI image
bazel build //examples/oci_publishing:hello_oci_unsigned_image

# Prepare signed OCI image with embedded signature
bazel build //examples/oci_publishing:hello_oci_signed_image

# Prepare signed OCI image with detached signature
bazel build //examples/oci_publishing:hello_oci_detached_image

2. Registry Publishing

# Publish unsigned component (requires local OCI registry at localhost:5000)
bazel run //examples/oci_publishing:publish_unsigned

# Publish signed component
bazel run //examples/oci_publishing:publish_signed

# Dry run publishing (for testing)
bazel run //examples/oci_publishing:publish_dry_run

3. Complete Workflow

# One-step component preparation and publishing
bazel run //examples/oci_publishing:publish_complete_workflow

# Publish to GitHub Container Registry (requires GITHUB_TOKEN)
# Set GITHUB_TOKEN environment variable and modify dry_run=False
bazel run //examples/oci_publishing:publish_to_github

# Multi-registry publishing
bazel run //examples/oci_publishing:publish_to_all_registries

4. Security Policy Management

# Build security policies
bazel build //examples/oci_publishing:basic_security_policy
bazel build //examples/oci_publishing:strict_security_policy
bazel build //examples/oci_publishing:enterprise_security_policy

# Secure publishing with policy enforcement
bazel run //examples/oci_publishing:secure_publish_basic
bazel run //examples/oci_publishing:secure_publish_strict
bazel run //examples/oci_publishing:secure_publish_enterprise

Registry Setup

Local Registry

Start a local OCI registry for testing:

docker run -d -p 5000:5000 --name registry registry:2

GitHub Container Registry

  1. Create a Personal Access Token with write:packages permission

  2. Set the environment variable:

    export GITHUB_TOKEN=ghp_your_token_here
  3. Modify the dry_run = False in the GitHub publish target

Docker Hub

  1. Create a Docker Hub access token

  2. Set the environment variable:

    export DOCKER_TOKEN=your_docker_token_here
  3. Configure the registry in wkg_registry_config

Registry Configuration

The example includes a comprehensive registry configuration supporting:

  • Local Registry: localhost:5000 (for testing)
  • GitHub Container Registry: ghcr.io (with token authentication)
  • Docker Hub: docker.io (with token authentication)
wkg_registry_config(
    name = "registry_config",
    registries = [
        "localhost|localhost:5000|oci",
        "github|ghcr.io|oci|token|${GITHUB_TOKEN}",
        "docker|docker.io|oci|token|${DOCKER_TOKEN}",
    ],
    default_registry = "localhost",
)

Signature Verification

The published components include cryptographic signatures that can be verified:

# Verify embedded signature
wasmsign2 verify -i bazel-bin/examples/oci_publishing/hello_oci_signed_image_oci.wasm

# Verify detached signature
wasmsign2 verify -i bazel-bin/examples/oci_publishing/hello_oci_detached_image_oci.wasm \
  -S bazel-bin/examples/oci_publishing/hello_oci_detached_image_signature.sig

Known Limitations

OpenSSH Key Format: Currently, wasmsign2 with OpenSSH format keys (-Z flag) has compatibility issues in the Bazel sandbox environment on some platforms. Use compact format keys (default) for reliable signing:

# ✅ WORKS: Compact format keys
wasm_keygen(
    name = "signing_keys",
    openssh_format = False,  # Default
)

# ⚠️ ISSUE: OpenSSH format keys may fail in sandbox
wasm_keygen(
    name = "openssh_keys",
    openssh_format = True,   # May cause I/O errors in sandbox
)

The compact format provides the same security guarantees and is fully compatible with wasmsign2 verification.

OCI Annotations

The published images include comprehensive OCI annotations:

  • org.opencontainers.image.description: Component description
  • org.opencontainers.image.source: Source repository URL
  • org.opencontainers.image.version: Component version
  • com.wasm.component.type: WebAssembly component type
  • com.wasm.component.security: Security/signing status
  • com.wasmsign2.signature.type: Signature type (if signed)
  • com.wasmsign2.key.format: Key format used for signing

Workflow Architecture

  1. Component Building: Rust → WASM component (using rust_wasm_component)
  2. Key Generation: OpenSSH key pairs (using wasm_keygen)
  3. Component Signing: wasmsign2 integration (optional)
  4. OCI Image Preparation: Metadata creation and annotation (using wasm_component_oci_image)
  5. Registry Publishing: wkg-based OCI push (using wasm_component_publish)
  6. End-to-End: Single macro for complete workflow (using wasm_component_oci_publish)

Testing the Example

  1. Build all components:

    bazel build //examples/oci_publishing/...
  2. Start local registry:

    docker run -d -p 5000:5000 --name registry registry:2
  3. Test dry run publishing:

    bazel run //examples/oci_publishing:publish_dry_run
  4. Publish to local registry:

    bazel run //examples/oci_publishing:publish_complete_workflow
  5. Verify the published component:

    # Pull the component back
    wkg pull --registry localhost:5000 --package examples/hello-complete --version complete-v1.0.0
    
    # Verify signature
    wasmsign2 verify -i hello-complete.wasm

This example demonstrates the complete production-ready workflow for publishing signed WebAssembly components to OCI registries using Bazel.

Security Policy Management

The example includes comprehensive security policy management for enterprise deployments:

Security Policy Types

  1. Basic Security Policy (basic_security_policy):

    • No signing required by default
    • Suitable for development and testing environments
    • Flexible configuration for different use cases
  2. Strict Security Policy (strict_security_policy):

    • Signing required for production registries
    • Registry-specific signing requirements
    • Component pattern-based policies
  3. Enterprise Security Policy (enterprise_security_policy):

    • All components must be signed
    • OpenSSH format signatures for compliance
    • Detached signatures for audit trails

Security Features

  • Policy-Driven Signing: Automatic signing based on registry and component policies
  • Component Validation: Built-in WebAssembly component validation
  • Registry Security Checks: Registry-specific security requirement enforcement
  • Compliance Annotations: Automatic security metadata in OCI annotations
  • Audit Trail: Comprehensive logging and security tracking
  • Key Management: Support for multiple key formats and sources

Policy Configuration

Security policies support:

  • Registry Policies: Different signing requirements per registry
  • Component Policies: Pattern-based rules for component names
  • Key Source Configuration: File, environment, or keychain-based keys
  • Signature Types: Embedded or detached signatures
  • Key Formats: Compact or OpenSSH format keys

Example policy configuration:

wasm_security_policy(
    name = "enterprise_policy",
    default_signing_required = True,
    signature_type = "detached",
    openssh_format = True,
    registry_policies = [
        "production|required|enterprise_keys",
        "staging|required|staging_keys",
        "development|optional",
    ],
    component_policies = [
        "prod-*|required|enterprise_keys",
        "test-*|optional",
    ],
)