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