123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- // Package config contains the configuration logic for CFSSL.
- package config
- import (
- "crypto/tls"
- "crypto/x509"
- "encoding/asn1"
- "encoding/json"
- "errors"
- "fmt"
- "os"
- "regexp"
- "strconv"
- "strings"
- "time"
- "github.com/cloudflare/cfssl/auth"
- cferr "github.com/cloudflare/cfssl/errors"
- "github.com/cloudflare/cfssl/helpers"
- "github.com/cloudflare/cfssl/log"
- ocspConfig "github.com/cloudflare/cfssl/ocsp/config"
- // empty import of zlint/v3 required to have lints registered.
- _ "github.com/zmap/zlint/v3"
- "github.com/zmap/zlint/v3/lint"
- )
- // A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is
- // not present in a SigningProfile, all of these fields may be copied from the
- // CSR into the signed certificate. If a CSRWhitelist *is* present in a
- // SigningProfile, only those fields with a `true` value in the CSRWhitelist 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 whitelisting through this
- // mechanism.
- type CSRWhitelist struct {
- Subject, PublicKeyAlgorithm, PublicKey, SignatureAlgorithm bool
- DNSNames, IPAddresses, EmailAddresses, URIs bool
- }
- // OID is our own version of asn1's ObjectIdentifier, so we can define a custom
- // JSON marshal / unmarshal.
- type OID asn1.ObjectIdentifier
- // CertificatePolicy represents the ASN.1 PolicyInformation structure from
- // https://tools.ietf.org/html/rfc3280.html#page-106.
- // Valid values of Type are "id-qt-unotice" and "id-qt-cps"
- type CertificatePolicy struct {
- ID OID
- Qualifiers []CertificatePolicyQualifier
- }
- // CertificatePolicyQualifier represents a single qualifier from an ASN.1
- // PolicyInformation structure.
- type CertificatePolicyQualifier struct {
- Type string
- Value string
- }
- // AuthRemote is an authenticated remote signer.
- type AuthRemote struct {
- RemoteName string `json:"remote"`
- AuthKeyName string `json:"auth_key"`
- }
- // CAConstraint specifies various CA constraints on the signed certificate.
- // CAConstraint would verify against (and override) the CA
- // extensions in the given CSR.
- type CAConstraint struct {
- IsCA bool `json:"is_ca"`
- MaxPathLen int `json:"max_path_len"`
- MaxPathLenZero bool `json:"max_path_len_zero"`
- }
- // A SigningProfile stores information that the CA needs to store
- // signature policy.
- type SigningProfile struct {
- Usage []string `json:"usages"`
- IssuerURL []string `json:"issuer_urls"`
- OCSP string `json:"ocsp_url"`
- CRL string `json:"crl_url"`
- CAConstraint CAConstraint `json:"ca_constraint"`
- OCSPNoCheck bool `json:"ocsp_no_check"`
- ExpiryString string `json:"expiry"`
- BackdateString string `json:"backdate"`
- AuthKeyName string `json:"auth_key"`
- CopyExtensions bool `json:"copy_extensions"`
- PrevAuthKeyName string `json:"prev_auth_key"` // to support key rotation
- RemoteName string `json:"remote"`
- NotBefore time.Time `json:"not_before"`
- NotAfter time.Time `json:"not_after"`
- NameWhitelistString string `json:"name_whitelist"`
- AuthRemote AuthRemote `json:"auth_remote"`
- CTLogServers []string `json:"ct_log_servers"`
- AllowedExtensions []OID `json:"allowed_extensions"`
- CertStore string `json:"cert_store"`
- // LintErrLevel controls preissuance linting for the signing profile.
- // 0 = no linting is performed [default]
- // 2..3 = reserved
- // 3 = all lint results except pass are considered errors
- // 4 = all lint results except pass and notice are considered errors
- // 5 = all lint results except pass, notice and warn are considered errors
- // 6 = all lint results except pass, notice, warn and error are considered errors.
- // 7 = lint is performed, no lint results are treated as errors.
- LintErrLevel lint.LintStatus `json:"lint_error_level"`
- // ExcludeLints lists ZLint lint names to exclude from preissuance linting.
- ExcludeLints []string `json:"ignored_lints"`
- // ExcludeLintSources lists ZLint lint sources to exclude from preissuance
- // linting.
- ExcludeLintSources []string `json:"ignored_lint_sources"`
- Policies []CertificatePolicy
- Expiry time.Duration
- Backdate time.Duration
- Provider auth.Provider
- PrevProvider auth.Provider // to suppport key rotation
- RemoteProvider auth.Provider
- RemoteServer string
- RemoteCAs *x509.CertPool
- ClientCert *tls.Certificate
- CSRWhitelist *CSRWhitelist
- NameWhitelist *regexp.Regexp
- ExtensionWhitelist map[string]bool
- ClientProvidesSerialNumbers bool
- // LintRegistry is the collection of lints that should be used if
- // LintErrLevel is configured. By default all ZLint lints are used. If
- // ExcludeLints or ExcludeLintSources are set then this registry will be
- // filtered in populate() to exclude the named lints and lint sources.
- LintRegistry lint.Registry
- }
- // UnmarshalJSON unmarshals a JSON string into an OID.
- func (oid *OID) UnmarshalJSON(data []byte) (err error) {
- if data[0] != '"' || data[len(data)-1] != '"' {
- return errors.New("OID JSON string not wrapped in quotes." + string(data))
- }
- data = data[1 : len(data)-1]
- parsedOid, err := parseObjectIdentifier(string(data))
- if err != nil {
- return err
- }
- *oid = OID(parsedOid)
- return
- }
- // MarshalJSON marshals an oid into a JSON string.
- func (oid OID) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"%v"`, asn1.ObjectIdentifier(oid))), nil
- }
- func parseObjectIdentifier(oidString string) (oid asn1.ObjectIdentifier, err error) {
- validOID, err := regexp.MatchString("\\d(\\.\\d+)*", oidString)
- if err != nil {
- return
- }
- if !validOID {
- err = errors.New("Invalid OID")
- return
- }
- segments := strings.Split(oidString, ".")
- oid = make(asn1.ObjectIdentifier, len(segments))
- for i, intString := range segments {
- oid[i], err = strconv.Atoi(intString)
- if err != nil {
- return
- }
- }
- return
- }
- const timeFormat = "2006-01-02T15:04:05"
- // populate is used to fill in the fields that are not in JSON
- //
- // First, the ExpiryString parameter is needed to parse
- // expiration timestamps from JSON. The JSON decoder is not able to
- // decode a string time duration to a time.Duration, so this is called
- // when loading the configuration to properly parse and fill out the
- // Expiry parameter.
- // This function is also used to create references to the auth key
- // and default remote for the profile.
- // It returns true if ExpiryString is a valid representation of a
- // time.Duration, and the AuthKeyString and RemoteName point to
- // valid objects. It returns false otherwise.
- func (p *SigningProfile) populate(cfg *Config) error {
- if p == nil {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("can't parse nil profile"))
- }
- var err error
- if p.RemoteName == "" && p.AuthRemote.RemoteName == "" {
- log.Debugf("parse expiry in profile")
- if p.ExpiryString == "" {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("empty expiry string"))
- }
- dur, err := time.ParseDuration(p.ExpiryString)
- if err != nil {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
- }
- log.Debugf("expiry is valid")
- p.Expiry = dur
- if p.BackdateString != "" {
- dur, err = time.ParseDuration(p.BackdateString)
- if err != nil {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
- }
- p.Backdate = dur
- }
- if !p.NotBefore.IsZero() && !p.NotAfter.IsZero() && p.NotAfter.Before(p.NotBefore) {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
- }
- if len(p.Policies) > 0 {
- for _, policy := range p.Policies {
- for _, qualifier := range policy.Qualifiers {
- if qualifier.Type != "" && qualifier.Type != "id-qt-unotice" && qualifier.Type != "id-qt-cps" {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("invalid policy qualifier type"))
- }
- }
- }
- }
- } else if p.RemoteName != "" {
- log.Debug("match remote in profile to remotes section")
- if p.AuthRemote.RemoteName != "" {
- log.Error("profile has both a remote and an auth remote specified")
- return cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
- }
- if remote := cfg.Remotes[p.RemoteName]; remote != "" {
- if err := p.updateRemote(remote); err != nil {
- return err
- }
- } else {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to find remote in remotes section"))
- }
- } else {
- log.Debug("match auth remote in profile to remotes section")
- if remote := cfg.Remotes[p.AuthRemote.RemoteName]; remote != "" {
- if err := p.updateRemote(remote); err != nil {
- return err
- }
- } else {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to find remote in remotes section"))
- }
- }
- if p.AuthKeyName != "" {
- log.Debug("match auth key in profile to auth_keys section")
- if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok {
- if key.Type == "standard" {
- p.Provider, err = auth.New(key.Key, nil)
- if err != nil {
- log.Debugf("failed to create new standard auth provider: %v", err)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to create new standard auth provider"))
- }
- } else {
- log.Debugf("unknown authentication type %v", key.Type)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("unknown authentication type"))
- }
- } else {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to find auth_key in auth_keys section"))
- }
- }
- if p.PrevAuthKeyName != "" {
- log.Debug("match previous auth key in profile to auth_keys section")
- if key, ok := cfg.AuthKeys[p.PrevAuthKeyName]; ok {
- if key.Type == "standard" {
- p.PrevProvider, err = auth.New(key.Key, nil)
- if err != nil {
- log.Debugf("failed to create new standard auth provider: %v", err)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to create new standard auth provider"))
- }
- } else {
- log.Debugf("unknown authentication type %v", key.Type)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("unknown authentication type"))
- }
- } else {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to find prev_auth_key in auth_keys section"))
- }
- }
- if p.AuthRemote.AuthKeyName != "" {
- log.Debug("match auth remote key in profile to auth_keys section")
- if key, ok := cfg.AuthKeys[p.AuthRemote.AuthKeyName]; ok {
- if key.Type == "standard" {
- p.RemoteProvider, err = auth.New(key.Key, nil)
- if err != nil {
- log.Debugf("failed to create new standard auth provider: %v", err)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to create new standard auth provider"))
- }
- } else {
- log.Debugf("unknown authentication type %v", key.Type)
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("unknown authentication type"))
- }
- } else {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to find auth_remote's auth_key in auth_keys section"))
- }
- }
- if p.NameWhitelistString != "" {
- log.Debug("compiling whitelist regular expression")
- rule, err := regexp.Compile(p.NameWhitelistString)
- if err != nil {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to compile name whitelist section"))
- }
- p.NameWhitelist = rule
- }
- p.ExtensionWhitelist = map[string]bool{}
- for _, oid := range p.AllowedExtensions {
- p.ExtensionWhitelist[asn1.ObjectIdentifier(oid).String()] = true
- }
- // By default perform any required preissuance linting with all ZLint lints.
- p.LintRegistry = lint.GlobalRegistry()
- // If ExcludeLintSources are present in config build a lint.SourceList while
- // validating that no unknown sources were specified.
- var excludedSources lint.SourceList
- if len(p.ExcludeLintSources) > 0 {
- for _, sourceName := range p.ExcludeLintSources {
- var lintSource lint.LintSource
- lintSource.FromString(sourceName)
- if lintSource == lint.UnknownLintSource {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- fmt.Errorf("failed to build excluded lint source list: unknown source %q",
- sourceName))
- }
- excludedSources = append(excludedSources, lintSource)
- }
- }
- opts := lint.FilterOptions{
- ExcludeNames: p.ExcludeLints,
- ExcludeSources: excludedSources,
- }
- if !opts.Empty() {
- // If ExcludeLints or ExcludeLintSources were not empty then filter out the
- // lints we don't want to use for preissuance linting with this profile.
- filteredRegistry, err := p.LintRegistry.Filter(opts)
- if err != nil {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- fmt.Errorf("failed to build filtered lint registry: %v", err))
- }
- p.LintRegistry = filteredRegistry
- }
- return nil
- }
- // updateRemote takes a signing profile and initializes the remote server object
- // to the hostname:port combination sent by remote.
- func (p *SigningProfile) updateRemote(remote string) error {
- if remote != "" {
- p.RemoteServer = remote
- }
- return nil
- }
- // OverrideRemotes takes a signing configuration and updates the remote server object
- // to the hostname:port combination sent by remote
- func (p *Signing) OverrideRemotes(remote string) error {
- if remote != "" {
- var err error
- for _, profile := range p.Profiles {
- err = profile.updateRemote(remote)
- if err != nil {
- return err
- }
- }
- err = p.Default.updateRemote(remote)
- if err != nil {
- return err
- }
- }
- return nil
- }
- // SetClientCertKeyPairFromFile updates the properties to set client certificates for mutual
- // authenticated TLS remote requests
- func (p *Signing) SetClientCertKeyPairFromFile(certFile string, keyFile string) error {
- if certFile != "" && keyFile != "" {
- cert, err := helpers.LoadClientCertificate(certFile, keyFile)
- if err != nil {
- return err
- }
- for _, profile := range p.Profiles {
- profile.ClientCert = cert
- }
- p.Default.ClientCert = cert
- }
- return nil
- }
- // SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS
- // remote requests
- func (p *Signing) SetRemoteCAsFromFile(caFile string) error {
- if caFile != "" {
- remoteCAs, err := helpers.LoadPEMCertPool(caFile)
- if err != nil {
- return err
- }
- p.SetRemoteCAs(remoteCAs)
- }
- return nil
- }
- // SetRemoteCAs updates the properties to set remote CAs for TLS
- // remote requests
- func (p *Signing) SetRemoteCAs(remoteCAs *x509.CertPool) {
- for _, profile := range p.Profiles {
- profile.RemoteCAs = remoteCAs
- }
- p.Default.RemoteCAs = remoteCAs
- }
- // NeedsRemoteSigner returns true if one of the profiles has a remote set
- func (p *Signing) NeedsRemoteSigner() bool {
- for _, profile := range p.Profiles {
- if profile.RemoteServer != "" {
- return true
- }
- }
- return p.Default.RemoteServer != ""
- }
- // NeedsLocalSigner returns true if one of the profiles doe not have a remote set
- func (p *Signing) NeedsLocalSigner() bool {
- for _, profile := range p.Profiles {
- if profile.RemoteServer == "" {
- return true
- }
- }
- return p.Default.RemoteServer == ""
- }
- // 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 (p *SigningProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk []string) {
- for _, keyUse := range p.Usage {
- if kuse, ok := KeyUsage[keyUse]; ok {
- ku |= kuse
- } else if ekuse, ok := ExtKeyUsage[keyUse]; ok {
- eku = append(eku, ekuse)
- } else {
- unk = append(unk, keyUse)
- }
- }
- return
- }
- // A valid profile must be a valid local profile or a valid remote profile.
- // A valid local profile has defined at least key usages to be used, and a
- // valid local default profile has defined at least a default expiration.
- // A valid remote profile (default or not) has remote signer initialized.
- // In addition, a remote profile must has a valid auth provider if auth
- // key defined. A valid profile must not include a lint_error_level outside of
- // [0,8).
- func (p *SigningProfile) validProfile(isDefault bool) bool {
- if p == nil {
- return false
- }
- if p.AuthRemote.RemoteName == "" && p.AuthRemote.AuthKeyName != "" {
- log.Debugf("invalid auth remote profile: no remote signer specified")
- return false
- }
- if p.RemoteName != "" {
- log.Debugf("validate remote profile")
- if p.RemoteServer == "" {
- log.Debugf("invalid remote profile: no remote signer specified")
- return false
- }
- if p.AuthKeyName != "" && p.Provider == nil {
- log.Debugf("invalid remote profile: auth key name is defined but no auth provider is set")
- return false
- }
- if p.AuthRemote.RemoteName != "" {
- log.Debugf("invalid remote profile: auth remote is also specified")
- return false
- }
- } else if p.AuthRemote.RemoteName != "" {
- log.Debugf("validate auth remote profile")
- if p.RemoteServer == "" {
- log.Debugf("invalid auth remote profile: no remote signer specified")
- return false
- }
- if p.AuthRemote.AuthKeyName == "" || p.RemoteProvider == nil {
- log.Debugf("invalid auth remote profile: no auth key is defined")
- return false
- }
- } else {
- log.Debugf("validate local profile")
- if !isDefault {
- if len(p.Usage) == 0 {
- log.Debugf("invalid local profile: no usages specified")
- return false
- } else if _, _, unk := p.Usages(); len(unk) == len(p.Usage) {
- log.Debugf("invalid local profile: no valid usages")
- return false
- }
- } else {
- if p.Expiry == 0 {
- log.Debugf("invalid local profile: no expiry set")
- return false
- }
- }
- }
- if p.LintErrLevel < 0 || p.LintErrLevel >= 8 {
- log.Debugf("invalid profile: lint_error_level outside of range [0,8)")
- return false
- }
- log.Debugf("profile is valid")
- return true
- }
- // This checks if the SigningProfile object contains configurations that are only effective with a local signer
- // which has access to CA private key.
- func (p *SigningProfile) hasLocalConfig() bool {
- if p.Usage != nil ||
- p.IssuerURL != nil ||
- p.OCSP != "" ||
- p.ExpiryString != "" ||
- p.BackdateString != "" ||
- p.CAConstraint.IsCA ||
- !p.NotBefore.IsZero() ||
- !p.NotAfter.IsZero() ||
- p.NameWhitelistString != "" ||
- len(p.CTLogServers) != 0 {
- return true
- }
- return false
- }
- // warnSkippedSettings prints a log warning message about skipped settings
- // in a SigningProfile, usually due to remote signer.
- func (p *Signing) warnSkippedSettings() {
- const warningMessage = `The configuration value by "usages", "issuer_urls", "ocsp_url", "crl_url", "ca_constraint", "expiry", "backdate", "not_before", "not_after", "cert_store" and "ct_log_servers" are skipped`
- if p == nil {
- return
- }
- if (p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "") && p.Default.hasLocalConfig() {
- log.Warning("default profile points to a remote signer: ", warningMessage)
- }
- for name, profile := range p.Profiles {
- if (profile.RemoteName != "" || profile.AuthRemote.RemoteName != "") && profile.hasLocalConfig() {
- log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage)
- }
- }
- }
- // Signing codifies the signature configuration policy for a CA.
- type Signing struct {
- Profiles map[string]*SigningProfile `json:"profiles"`
- Default *SigningProfile `json:"default"`
- }
- // Config stores configuration information for the CA.
- type Config struct {
- Signing *Signing `json:"signing"`
- OCSP *ocspConfig.Config `json:"ocsp"`
- AuthKeys map[string]AuthKey `json:"auth_keys,omitempty"`
- Remotes map[string]string `json:"remotes,omitempty"`
- }
- // Valid ensures that Config is a valid configuration. It should be
- // called immediately after parsing a configuration file.
- func (c *Config) Valid() bool {
- return c.Signing.Valid()
- }
- // Valid checks the signature policies, ensuring they are valid
- // policies. A policy is valid if it has defined at least key usages
- // to be used, and a valid default profile has defined at least a
- // default expiration.
- func (p *Signing) Valid() bool {
- if p == nil {
- return false
- }
- log.Debugf("validating configuration")
- if !p.Default.validProfile(true) {
- log.Debugf("default profile is invalid")
- return false
- }
- for _, sp := range p.Profiles {
- if !sp.validProfile(false) {
- log.Debugf("invalid profile")
- return false
- }
- }
- p.warnSkippedSettings()
- return true
- }
- // KeyUsage contains a mapping of string names to key usages.
- var KeyUsage = map[string]x509.KeyUsage{
- "signing": x509.KeyUsageDigitalSignature,
- "digital signature": x509.KeyUsageDigitalSignature,
- "content commitment": x509.KeyUsageContentCommitment,
- "key encipherment": x509.KeyUsageKeyEncipherment,
- "key agreement": x509.KeyUsageKeyAgreement,
- "data encipherment": x509.KeyUsageDataEncipherment,
- "cert sign": x509.KeyUsageCertSign,
- "crl sign": x509.KeyUsageCRLSign,
- "encipher only": x509.KeyUsageEncipherOnly,
- "decipher only": x509.KeyUsageDecipherOnly,
- }
- // ExtKeyUsage contains a mapping of string names to extended key
- // usages.
- var ExtKeyUsage = map[string]x509.ExtKeyUsage{
- "any": x509.ExtKeyUsageAny,
- "server auth": x509.ExtKeyUsageServerAuth,
- "client auth": x509.ExtKeyUsageClientAuth,
- "code signing": x509.ExtKeyUsageCodeSigning,
- "email protection": x509.ExtKeyUsageEmailProtection,
- "s/mime": x509.ExtKeyUsageEmailProtection,
- "ipsec end system": x509.ExtKeyUsageIPSECEndSystem,
- "ipsec tunnel": x509.ExtKeyUsageIPSECTunnel,
- "ipsec user": x509.ExtKeyUsageIPSECUser,
- "timestamping": x509.ExtKeyUsageTimeStamping,
- "ocsp signing": x509.ExtKeyUsageOCSPSigning,
- "microsoft sgc": x509.ExtKeyUsageMicrosoftServerGatedCrypto,
- "netscape sgc": x509.ExtKeyUsageNetscapeServerGatedCrypto,
- }
- // An AuthKey contains an entry for a key used for authentication.
- type AuthKey struct {
- // Type contains information needed to select the appropriate
- // constructor. For example, "standard" for HMAC-SHA-256,
- // "standard-ip" for HMAC-SHA-256 incorporating the client's
- // IP.
- Type string `json:"type"`
- // Key contains the key information, such as a hex-encoded
- // HMAC key.
- Key string `json:"key"`
- }
- // DefaultConfig returns a default configuration specifying basic key
- // usage and a 1 year expiration time. The key usages chosen are
- // signing, key encipherment, client auth and server auth.
- func DefaultConfig() *SigningProfile {
- d := helpers.OneYear
- return &SigningProfile{
- Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
- Expiry: d,
- ExpiryString: "8760h",
- }
- }
- // LoadFile attempts to load the configuration file stored at the path
- // and returns the configuration. On error, it returns nil.
- func LoadFile(path string) (*Config, error) {
- log.Debugf("loading configuration file from %s", path)
- if path == "" {
- return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path"))
- }
- body, err := os.ReadFile(path)
- if err != nil {
- return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file"))
- }
- return LoadConfig(body)
- }
- // LoadConfig attempts to load the configuration from a byte slice.
- // On error, it returns nil.
- func LoadConfig(config []byte) (*Config, error) {
- var cfg = &Config{}
- err := json.Unmarshal(config, &cfg)
- if err != nil {
- return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
- errors.New("failed to unmarshal configuration: "+err.Error()))
- }
- if cfg.Signing == nil {
- return nil, errors.New("No \"signing\" field present")
- }
- if cfg.Signing.Default == nil {
- log.Debugf("no default given: using default config")
- cfg.Signing.Default = DefaultConfig()
- } else {
- if err := cfg.Signing.Default.populate(cfg); err != nil {
- return nil, err
- }
- }
- for k := range cfg.Signing.Profiles {
- if err := cfg.Signing.Profiles[k].populate(cfg); err != nil {
- return nil, err
- }
- }
- if !cfg.Valid() {
- return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid configuration"))
- }
- log.Debugf("configuration ok")
- return cfg, nil
- }
|