@@ -3,10 +3,19 @@ package config
33
44import (
55 "encoding/json"
6+ "errors"
67 "fmt"
78 "os"
89)
910
11+ const (
12+ // KeyTypeP256 is one of the valid key types in configuration.
13+ KeyTypeP256 = "p256"
14+
15+ // KeyTypeRSA2048 is one of the valid key types in configuration.
16+ KeyTypeRSA2048 = "rsa2048"
17+ )
18+
1019// Load a configuration file from cfgPath.
1120func Load (cfgPath string ) (* Config , error ) {
1221 cfgBytes , err := os .ReadFile (cfgPath ) //nolint:gosec // Reading arbitrary config file is expected
@@ -21,9 +30,43 @@ func Load(cfgPath string) (*Config, error) {
2130 return nil , fmt .Errorf ("parsing %s: %w" , cfgPath , err )
2231 }
2332
33+ err = validate (& cfg )
34+ if err != nil {
35+ return nil , fmt .Errorf ("validating %s: %w" , cfgPath , err )
36+ }
37+
2438 return & cfg , nil
2539}
2640
41+ // validate the loaded configuration.
42+ // This checks domains are unique, key types are valid, and that an issuer CN is set.
43+ func validate (cfg * Config ) error {
44+ domains := make (map [string ]struct {}, 0 )
45+ var errs []error
46+ for i , site := range cfg .Sites {
47+ switch site .KeyType {
48+ case KeyTypeP256 , KeyTypeRSA2048 :
49+ // Valid key types
50+ default :
51+ errs = append (errs , fmt .Errorf ("site %d unsupported key type: %s" , i , site .KeyType ))
52+ }
53+
54+ for _ , d := range []string {site .Domains .Valid , site .Domains .Revoked , site .Domains .Expired } {
55+ _ , seen := domains [d ]
56+ if seen {
57+ errs = append (errs , fmt .Errorf ("site %d duplicate domain: %s" , i , d ))
58+ }
59+ domains [d ] = struct {}{}
60+ }
61+
62+ if site .IssuerCN == "" {
63+ errs = append (errs , fmt .Errorf ("site %d missing issuer CN" , i ))
64+ }
65+ }
66+
67+ return errors .Join (errs ... )
68+ }
69+
2770// Config is the structure of the JSON configuration file.
2871type Config struct {
2972 // Sites is a list of sites to host.
@@ -47,6 +90,7 @@ type Site struct {
4790 KeyType string
4891
4992 // Profile selects the ACME profile to use for this certificate.
93+ // Optional.
5094 Profile string
5195
5296 // Domain names to use.
0 commit comments