Waiting for input...
Star SPIKE on GitHub

spike policy

The spike policy command is the main entry point for managing access policies in SPIKE. It allows administrators to define, view, and manage rules that control access to secrets and resources based on workload identity (SPIFFE ID) and resource paths.

SPIKE provides two commands for managing policies:

  1. spike policy create—Traditional command-line interface (backward compatibility)
  2. spike policy apply—Enhanced command with YAML file support (recommended for new workflows)

While spike policy create checks for the existence of a policy, and errors out if we are overriding an existing policy, spike policy apply uses upsert semantics—it will create a new policy if one doesn’t exist, or update an existing policy if one with the same name already exists. This makes the spike policy apply command safe to use in automation and GitOps workflows.

Quick Start

# Using YAML file (recommended)
spike policy apply --file policy.yaml

YAML File Format

Basic Structure

# Policy name - must be unique within the system
name: "web-service-policy"

# SPIFFE ID pattern for workload matching
spiffeid: "spiffe://example.org/web-service/"

# Path pattern for access control
# Note: Trailing slashes are automatically removed during normalization
path: "secrets/web-service/database"

# List of permissions to grant
permissions:
  - read
  - write

Path Normalization

The apply command automatically normalizes paths by removing trailing slashes:

# These paths are all normalized to the same value:
path: "secrets/database/production"    # ✓ Normalized form
path: "secrets/database/production/"   # → "secrets/database/production"
path: "secrets/database/production//"  # → "secrets/database/production"

Realistic Path Examples

# Database secrets
name: "database-policy"
spiffeid: "spiffe://example.org/database/"
path: "secrets/database/production"
permissions: [read]

# Web service configuration
name: "web-service-policy"
spiffeid: "spiffe://example.org/web-service/"
path: "secrets/web-service/config"
permissions: [read, write]

# Cache credentials
name: "cache-policy"
spiffeid: "spiffe://example.org/cache/"
path: "secrets/cache/redis/session"
permissions: [read]

# Application environment variables
name: "app-env-policy"
spiffeid: "spiffe://example.org/app/"
path: "secrets/app/env/production"
permissions: [read, list]

All Available Permissions

name: "admin-policy"
spiffeid: "spiffe://example.org/admin/"
path: "secrets"
permissions:
  - read    # Permission to read secrets
  - write   # Permission to create, update, or delete secrets
  - list    # Permission to list resources
  - super   # Administrative permissions

Alternative YAML Formats

Flow Sequence for Permissions

name: "database-policy"
spiffeid: "spiffe://example.org/database/"
path: "secrets/database/production"
permissions: [read, write, list]

Quoted Values

name: "cache-policy"
spiffeid: "spiffe://example.org/cache/"
path: "secrets/cache/redis"
permissions:
  - "read"
  - "write"

Creating Policies Using Command-Line Flags

Instead of using a yaml file, you can provide command-line arguments to programmatically create your policies too:

# Create your first policy
spike policy create --name=my-service \
  --path="secrets/app/" \
  --spiffeid="spiffe://example.org/service/" \
  --permissions=read

# Verify your policy was created
spike policy list

What are SPIKE Policies?

Policies in SPIKE provide a secure and flexible way to control access to secrets and resources. Each policy defines:

  • Who can access resources (via SPIFFE ID patterns)
  • What resources can be accessed (via path patterns)
  • How resources can be accessed (via permissions)

Policies are the cornerstone of SPIKE’s security model, allowing for fine-grained access control based on workload identity. Using SPIFFE IDs as the foundation, SPIKE ensures that only authorized workloads can access sensitive information.

How Policies Work

When a workload attempts to access a resource in SPIKE:

  1. The workload presents its SPIFFE ID through a SPIFFE Verifiable Identity Document (SVID)
  2. SPIKE validates the SVID to verify the workload’s identity
  3. SPIKE checks if any policy matches both:
    • The workload’s SPIFFE ID against the policy’s SPIFFE ID pattern
    • The requested resource path against the policy’s path pattern
  4. If a match is found, SPIKE checks if the requested operation is allowed by the policy’s permissions
  5. Access is granted only if ALL conditions are met

