config.go 23 KB

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