Documentation
¶
Index ¶
- Constants
- Variables
- func BackfillAICFields(d *db.DB) error
- func BridgeTrustPEMs(database *db.DB, bridges []TrustBridgePolicy, caCfgs map[string]struct{ ... }) ([]*db.CrossCertRecord, error)
- func BuildAIC(cfg AICConfig) (pkix.Extension, error)
- func BuildChain(leaf *x509.Certificate, src CertSource, maxDepth int) ([]*x509.Certificate, bool, error)
- func BuildFederatedTrustPool(database *db.DB, localCAs map[string]*x509.Certificate, ...) (*x509.CertPool, error)
- func BuildJWKSJSON(certs []*x509.Certificate) ([]byte, error)
- func BuildPrincipalAuthorizationExtension(cfg PrincipalAuthorizationConfig) (pkix.Extension, error)
- func BuildRenewalToken(oldCertSerial []byte, principalUid PrincipalUid, newKeyHash []byte, ...) (pkix.Extension, error)
- func CRLFilename(caName string, partition, total int) string
- func CertToPEM(der []byte) []byte
- func CheckLDAPGroupMembership(entry *ldap.Entry, cfg *LDAPConfig, groupDN string) bool
- func CheckPolicy(sc *SignConfig) error
- func CheckPublicKeyStrength(pub any) error
- func ColdBackupCA(caName, certPath, keyPath, password, keyPassword, outPath string) error
- func DecryptKeyPKCS8(der []byte, password string) (crypto.Signer, error)
- func DecryptPrivateKey(blob []byte, priv crypto.PrivateKey) ([]byte, error)
- func DecryptPrivateKeyPEM(pemData []byte, password string) (crypto.Signer, error)
- func DefaultHashAlgo() asn1.ObjectIdentifier
- func DefaultPolicyPath(cfgDir string) string
- func EncryptKeyDERPKCS8(privDER []byte, password string) ([]byte, error)
- func EncryptKeyPKCS8(priv crypto.Signer, password string) ([]byte, error)
- func EncryptPrivateKey(privDER []byte, pub crypto.PublicKey) ([]byte, error)
- func EncryptPrivateKeyPEM(key crypto.Signer, password string) ([]byte, error)
- func EstablishTrustBridge(database *db.DB, issuerCert *x509.Certificate, issuerKey crypto.Signer, ...) (*db.CrossCertRecord, error)
- func ExportFederatedTrust(database *db.DB, source string) ([]byte, error)
- func ExportSubCA(database *db.DB, name string) (certPEM, keyPEM []byte, err error)
- func ExtractAdminScope(cert *x509.Certificate) string
- func ExtractCertFields(cert *x509.Certificate) (o, c, issuerDN, keyAlgo string, keySize int, sigAlgo, ski, aki, san string)
- func ExtractPrincipalUID(der []byte) (string, error)
- func ExtractSPKIHash(cert *x509.Certificate) string
- func ExtractTrustAnchorFields(cert *x509.Certificate) (o, c, keyAlgo string, keySize int, sha1fp string, pathLen int)
- func FetchCACertBundle(url string) ([]byte, error)
- func FlushSignerCache(keyPath ...string)
- func GenerateCRL(cfg *CRLConfig) ([]byte, error)
- func GenerateDeltaCRL(cfg *CRLConfig, dcfg *DeltaCRLConfig) ([]byte, error)
- func GenerateKey(keyType string) (crypto.Signer, error)
- func GenerateSubCAKey(keyType string) (crypto.Signer, error)
- func GetSubCACertChain(database *db.DB, subCAName string) ([]*x509.Certificate, error)
- func ImportExternalCA(database *db.DB, name string, certPEM, keyPEM []byte, password string) (*db.CAMeta, error)
- func IsAutoRenewable(certDER []byte, caCert *x509.Certificate) bool
- func IsEncryptedPEM(data []byte) bool
- func IsRootCAProfile(p Profile) bool
- func JWSToAlg(pub any) (string, error)
- func KeyToPEM(key crypto.Signer) ([]byte, error)
- func LoadAdminPublicKey(path string) (crypto.PublicKey, error)
- func LoadPrivateKey(keyPath string, keyPassword ...string) (crypto.Signer, error)
- func LoadSigner(certPath, keyPath string, keyPassword ...string) (*x509.Certificate, crypto.Signer, error)
- func LoadSignerAny(certPath, keyPath string, database *db.DB, caName, keyPassword string) (*x509.Certificate, crypto.Signer, error)
- func LoadSignerFromDB(database *db.DB, caName, password string) (*x509.Certificate, crypto.Signer, error)
- func LoadTrustPool(cfgCAs map[string]string, database *db.DB) (*x509.CertPool, error)
- func LoadTrustPoolWithSources(cfgCAs map[string]string, database *db.DB) (*x509.CertPool, map[string]string, error)
- func LookupLDAP(conn *ldap.Conn, cfg *LDAPConfig, username string) (*ldap.Entry, *pkix.Name, error)
- func NewLDAPConn(cfg *LDAPConfig) (*ldap.Conn, error)
- func NormalizeSerial(serial string) (string, error)
- func ParseCSR(pemBytes []byte) (*x509.CertificateRequest, error)
- func ParseCTLogPublicKey(s string) (crypto.PublicKey, error)
- func ParseHashAlgo(s string) (asn1.ObjectIdentifier, error)
- func ParsePrivateKey(keyPEM []byte, keyPassword ...string) (crypto.Signer, error)
- func ParseRevokeReason(s string) (int, error)
- func ParseSubCACert(certPEM []byte) (*x509.Certificate, error)
- func ParseSubCAKey(keyPEM []byte, keyPassword ...string) (crypto.Signer, error)
- func ProcessApproval(database *db.DB, requestID int, approver, decision, comment string, ...) (approved bool, issuedSerial string, err error)
- func RejectRequest(database *db.DB, requestID int, reason string) error
- func RemoteSignerConfig() *remotesigner.Config
- func Revoke(d *db.DB, caName, serial string, reason int) error
- func RevokeByPrincipalUid(d *db.DB, principalUid string, reason int) (int, error)
- func RevokeBySubCA(d *db.DB, caName string, reason int) (int, error)
- func RevokeSubCA(database *db.DB, name string, reason int) error
- func RevokeWithCascade(d *db.DB, caName, serial string, reason int) (int, error)
- func SPKIHash(pub crypto.PublicKey) []byte
- func SPKISHA256(cert *x509.Certificate) string
- func SanitizeCAName(name string) string
- func SeedCRLNumber(n int64)
- func SetRemoteSignerConfig(cfg *remotesigner.Config)
- func SignCACSR(cfg *OfflineSignConfig) ([]byte, *big.Int, error)
- func SubmitCertificate(url, apiKey string, cert *x509.Certificate, chain []*x509.Certificate, ...) (sctVersion int, logID string, timestamp uint64, extensions string, ...)
- func SubmitRequest(database *db.DB, csrDER []byte, cn, sanList, profile, caName, requester string, ...) (int, error)
- func TrustAnchorFederate(database *db.DB, remoteURL string) (int, error)
- func ValidateAdminCert(cert *x509.Certificate) error
- func ValidateAdminCertFromPEM(certPEM []byte) (*x509.Certificate, error)
- func ValidateAdminCertFromPEMWithPool(certPEM []byte, pool *x509.CertPool, targetCA string) (*x509.Certificate, error)
- func ValidateAdminCertFromPEMWithTarget(certPEM []byte, targetCA string) (*x509.Certificate, error)
- func ValidateAdminCertWithTarget(cert *x509.Certificate, chain *x509.CertPool, targetCA string) error
- func ValidateAndConsumeNonce(token *RenewalTokenExt, store NonceStorer) error
- func ValidateOutboundHTTPURL(rawurl string) error
- func ValidateParameterSubset(granted, declared Capability) error
- func ValidatePrincipalUidKeyHash(pu PrincipalUid) error
- func VerifyColdBackup(inPath, password string) (string, error)
- func VerifyDelegationAuthorization(userCert *x509.Certificate, aic *AICConfig, agentSPKI []byte) error
- func VerifySCT(cert *x509.Certificate, sctVersion int, logID string, timestamp uint64, ...) error
- type AIC
- type AICConfig
- type AggregatorConfig
- type AggregatorError
- type AggregatorReq
- type AggregatorResult
- type AlgorithmIdentifier
- type ArchivePolicy
- type ArchiveResult
- type AutoRenewCallback
- type AutoRenewPolicy
- type AutoRenewResult
- type CRLConfig
- type CRLNumberStore
- type Capability
- type CertAggregator
- type CertBufferItem
- type CertSigner
- type CertSource
- type ChainNode
- type ColdBackupEnvelope
- type CreateConfig
- type CreateResult
- type DBSource
- type DelegationAuthorization
- type DelegationMode
- type DelegationModeEnum
- type DelegationPolicy
- type DeltaCRLConfig
- type ExtField
- type IdentitySource
- type IdentitySourceConfig
- type IdentitySourceType
- type ImportTrustResult
- type IssueResult
- type JWK
- type JWKS
- type JWTSignOptions
- type Job
- type JobProcessor
- type JobQueue
- type JobRequest
- type JobRequestItem
- type JobResultItem
- type JobStatus
- type LDAPConfig
- type LDAPLookup
- type MemoryBuffer
- type NameConstraints
- type NonceStorer
- type OfflineSignConfig
- type PathVerificationResult
- type PersistConfig
- type PersistMode
- type Policy
- type PolicyDecision
- type PolicyMapping
- type PolicyMappingApplied
- type PolicyRule
- type PrincipalAuthorization
- type PrincipalAuthorizationConfig
- type PrincipalUid
- type Profile
- type Reason
- type RenewalToken
- type RenewalTokenExt
- type RevokedEntriesSinceSource
- type RevokedEntriesSource
- type RotatingSigner
- func (rs *RotatingSigner) Active() *SignerKey
- func (rs *RotatingSigner) Cert() *x509.Certificate
- func (rs *RotatingSigner) ClearLegacy()
- func (rs *RotatingSigner) Key() crypto.Signer
- func (rs *RotatingSigner) Legacy() *SignerKey
- func (rs *RotatingSigner) NeedsRotation(window time.Duration) bool
- func (rs *RotatingSigner) NotAfter() time.Time
- func (rs *RotatingSigner) Public() crypto.PublicKey
- func (rs *RotatingSigner) Rotate(cert *x509.Certificate, key crypto.Signer)
- func (rs *RotatingSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
- func (rs *RotatingSigner) Store(cert *x509.Certificate, key crypto.Signer)
- type SignCSRCallback
- type SignConfig
- type SignJWTResult
- type SignResult
- type SignerKey
- type StaticSource
- type SubCAConfig
- type SubCAMeta
- type SubCAResult
- type TrustBridgeConfig
- type TrustBridgePolicy
- type UserIdentity
- type ValidPolicyNode
- type VerifyPathOptions
- type VerifyResult
Constants ¶
const DefaultAgentProxyMaxValidity = 1 * time.Hour
DefaultAgentProxyMaxValidity is the default hard upper bound for agent-proxy certificate validity (1 hour).
const DefaultCACertURL = "https://curl.se/ca/cacert.pem"
const MaxAgentProxyValidity = 24 * time.Hour
MaxAgentProxyValidity is the spec-mandated hard ceiling for agent-proxy (authorized mode) certificate validity. Per AIC spec §3.4, agent sessions must not exceed 24 hours. M2 fix: this bound is enforced at the CA library layer so it cannot be silently bypassed by any caller-supplied configuration.
const MaxAuthorizationConstraints = 32
MaxAuthorizationConstraints caps the constraint list on a PrincipalAuthorization, mirroring types.MaxAuthorizationConstraints (the AIC extension enforces the same bound on its own copy).
const MaxGrantEntries = 256
MaxGrantEntries is the maximum number of entries in PrincipalAuthorization.grants (spec P1-A-24).
const MinRSAKeySize = 2048
MinRSAKeySize is the minimum RSA key length (bits) allowed for signing. Issuance is rejected below this value to prevent weak keys (NIST SP 800-57 / MLPS 2.0).
Variables ¶
var ( ErrNoResult = &AggregatorError{"no result"} ErrTimeout = &AggregatorError{"timeout"} )
var ( OIDSigECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} OIDSigECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} OIDSigECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} OIDSigRSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} OIDSigRSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} OIDSigRSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} OIDSigRSAPSSWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} OIDSigEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} )
Signature algorithm OID constants.
var ( // ── 1.x Identity and Permission Extensions ── OIDIdentityExt = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1} // 1.1 AIC (core patent: AIC + natural person binding + capability protocolization) OIDAIC = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1} OIDAICAgentIdentity = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1, 1} // DelegationAuthorization (.1.1.2, principal signature evidence; pre-v1.5 old name UserAuth). OIDAICDelegationAuthorization = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1, 2} // DelegationDepthControl (.1.1.4, spec v1.7.2 §3.7, FUTURE delegation depth control). OIDDelegationDepthControl = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1, 4} OIDDDCChainDepth = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1, 4, 1} OIDDDCMaxDepth = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 1, 4, 2} // 1.2 PrincipalAuthorization (v1.5: replaces old UserPermission) OIDPrincipalAuthorization = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 2} // 1.6 RenewalToken (auto-renewal token, I-D §6) OIDRenewalToken = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 1, 6} // ── 3.x National/Industry Certification Extensions ── OIDCertificationExt = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 3} // 3.1 MarketAccessId (complete credential, companion patent: national certification) OIDMarketAccessId = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 3, 1} // 3.2 TrustLevel OIDTrustLevel = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 3, 2} // 3.3 CrossBorder (reserved placeholder) OIDCrossBorder = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 3, 3} // ── 5.x GM (Chinese National Cryptography) Extensions ── OIDGM = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 5} OIDSM2Sig = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 5, 1} OIDSM3Hash = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 5, 2} OIDSM4Enc = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 5, 3} OIDSM2SM3Sig = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 5, 4} // ── 6.x Certificate Transparency Extensions ── OIDCT = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 6} OIDCTSCT = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 6, 1} OIDCTLog = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66257, 6, 2} )
IANA-assigned PEN: 66257, OID root: 1.3.6.1.4.1.66257
var ( ErrSubCAAlreadyExists = errors.New("sub-CA already exists") ErrSubCANotFound = errors.New("sub-CA not found") ErrSubCARevoked = errors.New("sub-CA is revoked") ErrSubCAExpired = errors.New("sub-CA is expired") ErrAdminCertRequired = errors.New("admin certificate with keyCertSign usage required") ErrInvalidAdminCert = errors.New("invalid admin certificate") )
var ErrNoAIC = fmt.Errorf("certificate has no AIC extension")
ErrNoAIC is returned when a certificate does not contain an AIC extension.
var ErrRootCAImport = errors.New("root CA key must not be imported into database; keep it offline")
var HashAlgoOIDs = map[string]asn1.ObjectIdentifier{
"sha256": {2, 16, 840, 1, 101, 3, 4, 2, 1},
"sha384": {2, 16, 840, 1, 101, 3, 4, 2, 2},
"sha512": {2, 16, 840, 1, 101, 3, 4, 2, 3},
"sha3-256": {2, 16, 840, 1, 101, 3, 4, 2, 8},
"sha3-384": {2, 16, 840, 1, 101, 3, 4, 2, 9},
"sha3-512": {2, 16, 840, 1, 101, 3, 4, 2, 10},
"sm3": {1, 2, 156, 10197, 1, 401},
}
HashAlgoOIDs maps hash algorithm name strings to OIDs.
var RevokeReasons = map[string]int{
"unspecified": 0,
"keyCompromise": 1,
"cACompromise": 2,
"affiliationChanged": 3,
"superseded": 4,
"cessationOfOperation": 5,
"certificateHold": 6,
}
Functions ¶
func BackfillAICFields ¶
BackfillAICFields scans all valid agent-proxy certificates that lack principal_uid/agent_id and backfills them from the AIC extension in cert_der. Idempotent — safe to call on every startup.
func BridgeTrustPEMs ¶
func BridgeTrustPEMs(database *db.DB, bridges []TrustBridgePolicy, caCfgs map[string]struct { Cert string Key string }) ([]*db.CrossCertRecord, error)
func BuildAIC ¶
BuildAIC constructs the AIC X.509v3 extension from configuration (v1.7.1 spec: DA required, critical=false). Validation coverage: V6 keyHash length, V8 lifetime 1..86400, V10/V15 constraint schemeId whitelist, V16 non-empty authorization, R1/R2/R4/R5 Reason required and length, nonce 32 bytes.
func BuildChain ¶
func BuildChain(leaf *x509.Certificate, src CertSource, maxDepth int) ([]*x509.Certificate, bool, error)
BuildChain builds a certificate path from leaf up to a trust anchor using the given source. It performs no trust/policy evaluation — only structural walks (issuer matching, cycle protection, depth bound). Returns the path leaf-first (chain[0]=leaf, chain[len-1]=root candidate) and whether the terminal cert is in the trust anchors.
func BuildFederatedTrustPool ¶
func BuildFederatedTrustPool(database *db.DB, localCAs map[string]*x509.Certificate, crossCerts []*db.CrossCertRecord) (*x509.CertPool, error)
func BuildJWKSJSON ¶
func BuildJWKSJSON(certs []*x509.Certificate) ([]byte, error)
BuildJWKSJSON returns the marshaled JWKS for a certificate set.
func BuildPrincipalAuthorizationExtension ¶
func BuildPrincipalAuthorizationExtension(cfg PrincipalAuthorizationConfig) (pkix.Extension, error)
BuildPrincipalAuthorizationExtension builds a PrincipalAuthorization X.509v3 extension from the configuration.
func BuildRenewalToken ¶
func BuildRenewalToken(oldCertSerial []byte, principalUid PrincipalUid, newKeyHash []byte, store NonceStorer) (pkix.Extension, error)
BuildRenewalToken constructs a RenewalToken X.509v3 extension. oldCertSerial is the DER-encoded serial number of the certificate requesting renewal, principalUid is the principal identity identifier, newKeyHash is the SHA-256 hash of the new public key (32 bytes). If store is non-nil, the nonce is persisted (for one-time-use enforcement).
func CRLFilename ¶
func CheckLDAPGroupMembership ¶
func CheckLDAPGroupMembership(entry *ldap.Entry, cfg *LDAPConfig, groupDN string) bool
func CheckPolicy ¶
func CheckPolicy(sc *SignConfig) error
func CheckPublicKeyStrength ¶
CheckPublicKeyStrength validates the strength of the public key to be signed, rejecting weak keys. Rules:
- RSA < MinRSAKeySize: reject
- EC curve not in NIST P-256/P-384/P-521 whitelist: reject
- Ed25519: always accept
- Unknown type: return warning (non-blocking, to prevent compatibility regression)
func ColdBackupCA ¶
ColdBackupCA reads the CA certificate and key, encrypts the key under password, and writes a tamper-evident JSON envelope to outPath. The key is loaded via ParsePrivateKey (supports encrypted PEM via keyPassword).
func DecryptPrivateKey ¶
func DecryptPrivateKey(blob []byte, priv crypto.PrivateKey) ([]byte, error)
func DecryptPrivateKeyPEM ¶
DecryptPrivateKeyPEM decrypts a PEM-encoded encrypted private key. Also handles unencrypted "PRIVATE KEY" and combined cert+key files.
func DefaultHashAlgo ¶
func DefaultHashAlgo() asn1.ObjectIdentifier
DefaultHashAlgo returns the default SHA-256 OID.
func DefaultPolicyPath ¶
func EncryptPrivateKey ¶
func EncryptPrivateKeyPEM ¶
EncryptPrivateKeyPEM encrypts a private key with a password using PKCS#8 EncryptedPrivateKeyInfo (PBKDF2-SHA256 + AES-256-CBC, RFC 5958). Output is PEM-compatible with OpenSSL's "ENCRYPTED PRIVATE KEY" format:
openssl pkey -aes-256-cbc -pass pass:xxx -in key.pem -out enc-key.pem
func EstablishTrustBridge ¶
func ExportFederatedTrust ¶
func ExportSubCA ¶
ExportSubCA exports a sub-CA as PEM certificates and private key.
func ExtractAdminScope ¶
func ExtractAdminScope(cert *x509.Certificate) string
ExtractAdminScope extracts the sub-CA management scope from an admin certificate. Scope is stored in OID 1.3.6.1.4.1.66257.1.5.1 and/or SAN URIs (urn:pki:ca:<scope>). The two are merged and de-duplicated.
func ExtractCertFields ¶
func ExtractCertFields(cert *x509.Certificate) (o, c, issuerDN, keyAlgo string, keySize int, sigAlgo, ski, aki, san string)
func ExtractPrincipalUID ¶
ExtractPrincipalUID parses the AIC PrincipalUid out of a certificate's DER. Returns ErrNoAIC when the cert carries no AIC or its PrincipalUid is empty.
func ExtractSPKIHash ¶
func ExtractSPKIHash(cert *x509.Certificate) string
func FetchCACertBundle ¶
func FlushSignerCache ¶
func FlushSignerCache(keyPath ...string)
func GenerateCRL ¶
func GenerateDeltaCRL ¶
func GenerateDeltaCRL(cfg *CRLConfig, dcfg *DeltaCRLConfig) ([]byte, error)
GenerateDeltaCRL builds a Delta CRL (RFC 5280 §5.2.4) covering only the certificates revoked since the base CRL thisUpdate. It carries the Delta CRL Indicator (2.5.29.27) and Base CRL Number (2.5.29.31) extensions, which let clients merge the delta with the base CRL.
The source must implement RevokedEntriesSinceSource (both *db.DB and *engine.Engine do). When the configured source does not, a full-CRL query is used and entries are filtered in memory.
func GenerateSubCAKey ¶
GenerateSubCAKey generates a private key for a sub-CA.
func GetSubCACertChain ¶
GetSubCACertChain returns the sub-CA certificate chain (sub-CA + parent CA).
func ImportExternalCA ¶
func IsAutoRenewable ¶
func IsAutoRenewable(certDER []byte, caCert *x509.Certificate) bool
func IsEncryptedPEM ¶
IsEncryptedPEM checks whether a PEM block is an encrypted private key.
func IsRootCAProfile ¶
func LoadPrivateKey ¶
func LoadSigner ¶
func LoadSignerAny ¶
func LoadSignerFromDB ¶
func LoadTrustPool ¶
func LookupLDAP ¶
func NewLDAPConn ¶
func NewLDAPConn(cfg *LDAPConfig) (*ldap.Conn, error)
func NormalizeSerial ¶
func ParseCTLogPublicKey ¶
ParseCTLogPublicKey parses a CT log public key given as either a base64 DER SPKI string or a PEM block (PUBLIC KEY). It returns the parsed key.
func ParseHashAlgo ¶
func ParseHashAlgo(s string) (asn1.ObjectIdentifier, error)
ParseHashAlgo parses a hash algorithm string (e.g. "sha256") to an OID. Returns nil if empty (caller should use default SHA-256).
func ParsePrivateKey ¶
func ParseRevokeReason ¶
func ParseSubCACert ¶
func ParseSubCACert(certPEM []byte) (*x509.Certificate, error)
ParseSubCACert parses a sub-CA certificate from PEM bytes.
func ParseSubCAKey ¶
ParseSubCAKey parses a sub-CA private key from PEM bytes. Supports both plain and encrypted (PKCS#8 PBES2) PEM. If key is encrypted, password can be provided; if empty, falls back to PKI_KEY_PASSWORD env.
func ProcessApproval ¶
func RemoteSignerConfig ¶
func RemoteSignerConfig() *remotesigner.Config
RemoteSignerConfig returns the current remote signer config.
func RevokeByPrincipalUid ¶
RevokeByPrincipalUid revokes all valid certificates matching the given PrincipalUid. Uses SQL-based filter (fast path) when the principal_uid column is populated, falls back to DER scan for legacy data.
func RevokeBySubCA ¶
RevokeBySubCA revokes all valid certificates under a given CA (sub-CA name). Returns the number of revoked certs.
func RevokeSubCA ¶
RevokeSubCA revokes a sub-CA by name.
func RevokeWithCascade ¶
RevokeWithCascade revokes a certificate and cascade-revokes all agent certificates with the same PrincipalUid.
func SPKIHash ¶
SPKIHash returns the SPKI DER SHA-256 digest of the public key (v1.7.1 keyHash computation method).
func SPKISHA256 ¶
func SPKISHA256(cert *x509.Certificate) string
SPKISHA256 returns base64url(SHA-256(SubjectPublicKeyInfo)) — the key_hash convention used for both X.509 PrincipalUid and AIC-JWT kid.
func SanitizeCAName ¶
func SeedCRLNumber ¶
func SeedCRLNumber(n int64)
SeedCRLNumber sets the CRL number counter to at least n. Call this at startup with the last known CRL number (from DB or parsed CRL file) to prevent RFC 5280 monotonicity violation across restarts.
func SetRemoteSignerConfig ¶
func SetRemoteSignerConfig(cfg *remotesigner.Config)
SetRemoteSignerConfig enables remote HSM signing for all LoadSigner calls.
func SubmitCertificate ¶
func SubmitRequest ¶
func ValidateAdminCert ¶
func ValidateAdminCert(cert *x509.Certificate) error
ValidateAdminCert verifies that a client certificate has admin privileges. Admin certificates must:
- Have DigitalSignature key usage
- Be signed by a trusted CA in the provided pool
- Have a valid scope matching the target sub-CA (if scope is set)
- Not be revoked (CRL check)
Note: admin certs are now entity certs (IsCA=false), not CA certs.
func ValidateAdminCertFromPEM ¶
func ValidateAdminCertFromPEM(certPEM []byte) (*x509.Certificate, error)
ValidateAdminCertFromPEM validates an admin certificate from PEM bytes.
func ValidateAdminCertFromPEMWithPool ¶
func ValidateAdminCertFromPEMWithPool(certPEM []byte, pool *x509.CertPool, targetCA string) (*x509.Certificate, error)
ValidateAdminCertFromPEMWithPool validates an admin certificate from PEM bytes against an explicit trust pool. Unlike ValidateAdminCertFromPEMWithTarget (which skips chain verification because it has no trust anchors), this performs full chain verification against the pool — the only path that prevents a self-signed or expired attacker certificate from being accepted as an "admin certificate" (H9 fix). When targetCA is non-empty, the certificate's management scope must also cover targetCA.
func ValidateAdminCertFromPEMWithTarget ¶
func ValidateAdminCertFromPEMWithTarget(certPEM []byte, targetCA string) (*x509.Certificate, error)
ValidateAdminCertFromPEMWithTarget validates an admin certificate from PEM bytes and, when targetCA is non-empty, checks that the certificate's management scope covers targetCA.
func ValidateAdminCertWithTarget ¶
func ValidateAdminCertWithTarget(cert *x509.Certificate, chain *x509.CertPool, targetCA string) error
ValidateAdminCertWithTarget performs full admin cert validation:
- chain: trust pool for chain verification (nil = skip chain check)
- targetCA: name of the sub-CA to manage (empty = skip scope check)
func ValidateAndConsumeNonce ¶
func ValidateAndConsumeNonce(token *RenewalTokenExt, store NonceStorer) error
ValidateAndConsumeNonce validates one-time nonce usage and consumes it. Combined check: length + not expired + not already used; atomically consumes on pass.
func ValidateOutboundHTTPURL ¶
ValidateOutboundHTTPURL checks that url is an http(s) URL with a non-empty host whose literal or resolved addresses are not internal/private/loopback (SSRF defense). Used when registering outbound destinations such as webhook subscriptions so the server cannot be used as a pivot to reach internal hosts.
func ValidateParameterSubset ¶
func ValidateParameterSubset(granted, declared Capability) error
ValidateParameterSubset checks whether the declared (AIC capability) parameters fall within the granted (PA grant authorization boundary) parameter range. Scheme mismatch or grant has no parameters → no parameter-level rules, pass. Out-of-bounds returns a non-nil error.
func ValidatePrincipalUidKeyHash ¶
func ValidatePrincipalUidKeyHash(pu PrincipalUid) error
ValidatePrincipalUidKeyHash validates that keyHash length matches the declared hashAlgo (v1.7.1 §5, spec P1-A-12). SHA-2/SHA-3 + SM3 (built-in pure Go implementation in types, C1) are validated against the mapping table for output length; algorithms requiring external dependencies like BLAKE2/BLAKE3 return a clear "unsupported" error.
func VerifyColdBackup ¶
VerifyColdBackup reads a cold backup envelope, verifies its MAC, decrypts the key, and checks that the decrypted key matches the enclosed certificate's public key. It returns a human-readable summary on success.
func VerifyDelegationAuthorization ¶
func VerifyDelegationAuthorization(userCert *x509.Certificate, aic *AICConfig, agentSPKI []byte) error
VerifyDelegationAuthorization verifies the DelegationAuthorization carried in an AICConfig against the DA signer's certificate:
- Reconstructs DelegationAuthTBS with the exact same field order the client signer and gateway-lib VerifyDelegationAuth use.
- Cross-validates the user certificate's SPKI hash against PrincipalUid.KeyHash (prevents forged user certs).
- Verifies the signature with the user certificate's public key (ECDSA/RSA/RSA-PSS/Ed25519), keyed off the declared algorithm OID.
agentSPKI is the DER encoding of the agent public key being certified (x509.MarshalPKIXPublicKey(sc.SubjectPubKey)).
Version negotiation:
- aic.Version == 0: try v2 when agentSPKI is non-empty, then v1.
- aic.Version == 1: only v1 (legacy DER).
- aic.Version == 2: only v2 (agentSPKI must be non-empty).
On success aic.Version is updated to the actual version verified (audit trail). Both versions failing returns an aggregated error (fail-closed). A nil userCert or nil AIC is treated as invalid (fail-closed).
func VerifySCT ¶
func VerifySCT(cert *x509.Certificate, sctVersion int, logID string, timestamp uint64, extensions string, sigDER []byte, logPubKey crypto.PublicKey) error
VerifySCT performs full RFC 6962 §3.2 signature verification of a v1 SCT against the CT log's public key. It reconstructs the exact TLS bytes the log signed over (SignedCertificateTimestamp → SCTSignedData: version | sig_type | timestamp | entry_type | 3-byte-length cert DER | 2-byte-length extensions) and verifies the DigitallySigned signature with the supplied log key.
The previous implementation only validated the TLS framing (algo bytes + length prefix) and never touched the log signature — any garbage SCT passed. Pass a nil logPubKey to skip the cryptographic check (callers that do this MUST treat the result as unverified).
Types ¶
type AIC ¶
type AIC struct {
Version int `asn1:"default:1"`
AgentId string `asn1:"utf8"`
PrincipalUid PrincipalUid `asn1:""`
Capabilities []Capability `asn1:"sequence"`
DelegationMode DelegationMode `asn1:"default:0"`
AuthorizationConstraints []Capability `asn1:"optional,omitempty,contextspecific,explicit,tag:0"`
DelegationAuthorization DelegationAuthorization `asn1:"optional,omitempty"`
Extensions []ExtField `asn1:"optional,omitempty,contextspecific,explicit,tag:1"`
}
AIC is the X.509v3 extension ASN.1 structure (v1.7.1 spec §AIC). ASN.1 field order: version, agentId, principalUid, capabilities, delegationMode, authorizationConstraints [0], delegationAuthorization, extensions [1]. delegationAuthorization is required by spec; Go encoding/asn1 cannot marshal "required but empty" DA (empty signature OID causes error), so the tag retains optional,omitempty; required semantics are enforced in ParseAIC/BuildAIC.
func ParseAIC ¶
func ParseAIC(cert *x509.Certificate) (*AIC, error)
ParseAIC parses the AIC extension from a certificate. If the certificate does not contain an AIC extension, returns nil (not an error). Per v1.7.1 spec, delegationAuthorization is required; missing returns an error.
func (*AIC) CheckPermission ¶
CheckPermission checks whether an agent certificate has a specified permission (matched by CapabilityId).
func (*AIC) Config ¶
Config reconstructs an AICConfig from a parsed AIC so that an AIC-bearing certificate can be re-issued with the same authorization constraints (L14: cmdReSign previously dropped the AIC when re-signing).
func (*AIC) HasProtocol ¶
HasProtocol checks whether an agent has a protocol capability with the specified SchemeId.
func (*AIC) IntersectPermissions ¶
IntersectPermissions returns the intersection of CapabilityId list with user permissions.
type AICConfig ¶
type AICConfig struct {
AgentId string
PrincipalUid PrincipalUid
DelegationMode DelegationMode
Capabilities []Capability
AuthorizationConstraints []Capability
DelegationAuthorization *DelegationAuthorization
Version int
}
AICConfig is the configuration needed to issue the AIC extension. BuildAIC uses required fields to construct the ASN.1 extension. Version is the DA / AIC envelope version:
- 0 (unspecified): BuildAIC applies the current default — version 2 with agent SPKI binding (agentKeyBinding must be populated before calling).
- 1: legacy v1 (no agentKeyBinding).
- 2: explicit v2.
- Any other value: BuildAIC rejects.
type AggregatorConfig ¶
type AggregatorConfig struct {
Window time.Duration // Time window (default 200ms)
BatchMax int // Maximum batch size (default 1000)
AutoSwitchAt int // Queue depth threshold for auto-switching to aggregation mode (default 50)
BufferSize int // Pending issuance queue capacity (default 10000)
}
AggregatorConfig is the aggregator configuration.
func DefaultAggregatorConfig ¶
func DefaultAggregatorConfig() AggregatorConfig
DefaultAggregatorConfig returns the default configuration.
type AggregatorError ¶
type AggregatorError struct {
// contains filtered or unexported fields
}
func (*AggregatorError) Error ¶
func (e *AggregatorError) Error() string
type AggregatorReq ¶
type AggregatorReq struct {
CN string
Profile string
KeyType string
CAName string
SAN string
Result chan *AggregatorResult // Result channel
}
AggregatorReq is a single issuance request in the aggregator.
type AggregatorResult ¶
type AggregatorResult struct {
Serial string
Cert *x509.Certificate
Err error
}
AggregatorResult is the issuance result.
type AlgorithmIdentifier ¶
type AlgorithmIdentifier struct {
Algorithm asn1.ObjectIdentifier
Parameters asn1.RawValue `asn1:"optional"`
}
AlgorithmIdentifier is the ASN.1 algorithm identifier (I-D §6 AlgorithmIdentifier).
type ArchivePolicy ¶
type ArchivePolicy struct {
Enabled bool `json:"enabled"`
RetentionDays int `json:"retention_days"` // archive certs after N days from expiry/revocation
ExcludeCAs []string `json:"exclude_cas,omitempty"`
IncludeCA string `json:"include_ca,omitempty"`
ArchiveExpired bool `json:"archive_expired"`
ArchiveRevoked bool `json:"archive_revoked"`
}
type ArchiveResult ¶
type ArchiveResult struct {
Archived int `json:"archived"`
ExpiredCount int `json:"expired_count"`
RevokedCount int `json:"revoked_count"`
}
func ArchiveCerts ¶
func ArchiveCerts(database *db.DB, policy *ArchivePolicy) (*ArchiveResult, error)
type AutoRenewCallback ¶
type AutoRenewPolicy ¶
type AutoRenewPolicy struct {
Enabled bool `json:"enabled"`
Interval time.Duration `json:"interval"`
WindowDays int `json:"window_days"`
DefaultValidity int `json:"default_validity_days"`
Profiles []string `json:"profiles,omitempty"` // only auto-renew these profiles (empty = all)
ExcludeCAs []string `json:"exclude_cas,omitempty"` // skip these CAs
NotifyOnly bool `json:"notify_only"` // dry-run: notify but don't renew
MaxRenewals int `json:"max_renewals"` // max per run (0 = unlimited)
}
type AutoRenewResult ¶
type AutoRenewResult struct {
Serial string `json:"serial"`
CAName string `json:"ca_name"`
CommonName string `json:"common_name"`
OldNotAfter string `json:"old_not_after"`
NewSerial string `json:"new_serial,omitempty"`
Action string `json:"action"` // renewed, skipped, error, notify
Error string `json:"error,omitempty"`
}
func AutoRenew ¶
func AutoRenew(database *db.DB, policy *AutoRenewPolicy, renewFn AutoRenewCallback, notifyFn func(event, caName, serial, cn, msg string)) []AutoRenewResult
type CRLConfig ¶
type CRLConfig struct {
DB *db.DB
CACert *x509.Certificate
CAKey crypto.Signer
CAName string
ValidityDays int
ThisUpdate time.Time
LastThisUpdate time.Time // previous thisUpdate to guarantee monotonicity against clock rollback
LastCRLNumber *big.Int // cRLNumber of the base CRL (for Delta CRL's Base CRL Number extension)
Partition int // 0-based partition index. -1 means all (generate full CRL)
TotalPartitions int // total partition count. 0 or 1 = no partitioning
// RevokedEntriesSource overrides the revoked-entries read path. When nil
// (CLI/init-full) the DB is used directly. When set (serve layer with the
// memory engine enabled) the engine is authoritative; revoked cross-cert
// entries are always read from the DB as the engine does not index them.
RevokedEntriesSource RevokedEntriesSource
// NumberStore persists the last CRL number per CA (H12 fix). When nil the
// in-memory counter is used and monotonicity is only guaranteed within a
// single process lifetime.
NumberStore CRLNumberStore
}
type CRLNumberStore ¶
type CRLNumberStore interface {
GetLastCRLNumber(caName string) (int64, error)
SetLastCRLNumber(caName string, number int64) error
}
CRLNumberStore persists the last used CRL number per CA so the counter can be re-seeded at startup, preserving RFC 5280 §5.2.4 monotonicity across restarts (H12 fix). When set on CRLConfig, generateCRL raises the in-memory counter to the persisted value before incrementing and records the new number after each successful generation.
type Capability ¶
type Capability struct {
SchemeId string `json:"scheme_id,omitempty" asn1:"utf8"`
CapabilityId string `json:"capability_id,omitempty" asn1:"utf8"`
Parameters []byte `json:"parameters,omitempty" asn1:"optional,omitempty,contextspecific,explicit,tag:0"`
}
Capability is the protocol-level capability container — Varwof only defines the container structure, not specific semantics. schemeId identifies the capability scheme (e.g. "varwof-gateway-v1"), capabilityId is the specific capability under that scheme, parameters are encoded as declared by schemeId.
Encoding specification (consistent with types Capability.FullID()): capabilityId is a pure action identifier (without scheme prefix), full permission identifier = schemeId + ":" + capabilityId, uniformly generated by FullID(); all matching/intersection/authorization decisions must be based on the full identifier.
func (Capability) FullID ¶
func (c Capability) FullID() string
FullID returns the full capability identifier (schemeId:capacityId), semantically identical to types Capability.FullID(). When schemeId is empty, it degrades to capabilityId (compatible with generic capabilities without a scheme).
type CertAggregator ¶
type CertAggregator struct {
// contains filtered or unexported fields
}
CertAggregator is the certificate issuance aggregator. Issues instantly under low load, automatically switches to time-window batch issuance under high load.
func NewCertAggregator ¶
func NewCertAggregator(cfg AggregatorConfig, signer CertSigner) *CertAggregator
NewCertAggregator creates an aggregator and starts the background processing goroutine.
func (*CertAggregator) Close ¶
func (a *CertAggregator) Close()
Close closes the aggregator and waits for all pending requests to complete.
func (*CertAggregator) Request ¶
func (a *CertAggregator) Request(req *AggregatorReq) *AggregatorResult
Request submits an issuance request. Under low load, issues instantly and returns directly; under high load, enqueues for batch processing.
type CertBufferItem ¶
type CertBufferItem struct {
Record *db.CertRecord
Key crypto.Signer
}
CertBufferItem is a single record pending persistence in the memory buffer.
type CertSigner ¶
type CertSigner interface {
SignBatch(items []*AggregatorReq, caName string) []*AggregatorResult
}
CertSigner is the signing interface called by the aggregator.
type CertSource ¶
type CertSource interface {
// FindCA returns every configured CA certificate (ca_meta) whose Subject
// matches the given issuer, plus the trust anchors. Implementations may
// return nil slices for either group.
FindIssuerCandidates(issuerRaw string) ([]*x509.Certificate, error)
// TrustAnchors returns the set of trusted root certificates.
TrustAnchors() ([]*x509.Certificate, error)
}
CertSource supplies certificates for path building. Both *db.DB and a test stub implement it.
type ColdBackupEnvelope ¶
type ColdBackupEnvelope struct {
Version int `json:"version"`
CAName string `json:"ca_name"`
CreatedAt string `json:"created_at"`
CertPEM string `json:"cert_pem"`
EncryptedKey string `json:"encrypted_key"` // base64(PBES2 DER)
CertSHA256 string `json:"cert_sha256"` // hex
KeyFP string `json:"key_fingerprint"` // hex SHA-256 of public key
MAC string `json:"mac"` // base64(HMAC-SHA256 over canonical fields)
MACSalt string `json:"mac_salt,omitempty"` // base64(16B salt), M11+
MACIterations int `json:"mac_iterations,omitempty"` // PBKDF2 iterations, M11+
}
ColdBackupEnvelope is the on-disk format for an offline Root CA cold backup. The private key is encrypted with PBES2 (AES-256-CBC, see pbes2.go) and the whole envelope carries an HMAC so tampering or a wrong password is detected before any secret key material is processed.
type CreateConfig ¶
type CreateConfig struct {
DB *db.DB
Name string
SubjectName string // optional, overrides Name as CN
Profile Profile
Parent *x509.Certificate
ParentKey crypto.Signer
KeyType string
ReuseKey crypto.Signer
Validity time.Duration
CRLBaseURL string
PermittedDomains []string
ExcludedDomains []string
PermittedEmails []string
ExcludedEmails []string
PermittedURIs []string
ExcludedURIs []string
PermittedIPRanges []string
ExcludedIPRanges []string
DefaultCountry string
DefaultOrg string
MaxPathLen int // override profile default (0 = use profile default)
OCSPURL string
IssuerURL string
}
type CreateResult ¶
type CreateResult struct {
Cert *x509.Certificate
CertDER []byte
Signer crypto.Signer
SerialHex string
}
func CreateCA ¶
func CreateCA(cfg *CreateConfig) (*CreateResult, error)
type DBSource ¶
DBSource adapts *db.DB to CertSource.
func (*DBSource) FindIssuerCandidates ¶
func (s *DBSource) FindIssuerCandidates(issuerRaw string) ([]*x509.Certificate, error)
func (*DBSource) TrustAnchors ¶
func (s *DBSource) TrustAnchors() ([]*x509.Certificate, error)
type DelegationAuthorization ¶
type DelegationAuthorization struct {
Reason Reason `asn1:""`
RequestedLifetime int `asn1:"default:0"`
Timestamp time.Time `asn1:"generalized"`
Nonce []byte `asn1:"octet"` // 32-byte random number, anti-replay (REQUIRED)
SignatureAlgorithm AlgorithmIdentifier `asn1:""`
SignatureValue []byte `asn1:"octet"`
}
DelegationAuthorization is the cryptographic evidence of user authorization (v1.7.1 spec §DelegationAuthorization). Field order (consistent with types): reason → requestedLifetime → timestamp → nonce → signatureAlgorithm → signatureValue. reason is required (authorization must have a reason). User certificate is located via PrincipalUid.KeyHash (SPKI SHA-256), no longer storing UserCertHash separately.
type DelegationMode ¶
type DelegationMode int
DelegationMode defines the Agent's delegation mode.
const ( DelegationAuthorized DelegationMode = 0 // Authorized delegation (Agent acts on behalf of user) DelegationRepresentative DelegationMode = 1 // Full representation (Agent fully represents user) )
type DelegationModeEnum ¶
type DelegationModeEnum int
DelegationModeEnum defines the delegation mode enumeration (draft-02 §8 DelegationModeEnum).
const ( DelegationModeAuthorizedOnly DelegationModeEnum = 0 DelegationModeRepresentativeAllowed DelegationModeEnum = 1 )
type DelegationPolicy ¶
type DelegationPolicy struct {
Version int `json:"version,omitempty" asn1:"default:1"`
MaxAgents int `json:"max_agents,omitempty" asn1:"default:1"`
AllowedMode int `json:"allowed_mode,omitempty" asn1:"enum,default:0"`
MaxSessionHours int `json:"max_session_hours,omitempty" asn1:"optional,omitempty,explicit,tag:0"`
}
DelegationPolicy controls how a principal delegates permissions to an Agent (v1.7.1 spec §DelegationPolicy).
type DeltaCRLConfig ¶
type DeltaCRLConfig struct {
// Since is the base CRL thisUpdate; only certificates revoked at or after
// this time are included in the delta.
Since time.Time
// BaseCRLNumber is the cRLNumber of the base CRL the delta applies to
// (encoded in the Base CRL Number extension, 2.5.29.31).
BaseCRLNumber *big.Int
}
DeltaCRLConfig carries Delta CRL parameters.
type ExtField ¶
type ExtField struct {
ExtnID asn1.ObjectIdentifier `asn1:"objectidentifier"`
Critical bool `asn1:"default:false"`
ExtnValue []byte `asn1:"octet"`
}
ExtField is a single extension field in the AIC internal extension slot. Vendors can use their own IANA PEN OIDs, users can use the Varwof-reserved .1.1.5.x space.
type IdentitySource ¶
type IdentitySource interface {
Lookup(ctx context.Context, source, username string) (*UserIdentity, error)
}
IdentitySource resolves a person's identity attributes from a directory service (LDAP/AD via bridge-ldap, or OAuth/OIDC via bridge-oauth) for automated certificate issuance.
Lookup resolves the identity for a username. The caller supplies the source_tag to route to a specific bridge backend; empty tries all backends in bridge configuration order.
func NewIdentitySource ¶
func NewIdentitySource(cfg *IdentitySourceConfig) (IdentitySource, error)
NewIdentitySource builds an IdentitySource from config. It returns an error for an unknown type or an empty bridge URL.
type IdentitySourceConfig ¶
type IdentitySourceConfig struct {
// Type is the identity source kind: "ldap" (bridge-ldap) or "oauth" (bridge-oauth). Default "ldap".
Type IdentitySourceType `json:"type,omitempty"`
// SourceURL is the base URL of the identity bridge service, e.g. "http://127.0.0.1:8082".
SourceURL string `json:"source_url,omitempty"`
// Token is the bridge management API bearer token. Empty = no auth.
Token string `json:"token,omitempty"`
// Source is the default source_tag used when a request does not specify one.
Source string `json:"source,omitempty"`
// Username is the automation account username (oauth type only, resource-owner grant).
Username string `json:"username,omitempty"`
// Password is the automation account password (oauth type only, resource-owner grant).
Password string `json:"password,omitempty"`
// TimeoutSec bounds each upstream bridge request. Default 10.
TimeoutSec int `json:"timeout_sec,omitempty"`
// OUFromGroups maps identity-source groups to certificate OU values
// (RBAC roles). Matching is exact OR case-insensitive suffix containment
// of the OU-portion of an LDAP group DN. When no rule matches, DefaultOU
// (or the source dept) is used.
OUFromGroups map[string]string `json:"ou_from_groups,omitempty"`
// DefaultOU is the OU written when no OUFromGroups rule matches and the
// source carries no dept. Empty = omit OU.
DefaultOU string `json:"default_ou,omitempty"`
// DisabledOK allows issuing identity-user certs for disabled accounts.
// Default false: disabled accounts are rejected (fail-closed).
DisabledOK bool `json:"disabled_ok,omitempty"`
}
IdentitySourceConfig configures the remote identity source used for the identity-user profile. See docs/api.md for the full field reference.
func (*IdentitySourceConfig) CertificateOUS ¶
func (c *IdentitySourceConfig) CertificateOUS(id *UserIdentity) []string
CertificateOUS from identity attributes applies the OUFromGroups mapping, falling back to DefaultOU or the source dept. Returns the OU list to embed in the certificate subject.
type IdentitySourceType ¶
type IdentitySourceType string
IdentitySourceType enumerates supported identity-source kinds.
const ( // IdentitySourceLDAP resolves persons via bridge-ldap's POST /api/v1/lookup. IdentitySourceLDAP IdentitySourceType = "ldap" // IdentitySourceOAuth resolves persons via bridge-oauth's password grant + // userinfo flow (service account). The configured username/password belong // to an automation account authorized in the IdP. IdentitySourceOAuth IdentitySourceType = "oauth" )
type ImportTrustResult ¶
func ImportTrustBundle ¶
type IssueResult ¶
type IssueResult struct {
Cert *x509.Certificate
Record *db.CertRecord
Key crypto.Signer
}
IssueResult is the result of a single certificate issuance.
func IssueAndBuffer ¶
func IssueAndBuffer(signerCfg *SignConfig, buffer *MemoryBuffer) (*IssueResult, error)
IssueAndBuffer issues a certificate and adds it to the memory buffer.
type JWTSignOptions ¶
type JWTSignOptions struct {
// Audience is the aud claim (REQUIRED by draft). Empty → defaults to
// "varwof-core" (the core issuer's own audience).
Audience []string
// Issuer overrides the iss claim. Empty → "varwof-core".
Issuer string
// TokenType overrides the default typ (aic+jwt). Kept for extensibility.
TokenType string
// Scope is an optional OAuth scope string mirroring the AIC capabilities
// (informational; capabilities remain the authority).
Scope string
// StatusListURI, when set, adds a status claim (RFC 9457 status list
// reference) pointing to the core revocation status list endpoint.
StatusListURI string
// StatusListIndex is the index within the status list.
StatusListIndex int
// DA is an optional inner DA JWS (typ aic+da+jwt, signed by the principal
// key). Authorized mode omits it (lifetime-bounded lightweight profile);
// representative mode REQUIRES it. When set, it is embedded in the outer
// "da" claim.
DA string
}
JWTSignOptions controls AIC-JWT issuance on top of SignConfig.
type Job ¶
type Job struct {
ID string `json:"id"`
Status JobStatus `json:"status"`
Progress int `json:"progress"` // completed count
Total int `json:"total"` // total count
CreatedAt time.Time `json:"created_at"`
Error string `json:"error,omitempty"`
Results []JobResultItem `json:"results,omitempty"`
// contains filtered or unexported fields
}
Job stores the complete state of an async job.
type JobProcessor ¶
type JobProcessor interface {
Process(items []JobRequestItem) []JobResultItem
}
JobProcessor is the actual issuance interface.
type JobQueue ¶
type JobQueue struct {
// contains filtered or unexported fields
}
JobQueue is an async job queue.
func NewJobQueue ¶
func NewJobQueue(workers int, ttl time.Duration, processor JobProcessor) *JobQueue
NewJobQueue creates an async job queue and starts background workers.
func (*JobQueue) Submit ¶
func (q *JobQueue) Submit(items []JobRequestItem) string
Submit submits an async issuance job and returns the job ID.
type JobRequest ¶
type JobRequest struct {
Items []JobRequestItem `json:"requests"`
}
JobRequest represents a single async issuance job.
type JobRequestItem ¶
type JobRequestItem struct {
CN string `json:"cn"`
SAN string `json:"san,omitempty"`
Profile string `json:"profile,omitempty"`
KeyType string `json:"key_type,omitempty"`
CA string `json:"ca,omitempty"`
}
JobRequestItem represents a single certificate issuance request.
type JobResultItem ¶
type JobResultItem struct {
Serial string `json:"serial,omitempty"`
CN string `json:"cn"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
}
JobResultItem represents a single certificate issuance result.
type LDAPConfig ¶
type LDAPConfig struct {
URL string `json:"url,omitempty"`
BindDN string `json:"bind_dn,omitempty"`
BindPassword string `json:"bind_password,omitempty"`
BaseDN string `json:"base_dn,omitempty"`
Filter string `json:"filter,omitempty"`
UIDAttr string `json:"uid_attr,omitempty"`
MapCN string `json:"map_cn,omitempty"`
MapOrg string `json:"map_o,omitempty"`
MapOU string `json:"map_ou,omitempty"`
MapL string `json:"map_l,omitempty"`
MapST string `json:"map_st,omitempty"`
MapC string `json:"map_c,omitempty"`
MapEmail string `json:"map_email,omitempty"`
}
type LDAPLookup ¶
type LDAPLookup interface {
Lookup(cfg *LDAPConfig, username string) (*pkix.Name, error)
CheckMembership(cfg *LDAPConfig, username, groupDN string) (bool, error)
}
LDAPLookup is the interface for directory service lookups. The default implementation uses go-ldap directly; a satellite (ldap-bridge) can provide a remote implementation over HTTP.
func NewDefaultLDAPLookup ¶
func NewDefaultLDAPLookup() LDAPLookup
type MemoryBuffer ¶
type MemoryBuffer struct {
// contains filtered or unexported fields
}
MemoryBuffer is a high-speed memory buffer for certificate issuance. It accumulates certificate records pending persistence and triggers batch writes to the external DB periodically or on count threshold.
func NewMemoryBuffer ¶
func NewMemoryBuffer(extDB *db.DB, cfg PersistConfig) (*MemoryBuffer, error)
NewMemoryBuffer creates a memory buffer and starts the background persistence goroutine.
func (*MemoryBuffer) Add ¶
func (b *MemoryBuffer) Add(item *CertBufferItem) error
Add adds a certificate record to the buffer. In realtime mode, writes directly to the external DB; in batch/async mode, writes to the in-memory queue.
func (*MemoryBuffer) Close ¶
func (b *MemoryBuffer) Close() error
Close closes the buffer, flushes all pending data, and releases resources.
func (*MemoryBuffer) Flush ¶
func (b *MemoryBuffer) Flush() error
Flush batch writes all pending persistence records from the buffer to the external DB.
func (*MemoryBuffer) Size ¶
func (b *MemoryBuffer) Size() int
Size returns the number of records currently pending persistence.
type NameConstraints ¶
type NonceStorer ¶
NonceStorer abstracts nonce persistence for one-time-use enforcement. Implemented by db.DB via StoreNonce/ConsumeNonce.
type OfflineSignConfig ¶
type OfflineSignConfig struct {
CACert *x509.Certificate
CAKey crypto.Signer
CSR *x509.CertificateRequest
Validity time.Duration
Hash string // sha256, sha384, sha512
PathLen int // 0 = sub-ca, 1+ = intermediate, -1 = no constraint
}
type PathVerificationResult ¶
type PathVerificationResult struct {
// Valid is true when every x509-level check (signature, validity, KU,
// basic constraints) passed.
Valid bool `json:"valid"`
// Chain is the ordered path leaf → root (length ≥ 1).
Chain []*x509.Certificate `json:"-"`
// RootIsTrusted is true when the path terminates in a trust anchor.
RootIsTrusted bool `json:"root_is_trusted"`
// Policy is the policy-processing outcome (nil when Valid is false or no
// policy processing was requested).
Policy *PolicyDecision `json:"policy,omitempty"`
// RejectReason describes why the path was rejected (empty when Valid).
RejectReason string `json:"reject_reason,omitempty"`
}
PathVerificationResult is the full output of VerifyPath.
func VerifyPath ¶
func VerifyPath(chain []*x509.Certificate, src CertSource, opts VerifyPathOptions) (*PathVerificationResult, error)
VerifyPath verifies a pre-built path (or builds one when src is non-nil):
- signature and validity on every hop (x509-level)
- trust anchor termination
- optional RFC 5280 §6.1 policy processing
When src is nil and chain is provided, only signature/validity + policy checks are run (no trust-anchor check beyond the caller's responsibility).
type PersistConfig ¶
type PersistConfig struct {
Mode PersistMode
BatchSize int // Batch trigger count (default 100)
BatchInterval time.Duration // Timer trigger interval (default 5 seconds)
QueueSize int // Queue capacity limit (default 10000)
}
PersistConfig is the runtime persistence configuration.
func DefaultPersistConfig ¶
func DefaultPersistConfig() PersistConfig
DefaultPersistConfig returns the default persistence configuration (realtime mode, compatible with existing behavior).
type PersistMode ¶
type PersistMode int
PersistMode defines the persistence mode after certificate issuance.
const ( PersistRealtime PersistMode = iota // Realtime persistence: write to external DB immediately after each issuance PersistBatch // Batch persistence: accumulate N records then batch write PersistAsync // Async persistence: write only to memory buffer, background async persistence )
func ParsePersistConfig ¶
func ParsePersistConfig(mode string) PersistMode
ParsePersistConfig parses the persistence mode from a configuration string.
type PolicyDecision ¶
type PolicyDecision struct {
// AcceptedUserPolicies is the non-empty intersection of the final policy
// set and the requester's user-initial-policy-set. When the requester
// accepted anyPolicy (empty user set), AcceptedUserPolicies lists the
// valid policies actually matched.
AcceptedUserPolicies []string
// MappedPolicies lists the effective policy mappings applied along the
// path (issuerDomainPolicy → subjectDomainPolicy at each mapping CA).
MappedPolicies []PolicyMappingApplied
// InhibitAnyPolicyHit is true when anyPolicy was suppressed by an
// inhibitAnyPolicy constraint along the path.
InhibitAnyPolicyHit bool
// ExplicitPolicyRequired is true when a requireExplicitPolicy constraint
// was in force at the leaf.
ExplicitPolicyRequired bool
// ValidPolicyTree describes, per depth, the valid policies at that
// certificate. Depth 0 is the leaf.
ValidPolicyTree []ValidPolicyNode
}
PolicyDecision is the outcome of RFC 5280 §6.1 policy processing over a verified chain.
func EvaluatePolicy ¶
func EvaluatePolicy(chain []*x509.Certificate, opts VerifyPathOptions) (*PolicyDecision, error)
EvaluatePolicy performs RFC 5280 §6.1 policy processing over an already structurally-valid path (chain[0] = leaf, ascending). It returns the policy decision, or an error when the path is malformed.
The walk implements, for each certificate depth i (leaf = 0):
- decrement anyPolicy/explicitPolicy/inhibitAnyPolicy counters
- apply policy mappings (2.5.29.33) of intermediate CAs
- intersect/accumulate the valid policy set
- honor requireExplicitPolicy, inhibitPolicyMapping, inhibitAnyPolicy
The final valid policy set is intersected with the user-initial-policy-set (empty = accept any). A non-empty intersection means the policy is accepted.
type PolicyMapping ¶
type PolicyMapping struct {
IssuerDomainPolicy string // Issuer domain policy OID (e.g. "2.5.29.32.0")
SubjectDomainPolicy string // Subject domain policy OID
}
PolicyMapping represents a single mapping in the RFC 5280 §4.2.1.5 Policy Mappings extension: issuerDomainPolicy maps to subjectDomainPolicy. Allowed only in CA certificates.
func ParsePolicyMapping ¶
func ParsePolicyMapping(s string) (PolicyMapping, error)
ParsePolicyMapping parses an "issuerDomainPolicy:subjectDomainPolicy" string into a PolicyMapping (for reuse by API/CLI layers).
func ParsePolicyMappings ¶
func ParsePolicyMappings(strs []string) ([]PolicyMapping, error)
ParsePolicyMappings batch-parses a list of strings ("issuer:subject" format) into []PolicyMapping; any invalid item causes the entire operation to fail.
type PolicyMappingApplied ¶
type PolicyRule ¶
type PolicyRule struct {
Comment string `json:"comment,omitempty"`
AllowedCNs []string `json:"allowed_cns,omitempty"`
DeniedCNs []string `json:"denied_cns,omitempty"`
AllowedSANs []string `json:"allowed_sans,omitempty"`
DeniedSANs []string `json:"denied_sans,omitempty"`
AllowedProfiles []string `json:"allowed_profiles,omitempty"`
AllowedKeyTypes []string `json:"allowed_key_types,omitempty"`
AllowedCAs []string `json:"allowed_cas,omitempty"`
MaxValidityDays int `json:"max_validity_days,omitempty"`
}
type PrincipalAuthorization ¶
type PrincipalAuthorization struct {
Version int `asn1:"default:1"`
Grants []Capability `asn1:"optional,omitempty"`
AuthorizationConstraints []Capability `asn1:"optional,omitempty,contextspecific,explicit,tag:0"`
DelegationPolicy DelegationPolicy `asn1:"optional,explicit,tag:1"`
Extensions []ExtField `asn1:"optional,omitempty,contextspecific,explicit,tag:2"`
}
PrincipalAuthorization corresponds to the subject authorization statement in X.509v3 extensions (OID 1.3.6.1.4.1.66257.1.2). ASN.1 (v1.7.1): version, grants, authorizationConstraints [0], delegationPolicy [1], extensions [2].
func ParsePrincipalAuthorizationExtension ¶
func ParsePrincipalAuthorizationExtension(exts []pkix.Extension) (*PrincipalAuthorization, error)
ParsePrincipalAuthorizationExtension parses the PrincipalAuthorization extension from the certificate extension list.
func (*PrincipalAuthorization) AllowsRepresentative ¶
func (pa *PrincipalAuthorization) AllowsRepresentative() bool
AllowsRepresentative checks whether the PrincipalAuthorization allows representative delegation.
func (*PrincipalAuthorization) GrantIds ¶
func (pa *PrincipalAuthorization) GrantIds() []string
GrantIds returns the full permission identifiers (scheme:capabilityId) for all Grants. Aligned with types Capability.FullID() spec: matching/authorization decisions use the full identifier.
func (*PrincipalAuthorization) PermIds ¶
func (pa *PrincipalAuthorization) PermIds() []string
PermIds is an alias for GrantIds, maintaining backward compatibility (legacy API callers).
type PrincipalAuthorizationConfig ¶
type PrincipalAuthorizationConfig struct {
Grants []Capability `json:"grants,omitempty"`
// AuthorizationConstraints is the principal's operational boundary — the
// time window / network / parameter limits that every delegation from this
// principal inherits. It is set when the *user* certificate is issued and
// is the source of truth the DA and AIC copy from; an agent can only
// narrow it, never widen it.
AuthorizationConstraints []Capability `json:"authorization_constraints,omitempty"`
DelegationPolicy *DelegationPolicy `json:"delegation_policy,omitempty"`
}
PrincipalAuthorizationConfig is the configuration needed to issue a PrincipalAuthorization extension.
type PrincipalUid ¶
type PrincipalUid struct {
Version int `asn1:"default:1"`
Realm string `asn1:"utf8"`
Identifier string `asn1:"utf8"`
KeyHash []byte `asn1:"octet"`
HashAlgo AlgorithmIdentifier `asn1:"optional,omitempty,explicit,tag:0"`
}
PrincipalUid is the structured ASN.1 type for principal identity (spec §3.2). ASN.1 SEQUENCE: { version INTEGER { v1(1) }, realm UTF8String, identifier UTF8String,
keyHash OCTET STRING (SIZE(1..64)), hashAlgo [0] EXPLICIT AlgorithmIdentifier OPTIONAL }
keyHash = hashAlgo(SPKI); hashAlgo defaults to SHA-256 when omitted. Communication format: {realm}:{identifier}:{keyFingerprint} (keyFingerprint is base64url encoded)
func MakePrincipalUidFromCert ¶
func MakePrincipalUidFromCert(realm, identifier string, cert *x509.Certificate) PrincipalUid
MakePrincipalUidFromCert constructs a PrincipalUid from a certificate (KeyHash = SPKI SHA-256, used for CA issuance).
func ParsePrincipalUid ¶
func ParsePrincipalUid(s string) (PrincipalUid, error)
ParsePrincipalUid parses a communication-format PrincipalUid string.
func (PrincipalUid) HashAlgoOID ¶
func (pu PrincipalUid) HashAlgoOID() asn1.ObjectIdentifier
HashAlgoOID returns the actually effective hash algorithm OID (empty → default SHA-256).
func (PrincipalUid) String ¶
func (pu PrincipalUid) String() string
String returns the communication format {realm}:{identifier}:{keyFingerprint} (spec §3.2).
type Profile ¶
type Profile string
const ( ProfileRootCA Profile = "root-ca" ProfileSubCA Profile = "sub-ca" ProfilePolicyCA Profile = "policy-ca" ProfileTLSServer Profile = "tls-server" ProfileTLSClient Profile = "tls-client" ProfileOCSPSigner Profile = "ocsp-signer" ProfileTimestamp Profile = "timestamp" ProfileCodeSigning Profile = "codesigning" ProfileEmail Profile = "email" ProfileDocument Profile = "document" ProfileAgentProxy Profile = "agent-proxy" ProfileCMP Profile = "cmp" // ProfileIdentityUser is a person's base identity certificate issued // automatically from a directory/identity source (bridge-ldap lookup or // bridge-oauth userinfo). CN/OU/email are filled from the identity source; // used by the serve layer with IdentitySourceConfig. ProfileIdentityUser Profile = "identity-user" // VPN certificate templates: used for mTLS-based VPN channels such as WireGuard/OpenVPN. // vpn-client is ClientAuth only (client certificate); vpn-server includes ServerAuth+ClientAuth // (server certificate, also allows client-side verification for mutual authentication). ProfileVPNClient Profile = "vpn-client" ProfileVPNServer Profile = "vpn-server" // Management certificate templates (m-*): built-in PKI management role certificate presets. // Automatically sets OU + ClientAuth EKU + DigitalSignature KU; // at issuance, only profile and CN need to be specified, no need to manually pass OU. ProfileMSuperAdmin Profile = "m-superadmin" ProfileMAdmin Profile = "m-admin" ProfileMOperator Profile = "m-operator" ProfileMRevoker Profile = "m-revoker" ProfileMAuditor Profile = "m-auditor" ProfileMReadonly Profile = "m-readonly" ProfileMConsole Profile = "m-console" ProfileMAutoRenew Profile = "m-auto-renew" ProfileMReporter Profile = "m-reporter" )
type Reason ¶
Reason is the reason description for delegation authorization (v1.7.1 spec §Reason), for audit/display only, not participating in permission decisions. Both fields are required: reasonCode 1..64, description 1..512.
type RenewalToken ¶
type RenewalToken struct {
Version int `asn1:"default:1"`
PrincipalUid PrincipalUid `asn1:"optional,contextspecific,tag:0"`
OldCertSerial []byte `asn1:"octet"`
NewKeyHash []byte `asn1:"octet"`
Timestamp time.Time `asn1:"generalized"`
Nonce []byte `asn1:"octet"` // SIZE(16)
ValidityPeriod int `asn1:"default:300"`
}
RenewalToken is the ASN.1 structure for automatic renewal tokens (I-D §6). 7 fields: version, principalUid, oldCertSerial, newKeyHash, timestamp, nonce, validityPeriod.
type RenewalTokenExt ¶
type RenewalTokenExt struct {
Version int `asn1:"default:1"`
PrincipalUid PrincipalUid `asn1:"optional,contextspecific,tag:0"`
OldCertSerial []byte `asn1:"octet"`
NewKeyHash []byte `asn1:"octet"`
Timestamp time.Time `asn1:"generalized"`
Nonce []byte `asn1:"octet"` // SIZE(16)
ValidityPeriod int `asn1:"default:300"`
}
RenewalTokenExt is the ASN.1 serialization structure for RenewalToken (used for DER encoding). Identical to RenewalToken (no CertificateIssuerName or other contextual fields).
func ParseRenewalToken ¶
func ParseRenewalToken(cert *pkix.Extension) (*RenewalTokenExt, error)
ParseRenewalToken parses a RenewalToken from a certificate extension.
func (*RenewalTokenExt) IsExpired ¶
func (r *RenewalTokenExt) IsExpired() bool
IsExpired checks whether the RenewalToken has expired (5-minute validity period).
func (*RenewalTokenExt) ValidateConstraints ¶
func (r *RenewalTokenExt) ValidateConstraints() error
ValidateConstraints validates RenewalToken constraints (spec §6).
func (*RenewalTokenExt) VerifyNonce ¶
func (r *RenewalTokenExt) VerifyNonce() bool
VerifyNonce verifies that the nonce length is 16 bytes (spec §6: SIZE(16)).
type RevokedEntriesSinceSource ¶
type RevokedEntriesSinceSource interface {
GetRevokedCertEntriesSince(caName string, since time.Time) ([]*db.RevokedCertEntry, error)
}
RevokedEntriesSinceSource is implemented by sources that support Delta CRL queries (revoked at/after a base thisUpdate). Both *db.DB and *engine.Engine satisfy it.
type RevokedEntriesSource ¶
type RevokedEntriesSource interface {
GetRevokedCertEntries(caName string) ([]*db.RevokedCertEntry, error)
}
RevokedEntriesSource supplies the revoked-certificate entries a CRL is built from. Both *db.DB and *engine.Engine satisfy it; when the resident memory engine is enabled CRL generation should prefer it (memory-authoritative reads, zero SQL, immediate visibility of revocations), falling back to the DB when the engine is not configured.
type RotatingSigner ¶
type RotatingSigner struct {
// contains filtered or unexported fields
}
RotatingSigner provides atomic hot-swap of the active CA signing key with a legacy key retained during the transition window.
func NewRotatingSigner ¶
func NewRotatingSigner(cert *x509.Certificate, key crypto.Signer) *RotatingSigner
NewRotatingSigner wraps a signer key as the initial active key.
func (*RotatingSigner) Active ¶
func (rs *RotatingSigner) Active() *SignerKey
Active returns the current active cert+key, or nil.
func (*RotatingSigner) Cert ¶
func (rs *RotatingSigner) Cert() *x509.Certificate
Cert returns the active certificate. Safe to call on nil receiver (nil).
func (*RotatingSigner) ClearLegacy ¶
func (rs *RotatingSigner) ClearLegacy()
ClearLegacy drops the retained legacy key, ending the transition window.
func (*RotatingSigner) Key ¶
func (rs *RotatingSigner) Key() crypto.Signer
Key returns the active signing key.
func (*RotatingSigner) Legacy ¶
func (rs *RotatingSigner) Legacy() *SignerKey
Legacy returns the retained legacy cert+key during the transition window, or nil.
func (*RotatingSigner) NeedsRotation ¶
func (rs *RotatingSigner) NeedsRotation(window time.Duration) bool
NeedsRotation reports whether the active CA certificate expires within the window (or is already expired).
func (*RotatingSigner) NotAfter ¶
func (rs *RotatingSigner) NotAfter() time.Time
NotAfter returns the active certificate's NotAfter (zero time if none).
func (*RotatingSigner) Public ¶
func (rs *RotatingSigner) Public() crypto.PublicKey
Public implements crypto.Signer.
func (*RotatingSigner) Rotate ¶
func (rs *RotatingSigner) Rotate(cert *x509.Certificate, key crypto.Signer)
Rotate is an alias for Store with clearer semantics: the previous active key becomes legacy, the new one becomes active.
func (*RotatingSigner) Sign ¶
func (rs *RotatingSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
Sign implements crypto.Signer, delegating to the active key.
func (*RotatingSigner) Store ¶
func (rs *RotatingSigner) Store(cert *x509.Certificate, key crypto.Signer)
Store atomically installs a new active cert+key, promoting the previous active key to legacy (dual-signing transition window).
type SignCSRCallback ¶
type SignConfig ¶
type SignConfig struct {
DB *db.DB
SkipDB bool // true = issue only, no DB write (high-throughput batch mode, caller responsible for persistence)
CAKey crypto.Signer
CACert *x509.Certificate
CAName string
SubjectPubKey any
Profile Profile
CommonName string
Subject *pkix.Name
SANs []string
CAScope []string
KeyType string
Hash string
CRLBaseURL string
OCSPURL string
IssuerURL string
Validity time.Duration
DefaultCountry string
DefaultOrg string
IssuerAltNames []string
SubjectInfoAccess []string
PolicyOIDs []string
// PolicyMappings is the RFC 5280 §4.2.1.5 Policy Mappings extension,
// each item maps issuerDomainPolicy to subjectDomainPolicy, allowed only in CA certificates
// (enterprise bridge / cross-domain trust scenarios).
PolicyMappings []PolicyMapping
// RequireExplicitPolicy is the RFC 5280 §4.2.1.11 Policy Constraints
// requireExplicitPolicy (skipCerts count). nil means this field is not generated.
RequireExplicitPolicy *int
// InhibitPolicyMapping is the RFC 5280 §4.2.1.11 Policy Constraints
// inhibitPolicyMapping (skipCerts count). nil means this field is not generated.
InhibitPolicyMapping *int
// InhibitAnyPolicy is the RFC 5280 §4.2.1.14 Inhibit anyPolicy extension's skipCerts
// count (0 means anyPolicy is prohibited on this certificate chain). nil means this extension is not generated.
InhibitAnyPolicy *int
DedupCN bool
MaxPathLen int
ExtraEKUOIDs []string
MustStaple bool
CRLPartitions int
NotBefore *time.Time
NotAfter *time.Time
PermittedDomains []string
ExcludedDomains []string
PermittedEmails []string
ExcludedEmails []string
PermittedURIs []string
ExcludedURIs []string
PermittedIPRanges []string
ExcludedIPRanges []string
Policy *Policy
PolicyFile string
// RequirePolicy (M4 fix): when true and no issuance policy is loaded, Sign()
// rejects issuance instead of warn-and-continue. The serve layer derives it
// from config enforce_policy. Library consumers may set it explicitly.
RequirePolicy bool
// RequireTLSServerSAN (F11 fix): when true, a TLS-server certificate with
// no subjectAltName (RFC 5280 §4.1.2.6 / RFC 6125) is rejected at issuance
// instead of warn-and-continue. Mirrors RequirePolicy so strict deployments
// can opt in without breaking existing CN-only issuance.
RequireTLSServerSAN bool
AIC *AICConfig // Agent Identity Certificate configuration
// SPIFFEID, when set, is placed in the certificate SAN URIs (RFC 7555
// spiffe:// URI) as the workload's SPIFFE identity. It is kept distinct from
// AIC.AgentId so the AIC extension can carry the plain agent name (matching
// the DA-authorized identity) while the SPIFFE ID lives only in the SAN —
// this is what the validating side (gateway) actually enforces on.
SPIFFEID string
PrincipalAuthorization *PrincipalAuthorizationConfig // user authorization
Scope string // admin scope: which CAs this admin can manage (comma-separated)
// MaxAgentProxyValidity is the hard upper bound for agent-proxy (authorized mode)
// certificate validity. 0 uses DefaultAgentProxyMaxValidity (1h); spec P1-B-09/25 and
// P2-A-04's "authorized certificate validity ≤24h" semantics — default 1h, can be relaxed
// up to ≤24h via configuration.
MaxAgentProxyValidity time.Duration
// ValidateCapabilities is an optional AIC capability registration validation hook.
// Injected by the upper layer (serve layer): passes the full identifiers of capabilities
// declared in the AIC ("scheme:capability_id" list) to the register capability registry
// for validation; returns an error if issuance should fail. nil means skip this validation
// (capability registration validation not enabled, backward compatible).
ValidateCapabilities func(caps []string) error
// UserCert is the DA signer (user) certificate whose SPKI hash must match
// AIC.PrincipalUid.KeyHash. When set (and AIC is non-nil), Sign() verifies
// the DelegationAuthorization signature at the library layer (M5 fix) — so
// library consumers cannot mint AIC certificates carrying unverified DA
// evidence.
UserCert *x509.Certificate
// DelegationAlreadyVerified asserts that the caller has already verified
// the DelegationAuthorization signature by other means. It is required when
// AIC carries a DelegationAuthorization but UserCert is nil: without either,
// Sign() refuses rather than minting a certificate whose delegation was
// never verified. Set it only where verification genuinely happened
// elsewhere (the serve /api/aic/issue path verifies the client's signed
// message itself) or where the DA carries no principal signature to verify
// (OAuth re-issuance, lab fixtures).
DelegationAlreadyVerified bool
// ConsumeDANonce is an optional anti-replay hook called once with the DA nonce
// after DA signature verification passes. Injected by the serve layer (engine or
// DB store); library consumers that need replay protection may supply their own.
// nil skips nonce consumption (no persistence → replayable).
ConsumeDANonce func(nonce []byte) error
}
func (*SignConfig) MaxAgentProxyValidityLimit ¶
func (sc *SignConfig) MaxAgentProxyValidityLimit() time.Duration
MaxAgentProxyValidityLimit returns the effective agent-proxy validity upper bound. M2 fix: any positive configured value is capped at the spec ceiling (24h); 0/negative falls back to the 1h default.
type SignJWTResult ¶
type SignJWTResult struct {
Token string // JWS compact serialization
Header aicjwt.Header
Claims aicjwt.OuterClaims
Principal PrincipalUid
AgentID string
CA *x509.Certificate
Alg string
}
SignJWTResult is the output of SignJWT.
func SignJWT ¶
func SignJWT(sc *SignConfig, opts JWTSignOptions) (*SignJWTResult, error)
SignJWT issues an AIC-JWT. It performs all AIC issuance validations shared with Sign(): required AIC/PA/DA checks, capability registration, PA−cap coverage, and — like Sign — the DA nonce consumption hook. It does NOT touch the database or build an X.509 certificate.
type SignResult ¶
type SignResult struct {
Cert *x509.Certificate
CertDER []byte
SerialHex string
PrivateKey crypto.Signer
// Record is the DB record for this certificate. In SkipDB mode, the database is not
// written; the caller is responsible for persistence (e.g. via RecordBuffer batch
// persistence); also populated in synchronous write mode.
Record *db.CertRecord
}
func CrossSign ¶
func CrossSign(d *db.DB, issuerCert *x509.Certificate, issuerKey crypto.Signer, issuerName string, targetCAMeta *db.CAMeta, validity time.Duration, nc *NameConstraints) (*SignResult, error)
func Sign ¶
func Sign(sc *SignConfig) (*SignResult, error)
type SignerKey ¶
type SignerKey struct {
Cert *x509.Certificate
Key crypto.Signer
}
SignerKey is a CA certificate + its private key.
type StaticSource ¶
type StaticSource struct {
CAs []*x509.Certificate
Roots []*x509.Certificate
}
StaticSource is an in-memory CertSource (test-friendly).
func (*StaticSource) FindIssuerCandidates ¶
func (s *StaticSource) FindIssuerCandidates(issuerRaw string) ([]*x509.Certificate, error)
func (*StaticSource) TrustAnchors ¶
func (s *StaticSource) TrustAnchors() ([]*x509.Certificate, error)
type SubCAConfig ¶
type SubCAConfig struct {
Name string // Unique name for the sub-CA
ParentCA string // Parent CA name (issuing CA)
KeyType string // Key type (ecdsa-p256, ecdsa-p384, rsa-2048, etc.)
Validity time.Duration // Certificate validity period
MaxPathLen int // Path length constraint (0 for end-entity only)
KeyUsage []string // Key usage extensions
Protocol string // Protocol identifier (scep, cmp, acme, est)
PermittedDomains []string // Name constraints: permitted domains
ExcludedDomains []string // Name constraints: excluded domains
CRLBaseURL string // Base URL for the CRL Distribution Point extension
}
SubCAConfig holds configuration for creating a new sub-CA.
type SubCAMeta ¶
type SubCAMeta struct {
ID int64
Name string
ParentCA string
Cert *x509.Certificate
CertDER []byte
KeyEncrypted []byte
Subject string
NotBefore time.Time
NotAfter time.Time
KeyAlgorithm string
Fingerprint string
Status string
Protocol string
KeyUsage string
MaxPathLen int
CreatedAt time.Time
RevokedAt *time.Time
RevokeReason *int
}
SubCAMeta holds metadata for an existing sub-CA.
func ListSubCAs ¶
ListSubCAs returns all sub-CAs, optionally filtered by protocol.
type SubCAResult ¶
type SubCAResult struct {
Name string
Cert *x509.Certificate
CertDER []byte
CertPEM []byte
Key crypto.Signer
KeyPEM []byte
SerialHex string
Fingerprint string
}
SubCAResult holds the result of sub-CA creation.
func IssueSubCA ¶
func IssueSubCA(database *db.DB, cfg *SubCAConfig, parentCert *x509.Certificate, parentKey crypto.Signer) (*SubCAResult, error)
IssueSubCA creates a new sub-CA certificate signed by the parent CA.
type TrustBridgeConfig ¶
type TrustBridgeConfig struct {
Bridges []TrustBridgePolicy `json:"bridges,omitempty"`
}
type TrustBridgePolicy ¶
type UserIdentity ¶
type UserIdentity struct {
Username string `json:"username"`
FullName string `json:"full_name,omitempty"`
Email string `json:"email,omitempty"`
Dept string `json:"dept,omitempty"`
Groups []string `json:"groups,omitempty"`
Source string `json:"source,omitempty"`
Disabled bool `json:"disabled"`
}
UserIdentity is the unified person identity model resolved from an identity source (bridge-ldap lookup or bridge-oauth userinfo). Phase 2 of identity-source unification: core maps these attributes into a base identity certificate ("identity-user" profile) without manual subject entry.
type ValidPolicyNode ¶
type VerifyPathOptions ¶
type VerifyPathOptions struct {
// UserInitialPolicySet is the set of acceptable certificate policies.
// An empty set means "any policy is acceptable" (RFC 5280 §6.1.1 empty
// user-initial-policy-set).
UserInitialPolicySet []string
// PolicyOID strings are parsed once; pass the ASN.1 OIDs to avoid
// re-parsing.
UserInitialPolicyOIDs []asn1ObjectIdentifier
// VerifyPolicy enables RFC 5280 §6.1 policy processing. When false, only
// structural validation (signatures, validity, trust) is performed.
VerifyPolicy bool
// CurrentTime overrides the "now" used for validity checks (default: now).
CurrentTime time.Time
// MaxDepth bounds chain length to protect against certificate loops.
// Default 16 (RFC 5280 recommends ≤ 8 for normal PKIs, but bridge CA
// chains can be longer).
MaxDepth int
}
VerifyPathOptions controls path verification.
type VerifyResult ¶
type VerifyResult struct {
Valid bool `json:"valid"`
Chain []ChainNode `json:"chain,omitempty"`
Verified bool `json:"verified"`
RootTrustSource string `json:"root_trust_source,omitempty"`
}
func VerifyCertificate ¶
func VerifyCertificate(cert *x509.Certificate, roots *x509.CertPool, sources map[string]string) (*VerifyResult, error)
Source Files
¶
- aggregator.go
- aic.go
- archive.go
- autorenew.go
- buffer.go
- certfields.go
- coldbackup.go
- create.go
- crl.go
- cross.go
- ct.go
- delegation_auth_verify.go
- encrypt.go
- escrow.go
- gmsm_stub.go
- identity.go
- import_ca.go
- jobqueue.go
- jwks.go
- jwtissue.go
- keyrotation.go
- ldap.go
- ldap_config.go
- oid.go
- pathval.go
- pbes2.go
- policy.go
- principal_auth.go
- ra.go
- renewal_token.go
- revoke.go
- sign.go
- sign_parameter.go
- sub.go
- trust.go
- trustbridge.go
- verify.go