Why Use Policies?

  • Zero Trust Security: Access is based on workload identity, not network location
  • Least Privilege: Grant only the permissions needed for each workload
  • Auditability: All access is tied to specific policies and identities
  • Flexibility: Patterns support regular expression matching, which allows a more fine-grained control over which resources the policy applies to.
  • Scalability: Policies work consistently across any deployment size

Features

  • Create policies with specific permissions and access patterns
  • Apply policies using upsert semantics (create new or update existing)
  • List all policies in human-readable or JSON format
  • Get policy details by ID or name
  • Delete policies with confirmation protection
  • Enhanced validation for permissions and parameters

Commands

spike policy list

spike policy list [--format=human|json] [--path=<pattern> | --spiffeid=<pattern>]

Lists all policies in the system. Can be filtered by a resource path pattern or a SPIFFE ID pattern.

Note: --path and --spiffeid flags cannot be used together.

spike policy create

spike policy create --name=<name> \
  --path=<path-pattern> \
  --spiffeid=<spiffe-id-pattern> \
  --permissions=<permissions>

Creates a new policy with the specified parameters.

spike policy apply

spike policy apply --file=<policy-file.yaml>

Creates a new policy with file-based input using YAML configuration.

YAML Configuration Format

When using the --file flag, the YAML file should follow this structure:

name: policy-name
spiffeid: spiffe://example.org/service/
path: secrets/database/production
permissions:
  - read
  - write

Example Files

SPIKE repository has the following example policies for your convenience:

Permission Types

PermissionDescription
readAllows reading secrets and resources
writeAllows creating, updating, and deleting secrets
listAllows listing resources and directories
superFull administrative permissions (use with caution)

Validation

All policy configurations are validated to ensure:

  1. Required fields: name, spiffeid, path, and permissions must be present
  2. Valid permissions: Only read, write, list, and super are allowed
  3. Valid YAML syntax: Proper YAML formatting is required (for YAML files)
  4. Non-empty values: All fields must have non-empty values

GitOps Integration

