diff --git a/build/build.sh b/build/build.sh index d898926..d8caaf1 100755 --- a/build/build.sh +++ b/build/build.sh @@ -8,7 +8,7 @@ TMP_DIR=$(pwd)/tmp rm -rf $TMP_DIR && mkdir -p $TMP_DIR/{admin,bin,logs,src} boulderDir=$TMP_DIR/src -boulderTag="v0.20250707.0" +boulderTag="v0.20250728.0" boulderUrl="https://github.com/letsencrypt/boulder/" cloneDir=$(pwd)/.. diff --git a/build/tmp2.patch b/build/tmp2.patch index c801dbf..03e9767 100644 --- a/build/tmp2.patch +++ b/build/tmp2.patch @@ -1,8 +1,8 @@ diff --git a/test/startservers.py b/test/startservers.py -index c42a1bb51..9eeac8906 100644 +index e4645852a..b988b48fe 100644 --- a/test/startservers.py +++ b/test/startservers.py -@@ -194,6 +194,9 @@ processes = [] +@@ -190,6 +190,9 @@ processes = [] challSrvProcess = None def install(race_detection): diff --git a/dev/versions b/dev/versions index 8f89cbd..3679d26 100755 --- a/dev/versions +++ b/dev/versions @@ -114,7 +114,7 @@ grep GO_VERSION ../boulder/docker-compose.yml | sed -e "s/\s*GO_VERSION:/ /" colorGoVersion2 build/docker-compose.yml $goversion echo -db_migrs=$(ls -1 ../boulder/sa/db/boulder_sa/ | grep -v 20240304000000_CertificateProfiles.sql | grep -v 20250115000000_AuthzProfiles.sql | grep -v 20250519000000_NullRegistrationsContact.sql | wc -l) +db_migrs=$(ls -1 ../boulder/sa/db/boulder_sa/ | grep -v 20240304000000_CertificateProfiles.sql | grep -v 20250115000000_AuthzProfiles.sql | grep -v 20250519000000_NullRegistrationsContact.sql | grep -v 20250110000000_NullRegistrationsLockCol.sql | wc -l) db_patches=$(ls -1 ../labca/patches/db_migrations* | wc -l) echo -n "Database migrations " colorEqual $db_migrs $db_patches diff --git a/gui/apply-boulder b/gui/apply-boulder index 2ca1491..10546bc 100755 --- a/gui/apply-boulder +++ b/gui/apply-boulder @@ -61,22 +61,22 @@ if ([ "$PKI_DOMAIN_MODE" == "lockdown" ] && [ "$PKI_LOCKDOWN_DOMAINS" != "" ]) | perl -i -p0e "s/(\"shortlived\".*?)(\"ignoredLints\": \[).*?(\s+)(\"w_ext_subject_key_identifier_missing_sub_cert\")/\1\2\3\"e_dnsname_not_valid_tld\",\3\"w_sub_cert_aia_contains_internal_names\",\3\4/igs" config/ca.json perl -i -p0e "s/(\"pkilint:cabf.serverauth.subscriber_rsa_digitalsignature_and_keyencipherment_present\",).*?(\])/\1\n \"pkilint:cabf.internal_domain_name\",\n \"zlint:e_dnsname_not_valid_tld\",\n \"zlint:w_sub_cert_aia_contains_internal_names\",\n \"certlint:special_name_in_san\",\n \"certlint:unknown_tld_in_san\",\n \"certlint:br_certificates_must_include_an_http_url_of_the_ocsp_responder\",\n \"x509lint:no_ocsp_over_http\",\n\2/igs" config/zlint.toml - perl -p0e "s/(ignore_lints = \[).*(\])/\1\"zlint:e_crl_next_update_invalid\"\2/igs" config/zlint.toml + perl -i -p0e "s/(\[e_pkimetal_lint_cabf_serverauth_crl\].*)(ignore_lints = \[).*(\])/\1\2\"zlint:e_crl_next_update_invalid\"\3/igs" config/zlint.toml fi -[ -e ../test/hostname-policy.yaml ] && cp ../test/hostname-policy.yaml ./ || true -[ -e ../boulder/test/hostname-policy.yaml ] && cp ../boulder/test/hostname-policy.yaml ./ || true -[ -e hostname-policy.json ] && rm hostname-policy.json || true +[ -e ../test/ident-policy.yaml ] && cp ../test/ident-policy.yaml ./ || true +[ -e ../boulder/test/ident-policy.yaml ] && cp ../boulder/test/ident-policy.yaml ./ || true +[ -e hostname-policy.yaml ] && rm hostname-policy.yaml || true [ -e config/expired-authz-purger2.json ] && rm config/expired-authz-purger2.json || true [ -e config/janitor.json ] && rm config/janitor.json || true -cat hostname-policy.yaml | tr '\n' '\r' | sed -e "s/\r# Lockdown.*//" | tr '\r' '\n' > hostname-policy.yaml.bak && mv hostname-policy.yaml.bak hostname-policy.yaml -cat hostname-policy.yaml | tr '\n' '\r' | sed -e "s/\r# Whitelist.*//" | tr '\r' '\n' > hostname-policy.yaml.bak && mv hostname-policy.yaml.bak hostname-policy.yaml +cat ident-policy.yaml | tr '\n' '\r' | sed -e "s/\r# Lockdown.*//" | tr '\r' '\n' > ident-policy.yaml.bak && mv ident-policy.yaml.bak ident-policy.yaml +cat ident-policy.yaml | tr '\n' '\r' | sed -e "s/\r# Whitelist.*//" | tr '\r' '\n' > ident-policy.yaml.bak && mv ident-policy.yaml.bak ident-policy.yaml if [ "$PKI_DOMAIN_MODE" == "lockdown" ] && [ "$PKI_LOCKDOWN_DOMAINS" != "" ]; then - echo >> hostname-policy.yaml - echo "# Lockdown are the domains that this LabCA instance can issue certificates for" >> hostname-policy.yaml - echo "Lockdown:" >> hostname-policy.yaml + echo >> ident-policy.yaml + echo "# Lockdown are the domains that this LabCA instance can issue certificates for" >> ident-policy.yaml + echo "Lockdown:" >> ident-policy.yaml for d in $(echo $PKI_LOCKDOWN_DOMAINS | sed -e "s/\\\r/ /g" | sed -e "s/\\\n/ /g" | tr '\r' ' '); do - echo " - \"$d\"" >> hostname-policy.yaml + echo " - \"$d\"" >> ident-policy.yaml done allow_public="false" @@ -85,16 +85,16 @@ if [ "$PKI_DOMAIN_MODE" == "lockdown" ] && [ "$PKI_LOCKDOWN_DOMAINS" != "" ]; th allow_public="true" fi - echo >> hostname-policy.yaml - echo "LockdownAllowPublicContacts: $allow_public" >> hostname-policy.yaml + echo >> ident-policy.yaml + echo "LockdownAllowPublicContacts: $allow_public" >> ident-policy.yaml fi if [ "$PKI_DOMAIN_MODE" == "whitelist" ] && [ "$PKI_WHITELIST_DOMAINS" != "" ]; then - echo >> hostname-policy.yaml - echo "# Whitelist are the domains that this LabCA instance can issue certificates for" >> hostname-policy.yaml - echo "# in *addition* to all normal public domains" >> hostname-policy.yaml - echo "Whitelist:" >> hostname-policy.yaml + echo >> ident-policy.yaml + echo "# Whitelist are the domains that this LabCA instance can issue certificates for" >> ident-policy.yaml + echo "# in *addition* to all normal public domains" >> ident-policy.yaml + echo "Whitelist:" >> ident-policy.yaml for d in $(echo $PKI_WHITELIST_DOMAINS | sed -e "s/\\\r/ /g" | sed -e "s/\\\n/ /g" | tr '\r' ' '); do - echo " - \"$d\"" >> hostname-policy.yaml + echo " - \"$d\"" >> ident-policy.yaml done fi if [ "$PKI_DOMAIN_MODE" == "lockdown" ] || [ "$PKI_DOMAIN_MODE" == "whitelist" ]; then diff --git a/install b/install index 6f31d59..8b0dae5 100755 --- a/install +++ b/install @@ -30,7 +30,7 @@ dockerComposeVersion="v2.5.0" labcaUrl="https://github.com/hakwerk/labca/" boulderUrl="https://github.com/letsencrypt/boulder/" -boulderTag="v0.20250707.0" +boulderTag="v0.20250728.0" # # Color configuration @@ -846,6 +846,21 @@ check_dockeronly() { fi } +# Do some cleanup of common issues... +sweepup() { + cd "$boulderDir" + STATUS=$(docker inspect -f '{{.State.Status}}' "labca-bredis-1") + cnt=$(docker compose logs bredis | tail -100 | grep "sslv3 alert bad certificate" | wc -l) + if [ "$STATUS" == "starting" ] || [ "$cnt" -gt "5" ]; then + msg="Restarting redis container" + msg_info "$msg" + docker compose stop bredis &>>$installLog + docker compose rm -f bredis &>>$installLog + docker compose up -d bredis &>>$installLog + msg_ok "$msg" + fi +} + # # The actual main function to tie it all together # @@ -917,6 +932,8 @@ main() { cleanup startup + sweepup + echo -e "$DONE" echo diff --git a/patches/bad-key-revoker_main.patch b/patches/bad-key-revoker_main.patch index f70a199..2589ba8 100644 --- a/patches/bad-key-revoker_main.patch +++ b/patches/bad-key-revoker_main.patch @@ -1,8 +1,8 @@ diff --git a/cmd/bad-key-revoker/main.go b/cmd/bad-key-revoker/main.go -index 8e6cfac85..8880ed301 100644 +index 34c58eae5..dd40b9469 100644 --- a/cmd/bad-key-revoker/main.go +++ b/cmd/bad-key-revoker/main.go -@@ -270,6 +270,11 @@ type Config struct { +@@ -275,6 +275,11 @@ type Config struct { TLS cmd.TLSConfig RAService *cmd.GRPCClientConfig @@ -14,12 +14,12 @@ index 8e6cfac85..8880ed301 100644 // MaximumRevocations specifies the maximum number of certificates associated with // a key hash that bad-key-revoker will attempt to revoke. If the number of certificates // is higher than MaximumRevocations bad-key-revoker will error out and refuse to -@@ -289,6 +294,8 @@ type Config struct { - // or no work to do. - BackoffIntervalMax config.Duration `validate:"-"` - -+ UserAgent string +@@ -301,6 +306,8 @@ type Config struct { + // the database's maximum replication lag, and always well under 24 + // hours. + MaxExpectedReplicationLag config.Duration `validate:"-"` + - // Deprecated: the bad-key-revoker no longer sends emails; we use ARI. - // TODO(#8199): Remove this config stanza entirely. - Mailer struct { ++ UserAgent string + } + + Syslog cmd.SyslogConfig diff --git a/patches/ceremony_ecdsa.patch b/patches/ceremony_ecdsa.patch index 31aa2e3..e2d28c3 100644 --- a/patches/ceremony_ecdsa.patch +++ b/patches/ceremony_ecdsa.patch @@ -1,8 +1,8 @@ diff --git a/cmd/ceremony/ecdsa.go b/cmd/ceremony/ecdsa.go -index 65f5c6f99..24102ad8e 100644 +index 3adec7313..dc00269fd 100644 --- a/cmd/ceremony/ecdsa.go +++ b/cmd/ceremony/ecdsa.go -@@ -29,7 +29,7 @@ var curveToOIDDER = map[string][]byte{ +@@ -30,7 +30,7 @@ var curveToOIDDER = map[string][]byte{ // ecArgs constructs the private and public key template attributes sent to the // device and specifies which mechanism should be used. curve determines which // type of key should be generated. @@ -11,7 +11,7 @@ index 65f5c6f99..24102ad8e 100644 encodedCurve := curveToOIDDER[curve.Params().Name] log.Printf("\tEncoded curve parameters for %s: %X\n", curve.Params().Name, encodedCurve) return generateArgs{ -@@ -50,7 +50,7 @@ func ecArgs(label string, curve elliptic.Curve, keyID []byte) generateArgs { +@@ -51,7 +51,7 @@ func ecArgs(label string, curve elliptic.Curve, keyID []byte) generateArgs { // Prevent attributes being retrieved pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true), // Prevent the key being extracted from the device @@ -20,7 +20,7 @@ index 65f5c6f99..24102ad8e 100644 // Allow the key to sign data pkcs11.NewAttribute(pkcs11.CKA_SIGN, true), }, -@@ -81,7 +81,7 @@ func ecPub( +@@ -82,7 +82,7 @@ func ecPub( // specified by curveStr and with the provided label. It returns the public // part of the generated key pair as a ecdsa.PublicKey and the random key ID // that the HSM uses to identify the key pair. @@ -29,7 +29,7 @@ index 65f5c6f99..24102ad8e 100644 curve, present := stringToCurve[curveStr] if !present { return nil, nil, fmt.Errorf("curve %q not supported", curveStr) -@@ -92,7 +92,7 @@ func ecGenerate(session *pkcs11helpers.Session, label, curveStr string) (*ecdsa. +@@ -93,7 +93,7 @@ func ecGenerate(session *pkcs11helpers.Session, label, curveStr string) (*ecdsa. return nil, nil, err } log.Printf("Generating ECDSA key with curve %s and ID %x\n", curveStr, keyID) diff --git a/patches/ceremony_key.patch b/patches/ceremony_key.patch index 77d51f1..32b9d0e 100644 --- a/patches/ceremony_key.patch +++ b/patches/ceremony_key.patch @@ -1,19 +1,19 @@ diff --git a/cmd/ceremony/key.go b/cmd/ceremony/key.go -index e0ed20594..4c4656b4d 100644 +index 2315a2081..f3210c75d 100644 --- a/cmd/ceremony/key.go +++ b/cmd/ceremony/key.go -@@ -56,12 +56,12 @@ func generateKey(session *pkcs11helpers.Session, label string, outputPath string +@@ -57,12 +57,12 @@ func generateKey(session *pkcs11helpers.Session, label string, outputPath string var keyID []byte switch config.Type { case "rsa": - pubKey, keyID, err = rsaGenerate(session, label, config.RSAModLength) + pubKey, keyID, err = rsaGenerate(session, label, config.RSAModLength, config.Extractable) if err != nil { - return nil, fmt.Errorf("failed to generate RSA key pair: %s", err) + return nil, fmt.Errorf("failed to generate RSA key pair: %w", err) } case "ecdsa": - pubKey, keyID, err = ecGenerate(session, label, config.ECDSACurve) + pubKey, keyID, err = ecGenerate(session, label, config.ECDSACurve, config.Extractable) if err != nil { - return nil, fmt.Errorf("failed to generate ECDSA key pair: %s", err) + return nil, fmt.Errorf("failed to generate ECDSA key pair: %w", err) } diff --git a/patches/cmd_config.patch b/patches/cmd_config.patch index f6b0049..196ce0a 100644 --- a/patches/cmd_config.patch +++ b/patches/cmd_config.patch @@ -1,8 +1,8 @@ diff --git a/cmd/config.go b/cmd/config.go -index 13842fdf9..33cb282cb 100644 +index 29649639f..776ebb5f2 100644 --- a/cmd/config.go +++ b/cmd/config.go -@@ -471,7 +471,7 @@ type GRPCServerConfig struct { +@@ -462,7 +462,7 @@ type GRPCServerConfig struct { // this controls how long it takes before a client learns about changes to its // backends. // https://pkg.go.dev/google.golang.org/grpc/keepalive#ServerParameters diff --git a/patches/config_bad-key-revoker.patch b/patches/config_bad-key-revoker.patch index bff7676..09a13a8 100644 --- a/patches/config_bad-key-revoker.patch +++ b/patches/config_bad-key-revoker.patch @@ -1,5 +1,5 @@ diff --git a/test/config/bad-key-revoker.json b/test/config/bad-key-revoker.json -index d70aadc5f..99dfde454 100644 +index 731dfee0d..22c6f1718 100644 --- a/test/config/bad-key-revoker.json +++ b/test/config/bad-key-revoker.json @@ -5,6 +5,13 @@ @@ -16,12 +16,15 @@ index d70aadc5f..99dfde454 100644 "tls": { "caCertFile": "test/certs/ipki/minica.pem", "certFile": "test/certs/ipki/bad-key-revoker.boulder/cert.pem", -@@ -32,7 +39,7 @@ +@@ -22,9 +29,9 @@ }, "maximumRevocations": 15, "findCertificatesBatchSize": 10, - "interval": "50ms", + "interval": "5m", - "backoffIntervalMax": "2s" + "backoffIntervalMax": "2s", +- "maxExpectedReplicationLag": "100ms" ++ "maxExpectedReplicationLag": "10m" }, "syslog": { + "stdoutlevel": 4, diff --git a/patches/config_ra.patch b/patches/config_ra.patch index 4dac21d..dcc6016 100644 --- a/patches/config_ra.patch +++ b/patches/config_ra.patch @@ -1,5 +1,5 @@ diff --git a/test/config/ra.json b/test/config/ra.json -index 613c5e1a1..c43053523 100644 +index ade9fcc1c..994fa031a 100644 --- a/test/config/ra.json +++ b/test/config/ra.json @@ -3,7 +3,8 @@ @@ -31,8 +31,8 @@ index 613c5e1a1..c43053523 100644 }, "maxContactsPerRegistration": 3, "debugAddr": ":8002", -- "hostnamePolicyFile": "test/hostname-policy.yaml", -+ "hostnamePolicyFile": "labca/hostname-policy.yaml", +- "hostnamePolicyFile": "test/ident-policy.yaml", ++ "hostnamePolicyFile": "labca/ident-policy.yaml", "goodkey": {}, "issuerCerts": [ - "test/certs/webpki/int-rsa-a.cert.pem", @@ -45,7 +45,7 @@ index 613c5e1a1..c43053523 100644 ], "validationProfiles": { "legacy": { -@@ -67,9 +63,9 @@ +@@ -68,9 +64,9 @@ }, "defaultProfileName": "legacy", "tls": { @@ -58,7 +58,7 @@ index 613c5e1a1..c43053523 100644 }, "vaService": { "dnsAuthority": "consul.service.consul", -@@ -163,7 +159,7 @@ +@@ -164,7 +160,7 @@ }, "ctLogs": { "stagger": "500ms", diff --git a/patches/config_wfe2.patch b/patches/config_wfe2.patch index 4bb9f87..d3fe07b 100644 --- a/patches/config_wfe2.patch +++ b/patches/config_wfe2.patch @@ -19,7 +19,7 @@ index 51c7aa8ef..1ed5d37af 100644 "directoryCAAIdentity": "happy-hacker-ca.invalid", - "directoryWebsite": "https://github.com/letsencrypt/boulder", + "directoryWebsite": "https://github.com/hakwerk/labca", -+ "hostnamePolicyFile": "labca/hostname-policy.yaml", ++ "hostnamePolicyFile": "labca/ident-policy.yaml", "legacyKeyIDPrefix": "http://boulder.service.consul:4000/reg/", "goodkey": {}, "tls": { diff --git a/patches/docker-compose.patch b/patches/docker-compose.patch index 70317d1..b4522bd 100644 --- a/patches/docker-compose.patch +++ b/patches/docker-compose.patch @@ -66,7 +66,7 @@ index 8092b1522..b9a8ac069 100644 + restart: always bmysql: - image: mariadb:10.6.22 + image: mariadb:10.11.13 + volumes: + - dbdata:/var/lib/mysql networks: diff --git a/patches/policy_pa.patch b/patches/policy_pa.patch index f8642bd..4fcb580 100644 --- a/patches/policy_pa.patch +++ b/patches/policy_pa.patch @@ -1,32 +1,32 @@ diff --git a/policy/pa.go b/policy/pa.go -index f53100322..107c5986e 100644 +index 961b67cb6..4e0ea33f6 100644 --- a/policy/pa.go +++ b/policy/pa.go @@ -31,6 +31,9 @@ type AuthorityImpl struct { - blocklist map[string]bool - exactBlocklist map[string]bool - wildcardExactBlocklist map[string]bool -+ whitelist map[string]bool -+ lockdown map[string]bool -+ ldPublicContacts bool - blocklistMu sync.RWMutex + domainBlocklist map[string]bool + fqdnBlocklist map[string]bool + wildcardFqdnBlocklist map[string]bool ++ whitelist map[string]bool ++ lockdown map[string]bool ++ ldPublicContacts bool + ipPrefixBlocklist []netip.Prefix + blocklistMu sync.RWMutex - enabledChallenges map[core.AcmeChallenge]bool -@@ -66,6 +69,10 @@ type blockedNamesPolicy struct { - // time above and beyond the high-risk domains. Managing these entries separately - // from HighRiskBlockedNames makes it easier to vet changes accurately. - AdminBlockedNames []string `yaml:"AdminBlockedNames"` +@@ -72,6 +75,10 @@ type blockedIdentsPolicy struct { + // AdminBlockedPrefixes is a list of IP address prefixes. All IP addresses + // contained within the prefix are blocked. + AdminBlockedPrefixes []string `yaml:"AdminBlockedPrefixes"` + + Whitelist []string `yaml:"Whitelist"` + Lockdown []string `yaml:"Lockdown"` + LockdownAllowPublicContacts bool `yaml:"LockdownAllowPublicContacts"` } - // LoadHostnamePolicyFile will load the given policy file, returning an error if -@@ -125,10 +132,21 @@ func (pa *AuthorityImpl) processHostnamePolicy(policy blockedNamesPolicy) error - // wildcardNameMap to block issuance for `*.`+parts[1] - wildcardNameMap[parts[1]] = true + // LoadIdentPolicyFile will load the given policy file, returning an error if it +@@ -143,11 +150,23 @@ func (pa *AuthorityImpl) processIdentPolicy(policy blockedIdentsPolicy) error { + prefixes = append(prefixes, prefix) } + + whiteMap := make(map[string]bool) + for _, v := range policy.Whitelist { + whiteMap[v] = true @@ -35,17 +35,19 @@ index f53100322..107c5986e 100644 + for _, v := range policy.Lockdown { + lockMap[v] = true + } ++ pa.blocklistMu.Lock() - pa.blocklist = nameMap - pa.exactBlocklist = exactNameMap - pa.wildcardExactBlocklist = wildcardNameMap + pa.domainBlocklist = nameMap + pa.fqdnBlocklist = exactNameMap + pa.wildcardFqdnBlocklist = wildcardNameMap + pa.ipPrefixBlocklist = prefixes + pa.whitelist = whiteMap + pa.lockdown = lockMap + pa.ldPublicContacts = policy.LockdownAllowPublicContacts pa.blocklistMu.Unlock() return nil } -@@ -199,7 +217,7 @@ var ( +@@ -218,7 +237,7 @@ var ( // - exactly equal to an IANA registered TLD // // It does NOT ensure that the domain is absent from any PA blocked lists. @@ -54,33 +56,40 @@ index f53100322..107c5986e 100644 if domain == "" { return errEmptyIdentifier } -@@ -232,7 +250,9 @@ func validNonWildcardDomain(domain string) error { +@@ -251,7 +270,9 @@ func validNonWildcardDomain(domain string) error { return errTooManyLabels } if len(labels) < 2 { - return errTooFewLabels -+ if !pa.lockdown[domain] && !pa.whitelist[domain] { ++ if (len(pa.lockdown) > 0 || len(pa.whitelist) > 0) && !pa.lockdown[domain] && !pa.whitelist[domain] { + return errTooFewLabels + } } for _, label := range labels { // Check that this is a valid LDH Label: "A string consisting of ASCII -@@ -276,6 +296,14 @@ func validNonWildcardDomain(domain string) error { +@@ -295,12 +316,17 @@ func validNonWildcardDomain(domain string) error { } } +- // Names must end in an ICANN TLD, but they must not be equal to an ICANN TLD. +- icannTLD, err := iana.ExtractSuffix(domain) + ok, err := pa.checkWhitelist(domain, isContact) -+ if err != nil { + if err != nil { +- return errNonPublic + return err + } + if ok { + return nil -+ } + } +- if icannTLD == domain { + - // Names must end in an ICANN TLD, but they must not be equal to an ICANN TLD. - icannTLD, err := iana.ExtractSuffix(domain) - if err != nil { -@@ -291,9 +319,9 @@ func validNonWildcardDomain(domain string) error { ++ // Names must not be equal to an ICANN TLD. ++ icannTLD, err := iana.ExtractSuffix(domain) ++ if err == nil && icannTLD == domain { + return errICANNTLD + } + +@@ -310,9 +336,9 @@ func validNonWildcardDomain(domain string) error { // ValidDomain checks that a domain is valid and that it doesn't contain any // invalid wildcard characters. It does NOT ensure that the domain is absent // from any PA blocked lists. @@ -92,7 +101,7 @@ index f53100322..107c5986e 100644 } // Names containing more than one wildcard are invalid. -@@ -312,7 +340,7 @@ func ValidDomain(domain string) error { +@@ -331,7 +357,7 @@ func ValidDomain(domain string) error { // Names must end in an ICANN TLD, but they must not be equal to an ICANN TLD. icannTLD, err := iana.ExtractSuffix(baseDomain) @@ -101,7 +110,7 @@ index f53100322..107c5986e 100644 return errNonPublic } // Names must have a non-wildcard label immediately adjacent to the ICANN -@@ -320,7 +348,7 @@ func ValidDomain(domain string) error { +@@ -339,7 +365,7 @@ func ValidDomain(domain string) error { if baseDomain == icannTLD { return errICANNTLDWildcard } @@ -110,7 +119,7 @@ index f53100322..107c5986e 100644 } // ValidIP checks that an IP address: -@@ -363,14 +391,14 @@ var forbiddenMailDomains = map[string]bool{ +@@ -382,14 +408,14 @@ var forbiddenMailDomains = map[string]bool{ // ValidEmail returns an error if the input doesn't parse as an email address, // the domain isn't a valid hostname in Preferred Name Syntax, or its on the // list of domains forbidden for mail (because they are often used in examples). @@ -127,7 +136,7 @@ index f53100322..107c5986e 100644 if err != nil { return berrors.InvalidEmailError("contact email has invalid domain: %s", err) } -@@ -412,7 +440,7 @@ func subError(ident identifier.ACMEIdentifier, err error) berrors.SubBoulderErro +@@ -431,7 +457,7 @@ func subError(ident identifier.ACMEIdentifier, err error) berrors.SubBoulderErro // // Precondition: all input identifier values must be in lowercase. func (pa *AuthorityImpl) WillingToIssue(idents identifier.ACMEIdentifiers) error { @@ -136,18 +145,18 @@ index f53100322..107c5986e 100644 if err != nil { return err } -@@ -442,6 +470,10 @@ func (pa *AuthorityImpl) WillingToIssue(idents identifier.ACMEIdentifiers) error - } - } +@@ -448,6 +474,10 @@ func (pa *AuthorityImpl) WillingToIssue(idents identifier.ACMEIdentifiers) error + // The base domain is the wildcard request with the `*.` prefix removed + baseDomain := strings.TrimPrefix(ident.Value, "*.") + if ok, _ := pa.checkWhitelist(ident.Value, false); ok { + return nil + } + - // For both wildcard and non-wildcard domains, check whether any parent domain - // name is on the regular blocklist. - err := pa.checkHostLists(ident.Value) -@@ -483,12 +515,12 @@ func (pa *AuthorityImpl) WillingToIssue(idents identifier.ACMEIdentifiers) error + // The base domain can't be in the wildcard exact blocklist + err = pa.checkWildcardBlocklist(baseDomain) + if err != nil { +@@ -496,12 +526,12 @@ func (pa *AuthorityImpl) WillingToIssue(idents identifier.ACMEIdentifiers) error // // If multiple identifiers are invalid, the error will contain suberrors // specific to each identifier. @@ -162,7 +171,7 @@ index f53100322..107c5986e 100644 if err != nil { subErrors = append(subErrors, subError(ident, err)) } -@@ -530,6 +562,34 @@ func combineSubErrors(subErrors []berrors.SubBoulderError) error { +@@ -543,6 +573,34 @@ func combineSubErrors(subErrors []berrors.SubBoulderError) error { return nil } @@ -194,16 +203,16 @@ index f53100322..107c5986e 100644 + } +} + - // checkWildcardHostList checks the wildcardExactBlocklist for a given domain. + // checkWildcardBlocklist checks the wildcardExactBlocklist for a given domain. // If the domain is not present on the list nil is returned, otherwise // errPolicyForbidden is returned. -@@ -559,6 +619,9 @@ func (pa *AuthorityImpl) checkHostLists(domain string) error { - labels := strings.Split(domain, ".") - for i := range labels { - joined := strings.Join(labels[i:], ".") -+ if pa.lockdown[domain] { -+ continue -+ } - if pa.blocklist[joined] { - return errPolicyForbidden - } +@@ -574,6 +632,9 @@ func (pa *AuthorityImpl) checkBlocklists(ident identifier.ACMEIdentifier) error + labels := strings.Split(ident.Value, ".") + for i := range labels { + joined := strings.Join(labels[i:], ".") ++ if pa.lockdown[joined] { ++ return nil ++ } + if pa.domainBlocklist[joined] { + return errPolicyForbidden + } diff --git a/patches/test_certs_generate.patch b/patches/test_certs_generate.patch index dfc50e3..6ee5ea6 100644 --- a/patches/test_certs_generate.patch +++ b/patches/test_certs_generate.patch @@ -1,8 +1,8 @@ diff --git a/test/certs/generate.sh b/test/certs/generate.sh -index f6ef272d3..e58c54b6c 100755 +index f6ef272d3..bfc60f293 100755 --- a/test/certs/generate.sh +++ b/test/certs/generate.sh -@@ -63,9 +63,9 @@ webpki() ( +@@ -63,16 +63,50 @@ webpki() ( # This function executes in a subshell, so this cd does not affect the parent # script. cd ../.. @@ -14,8 +14,10 @@ index f6ef272d3..e58c54b6c 100755 + # go run ./labca/certs/webpki.go ) ++umask 0022 ++ if ! [ -d ipki ]; then -@@ -73,6 +73,36 @@ if ! [ -d ipki ]; then + echo "Generating ipki/..." ipki fi @@ -35,6 +37,8 @@ index f6ef272d3..e58c54b6c 100755 + cd ipki + mv redis redis.bak + minica -domains redis -ip-addresses 10.77.77.2,10.77.77.3,10.77.77.4,10.77.77.5 ++ chmod go+rx redis ++ chmod go+r redis/* + cd - +fi + diff --git a/patches/test_config_ca.patch b/patches/test_config_ca.patch index 9fea312..52c94be 100644 --- a/patches/test_config_ca.patch +++ b/patches/test_config_ca.patch @@ -1,5 +1,5 @@ diff --git a/test/config/ca.json b/test/config/ca.json -index e9a866ee6..e44b75aed 100644 +index 6e60285a5..672cb29ce 100644 --- a/test/config/ca.json +++ b/test/config/ca.json @@ -1,11 +1,11 @@ @@ -13,12 +13,12 @@ index e9a866ee6..e44b75aed 100644 + "certFile": "labca/certs/ipki/ca.boulder/cert.pem", + "keyFile": "labca/certs/ipki/ca.boulder/key.pem" }, -- "hostnamePolicyFile": "test/hostname-policy.yaml", -+ "hostnamePolicyFile": "labca/hostname-policy.yaml", +- "hostnamePolicyFile": "test/ident-policy.yaml", ++ "hostnamePolicyFile": "labca/ident-policy.yaml", "grpcCA": { "maxConnectionAge": "30s", "address": ":9093", -@@ -60,7 +60,8 @@ +@@ -64,7 +64,8 @@ "includeCRLDistributionPoints": true, "maxValidityPeriod": "7776000s", "maxValidityBackdate": "1h5m", @@ -27,27 +27,27 @@ index e9a866ee6..e44b75aed 100644 + "lintConfig": "labca/config/zlint.toml", "ignoredLints": [ "w_subject_common_name_included", - "w_ext_subject_key_identifier_not_recommended_subscriber" -@@ -76,7 +77,8 @@ + "e_dnsname_not_valid_tld", +@@ -81,7 +82,8 @@ "includeCRLDistributionPoints": true, - "maxValidityPeriod": "583200s", + "maxValidityPeriod": "160h", "maxValidityBackdate": "1h5m", - "lintConfig": "test/config-next/zlint.toml", + "includeCRLDistributionPoints": true, + "lintConfig": "labca/config/zlint.toml", "ignoredLints": [ - "w_ext_subject_key_identifier_missing_sub_cert" - ] -@@ -91,7 +93,7 @@ + "w_ext_subject_key_identifier_missing_sub_cert", + "e_dnsname_not_valid_tld" +@@ -97,7 +99,7 @@ "includeCRLDistributionPoints": true, - "maxValidityPeriod": "160h", + "maxValidityPeriod": "583200s", "maxValidityBackdate": "1h5m", - "lintConfig": "test/config-next/zlint.toml", + "lintConfig": "labca/config-next/zlint.toml", "ignoredLints": [ - "w_ext_subject_key_identifier_missing_sub_cert" - ] -@@ -100,78 +102,19 @@ + "w_ext_subject_key_identifier_missing_sub_cert", + "e_dnsname_not_valid_tld" +@@ -107,78 +109,19 @@ "crlProfile": { "validityInterval": "216h", "maxBackdate": "1h5m", @@ -130,7 +130,7 @@ index e9a866ee6..e44b75aed 100644 "numSessions": 2 } } -@@ -183,7 +126,7 @@ +@@ -190,7 +133,7 @@ "goodkey": {}, "ocspLogMaxLength": 4000, "ocspLogPeriod": "500ms", @@ -139,7 +139,7 @@ index e9a866ee6..e44b75aed 100644 "features": {} }, "pa": { -@@ -197,7 +140,7 @@ +@@ -205,7 +148,7 @@ } }, "syslog": { diff --git a/patches/test_startservers.patch b/patches/test_startservers.patch index 5dd6bea..618b6a6 100644 --- a/patches/test_startservers.patch +++ b/patches/test_startservers.patch @@ -1,8 +1,8 @@ diff --git a/test/startservers.py b/test/startservers.py -index 8c812ea01..c42a1bb51 100644 +index 4e2ce1b24..e4645852a 100644 --- a/test/startservers.py +++ b/test/startservers.py -@@ -90,6 +90,10 @@ SERVICES = ( +@@ -86,6 +86,10 @@ SERVICES = ( 9667, None, None, ('./bin/boulder', 'crl-storer', '--config', os.path.join(config_dir, 'crl-storer.json'), '--addr', ':9309', '--debug-addr', ':9667'), ('s3-test-srv',)), diff --git a/patches/wfe2_main.patch b/patches/wfe2_main.patch index 2386460..be9f1fb 100644 --- a/patches/wfe2_main.patch +++ b/patches/wfe2_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/boulder-wfe2/main.go b/cmd/boulder-wfe2/main.go -index 955fe406c..33cc238d9 100644 +index 955fe406c..ae127564e 100644 --- a/cmd/boulder-wfe2/main.go +++ b/cmd/boulder-wfe2/main.go @@ -12,14 +12,17 @@ import ( @@ -57,7 +57,7 @@ index 955fe406c..33cc238d9 100644 + if c.WFE.HostnamePolicyFile == "" { + cmd.Fail("HostnamePolicyFile must be provided.") + } -+ err = pa.LoadHostnamePolicyFile(c.WFE.HostnamePolicyFile) ++ err = pa.LoadIdentPolicyFile(c.WFE.HostnamePolicyFile) + cmd.FailOnError(err, "Couldn't load hostname policy file") + ratelimits.PA = pa +