Documentation
¶
Overview ¶
Package authority implements an in-process Certification Authority.
LoadConfig reads issuers and certificate profiles from YAML or JSON, NewAuthority builds Issuer objects whose signers come from cryptoprov and whose chains are verified with certutil, and Issuer.Sign issues X.509 certificates from PEM CSRs according to a named profile. Issuers also sign OCSP responses (directly or through a delegated responder) and NewRoot bootstraps a self-signed root.
Index ¶
- Constants
- Variables
- func NewRoot(profile string, cfg *Config, provider cryptoprov.Provider, ...) (certPEM, csrPEM, key []byte, err error)
- func OCSPReasonStringToCode(reason string) (reasonCode int, err error)
- type AIAConfig
- type Authority
- func (s *Authority) AddIssuer(issuer *Issuer) error
- func (s *Authority) AddProfile(label string, p *CertProfile)
- func (s *Authority) Crypto() *cryptoprov.Crypto
- func (s *Authority) GetIssuerByKeyHash(alg crypto.Hash, val []byte) (*Issuer, error)
- func (s *Authority) GetIssuerByKeyID(ikid string) (*Issuer, error)
- func (s *Authority) GetIssuerByLabel(label string) (*Issuer, error)
- func (s *Authority) GetIssuerByNameHash(alg crypto.Hash, val []byte) (*Issuer, error)
- func (s *Authority) GetIssuerByProfile(profile string) (*Issuer, error)
- func (s *Authority) Issuers() []*Issuer
- func (s *Authority) Profile(label string) *CertProfile
- func (s *Authority) Profiles() map[string]*CertProfile
- type CAConfig
- type CAConstraint
- type CertProfile
- func (p *CertProfile) AllowedExtensionsStrings() []string
- func (p *CertProfile) Copy() *CertProfile
- func (p *CertProfile) FindExtension(oid asn1.ObjectIdentifier) *csr.X509Extension
- func (p *CertProfile) IsAllowed(role string) bool
- func (p *CertProfile) IsAllowedExtention(oid csr.OID) bool
- func (p *CertProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk []string)
- func (p *CertProfile) Validate() error
- type Config
- type Issuer
- func (ca *Issuer) AddProfile(label string, p *CertProfile)
- func (ca *Issuer) AiaURL() string
- func (ca *Issuer) Bundle() *certutil.Bundle
- func (ca *Issuer) CreateDelegatedOCSPSigner() (*OCSPResponder, error)
- func (ca *Issuer) CrlExpiry() time.Duration
- func (ca *Issuer) CrlRenewal() time.Duration
- func (ca *Issuer) CrlURL() string
- func (ca *Issuer) GenCert(crypto cryptoprov.Provider, req *csr.CertificateRequest, ...) (*x509.Certificate, []byte, error)
- func (ca *Issuer) KeyHash(h crypto.Hash) []byte
- func (ca *Issuer) Label() string
- func (ca *Issuer) NameHash(h crypto.Hash) []byte
- func (ca *Issuer) OcspExpiry() time.Duration
- func (ca *Issuer) OcspURL() string
- func (ca *Issuer) PEM() string
- func (ca *Issuer) Profile(name string) *CertProfile
- func (ca *Issuer) Profiles() map[string]*CertProfile
- func (ca *Issuer) Sign(raReq csr.SignRequest) (*x509.Certificate, []byte, error)
- func (ca *Issuer) SignOCSP(req *OCSPSignRequest) ([]byte, error)
- func (ca *Issuer) SignProof(data []byte) (string, error)
- func (ca *Issuer) Signer() crypto.Signer
- func (ca *Issuer) SubjectKID() string
- func (ca *Issuer) VerifyProof(data []byte, proof string) error
- type IssuerConfig
- type OCSPResponder
- type OCSPSignRequest
Constants ¶
const ( // OCSPStatusGood specifies name for good status OCSPStatusGood = "good" // OCSPStatusRevoked specifies name for revoked status OCSPStatusRevoked = "revoked" // OCSPStatusUnknown specifies name for unknown status OCSPStatusUnknown = "unknown" )
Variables ¶
var ( // DefaultCRLRenewal specifies default duration for CRL renewal DefaultCRLRenewal = 12 * time.Hour // 12 hours // DefaultCRLExpiry specifies default duration for CRL expiry DefaultCRLExpiry = 2 * 24 * time.Hour // 2 days // DefaultOCSPExpiry specifies default for OCSP expiry DefaultOCSPExpiry = 8 * time.Hour // 8 hours )
var ( // CTPoisonOID is the object ID of the critical poison extension for precertificates // https://tools.ietf.org/html/rfc6962#page-9 CTPoisonOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} // SCTListOID is the object ID for the Signed Certificate Timestamp certificate extension // https://tools.ietf.org/html/rfc6962#page-14 SCTListOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} )
var OCSPStatusCode = map[string]int{ OCSPStatusGood: ocsp.Good, OCSPStatusRevoked: ocsp.Revoked, OCSPStatusUnknown: ocsp.Unknown, }
OCSPStatusCode is a map between string statuses sent by cli/api to ocsp int statuses
Functions ¶
func NewRoot ¶
func NewRoot(profile string, cfg *Config, provider cryptoprov.Provider, req *csr.CertificateRequest) (certPEM, csrPEM, key []byte, err error)
NewRoot creates a new root certificate from the certificate request.
func OCSPReasonStringToCode ¶
OCSPReasonStringToCode tries to convert a reason string to an integer code
Types ¶
type AIAConfig ¶
type AIAConfig struct {
// AiaURL specifies a template for AIA URL.
// The ${ISSUER_ID} variable will be replaced with a Subject Key Identifier of the issuer.
AiaURL string `json:"issuer_url" yaml:"issuer_url"`
// OcspURL specifies a template for OCSP URL.
// The ${ISSUER_ID} variable will be replaced with a Subject Key Identifier of the issuer.
OcspURL string `json:"ocsp_url" yaml:"ocsp_url"`
// DefaultOcspURL specifies a template for CRL URL.
// The ${ISSUER_ID} variable will be replaced with a Subject Key Identifier of the issuer.
CrlURL string `json:"crl_url" yaml:"crl_url"`
// CRLExpiry specifies value in 72h format for duration of CRL next update time
CRLExpiry time.Duration `json:"crl_expiry,omitempty" yaml:"crl_expiry,omitempty"`
// OCSPExpiry specifies value in 8h format for duration of OCSP next update time
OCSPExpiry time.Duration `json:"ocsp_expiry,omitempty" yaml:"ocsp_expiry,omitempty"`
// CRLRenewal specifies value in 8h format for duration of CRL renewal before next update time
CRLRenewal time.Duration `json:"crl_renewal,omitempty" yaml:"crl_renewal,omitempty"`
// DelegatedOCSPProfile specifies to use delegated OCSP responder
DelegatedOCSPProfile string `json:"delegated_ocsp_profile,omitempty" yaml:"delegated_ocsp_profile,omitempty"`
}
AIAConfig contains AIA configuration info
func (*AIAConfig) GetCRLExpiry ¶
GetCRLExpiry specifies value in 72h format for duration of CRL next update time
func (*AIAConfig) GetCRLRenewal ¶
GetCRLRenewal specifies value in 8h format for duration of CRL renewal before next update time
func (*AIAConfig) GetOCSPExpiry ¶
GetOCSPExpiry specifies value in 8h format for duration of OCSP next update time
type Authority ¶
type Authority struct {
RootBundle []byte
CaBundle []byte
// contains filtered or unexported fields
}
Authority defines the CA: a registry of issuers and of the profiles that are not served by one issuer (wildcard profiles).
An Authority is safe for concurrent use. Lookups read an immutable snapshot of the registry; AddIssuer and AddProfile publish a new snapshot (XPKI-055). Profiles and Issuers return copies that the caller owns. The *CertProfile values are the registered profiles themselves, shared with every reader: a profile belongs to the registry once it is added and must not be modified afterwards; register a Copy to change one.
func NewAuthority ¶
func NewAuthority(cfg *Config, crypto *cryptoprov.Crypto) (*Authority, error)
NewAuthority returns new instance of Authority
func (*Authority) AddIssuer ¶
AddIssuer adds issuer to the Authority and registers its profiles, except the wildcard ones. It is an error, and nothing is added, when an issuer with the same label is registered, when one of the profiles is already registered by an issuer (the error names the profile and that issuer), or when one of the profiles is nil. An issuer with the same subject key id as a registered one replaces it in the key id lookup only.
func (*Authority) AddProfile ¶
func (s *Authority) AddProfile(label string, p *CertProfile)
AddProfile adds or replaces the CertProfile named label. The profile must not be modified after this call.
func (*Authority) Crypto ¶
func (s *Authority) Crypto() *cryptoprov.Crypto
Crypto returns the provider
func (*Authority) GetIssuerByKeyHash ¶
GetIssuerByKeyHash returns matching Issuer by key hash
func (*Authority) GetIssuerByKeyID ¶
GetIssuerByKeyID by IKID
func (*Authority) GetIssuerByLabel ¶
GetIssuerByLabel by label
func (*Authority) GetIssuerByNameHash ¶
GetIssuerByNameHash returns matching Issuer by name hash
func (*Authority) GetIssuerByProfile ¶
GetIssuerByProfile by profile
func (*Authority) Profile ¶ added in v1.0.310
func (s *Authority) Profile(label string) *CertProfile
Profile returns the CertProfile named label, or nil.
func (*Authority) Profiles ¶
func (s *Authority) Profiles() map[string]*CertProfile
Profiles returns a copy of the profiles map. The caller owns the map; the profiles are shared and must not be modified.
type CAConfig ¶
type CAConfig struct {
// Issuers specifies the list of issuing authorities.
Issuers []IssuerConfig `json:"issuers,omitempty" yaml:"issuers,omitempty"`
// RootsBundleFiles specifies locations of the Root bundle files
RootsBundleFiles []string `json:"root_bundles,omitempty" yaml:"root_bundles,omitempty"`
// CABundleFiles specifies locations of the CA bundle files
CABundleFiles []string `json:"ca_bundles,omitempty" yaml:"ca_bundles,omitempty"`
}
CAConfig contains configuration info for CA
type CAConstraint ¶
type CAConstraint struct {
IsCA bool `json:"is_ca" yaml:"is_ca"`
MaxPathLen int `json:"max_path_len" yaml:"max_path_len"`
}
CAConstraint specifies various CA constraints on the signed certificate. CAConstraint would verify against (and override) the CA extensions in the given CSR.
type CertProfile ¶
type CertProfile struct {
IssuerLabel string `json:"issuer_label" yaml:"issuer_label"`
Description string `json:"description" yaml:"description"`
// Usage provides a list key usages
Usage []string `json:"usages" yaml:"usages"`
CAConstraint CAConstraint `json:"ca_constraint" yaml:"ca_constraint"`
OCSPNoCheck bool `json:"ocsp_no_check" yaml:"ocsp_no_check"`
Expiry csr.Duration `json:"expiry" yaml:"expiry"`
Backdate csr.Duration `json:"backdate" yaml:"backdate"`
// Extensions are added to every certificate issued with the profile.
// They take precedence over request and CSR extensions with the same OID.
Extensions []csr.X509Extension `json:"extensions" yaml:"extensions"`
// AllowedExtensions lists extension OIDs that a request may supply.
// For SignRequest.Extensions (trusted RA) an empty list allows all.
// For CSR extensions (untrusted) an empty list allows none, and key
// usages, SAN, basic constraints, key identifiers and OCSP no-check
// are never taken from a CSR (XPKI-049). A CSR AIA or CRL DP is
// ignored when the issuer generates its own.
AllowedExtensions []csr.OID `json:"allowed_extensions" yaml:"allowed_extensions"`
// AllowedNames specifies a RegExp to check for allowed names.
// If not provided, then all values are allowed
AllowedNames string `json:"allowed_names" yaml:"allowed_names"`
// AllowedDNS specifies a RegExp to check for allowed DNS.
// If not provided, then all values are allowed
AllowedDNS string `json:"allowed_dns" yaml:"allowed_dns"`
// AllowedEmail specifies a RegExp to check for allowed email.
// If not provided, then all values are allowed
AllowedEmail string `json:"allowed_email" yaml:"allowed_email"`
// AllowedURI specifies a RegExp to check for allowed URI.
// If not provided, then all values are allowed
AllowedURI string `json:"allowed_uri" yaml:"allowed_uri"`
// AllowedFields provides booleans for fields in the CSR.
// If a AllowedFields is not present in a CertProfile,
// all of these fields may be copied from the CSR into the signed certificate.
// CSR extensions are governed by AllowedExtensions, never by this list.
// If a AllowedFields *is* present in a CertProfile,
// only those fields with a `true` value in the AllowedFields may
// be copied from the CSR to the signed certificate.
// Note that some of these fields, like Subject, can be provided or
// partially provided through the API.
// Since API clients are expected to be trusted, but CSRs are not, fields
// provided through the API are not subject to validation through this
// mechanism.
AllowedCSRFields *csr.AllowedFields `json:"allowed_fields" yaml:"allowed_fields"`
Policies []csr.CertificatePolicy `json:"policies" yaml:"policies"`
// PoliciesCritical specifies to mark Policies as Critical extension
PoliciesCritical bool `json:"policies_critical" yaml:"policies_critical"`
AllowedRoles []string `json:"allowed_roles" yaml:"allowed_roles"`
DeniedRoles []string `json:"denied_roles" yaml:"denied_roles"`
AllowedNamesRegex *regexp.Regexp `json:"-" yaml:"-"`
AllowedDNSRegex *regexp.Regexp `json:"-" yaml:"-"`
AllowedEmailRegex *regexp.Regexp `json:"-" yaml:"-"`
AllowedURIRegex *regexp.Regexp `json:"-" yaml:"-"`
}
CertProfile provides certificate profile
func (*CertProfile) AllowedExtensionsStrings ¶
func (p *CertProfile) AllowedExtensionsStrings() []string
AllowedExtensionsStrings returns slice of strings
func (*CertProfile) FindExtension ¶ added in v0.2.0
func (p *CertProfile) FindExtension(oid asn1.ObjectIdentifier) *csr.X509Extension
FindExtension returns extension, or nil
func (*CertProfile) IsAllowed ¶
func (p *CertProfile) IsAllowed(role string) bool
IsAllowed returns true, if a role is allowed to request this profile
func (*CertProfile) IsAllowedExtention ¶
func (p *CertProfile) IsAllowedExtention(oid csr.OID) bool
IsAllowedExtention returns true if a SignRequest may supply the extension. An empty AllowedExtensions allows every extension from the trusted RA.
func (*CertProfile) Usages ¶
func (p *CertProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk []string)
Usages parses the list of key uses in the profile, translating them to a list of X.509 key usages and extended key usages. The unknown uses are collected into a slice that is also returned.
func (*CertProfile) Validate ¶
func (p *CertProfile) Validate() error
Validate returns an error if the profile is invalid
type Config ¶
type Config struct {
Authority *CAConfig `json:"authority,omitempty" yaml:"authority,omitempty"`
Profiles map[string]*CertProfile `json:"profiles" yaml:"profiles"`
}
Config provides configuration for Certification Authority
func LoadConfig ¶
LoadConfig loads the configuration file stored at the path and returns the configuration.
func (*Config) DefaultCertProfile ¶
func (c *Config) DefaultCertProfile() *CertProfile
DefaultCertProfile returns default CertProfile
type Issuer ¶
type Issuer struct {
// contains filtered or unexported fields
}
Issuer of certificates
func CreateIssuer ¶
func CreateIssuer(cfg *IssuerConfig, certBytes, intCAbytes, rootBytes []byte, signer crypto.Signer) (*Issuer, error)
CreateIssuer returns Issuer created directly from crypto.Signer, this method is mostly used for testing
func NewIssuer ¶
func NewIssuer(cfg *IssuerConfig, prov *cryptoprov.Crypto) (*Issuer, error)
NewIssuer creates Issuer from provided configuration
func NewIssuerWithBundles ¶
func NewIssuerWithBundles(cfg *IssuerConfig, prov *cryptoprov.Crypto, caPem, rootPem []byte) (*Issuer, error)
NewIssuerWithBundles creates Issuer from provided configuration
func (*Issuer) AddProfile ¶
func (ca *Issuer) AddProfile(label string, p *CertProfile)
AddProfile adds or replaces the CertProfile named label. The profile must not be modified after this call. Replacing the delegated_ocsp_profile takes effect at the next responder renewal, which fails if the new profile is not valid for delegation.
func (*Issuer) CreateDelegatedOCSPSigner ¶ added in v0.3.0
func (ca *Issuer) CreateDelegatedOCSPSigner() (*OCSPResponder, error)
CreateDelegatedOCSPSigner returns the responder that signs OCSP responses. Without a delegated_ocsp_profile it returns the CA key and certificate. Otherwise it returns the cached delegated responder, first issuing a new one when the cached one expires within the OCSP expiry interval, and waiting for a renewal in progress. While renewal is due and the last attempt failed, it returns that error, even if the cached responder is still valid (SignOCSP keeps using a valid cached responder instead); a new attempt is made at most every ocspRenewRetryInterval. It is safe for concurrent use.
func (*Issuer) CrlRenewal ¶
CrlRenewal is duration for CRL renewal interval
func (*Issuer) GenCert ¶ added in v0.3.0
func (ca *Issuer) GenCert(crypto cryptoprov.Provider, req *csr.CertificateRequest, profile, certFile, keyFile string) (*x509.Certificate, []byte, error)
GenCert creates certificate and stores key and certs to specified location
func (*Issuer) OcspExpiry ¶
OcspExpiry is duration for OCSP next update interval
func (*Issuer) Profile ¶
func (ca *Issuer) Profile(name string) *CertProfile
Profile returns CertProfile
func (*Issuer) Profiles ¶
func (ca *Issuer) Profiles() map[string]*CertProfile
Profiles returns a copy of the CertProfiles map. The caller owns the map; the profiles are shared with the issuer and must not be modified (XPKI-055).
func (*Issuer) Sign ¶
func (ca *Issuer) Sign(raReq csr.SignRequest) (*x509.Certificate, []byte, error)
Sign signs a new certificate based on the PEM-encoded certificate request with the specified profile.
func (*Issuer) SignOCSP ¶
func (ca *Issuer) SignOCSP(req *OCSPSignRequest) ([]byte, error)
SignOCSP return an OCSP response.
type IssuerConfig ¶
type IssuerConfig struct {
// Disabled specifies if the certificate disabled to use
Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty"`
// Label specifies Issuer's label
Label string `json:"label,omitempty" yaml:"label,omitempty"`
// Type specifies type: tls|codesign|timestamp|ocsp|spiffe|trusty
Type string `json:"type,omitempty" yaml:"type,omitempty"`
// CertFile specifies location of the cert
CertFile string `json:"cert,omitempty" yaml:"cert,omitempty"`
// KeyFile specifies location of the key
KeyFile string `json:"key,omitempty" yaml:"key,omitempty"`
// CABundleFile specifies location of the CA bundle file
CABundleFile string `json:"ca_bundle,omitempty" yaml:"ca_bundle,omitempty"`
// RootBundleFile specifies location of the Root CA file
RootBundleFile string `json:"root_bundle,omitempty" yaml:"root_bundle,omitempty"`
// OmitDisabledExtensions specifies to not fail a request,
// but omit not allowed extensions
OmitDisabledExtensions bool `json:"omit_disabled_extensions,omitempty" yaml:"omit_disabled_extensions,omitempty"`
// AIA specifies AIA configuration
AIA *AIAConfig `json:"aia,omitempty" yaml:"aia,omitempty"`
// AllowedProfiles, if populated, restricts the issuer to the listed
// profiles, both issuer-specific and wildcard (`issuer_label: "*"`)
// ones. If empty, the issuer gets its issuer-specific profiles and no
// wildcard profiles (XPKI-057).
AllowedProfiles []string `json:"allowed_profiles" yaml:"allowed_profiles"`
// Profiles are populated after loading
Profiles map[string]*CertProfile `json:"-" yaml:"-"`
}
IssuerConfig contains configuration info for the issuing certificate
func (*IssuerConfig) GetDisabled ¶
func (c *IssuerConfig) GetDisabled() bool
GetDisabled specifies if the certificate disabled to use
type OCSPResponder ¶ added in v0.3.0
type OCSPResponder struct {
Signer crypto.Signer
Cert *x509.Certificate
}
OCSPResponder is a key and certificate that sign OCSP responses for an Issuer: either the CA itself or a delegated OCSP signing certificate. It is shared between callers and must not be modified.
type OCSPSignRequest ¶
type OCSPSignRequest struct {
SerialNumber *big.Int
Status string
Reason int
RevokedAt time.Time
Extensions []pkix.Extension
// IssuerHash is the hashing function used to hash the issuer subject and public key
// in the OCSP response. Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384,
// and crypto.SHA512. If zero, the default is crypto.SHA1.
IssuerHash crypto.Hash
// If provided ThisUpdate will override the default usage of time.Now().Truncate(time.Hour)
ThisUpdate *time.Time
// If provided NextUpdate will override the default usage of ThisUpdate.Add(signerInterval)
NextUpdate *time.Time
}
OCSPSignRequest represents the desired contents of a specific OCSP response.