YAML files can be easily integrated into GitOps workflows:

  1. Store policy YAML files in a Git repository

    policies/
    ├── web-service-policy.yaml
    ├── database-policy.yaml
    └── admin-policy.yaml
    
  2. Use CI/CD pipelines to validate policies before deployment

    # Validation step in CI
    for policy in policies/*.yaml; do
      spike policy apply --file "$policy"
      # - ensure that the policy is created
      # - delete the policy
      # - ensure that the policy is gone
    done
    
  3. Apply policies using spike policy apply --file in deployment scripts

    # Deployment script
    for policy in policies/*.yaml; do
      spike policy apply --file "$policy"
    done
    
  4. Version control changes to policies alongside application code

  5. Use upsert semantics to safely apply policy changes without worrying about conflicts

spike policy get

spike policy get <id> [--format=human|json]
spike policy get --name=<name> [--format=human|json]

Gets details of a specific policy by ID or name. Use --format=json for machine-readable output.

spike policy delete

spike policy delete <id>
spike policy delete --name=<name>

Deletes a policy by ID or name. Requires confirmation.

Usage Examples

# Create a policy for a web service with read and write access
spike policy create \
  --name=web-service \
  --path="secrets/web/" \
  --spiffeid="spiffe://example.org/web/" \
  --permissions=read,write

# Create a policy with multiple permissions
spike policy create \
  --name=admin-service \
  --path="secrets/" \
  --spiffeid="spiffe://example.org/admin/" \
  --permissions=read,write,list

# Apply a policy using a YAML file
spike policy apply --file=policy.yaml

# List all policies in JSON format (useful for automation)
spike policy list --format=json

# Get details of a specific policy by name
spike policy get --name=web-service

# Get policy details in JSON format
spike policy get --name=web-service --format=json

# Delete a policy and confirm deletion
spike policy delete --name=web-service

Pattern Syntax

SPIKE policies support regular expression pattern matching for both SPIFFE IDs and resource paths:

  • If the pattern is a single "*", then it matches anything.
  • For any other pattern, the pattern is compiled as a “regular expression”.

This would mean, for an exact match, you would need to include ^ and $ in your patterns as well.

For example:

  • secrets/db matches global/secrets/db and secrets/db/local
  • Whereas, ^secrets/db$ only matches secrets/db and nothing else (global/secrets/db and secrets/db/local will not match)

Thus, for precise control, you might want to include ^ and $ at the beginning and end of your patterns respectively for an exact match.

How Regular Expressions are Used For Policy Matching

More specifically, SPIKE compiles SPIFFE ID patterns and path patterns defined in the policies into regular expressions.

Here is a simplified version of how this regular expression compilation happens behind-the-scenes:

pathRegex, err := regexp.Compile(policy.PathPattern)
// ... error handling omitted for brevity.
policy.PathRegex = pathRegex
// `pathRegEx` is used for policy validation.

As seen from the example above, both the path pattern and the SPIFFE ID pattern that are provided during policy creation which are used “AS IS” to create regular expression matchers. These patterns are compiled into Go’s built-in regex engine, ensuring that the matching process strictly adheres to the patterns defined in the policy, allowing for precise and flexible access control.

Simplicity Is the Key

Because of the regular expression usage in SPIKE policies, a policy create operation can define more flexible matching patterns. However, keeping patterns simple is both more secure and easier to manage and reason about. Creating a pattern that is too broad or that uses overly complex regular expressions may lead to unintended consequences and security risks. Simplicity is important to ensure patterns are clear, predictable, and effective.

When a workload attempts to access a resource, its SPIFFE ID and the requested resource path are matched against these compiled regular expressions. This ensures that both identity and resource patterns follow the specified rules and allow for flexibility with wildcards or exact matches.

Path Pattern Examples

secrets/               # All resources in the secrets directory
secrets/database/      # Only resources in the database subdirectory  
secrets/database/creds # Only the specific creds resource

# You can provide regular expressions for a more fine-tuned
# pattern match:
^secrets/db-[123]$ # Matches secrets/db-2, but not secrets/db-4.

Path Patterns in SPIKE

Path patterns in SPIKE are designed to provide flexibility but also follow certain conventions for clarity and usability. While the path pattern is suggested (but not mandated) to look like a UNIX-style path for familiarity, SPIKE secret paths DO NOT start with a leading slash.

This is because SPIKE paths represent logical key namespaces, not hierarchical filesystem paths. They are always relative to the secrets engine mount point, making the leading slash redundant and potentially confusing.

Example:

  • Correct: secrets/app/config
  • Redundant/Confusing: /secrets/app/config

Additionally, although there is currently no restriction on how the path is formed, it is worth noting that future versions of SPIKE may restrict paths from having a trailing slash to avoid ambiguity and maintain consistency in naming practices.

Best Practices for Path Patterns:

  1. Avoid leading slashes.
  2. Avoid trailing slashes to ensure forward compatibility.
  3. Use descriptive and meaningful names that reflect the resource’s purpose or hierarchy.

SPIFFE ID Pattern Examples

spiffe://example.org/              # Workloads in the example.org trust domain
spiffe://example.org/web/          # Only web workloads
^spiffe://example.org/web/server$  # Only the specific web server workload

Best Practices

  • Follow the principle of least privilege when assigning permissions
  • Use descriptive policy names that reflect their purpose
  • Create separate policies for different workload types
  • Use specific path patterns rather than overly broad ones
  • Regularly audit and review your policies
  • Never assign super permissions unless absolutely necessary

spike Command Index