config.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. // Package config contains the configuration logic for CFSSL.
  2. package config
  3. import (
  4. "crypto/tls"
  5. "crypto/x509"
  6. "encoding/asn1"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "os"
  11. "regexp"
  12. "strconv"
  13. "strings"
  14. "time"
  15. "github.com/cloudflare/cfssl/auth"
  16. cferr "github.com/cloudflare/cfssl/errors"
  17. "github.com/cloudflare/cfssl/helpers"
  18. "github.com/cloudflare/cfssl/log"
  19. ocspConfig "github.com/cloudflare/cfssl/ocsp/config"
  20. // empty import of zlint/v3 required to have lints registered.
  21. _ "github.com/zmap/zlint/v3"
  22. "github.com/zmap/zlint/v3/lint"
  23. )
  24. // A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is
  25. // not present in a SigningProfile, all of these fields may be copied from the
  26. // CSR into the signed certificate. If a CSRWhitelist *is* present in a
  27. // SigningProfile, only those fields with a `true` value in the CSRWhitelist may
  28. // be copied from the CSR to the signed certificate. Note that some of these
  29. // fields, like Subject, can be provided or partially provided through the API.
  30. // Since API clients are expected to be trusted, but CSRs are not, fields
  31. // provided through the API are not subject to whitelisting through this
  32. // mechanism.
  33. type CSRWhitelist struct {
  34. Subject, PublicKeyAlgorithm, PublicKey, SignatureAlgorithm bool
  35. DNSNames, IPAddresses, EmailAddresses, URIs bool
  36. }
  37. // OID is our own version of asn1's ObjectIdentifier, so we can define a custom
  38. // JSON marshal / unmarshal.
  39. type OID asn1.ObjectIdentifier
  40. // CertificatePolicy represents the ASN.1 PolicyInformation structure from
  41. // https://tools.ietf.org/html/rfc3280.html#page-106.
  42. // Valid values of Type are "id-qt-unotice" and "id-qt-cps"
  43. type CertificatePolicy struct {
  44. ID OID
  45. Qualifiers []CertificatePolicyQualifier
  46. }
  47. // CertificatePolicyQualifier represents a single qualifier from an ASN.1
  48. // PolicyInformation structure.
  49. type CertificatePolicyQualifier struct {
  50. Type string
  51. Value string
  52. }
  53. // AuthRemote is an authenticated remote signer.
  54. type AuthRemote struct {
  55. RemoteName string `json:"remote"`
  56. AuthKeyName string `json:"auth_key"`
  57. }
  58. // CAConstraint specifies various CA constraints on the signed certificate.
  59. // CAConstraint would verify against (and override) the CA
  60. // extensions in the given CSR.
  61. type CAConstraint struct {
  62. IsCA bool `json:"is_ca"`
  63. MaxPathLen int `json:"max_path_len"`
  64. MaxPathLenZero bool `json:"max_path_len_zero"`
  65. }
  66. // A SigningProfile stores information that the CA needs to store
  67. // signature policy.
  68. type SigningProfile struct {
  69. Usage []string `json:"usages"`
  70. IssuerURL []string `json:"issuer_urls"`
  71. OCSP string `json:"ocsp_url"`
  72. CRL string `json:"crl_url"`
  73. CAConstraint CAConstraint `json:"ca_constraint"`
  74. OCSPNoCheck bool `json:"ocsp_no_check"`
  75. ExpiryString string `json:"expiry"`
  76. BackdateString string `json:"backdate"`
  77. AuthKeyName string `json:"auth_key"`
  78. CopyExtensions bool `json:"copy_extensions"`
  79. PrevAuthKeyName string `json:"prev_auth_key"` // to support key rotation
  80. RemoteName string `json:"remote"`
  81. NotBefore time.Time `json:"not_before"`
  82. NotAfter time.Time `json:"not_after"`
  83. NameWhitelistString string `json:"name_whitelist"`
  84. AuthRemote AuthRemote `json:"auth_remote"`
  85. CTLogServers []string `json:"ct_log_servers"`
  86. AllowedExtensions []OID `json:"allowed_extensions"`
  87. CertStore string `json:"cert_store"`
  88. // LintErrLevel controls preissuance linting for the signing profile.
  89. // 0 = no linting is performed [default]
  90. // 2..3 = reserved
  91. // 3 = all lint results except pass are considered errors
  92. // 4 = all lint results except pass and notice are considered errors
  93. // 5 = all lint results except pass, notice and warn are considered errors
  94. // 6 = all lint results except pass, notice, warn and error are considered errors.
  95. // 7 = lint is performed, no lint results are treated as errors.
  96. LintErrLevel lint.LintStatus `json:"lint_error_level"`
  97. // ExcludeLints lists ZLint lint names to exclude from preissuance linting.
  98. ExcludeLints []string `json:"ignored_lints"`
  99. // ExcludeLintSources lists ZLint lint sources to exclude from preissuance
  100. // linting.
  101. ExcludeLintSources []string `json:"ignored_lint_sources"`
  102. Policies []CertificatePolicy
  103. Expiry time.Duration
  104. Backdate time.Duration
  105. Provider auth.Provider
  106. PrevProvider auth.Provider // to suppport key rotation
  107. RemoteProvider auth.Provider
  108. RemoteServer string
  109. RemoteCAs *x509.CertPool
  110. ClientCert *tls.Certificate
  111. CSRWhitelist *CSRWhitelist
  112. NameWhitelist *regexp.Regexp
  113. ExtensionWhitelist map[string]bool
  114. ClientProvidesSerialNumbers bool
  115. // LintRegistry is the collection of lints that should be used if
  116. // LintErrLevel is configured. By default all ZLint lints are used. If
  117. // ExcludeLints or ExcludeLintSources are set then this registry will be
  118. // filtered in populate() to exclude the named lints and lint sources.
  119. LintRegistry lint.Registry
  120. }
  121. // UnmarshalJSON unmarshals a JSON string into an OID.
  122. func (oid *OID) UnmarshalJSON(data []byte) (err error) {
  123. if data[0] != '"' || data[len(data)-1] != '"' {
  124. return errors.New("OID JSON string not wrapped in quotes." + string(data))
  125. }
  126. data = data[1 : len(data)-1]
  127. parsedOid, err := parseObjectIdentifier(string(data))
  128. if err != nil {
  129. return err
  130. }
  131. *oid = OID(parsedOid)
  132. return
  133. }
  134. // MarshalJSON marshals an oid into a JSON string.
  135. func (oid OID) MarshalJSON() ([]byte, error) {
  136. return []byte(fmt.Sprintf(`"%v"`, asn1.ObjectIdentifier(oid))), nil
  137. }
  138. func parseObjectIdentifier(oidString string) (oid asn1.ObjectIdentifier, err error) {
  139. validOID, err := regexp.MatchString("\\d(\\.\\d+)*", oidString)
  140. if err != nil {
  141. return
  142. }
  143. if !validOID {
  144. err = errors.New("Invalid OID")
  145. return
  146. }
  147. segments := strings.Split(oidString, ".")
  148. oid = make(asn1.ObjectIdentifier, len(segments))
  149. for i, intString := range segments {
  150. oid[i], err = strconv.Atoi(intString)
  151. if err != nil {
  152. return
  153. }
  154. }
  155. return
  156. }
  157. const timeFormat = "2006-01-02T15:04:05"
  158. // populate is used to fill in the fields that are not in JSON
  159. //
  160. // First, the ExpiryString parameter is needed to parse
  161. // expiration timestamps from JSON. The JSON decoder is not able to
  162. // decode a string time duration to a time.Duration, so this is called
  163. // when loading the configuration to properly parse and fill out the
  164. // Expiry parameter.
  165. // This function is also used to create references to the auth key
  166. // and default remote for the profile.
  167. // It returns true if ExpiryString is a valid representation of a
  168. // time.Duration, and the AuthKeyString and RemoteName point to
  169. // valid objects. It returns false otherwise.
  170. func (p *SigningProfile) populate(cfg *Config) error {
  171. if p == nil {
  172. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("can't parse nil profile"))
  173. }
  174. var err error
  175. if p.RemoteName == "" && p.AuthRemote.RemoteName == "" {
  176. log.Debugf("parse expiry in profile")
  177. if p.ExpiryString == "" {
  178. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("empty expiry string"))
  179. }
  180. dur, err := time.ParseDuration(p.ExpiryString)
  181. if err != nil {
  182. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
  183. }
  184. log.Debugf("expiry is valid")
  185. p.Expiry = dur
  186. if p.BackdateString != "" {
  187. dur, err = time.ParseDuration(p.BackdateString)
  188. if err != nil {
  189. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
  190. }
  191. p.Backdate = dur
  192. }
  193. if !p.NotBefore.IsZero() && !p.NotAfter.IsZero() && p.NotAfter.Before(p.NotBefore) {
  194. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
  195. }
  196. if len(p.Policies) > 0 {
  197. for _, policy := range p.Policies {
  198. for _, qualifier := range policy.Qualifiers {
  199. if qualifier.Type != "" && qualifier.Type != "id-qt-unotice" && qualifier.Type != "id-qt-cps" {
  200. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  201. errors.New("invalid policy qualifier type"))
  202. }
  203. }
  204. }
  205. }
  206. } else if p.RemoteName != "" {
  207. log.Debug("match remote in profile to remotes section")
  208. if p.AuthRemote.RemoteName != "" {
  209. log.Error("profile has both a remote and an auth remote specified")
  210. return cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
  211. }
  212. if remote := cfg.Remotes[p.RemoteName]; remote != "" {
  213. if err := p.updateRemote(remote); err != nil {
  214. return err
  215. }
  216. } else {
  217. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  218. errors.New("failed to find remote in remotes section"))
  219. }
  220. } else {
  221. log.Debug("match auth remote in profile to remotes section")
  222. if remote := cfg.Remotes[p.AuthRemote.RemoteName]; remote != "" {
  223. if err := p.updateRemote(remote); err != nil {
  224. return err
  225. }
  226. } else {
  227. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  228. errors.New("failed to find remote in remotes section"))
  229. }
  230. }
  231. if p.AuthKeyName != "" {
  232. log.Debug("match auth key in profile to auth_keys section")
  233. if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok {
  234. if key.Type == "standard" {
  235. p.Provider, err = auth.New(key.Key, nil)
  236. if err != nil {
  237. log.Debugf("failed to create new standard auth provider: %v", err)
  238. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  239. errors.New("failed to create new standard auth provider"))
  240. }
  241. } else {
  242. log.Debugf("unknown authentication type %v", key.Type)
  243. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  244. errors.New("unknown authentication type"))
  245. }
  246. } else {
  247. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  248. errors.New("failed to find auth_key in auth_keys section"))
  249. }
  250. }
  251. if p.PrevAuthKeyName != "" {
  252. log.Debug("match previous auth key in profile to auth_keys section")
  253. if key, ok := cfg.AuthKeys[p.PrevAuthKeyName]; ok {
  254. if key.Type == "standard" {
  255. p.PrevProvider, err = auth.New(key.Key, nil)
  256. if err != nil {
  257. log.Debugf("failed to create new standard auth provider: %v", err)
  258. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  259. errors.New("failed to create new standard auth provider"))
  260. }
  261. } else {
  262. log.Debugf("unknown authentication type %v", key.Type)
  263. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  264. errors.New("unknown authentication type"))
  265. }
  266. } else {
  267. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  268. errors.New("failed to find prev_auth_key in auth_keys section"))
  269. }
  270. }
  271. if p.AuthRemote.AuthKeyName != "" {
  272. log.Debug("match auth remote key in profile to auth_keys section")
  273. if key, ok := cfg.AuthKeys[p.AuthRemote.AuthKeyName]; ok {
  274. if key.Type == "standard" {
  275. p.RemoteProvider, err = auth.New(key.Key, nil)
  276. if err != nil {
  277. log.Debugf("failed to create new standard auth provider: %v", err)
  278. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  279. errors.New("failed to create new standard auth provider"))
  280. }
  281. } else {
  282. log.Debugf("unknown authentication type %v", key.Type)
  283. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  284. errors.New("unknown authentication type"))
  285. }
  286. } else {
  287. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  288. errors.New("failed to find auth_remote's auth_key in auth_keys section"))
  289. }
  290. }
  291. if p.NameWhitelistString != "" {
  292. log.Debug("compiling whitelist regular expression")
  293. rule, err := regexp.Compile(p.NameWhitelistString)
  294. if err != nil {
  295. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  296. errors.New("failed to compile name whitelist section"))
  297. }
  298. p.NameWhitelist = rule
  299. }
  300. p.ExtensionWhitelist = map[string]bool{}
  301. for _, oid := range p.AllowedExtensions {
  302. p.ExtensionWhitelist[asn1.ObjectIdentifier(oid).String()] = true
  303. }
  304. // By default perform any required preissuance linting with all ZLint lints.
  305. p.LintRegistry = lint.GlobalRegistry()
  306. // If ExcludeLintSources are present in config build a lint.SourceList while
  307. // validating that no unknown sources were specified.
  308. var excludedSources lint.SourceList
  309. if len(p.ExcludeLintSources) > 0 {
  310. for _, sourceName := range p.ExcludeLintSources {
  311. var lintSource lint.LintSource
  312. lintSource.FromString(sourceName)
  313. if lintSource == lint.UnknownLintSource {
  314. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  315. fmt.Errorf("failed to build excluded lint source list: unknown source %q",
  316. sourceName))
  317. }
  318. excludedSources = append(excludedSources, lintSource)
  319. }
  320. }
  321. opts := lint.FilterOptions{
  322. ExcludeNames: p.ExcludeLints,
  323. ExcludeSources: excludedSources,
  324. }
  325. if !opts.Empty() {
  326. // If ExcludeLints or ExcludeLintSources were not empty then filter out the
  327. // lints we don't want to use for preissuance linting with this profile.
  328. filteredRegistry, err := p.LintRegistry.Filter(opts)
  329. if err != nil {
  330. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  331. fmt.Errorf("failed to build filtered lint registry: %v", err))
  332. }
  333. p.LintRegistry = filteredRegistry
  334. }
  335. return nil
  336. }
  337. // updateRemote takes a signing profile and initializes the remote server object
  338. // to the hostname:port combination sent by remote.
  339. func (p *SigningProfile) updateRemote(remote string) error {
  340. if remote != "" {
  341. p.RemoteServer = remote
  342. }
  343. return nil
  344. }
  345. // OverrideRemotes takes a signing configuration and updates the remote server object
  346. // to the hostname:port combination sent by remote
  347. func (p *Signing) OverrideRemotes(remote string) error {
  348. if remote != "" {
  349. var err error
  350. for _, profile := range p.Profiles {
  351. err = profile.updateRemote(remote)
  352. if err != nil {
  353. return err
  354. }
  355. }
  356. err = p.Default.updateRemote(remote)
  357. if err != nil {
  358. return err
  359. }
  360. }
  361. return nil
  362. }
  363. // SetClientCertKeyPairFromFile updates the properties to set client certificates for mutual
  364. // authenticated TLS remote requests
  365. func (p *Signing) SetClientCertKeyPairFromFile(certFile string, keyFile string) error {
  366. if certFile != "" && keyFile != "" {
  367. cert, err := helpers.LoadClientCertificate(certFile, keyFile)
  368. if err != nil {
  369. return err
  370. }
  371. for _, profile := range p.Profiles {
  372. profile.ClientCert = cert
  373. }
  374. p.Default.ClientCert = cert
  375. }
  376. return nil
  377. }
  378. // SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS
  379. // remote requests
  380. func (p *Signing) SetRemoteCAsFromFile(caFile string) error {
  381. if caFile != "" {
  382. remoteCAs, err := helpers.LoadPEMCertPool(caFile)
  383. if err != nil {
  384. return err
  385. }
  386. p.SetRemoteCAs(remoteCAs)
  387. }
  388. return nil
  389. }
  390. // SetRemoteCAs updates the properties to set remote CAs for TLS
  391. // remote requests
  392. func (p *Signing) SetRemoteCAs(remoteCAs *x509.CertPool) {
  393. for _, profile := range p.Profiles {
  394. profile.RemoteCAs = remoteCAs
  395. }
  396. p.Default.RemoteCAs = remoteCAs
  397. }
  398. // NeedsRemoteSigner returns true if one of the profiles has a remote set
  399. func (p *Signing) NeedsRemoteSigner() bool {
  400. for _, profile := range p.Profiles {
  401. if profile.RemoteServer != "" {
  402. return true
  403. }
  404. }
  405. return p.Default.RemoteServer != ""
  406. }
  407. // NeedsLocalSigner returns true if one of the profiles doe not have a remote set
  408. func (p *Signing) NeedsLocalSigner() bool {
  409. for _, profile := range p.Profiles {
  410. if profile.RemoteServer == "" {
  411. return true
  412. }
  413. }
  414. return p.Default.RemoteServer == ""
  415. }
  416. // Usages parses the list of key uses in the profile, translating them
  417. // to a list of X.509 key usages and extended key usages. The unknown
  418. // uses are collected into a slice that is also returned.
  419. func (p *SigningProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk []string) {
  420. for _, keyUse := range p.Usage {
  421. if kuse, ok := KeyUsage[keyUse]; ok {
  422. ku |= kuse
  423. } else if ekuse, ok := ExtKeyUsage[keyUse]; ok {
  424. eku = append(eku, ekuse)
  425. } else {
  426. unk = append(unk, keyUse)
  427. }
  428. }
  429. return
  430. }
  431. // A valid profile must be a valid local profile or a valid remote profile.
  432. // A valid local profile has defined at least key usages to be used, and a
  433. // valid local default profile has defined at least a default expiration.
  434. // A valid remote profile (default or not) has remote signer initialized.
  435. // In addition, a remote profile must has a valid auth provider if auth
  436. // key defined. A valid profile must not include a lint_error_level outside of
  437. // [0,8).
  438. func (p *SigningProfile) validProfile(isDefault bool) bool {
  439. if p == nil {
  440. return false
  441. }
  442. if p.AuthRemote.RemoteName == "" && p.AuthRemote.AuthKeyName != "" {
  443. log.Debugf("invalid auth remote profile: no remote signer specified")
  444. return false
  445. }
  446. if p.RemoteName != "" {
  447. log.Debugf("validate remote profile")
  448. if p.RemoteServer == "" {
  449. log.Debugf("invalid remote profile: no remote signer specified")
  450. return false
  451. }
  452. if p.AuthKeyName != "" && p.Provider == nil {
  453. log.Debugf("invalid remote profile: auth key name is defined but no auth provider is set")
  454. return false
  455. }
  456. if p.AuthRemote.RemoteName != "" {
  457. log.Debugf("invalid remote profile: auth remote is also specified")
  458. return false
  459. }
  460. } else if p.AuthRemote.RemoteName != "" {
  461. log.Debugf("validate auth remote profile")
  462. if p.RemoteServer == "" {
  463. log.Debugf("invalid auth remote profile: no remote signer specified")
  464. return false
  465. }
  466. if p.AuthRemote.AuthKeyName == "" || p.RemoteProvider == nil {
  467. log.Debugf("invalid auth remote profile: no auth key is defined")
  468. return false
  469. }
  470. } else {
  471. log.Debugf("validate local profile")
  472. if !isDefault {
  473. if len(p.Usage) == 0 {
  474. log.Debugf("invalid local profile: no usages specified")
  475. return false
  476. } else if _, _, unk := p.Usages(); len(unk) == len(p.Usage) {
  477. log.Debugf("invalid local profile: no valid usages")
  478. return false
  479. }
  480. } else {
  481. if p.Expiry == 0 {
  482. log.Debugf("invalid local profile: no expiry set")
  483. return false
  484. }
  485. }
  486. }
  487. if p.LintErrLevel < 0 || p.LintErrLevel >= 8 {
  488. log.Debugf("invalid profile: lint_error_level outside of range [0,8)")
  489. return false
  490. }
  491. log.Debugf("profile is valid")
  492. return true
  493. }
  494. // This checks if the SigningProfile object contains configurations that are only effective with a local signer
  495. // which has access to CA private key.
  496. func (p *SigningProfile) hasLocalConfig() bool {
  497. if p.Usage != nil ||
  498. p.IssuerURL != nil ||
  499. p.OCSP != "" ||
  500. p.ExpiryString != "" ||
  501. p.BackdateString != "" ||
  502. p.CAConstraint.IsCA ||
  503. !p.NotBefore.IsZero() ||
  504. !p.NotAfter.IsZero() ||
  505. p.NameWhitelistString != "" ||
  506. len(p.CTLogServers) != 0 {
  507. return true
  508. }
  509. return false
  510. }
  511. // warnSkippedSettings prints a log warning message about skipped settings
  512. // in a SigningProfile, usually due to remote signer.
  513. func (p *Signing) warnSkippedSettings() {
  514. 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`
  515. if p == nil {
  516. return
  517. }
  518. if (p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "") && p.Default.hasLocalConfig() {
  519. log.Warning("default profile points to a remote signer: ", warningMessage)
  520. }
  521. for name, profile := range p.Profiles {
  522. if (profile.RemoteName != "" || profile.AuthRemote.RemoteName != "") && profile.hasLocalConfig() {
  523. log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage)
  524. }
  525. }
  526. }
  527. // Signing codifies the signature configuration policy for a CA.
  528. type Signing struct {
  529. Profiles map[string]*SigningProfile `json:"profiles"`
  530. Default *SigningProfile `json:"default"`
  531. }
  532. // Config stores configuration information for the CA.
  533. type Config struct {
  534. Signing *Signing `json:"signing"`
  535. OCSP *ocspConfig.Config `json:"ocsp"`
  536. AuthKeys map[string]AuthKey `json:"auth_keys,omitempty"`
  537. Remotes map[string]string `json:"remotes,omitempty"`
  538. }
  539. // Valid ensures that Config is a valid configuration. It should be
  540. // called immediately after parsing a configuration file.
  541. func (c *Config) Valid() bool {
  542. return c.Signing.Valid()
  543. }
  544. // Valid checks the signature policies, ensuring they are valid
  545. // policies. A policy is valid if it has defined at least key usages
  546. // to be used, and a valid default profile has defined at least a
  547. // default expiration.
  548. func (p *Signing) Valid() bool {
  549. if p == nil {
  550. return false
  551. }
  552. log.Debugf("validating configuration")
  553. if !p.Default.validProfile(true) {
  554. log.Debugf("default profile is invalid")
  555. return false
  556. }
  557. for _, sp := range p.Profiles {
  558. if !sp.validProfile(false) {
  559. log.Debugf("invalid profile")
  560. return false
  561. }
  562. }
  563. p.warnSkippedSettings()
  564. return true
  565. }
  566. // KeyUsage contains a mapping of string names to key usages.
  567. var KeyUsage = map[string]x509.KeyUsage{
  568. "signing": x509.KeyUsageDigitalSignature,
  569. "digital signature": x509.KeyUsageDigitalSignature,
  570. "content commitment": x509.KeyUsageContentCommitment,
  571. "key encipherment": x509.KeyUsageKeyEncipherment,
  572. "key agreement": x509.KeyUsageKeyAgreement,
  573. "data encipherment": x509.KeyUsageDataEncipherment,
  574. "cert sign": x509.KeyUsageCertSign,
  575. "crl sign": x509.KeyUsageCRLSign,
  576. "encipher only": x509.KeyUsageEncipherOnly,
  577. "decipher only": x509.KeyUsageDecipherOnly,
  578. }
  579. // ExtKeyUsage contains a mapping of string names to extended key
  580. // usages.
  581. var ExtKeyUsage = map[string]x509.ExtKeyUsage{
  582. "any": x509.ExtKeyUsageAny,
  583. "server auth": x509.ExtKeyUsageServerAuth,
  584. "client auth": x509.ExtKeyUsageClientAuth,
  585. "code signing": x509.ExtKeyUsageCodeSigning,
  586. "email protection": x509.ExtKeyUsageEmailProtection,
  587. "s/mime": x509.ExtKeyUsageEmailProtection,
  588. "ipsec end system": x509.ExtKeyUsageIPSECEndSystem,
  589. "ipsec tunnel": x509.ExtKeyUsageIPSECTunnel,
  590. "ipsec user": x509.ExtKeyUsageIPSECUser,
  591. "timestamping": x509.ExtKeyUsageTimeStamping,
  592. "ocsp signing": x509.ExtKeyUsageOCSPSigning,
  593. "microsoft sgc": x509.ExtKeyUsageMicrosoftServerGatedCrypto,
  594. "netscape sgc": x509.ExtKeyUsageNetscapeServerGatedCrypto,
  595. }
  596. // An AuthKey contains an entry for a key used for authentication.
  597. type AuthKey struct {
  598. // Type contains information needed to select the appropriate
  599. // constructor. For example, "standard" for HMAC-SHA-256,
  600. // "standard-ip" for HMAC-SHA-256 incorporating the client's
  601. // IP.
  602. Type string `json:"type"`
  603. // Key contains the key information, such as a hex-encoded
  604. // HMAC key.
  605. Key string `json:"key"`
  606. }
  607. // DefaultConfig returns a default configuration specifying basic key
  608. // usage and a 1 year expiration time. The key usages chosen are
  609. // signing, key encipherment, client auth and server auth.
  610. func DefaultConfig() *SigningProfile {
  611. d := helpers.OneYear
  612. return &SigningProfile{
  613. Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
  614. Expiry: d,
  615. ExpiryString: "8760h",
  616. }
  617. }
  618. // LoadFile attempts to load the configuration file stored at the path
  619. // and returns the configuration. On error, it returns nil.
  620. func LoadFile(path string) (*Config, error) {
  621. log.Debugf("loading configuration file from %s", path)
  622. if path == "" {
  623. return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path"))
  624. }
  625. body, err := os.ReadFile(path)
  626. if err != nil {
  627. return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file"))
  628. }
  629. return LoadConfig(body)
  630. }
  631. // LoadConfig attempts to load the configuration from a byte slice.
  632. // On error, it returns nil.
  633. func LoadConfig(config []byte) (*Config, error) {
  634. var cfg = &Config{}
  635. err := json.Unmarshal(config, &cfg)
  636. if err != nil {
  637. return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
  638. errors.New("failed to unmarshal configuration: "+err.Error()))
  639. }
  640. if cfg.Signing == nil {
  641. return nil, errors.New("No \"signing\" field present")
  642. }
  643. if cfg.Signing.Default == nil {
  644. log.Debugf("no default given: using default config")
  645. cfg.Signing.Default = DefaultConfig()
  646. } else {
  647. if err := cfg.Signing.Default.populate(cfg); err != nil {
  648. return nil, err
  649. }
  650. }
  651. for k := range cfg.Signing.Profiles {
  652. if err := cfg.Signing.Profiles[k].populate(cfg); err != nil {
  653. return nil, err
  654. }
  655. }
  656. if !cfg.Valid() {
  657. return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid configuration"))
  658. }
  659. log.Debugf("configuration ok")
  660. return cfg, nil
  661. }