package cmd import ( "crypto/tls" "crypto/x509" "encoding/json" "errors" "fmt" "io/ioutil" "strings" "time" "github.com/letsencrypt/boulder/core" ) // PasswordConfig either contains a password or the path to a file // containing a password type PasswordConfig struct { Password string PasswordFile string } // Pass returns a password, either directly from the configuration // struct or by reading from a specified file func (pc *PasswordConfig) Pass() (string, error) { if pc.PasswordFile != "" { contents, err := ioutil.ReadFile(pc.PasswordFile) if err != nil { return "", err } return strings.TrimRight(string(contents), "\n"), nil } return pc.Password, nil } // ServiceConfig contains config items that are common to all our services, to // be embedded in other config structs. type ServiceConfig struct { // DebugAddr is the address to run the /debug handlers on. DebugAddr string GRPC *GRPCServerConfig TLS TLSConfig } // DBConfig defines how to connect to a database. The connect string may be // stored in a file separate from the config, because it can contain a password, // which we want to keep out of configs. type DBConfig struct { DBConnect string // A file containing a connect URL for the DB. DBConnectFile string MaxDBConns int MaxIdleDBConns int } // URL returns the DBConnect URL represented by this DBConfig object, either // loading it from disk or returning a default value. Leading and trailing // whitespace is stripped. func (d *DBConfig) URL() (string, error) { if d.DBConnectFile != "" { url, err := ioutil.ReadFile(d.DBConnectFile) return strings.TrimSpace(string(url)), err } return d.DBConnect, nil } type SMTPConfig struct { PasswordConfig Server string Port string Username string } // PAConfig specifies how a policy authority should connect to its // database, what policies it should enforce, and what challenges // it should offer. type PAConfig struct { DBConfig EnforcePolicyWhitelist bool Challenges map[string]bool ChallengesWhitelistFile string } // HostnamePolicyConfig specifies a file from which to load a policy regarding // what hostnames to issue for. type HostnamePolicyConfig struct { HostnamePolicyFile string } // CheckChallenges checks whether the list of challenges in the PA config // actually contains valid challenge names func (pc PAConfig) CheckChallenges() error { if len(pc.Challenges) == 0 { return errors.New("empty challenges map in the Policy Authority config is not allowed") } for name := range pc.Challenges { if !core.ValidChallenge(name) { return fmt.Errorf("Invalid challenge in PA config: %s", name) } } return nil } // TLSConfig represents certificates and a key for authenticated TLS. type TLSConfig struct { CertFile *string KeyFile *string CACertFile *string } // Load reads and parses the certificates and key listed in the TLSConfig, and // returns a *tls.Config suitable for either client or server use. func (t *TLSConfig) Load() (*tls.Config, error) { if t == nil { return nil, fmt.Errorf("nil TLS section in config") } if t.CertFile == nil { return nil, fmt.Errorf("nil CertFile in TLSConfig") } if t.KeyFile == nil { return nil, fmt.Errorf("nil KeyFile in TLSConfig") } if t.CACertFile == nil { return nil, fmt.Errorf("nil CACertFile in TLSConfig") } caCertBytes, err := ioutil.ReadFile(*t.CACertFile) if err != nil { return nil, fmt.Errorf("reading CA cert from %q: %s", *t.CACertFile, err) } rootCAs := x509.NewCertPool() if ok := rootCAs.AppendCertsFromPEM(caCertBytes); !ok { return nil, fmt.Errorf("parsing CA certs from %s failed", *t.CACertFile) } cert, err := tls.LoadX509KeyPair(*t.CertFile, *t.KeyFile) if err != nil { return nil, fmt.Errorf("loading key pair from %q and %q: %s", *t.CertFile, *t.KeyFile, err) } return &tls.Config{ RootCAs: rootCAs, ClientCAs: rootCAs, ClientAuth: tls.RequireAndVerifyClientCert, Certificates: []tls.Certificate{cert}, }, nil } // RPCServerConfig contains configuration particular to a specific RPC server // type (e.g. RA, SA, etc) type RPCServerConfig struct { Server string // Queue name where the server receives requests RPCTimeout ConfigDuration } // OCSPUpdaterConfig provides the various window tick times and batch sizes needed // for the OCSP (and SCT) updater type OCSPUpdaterConfig struct { ServiceConfig DBConfig NewCertificateWindow ConfigDuration OldOCSPWindow ConfigDuration MissingSCTWindow ConfigDuration RevokedCertificateWindow ConfigDuration NewCertificateBatchSize int OldOCSPBatchSize int MissingSCTBatchSize int RevokedCertificateBatchSize int OCSPMinTimeToExpiry ConfigDuration OCSPStaleMaxAge ConfigDuration OldestIssuedSCT ConfigDuration ParallelGenerateOCSPRequests int AkamaiBaseURL string AkamaiClientToken string AkamaiClientSecret string AkamaiAccessToken string // When AkamaiV3Network is not provided, the Akamai CCU API v2 is used. When // AkamaiV3Network is set to "staging" or "production" the Akamai CCU API v3 // is used. AkamaiV3Network string AkamaiPurgeRetries int AkamaiPurgeRetryBackoff ConfigDuration SignFailureBackoffFactor float64 SignFailureBackoffMax ConfigDuration Publisher *GRPCClientConfig SAService *GRPCClientConfig OCSPGeneratorService *GRPCClientConfig Features map[string]bool } // GoogleSafeBrowsingConfig is the JSON config struct for the VA's use of the // Google Safe Browsing API. type GoogleSafeBrowsingConfig struct { APIKey string DataDir string ServerURL string } // SyslogConfig defines the config for syslogging. type SyslogConfig struct { StdoutLevel int SyslogLevel int } // StatsdConfig defines the config for Statsd. type StatsdConfig struct { Server string Prefix string } // ConfigDuration is just an alias for time.Duration that allows // serialization to YAML as well as JSON. type ConfigDuration struct { time.Duration } // ErrDurationMustBeString is returned when a non-string value is // presented to be deserialized as a ConfigDuration var ErrDurationMustBeString = errors.New("cannot JSON unmarshal something other than a string into a ConfigDuration") // UnmarshalJSON parses a string into a ConfigDuration using // time.ParseDuration. If the input does not unmarshal as a // string, then UnmarshalJSON returns ErrDurationMustBeString. func (d *ConfigDuration) UnmarshalJSON(b []byte) error { s := "" err := json.Unmarshal(b, &s) if err != nil { if _, ok := err.(*json.UnmarshalTypeError); ok { return ErrDurationMustBeString } return err } dd, err := time.ParseDuration(s) d.Duration = dd return err } // MarshalJSON returns the string form of the duration, as a byte array. func (d ConfigDuration) MarshalJSON() ([]byte, error) { return []byte(d.Duration.String()), nil } // UnmarshalYAML uses the same frmat as JSON, but is called by the YAML // parser (vs. the JSON parser). func (d *ConfigDuration) UnmarshalYAML(unmarshal func(interface{}) error) error { var s string if err := unmarshal(&s); err != nil { return err } dur, err := time.ParseDuration(s) if err != nil { return err } d.Duration = dur return nil } // LogDescription contains the information needed to submit certificates // to a CT log and verify returned receipts type LogDescription struct { URI string Key string SubmitFinalCert bool } // GRPCClientConfig contains the information needed to talk to the gRPC service type GRPCClientConfig struct { ServerAddresses []string Timeout ConfigDuration } // GRPCServerConfig contains the information needed to run a gRPC service type GRPCServerConfig struct { Address string `json:"address"` // ClientNames is a list of allowed client certificate subject alternate names // (SANs). The server will reject clients that do not present a certificate // with a SAN present on the `ClientNames` list. ClientNames []string `json:"clientNames"` // gRPC multiplexes RPCs across HTTP/2 streams in a single TCP connection. // HTTP/2 servers are allowed to set a limit on the number of streams a client // will create. In Go by default that limit is 250. We can override that for // our servers with this config value. In practice this is a limit on how many // concurrent requests we can handle. MaxConcurrentStreams int } // PortConfig specifies what ports the VA should call to on the remote // host when performing its checks. type PortConfig struct { HTTPPort int HTTPSPort int TLSPort int } // CAADistributedResolverConfig specifies the HTTP client setup and interfaces // needed to resolve CAA addresses over multiple paths type CAADistributedResolverConfig struct { Timeout ConfigDuration MaxFailures int Proxies []string } type CTGroup struct { Name string Logs []LogDescription }