Documentation
¶
Overview ¶
Package sigv4a signs and verifies HTTP requests with AWS Signature Version 4A (the AWS4-ECDSA-P256-SHA256 scheme): the same canonical-request construction as classic SigV4 (shared via web/middleware/internal/awssig), but signed with an ECDSA P-256 key derived deterministically from the credential instead of an HMAC key. Verifiers can therefore hold only the public key — material that verifies signatures but can never mint them.
Index ¶
- Constants
- Variables
- func DeriveKeyPair(accessKeyID, secretAccessKey string) (*ecdsa.PrivateKey, error)
- func KeyID(ctx context.Context) (string, bool)
- func TwirpError(ctx context.Context, err error) error
- func User(ctx context.Context) (*iamv1.User, bool)
- func WithUser(ctx context.Context, u *iamv1.User) context.Context
- type Credential
- type Lookuper
- type LookuperFunc
- type PublicKeyLookuper
- type PublicKeyLookuperFunc
- type Signer
- type Verifier
Constants ¶
const ( UnsignedPayload = awssig.UnsignedPayload StreamingPayload = "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD" )
Payload-hash sentinels. UnsignedPayload matches exactly (AWS defines it case-sensitively); any STREAMING-* sentinel is rejected inside awssig.ResolvePayloadHash.
Variables ¶
var ( ErrMissingAuth = errors.New("sigv4a: missing or malformed Authorization") ErrMissingSignedHost = errors.New("sigv4a: host must appear in SignedHeaders") ErrMissingRegionSet = errors.New("sigv4a: x-amz-region-set must appear in SignedHeaders") ErrUnknownKey = errors.New("sigv4a: unknown access key id") ErrClockSkew = errors.New("sigv4a: request time outside allowed skew") ErrScopeMismatch = errors.New("sigv4a: credential scope does not match") ErrStreamingUnsupported = awssig.ErrStreamingUnsupported ErrBodyHash = awssig.ErrBodyHash ErrBodyTooLarge = awssig.ErrBodyTooLarge ErrNotConfigured = errors.New("sigv4a: neither Verifier.Lookup nor Verifier.KeyLookup is set") )
Errors returned by Verify. Callers typically map ErrUnauthorized and ErrUnknownKey to 403 and the rest to 400.
Functions ¶
func DeriveKeyPair ¶
func DeriveKeyPair(accessKeyID, secretAccessKey string) (*ecdsa.PrivateKey, error)
DeriveKeyPair deterministically derives the SigV4A ECDSA P-256 keypair for a credential. It implements AWS's counter-mode KDF (NIST SP 800-108 style, PRF = HMAC-SHA256, key = "AWS4A"+secret) with rejection sampling: a candidate above N-2 retries with the next counter byte (1..254), an accepted candidate is incremented by one to land in [1, N-1]. The per-attempt rejection probability is ~2^-32, so the loop virtually always succeeds on the first pass.
The keypair is a pure function of (accessKeyID, secretAccessKey): unlike the SigV4 HMAC ladder there is no date/region/service scoping, so the same key signs and verifies for the credential's whole lifetime.
The big.Int comparison is not constant-time; that is acceptable because derivation only ever runs over our own stored secret, never comparing against attacker-controlled input.
func KeyID ¶
KeyID returns the verified access key id stored by Middleware, if any. The value is stored via authctx, so it is also visible to sigv4.KeyID and authctx.KeyID directly.
func TwirpError ¶
TwirpError maps a verification error to the twirp error middlewares write to clients. Sentinels that describe the caller's own request keep their message; key and signature failures collapse to one opaque message so a probe cannot distinguish unknown, disabled, and mis-signed credentials. Unexpected errors are logged with their cause and surfaced as an opaque internal error.
func User ¶
User returns the IAM user associated with the verified caller, if any. The bool is false when no middleware populated it.
func WithUser ¶
WithUser stores the IAM user resolved for the verified caller in ctx. It is the local-verification counterpart to iamsts.Caller: middleware resolves the access key id from KeyID to its owning user and stashes it here so downstream code (logging interceptors, handlers) can attribute the call without re-querying the backing store. The value is stored via authctx, so it is also visible to sigv4.User and authctx.User directly.
Types ¶
type Credential ¶
Credential is the parsed Credential= component of a SigV4A Authorization header: the access key id plus the literal, unnormalized scope strings.
func ParseCredential ¶
func ParseCredential(authorization string) (*Credential, error)
ParseCredential extracts the credential scope from an AWS4-ECDSA-P256-SHA256 Authorization header value. It returns ErrMissingAuth for anything malformed, matching Verify.
type Lookuper ¶
type Lookuper interface {
// Lookup resolves an access key id to its secret access key. Return
// ErrUnknownKey for unknown keys. This is the one piece you must supply.
Lookup(accessKeyID string) (secretAccessKey string, err error)
}
Lookuper encapsulates the secret access key lookup so that the underlying logic can have arbitrary implementations.
type LookuperFunc ¶
LookuperFunc adapts an ordinary function to the Lookuper interface, the same way http.HandlerFunc adapts a function to http.Handler.
type PublicKeyLookuper ¶
type PublicKeyLookuper interface {
LookupPublicKey(ctx context.Context, accessKeyID string) (*ecdsa.PublicKey, error)
}
PublicKeyLookuper resolves an access key id to the credential's SigV4A ECDSA P-256 public key. Return ErrUnknownKey when the key does not exist or may not sign (disabled key or user); any other error is treated as a server fault. Public keys are verification-only material: an implementation can hold and cache them without ever being able to mint a signature.
type PublicKeyLookuperFunc ¶
PublicKeyLookuperFunc adapts an ordinary function to PublicKeyLookuper.
func (PublicKeyLookuperFunc) LookupPublicKey ¶
func (f PublicKeyLookuperFunc) LookupPublicKey(ctx context.Context, accessKeyID string) (*ecdsa.PublicKey, error)
LookupPublicKey calls f.
type Signer ¶
type Signer struct {
// Now is overridable for tests. Defaults to time.Now.
Now func() time.Time
// contains filtered or unexported fields
}
Signer signs outgoing HTTP requests with AWS Signature Version 4A. It is the client-side counterpart to Verifier and shares its canonicalization through awssig, so the two agree by construction.
The ECDSA keypair is derived once at construction; the secret access key is not retained. Application code usually wants the sigv4aclient subpackage, which wraps a Signer in an http.RoundTripper.
func NewSigner ¶
NewSigner derives the SigV4A keypair for the credential and returns a Signer that signs for the given region (the X-Amz-Region-Set value; a single region name for within.website services) and service.
type Verifier ¶
type Verifier struct {
// Region must be covered by the request's signed X-Amz-Region-Set;
// Service must match the credential scope.
Region string
Service string
// Lookup resolves an access key id to its secret. Return ErrUnknownKey
// for unknown keys. This is the one piece you must supply.
Lookup Lookuper
// KeyLookup resolves an access key id to its ECDSA public key. When set
// it takes precedence over Lookup, and the verifier never sees the raw
// secret — this is how services that must not hold secrets verify
// locally (see web/middleware/sigv4a/iamsts). Exactly one of Lookup or
// KeyLookup must be set.
KeyLookup PublicKeyLookuper
// MaxClockSkew bounds how far the request's X-Amz-Date may be from now.
// Defaults to 15 minutes (matching AWS) when zero.
MaxClockSkew time.Duration
// DisablePathEscaping selects S3-style canonicalization, where the path
// is used as-is rather than being URI-encoded a second time. Set true
// when emulating S3; leave false for every other AWS service.
DisablePathEscaping bool
// MaxBodySize caps how many bytes of the body will be buffered to verify
// the payload hash. Zero means unlimited. Requests that exceed it are
// rejected with ErrBodyTooLarge.
MaxBodySize int64
// Now is overridable for tests. Defaults to time.Now.
Now func() time.Time
}
Verifier validates SigV4A-signed requests for a single region/service.
func (*Verifier) Middleware ¶
Middleware returns net/http middleware that rejects unsigned or invalid requests with 401/403 and otherwise passes them through. On success it stores the verified access key id in the request context.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package iamsts authenticates HTTP requests signed with AWS Signature Version 4A by verifying them locally against a cached ECDSA public key fetched from IAM's key service.
|
Package iamsts authenticates HTTP requests signed with AWS Signature Version 4A by verifying them locally against a cached ECDSA public key fetched from IAM's key service. |
|
Package sigv4aclient provides an http.RoundTripper that signs outgoing requests with AWS Signature Version 4A. It is the SigV4A counterpart to web/middleware/sigv4/sigv4client (which signs classic SigV4 for real AWS services): use this package for within.website services verified by web/middleware/sigv4a.
|
Package sigv4aclient provides an http.RoundTripper that signs outgoing requests with AWS Signature Version 4A. It is the SigV4A counterpart to web/middleware/sigv4/sigv4client (which signs classic SigV4 for real AWS services): use this package for within.website services verified by web/middleware/sigv4a. |