config.go 21 KB

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