// Package sshpush — auth.go provides the operator OIDC token // validation hook used by SSH-push apply paths (P04, v0.13; C-44). // // The SSH-push transport moves state to peers (systemd units, nft // rules, drain commands, txn bundles). Any state-changing apply // MUST validate $ORCA_OIDC_TOKEN against the issuer's JWKS before // touching a peer. This file exposes AuthorizeApply, a helper the // CLI calls before fan-out; the actual JWKS verification is in // internal/identity.VerifyOperatorToken (kept there to centralize // the OIDC client logic). package sshpush import ( "context" "fmt" "os" "git.cloudinit.dev/coreci/orca/internal/identity" ) // AuthorizeApply validates $ORCA_OIDC_TOKEN against the issuer's // JWKS and returns the verified operator actor string ("oidc:") // for audit logging. Returns an error if the token is missing or // invalid; the caller MUST refuse the apply in that case. // // When issuer is empty, the function returns an error — apply paths // require an OIDC issuer to be configured. The clientID defaults to // "orca-cli" when empty. func AuthorizeApply(ctx context.Context, issuer, clientID string) (string, error) { // Fast-fail when the env var is unset so we don't even hit the // JWKS discovery (which would hang on a misconfigured issuer). if os.Getenv(identity.EnvOIDCToken) == "" { return "", fmt.Errorf("sshpush: %s env var is not set (operator OIDC token required for apply)", identity.EnvOIDCToken) } claims, err := identity.VerifyOperatorToken(ctx, issuer, clientID) if err != nil { return "", fmt.Errorf("sshpush: %w", err) } return identity.OperatorActor(claims), nil }