Skip to content

shiftleftcyber/securesbom-sdk-golang

Repository files navigation

SecureSBOM Go SDK

Go Version License Go Report Card GoDoc

A Go SDK for cryptographically signing and verifying Software Bill of Materials (SBOM) documents using the ShiftLeftCyber SecureSBOM API.

Features

  • Sign SBOMs: Cryptographically sign SBOM documents for authenticity and integrity

  • Sign Digests: Create detached signatures from precomputed digests

  • Verify Signatures: Validate signed SBOMs to ensure they haven been tampered with

  • Key Management: Generate, list, and retrieve signing keys

  • Production Ready: Comprehensive error handling and testing

Installation

go get github.com/shiftleftcyber/securesbom-sdk-golang

Quick Start

API Key

Get your API key from ShiftLeftCyber.

Basic Usage

package main

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

    "github.com/shiftleftcyber/securesbom-sdk-golang/pkg/securesbom"
)

func main() {
    // Create client
    client := securesbom.NewConfigBuilder().
        WithAPIKey("your-api-key").
        WithTimeout(30 * time.Second).
        FromEnv()

    if signBaseURL != "" {
        config = config.WithBaseURL(signBaseURL)
    }

    baseClient, err := config.BuildClient()
    if err != nil {
        return nil, err
    }

    ctx := context.Background()

    // Load SBOM
    sbom, err := securesbom.LoadSBOMFromFile("sbom.json")
    if err != nil {
        log.Fatal(err)
    }

    // Sign SBOM
    result, err := client.SignSBOM(ctx, "your-key-id", sbom.Data())
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("SBOM signed successfully\n")
}

Usage Examples

Signing an SBOM

// Create client with retry logic
baseClient, _ := securesbom.NewConfigBuilder().
    WithAPIKey("your-api-key").
    FromEnv().
    BuildClient()

client := securesbom.WithRetryingClient(baseClient, securesbom.RetryConfig{
    MaxAttempts: 3,
    InitialWait: 1 * time.Second,
    MaxWait:     10 * time.Second,
    Multiplier:  2.0,
})

// Load and sign SBOM
sbom, _ := securesbom.LoadSBOMFromFile("sbom.json")
result, err := client.SignSBOM(ctx, "key-123", sbom.Data())
if err != nil {
    log.Fatal(err)
}

// Save signed SBOM
signedData, _ := json.Marshal(result)
os.WriteFile("signed-sbom.json", signedData, 0644)

Signing a Digest

client, _ := securesbom.NewConfigBuilder().
    WithAPIKey("your-api-key").
    FromEnv().
    BuildClient()

