Files
seaweedfs/weed/credential
Chris LuandGitHub 6b6e6d8547 s3: apply filer identity changes despite a static config file (#10392)
* s3: apply filer identity changes despite a static config file

A -config file with inline identities disabled the metadata-subscription
reload entirely, leaving the best-effort filer->s3 push as the only way
s3.configure changes could reach a running gateway. Reload on IAM events
regardless: the merge keeps the file's identities protected, and a full
credential-manager snapshot now also drops dynamic identities the store
no longer has, so revocation works without a restart.

* s3: log identity propagation failures as warnings

* s3: retry failed IAM reloads and reconcile policies and groups

An event-driven reload that fails now hands off to a coalescing retry
loop, so a transient filer error cannot strand a revoked credential
until the next IAM event. Full-state merges also drop dynamic policies
the store no longer has, keeping the static file's, and treat the group
snapshot as authoritative even when empty.

* s3: serialize IAM configuration loads

The SIGHUP file reload, subscription reloads, the retry loop, and the
postgres poll run on different goroutines. Without an end-to-end lock a
load holding an older store snapshot can commit after a newer one and
revert it. Hold reloadMu from snapshot through commit in both load
entry points; partial merges from pushed updates stay lock-free and
self-heal through the next event-driven reload.

* s3: keep static-file groups through full-state reconciliation

Group names from the static config file are tracked like identities and
policies, and a full snapshot that does not carry them keeps the current
definition and its memberships instead of dropping them.

* credential: include groups in postgres configuration snapshots

Full-state reconciliation treats absent groups as deleted, so a
snapshot that never carries them would erase every dynamic group.

* s3: revoke static-file groups dropped from the config file

A file reload is authoritative for the file's group set while keeping
dynamic groups, mirroring how full snapshots are authoritative for
dynamic groups while keeping the file's.

* credential: fail filer snapshots on unreadable entries

A skipped identity or policy file made the load report success with an
incomplete snapshot, which reconciliation reads as deletion and the
retry loop never sees. Unparseable content is still skipped: it is
durable, matches boot behavior, and must not block reloads forever.

* s3: ignore groups in static config files

Groups are managed through the IAM API and the dynamic store; no
deployment defines them in a bootstrap config file. Ignoring them with
a warning removes the two-directional group merge: full snapshots are
plainly authoritative and file reloads never touch groups.
2026-07-27 14:06:04 -07:00
..

Credential Store Integration

This document shows how the credential store has been integrated into SeaweedFS's S3 API and IAM API components.

Quick Start

  1. Generate credential configuration:

    weed scaffold -config=credential -output=.
    
  2. Edit credential.toml to enable your preferred store (filer_etc is enabled by default)

  3. Start S3 API server - it will automatically load credential.toml:

    weed s3 -filer=localhost:8888
    

Integration Overview

The credential store provides a pluggable backend for storing S3 identities and credentials, supporting:

  • Filer-based storage (filer_etc) - Uses existing filer storage (default)
  • PostgreSQL - Shared database for multiple servers
  • Memory - In-memory storage for testing

Configuration

Using credential.toml

Generate the configuration template:

weed scaffold -config=credential

This creates a credential.toml file with all available options. The filer_etc store is enabled by default:

# Filer-based credential store (default, uses existing filer storage)
[credential.filer_etc]
enabled = true


# PostgreSQL credential store (recommended for multi-node deployments)
[credential.postgres]
enabled = false
hostname = "localhost"
port = 5432
username = "seaweedfs"
password = "your_password"
database = "seaweedfs"

# Memory credential store (for testing only, data is lost on restart)
[credential.memory]
enabled = false

The credential.toml file is automatically loaded from these locations (in priority order):

  • ./credential.toml
  • $HOME/.seaweedfs/credential.toml
  • /etc/seaweedfs/credential.toml

Server Configuration

Both S3 API and IAM API servers automatically load credential.toml during startup. No additional configuration is required.

Usage Examples

Filer-based Store (Default)

[credential.filer_etc]
enabled = true

This uses the existing filer storage and is compatible with current deployments.

PostgreSQL Store

[credential.postgres]
enabled = true
hostname = "localhost"
port = 5432
username = "seaweedfs"
password = "your_password"
database = "seaweedfs"
schema = "public"
sslmode = "disable"
table_prefix = "sw_"
connection_max_idle = 10
connection_max_open = 100
connection_max_lifetime_seconds = 3600

Memory Store (Testing)

[credential.memory]
enabled = true

Environment Variables

All credential configuration can be overridden with environment variables:

# Override PostgreSQL password
export WEED_CREDENTIAL_POSTGRES_PASSWORD=secret


# Override PostgreSQL hostname
export WEED_CREDENTIAL_POSTGRES_HOSTNAME=db.example.com

# Enable/disable stores
export WEED_CREDENTIAL_FILER_ETC_ENABLED=true

Rules:

  • Prefix with WEED_CREDENTIAL_
  • Convert to uppercase
  • Replace . with _

Implementation Details

Components automatically load credential configuration during startup:

// Server initialization
if credConfig, err := credential.LoadCredentialConfiguration(); err == nil && credConfig != nil {
    credentialManager, err := credential.NewCredentialManager(
        credConfig.Store,
        credConfig.Config,
        credConfig.Prefix,
    )
    if err != nil {
        return nil, fmt.Errorf("failed to initialize credential manager: %v", err)
    }
    // Use credential manager for operations
}

Benefits

  1. Easy Configuration - Generate template with weed scaffold -config=credential
  2. Pluggable Storage - Switch between filer_etc, PostgreSQL without code changes
  3. Backward Compatibility - Filer-based storage works with existing deployments
  4. Scalability - Database stores support multiple concurrent servers
  5. Performance - Database access can be faster than file-based storage
  6. Testing - Memory store simplifies unit testing
  7. Environment Override - All settings can be overridden with environment variables

Error Handling

When a credential store is configured, it must initialize successfully or the server will fail to start:

if credConfig != nil {
    credentialManager, err = credential.NewCredentialManager(...)
    if err != nil {
        return nil, fmt.Errorf("failed to initialize credential manager: %v", err)
    }
}

This ensures explicit configuration - if you configure a credential store, it must work properly.