result, err := client.SignDigest(ctx, securesbom.SignDigestRequest{
    DigestB64:     "base64-encoded-digest",
    HashAlgorithm: "sha256",
    KeyID:         "key-123",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("%s %s\n", result.SignatureAlgorithm, result.Signature)

Verifying a Signed SBOM

client, _ := securesbom.NewConfigBuilder().
    WithAPIKey("your-api-key").
    FromEnv().
    BuildClient()

// Load signed SBOM
signedSBOM, _ := securesbom.LoadSBOMFromFile("signed-sbom.json")

// Verify signature
result, err := client.VerifySBOM(ctx, "key-123", signedSBOM.Data())
if err != nil {
    log.Fatal(err)
}

if result.Valid {
    fmt.Println("✓ Signature is valid")
} else {
    fmt.Println("✗ Signature is invalid:", result.Message)
    os.Exit(1)
}

Key Management

client, _ := securesbom.NewConfigBuilder().
    WithAPIKey("your-api-key").
    BuildClient()

// List all keys
keys, err := client.ListKeys(ctx)
if err != nil {
    log.Fatal(err)
}

for _, key := range keys.Keys {
    fmt.Printf("Key: %s (created: %s)\n", key.ID, key.CreatedAt)
}

// Generate new key
newKey, err := client.GenerateKey(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("New key ID: %s\n", newKey.ID)

// Get public key
publicKey, err := client.GetPublicKey(ctx, newKey.ID)
if err != nil {
    log.Fatal(err)
}
fmt.Println(publicKey)

Using Environment Variables

// Set environment variables
// SECURE_SBOM_API_KEY=your-api-key

client, err := securesbom.NewConfigBuilder().
    FromEnv().
    BuildClient()

Command Line Examples

The SDK includes example CLI applications demonstrating real-world usage.

Install Examples

# Clone repository
git clone https://github.com/shiftleftcyber/securesbom-sdk-golang.git
cd securesbom-sdk-golang

# Build examples
make build-examples

# Or install to $GOPATH/bin
make install-examples

Sign and Verify a CycloneDX SBOM

export SECURE_SBOM_API_KEY="your-api-key"
export SECURE_SBOM_SIGNING_KEY_ID="my-key-123"

# Sign from file
./bin/sign -key-id ${SECURE_SBOM_SIGNING_KEY_ID} -sbom samples/cdx/sbomex-cdx.json -output output.json

# extract the signed SBOM from the response payload
cat output.json | jq .signed_sbom > sbomex-cdx.signed.json

# Verify the SBOM which contains the embedded signature
./bin/verify -key-id ${SECURE_SBOM_SIGNING_KEY_ID} -sbom sbomex-cdx.signed.json

Sign and Verify a SPDX SBOM

# Verify and show result
./bin/sign -key-id ${SECURE_SBOM_SIGNING_KEY_ID} -sbom samples/spdx/sbom-tool/sbomex-spdx.json -output output.json

# Verify using the SBOM and Signautre from the response object
./bin/verify -key-id ${SECURE_SBOM_SIGNING_KEY_ID} -sbom samples/spdx/sbom-tool/sbomex-spdx.json -signature $(cat output.json | jq -r .signature_b64)

Sign a Digest

export SECURE_SBOM_API_KEY="your-api-key"

./bin/digest -key-id my-key-123 -hash-algorithm sha256 -digest Zm9vYmFy

Manage Keys

# List all keys
./bin/keymgmt list

# Generate new key
./bin/keymgmt generate

# Get public key
./bin/keymgmt public my-key-123 -output public.pem

Configuration

Configuration Builder

The SDK uses a builder pattern for flexible configuration:

config := securesbom.NewConfigBuilder().
    WithAPIKey("api-key").           // Required
    WithTimeout(30 * time.Second).   // Optional (default: 30s)
    WithUserAgent("my-app/1.0").     // Optional
    FromEnv().                        // Load from environment
    Build()

Retry Configuration

Add automatic retries with exponential backoff:

retryConfig := securesbom.RetryConfig{
    MaxAttempts: 3,                    // Number of retry attempts
    InitialWait: 1 * time.Second,      // Initial wait time
    MaxWait:     10 * time.Second,     // Maximum wait time
    Multiplier:  2.0,                  // Backoff multiplier
}

retryingClient := securesbom.WithRetryingClient(baseClient, retryConfig)

Environment Variables

  • SECURE_SBOM_API_KEY - Your API key

API Reference

Client Methods

type ClientInterface interface {
    // Health check
    HealthCheck(ctx context.Context) error

    // Key management
    ListKeys(ctx context.Context) (*KeyListResponse, error)
    GenerateKey(ctx context.Context) (*GeneratedKey, error)
    GetPublicKey(ctx context.Context, keyID string) (string, error)

    // SBOM operations
    SignSBOM(ctx context.Context, keyID string, sbom interface{}) (*SignResult, error)
    VerifySBOM(ctx context.Context, keyID string, signedSBOM interface{}) (*VerifyResult, error)
}

SBOM Utilities

// Load SBOM from various sources
sbom, err := securesbom.LoadSBOMFromFile("path/to/sbom.json")
sbom, err := securesbom.LoadSBOMFromReader(reader)

// Create SBOM from data
sbom := securesbom.NewSBOM(data)

// Write SBOM
err = sbom.WriteToFile("output.json")
err = sbom.WriteToWriter(writer)
str := sbom.String()

Error Handling

The SDK provides structured error types:

result, err := client.SignSBOM(ctx, keyID, sbom)
if err != nil {
    if apiErr, ok := err.(*securesbom.APIError); ok {
        fmt.Printf("API Error %d: %s\n", apiErr.StatusCode, apiErr.Message)
        if apiErr.Temporary() {
            // Retry logic
        }
    }
    return err
}

Testing

# Run all tests
make test

# Run tests with coverage
make coverage

# Run only SDK tests (not examples)
make test-sdk

# Run short tests
make test-short

Development

# Install development tools
make dev-setup

# Format code
make fmt

# Run linters
make lint

# Run all checks
make check

# Build examples
make build

CI/CD

The project includes GitHub Actions workflows for:

  • Pull Request validation (tests, lint, build)
  • Main branch builds (artifacts published)
  • Release automation (cross-platform binaries, documentation)

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and linting (make check)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

This project is licensed under the Apache-2.0 License - see the LICENSE file for details.

Support

Acknowledgments

Built by ShiftLeftCyber for securing software supply chains.

About

golang implementation of the SecureSBOM SDK

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors