diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05e9ed4..e6a1997 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: fail-fast: false matrix: GO_VERSION: - - 1.21.4 + - 1.21.5 steps: - name: Checkout diff --git a/build/Dockerfile-boulder b/build/Dockerfile-boulder index 67c21a6..38a3f8c 100644 --- a/build/Dockerfile-boulder +++ b/build/Dockerfile-boulder @@ -1,4 +1,4 @@ -FROM letsencrypt/boulder-tools:go1.21.4_2023-11-09 AS boulder-tools +FROM letsencrypt/boulder-tools:go1.21.5_2023-12-11 AS boulder-tools FROM ubuntu:focal diff --git a/build/build.sh b/build/build.sh index a03e2d9..4d0d821 100755 --- a/build/build.sh +++ b/build/build.sh @@ -8,13 +8,13 @@ TMP_DIR=$(pwd)/tmp rm -rf $TMP_DIR && mkdir -p $TMP_DIR/{admin,bin,logs,src} boulderDir=$TMP_DIR/src -boulderTag="release-2023-12-04" +boulderTag="release-2024-01-08" boulderUrl="https://github.com/letsencrypt/boulder/" cloneDir=$(pwd)/.. GIT_VERSION=$(git describe --always --tags 2>/dev/null) BUILD_HOST=labca-$GIT_VERSION -BUILD_IMAGE=$(eval echo $(grep boulder-tools ../patches/docker-compose.patch | head -1 | sed -e "s/image://" | sed -e "s/&boulder_image//")) +BUILD_IMAGE=$(eval echo $(grep boulder-tools ../patches/docker-compose.patch | head -3 | tail -1 | sed -e "s/\+\s*image://" | sed -e "s/&boulder_image//")) git clone --branch $boulderTag --depth 1 $boulderUrl $boulderDir 2>/dev/null cd $boulderDir diff --git a/build/tmp.patch b/build/tmp.patch index 7b67ebc..a90a78c 100644 --- a/build/tmp.patch +++ b/build/tmp.patch @@ -1,17 +1,17 @@ diff --git a/docker-compose.yml b/docker-compose.yml -index 74f1cf0f8..da119321b 100644 +index aeb34b387..16db397ae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml -@@ -3,7 +3,7 @@ name: labca - services: - boulder: - # Should match one of the GO_DEV_VERSIONS in test/boulder-tools/tag_and_upload.sh. -- image: &boulder_image letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-go1.21.4_2023-11-09} +@@ -5,7 +5,7 @@ services: + # The `letsencrypt/boulder-tools:latest` tag is automatically built in local + # dev environments. In CI a specific BOULDER_TOOLS_TAG is passed, and it is + # pulled with `docker compose pull`. +- image: &boulder_image letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-go1.21.5_2023-12-11} + image: ghcr.io/hakwerk/labca-boulder:${LABCA_IMAGE_VERSION:-latest} - environment: - # To solve HTTP-01 and TLS-ALPN-01 challenges, change the IP in FAKE_DNS - # to the IP address where your ACME client's solver is listening. -@@ -15,12 +15,9 @@ services: + build: + context: test/boulder-tools/ + # Should match one of the GO_DEV_VERSIONS in test/boulder-tools/tag_and_upload.sh. +@@ -22,12 +22,9 @@ services: # Forward the parent env's GOEXPERIMENT value into the container. GOEXPERIMENT: ${GOEXPERIMENT:-} volumes: @@ -27,7 +27,7 @@ index 74f1cf0f8..da119321b 100644 networks: bluenet: ipv4_address: 10.77.77.77 -@@ -44,6 +41,7 @@ services: +@@ -51,6 +48,7 @@ services: depends_on: - bmysql - bconsul @@ -35,7 +35,7 @@ index 74f1cf0f8..da119321b 100644 entrypoint: labca/entrypoint.sh working_dir: &boulder_working_dir /opt/boulder logging: -@@ -78,8 +76,10 @@ services: +@@ -85,8 +83,10 @@ services: bconsul: image: hashicorp/consul:1.15.4 @@ -47,7 +47,7 @@ index 74f1cf0f8..da119321b 100644 networks: consulnet: ipv4_address: 10.55.55.10 -@@ -87,27 +87,28 @@ services: +@@ -94,27 +94,28 @@ services: ipv4_address: 10.77.77.10 rednet: ipv4_address: 10.88.88.10 @@ -86,7 +86,7 @@ index 74f1cf0f8..da119321b 100644 logging: driver: "json-file" options: -@@ -124,27 +125,26 @@ services: +@@ -131,27 +132,26 @@ services: - 80:80 - 443:443 volumes: @@ -128,7 +128,7 @@ index 74f1cf0f8..da119321b 100644 expose: - 3030 environment: -@@ -155,6 +155,14 @@ services: +@@ -162,6 +162,14 @@ services: volumes: dbdata: diff --git a/build/tmp2.patch b/build/tmp2.patch index 4a85afc..59b4028 100644 --- a/build/tmp2.patch +++ b/build/tmp2.patch @@ -1,10 +1,10 @@ diff --git a/test/startservers.py b/test/startservers.py -index 6aa2f9a..7d17d7f 100644 +index 135e6c9e4..04cd88adf 100644 --- a/test/startservers.py +++ b/test/startservers.py -@@ -159,6 +159,9 @@ def setupHierarchyOriginal(): - - +@@ -160,6 +160,9 @@ def setupHierarchyOriginal(): + + def install(race_detection): + return True + diff --git a/dev/versions b/dev/versions new file mode 100755 index 0000000..b69a576 --- /dev/null +++ b/dev/versions @@ -0,0 +1,96 @@ +#!/bin/sh + +set -e + +COL_NC='\\e\[0m' # No Color +COL_LIGHT_GREEN='\\e\[1;32m' +COL_YELLOW='\\e\[1;33m' +COL_LIGHT_RED='\\e\[1;31m' + +colorBoulderTag() { + local fileName="$1" + local expectVersion="$2" + + actualVersion=$(grep -R boulderTag= $fileName | sed -e "s/boulderTag=\"\(.*\)\"/\1/") + sub=$(echo $actualVersion | cut -c1-8) + if [ "$actualVersion" = "$expectVersion" ]; then + actualVersion="${COL_LIGHT_GREEN}${actualVersion}${COL_NC}" + elif [ "$sub" = "release-" ]; then + actualVersion="${COL_LIGHT_RED}${actualVersion}${COL_NC}" + else + actualVersion="${COL_YELLOW}${actualVersion}${COL_NC}" + fi + result=$(grep -R boulderTag= $fileName | sed -e "s/\(boulderTag=\"\).*\(\"\)/\1${actualVersion}\2/") + echo "$fileName: $result" +} + +colorCITag() { + local fileName="$1" + + first=$(grep go1. ../boulder/.github/workflows/boulder-ci.yml | head -1 | sed -e "s/\s*-\s*//") + second=$(grep go1. ../boulder/.github/workflows/boulder-ci.yml | head -2 | tail -1 | sed -e "s/\s*-\s*//") + + if [ ! -z "$(grep -R boulder-tools: $fileName | grep -v automatically | grep $first || echo "")" ]; then + res=$(grep -R boulder-tools: $fileName | grep -v automatically | sed -e "s/$first/${COL_LIGHT_GREEN}$first${COL_NC}/") + elif [ ! -z "$(grep -R boulder-tools: $fileName | grep -v automatically | grep $second || echo "")" ]; then + res=$(grep -R boulder-tools: $fileName | grep -v automatically | sed -e "s/$second/${COL_YELLOW}$second${COL_NC}/") + else + res=$(grep -R boulder-tools: $fileName | grep -v automatically | sed -e "s/\(:-*\)\([cgor\.0-9_-]*\)/\1${COL_LIGHT_RED}\2${COL_NC}/g") + fi + + echo "$fileName:$res" +} + +colorNGTag() { + local fileName="$1" + local expectVersion="$2" + + if [ ! -z "$(grep -R nginx: $fileName | egrep "[\"0-9]+" | grep $expectVersion || echo "")" ]; then + res=$(grep -R nginx: $fileName | egrep "[\"0-9]+" | sed -e "s/$expectVersion/${COL_LIGHT_GREEN}$expectVersion${COL_NC}/") + else + res=$(grep -R nginx: $fileName | egrep "[\"0-9]+" | sed -e "s/\(.*:\)\([0-9\.]*\)/\1${COL_LIGHT_RED}\2${COL_NC}/") + fi + echo "$fileName:$res" +} + +colorGoVersion() { + local fileName="$1" + local expectVersion="$2" + + if [ ! -z "$(grep GO_VERSION -A 3 $fileName | egrep "\- [\"0-9]+" | grep $expectVersion || echo "")" ]; then + res=$(grep GO_VERSION -A 3 $fileName | egrep "\- [\"0-9]+" | sed -e "s/$expectVersion/${COL_LIGHT_GREEN}$expectVersion${COL_NC}/") + else + res=$(grep GO_VERSION -A 3 $fileName | egrep "\- [\"0-9]+" | sed -e "s/\([0-9\.]*\)/${COL_LIGHT_RED}\1${COL_NC}/g") + fi + echo "$fileName:$res" +} + +echo + +cd ../boulder +bversion=$(git describe --tags $(git rev-list --tags --max-count=1)) +cd - >/dev/null +echo "Boulder tag: $bversion" +colorBoulderTag install $bversion +colorBoulderTag build/build.sh $bversion +echo + +echo "Boulder CI tag(s):" +grep go1. ../boulder/.github/workflows/boulder-ci.yml +colorCITag build/tmp.patch +colorCITag build/Dockerfile-boulder +echo + +ngversion=$(grep -R nginx: .github/Dockerfile | egrep "[\"0-9]+" | sed -e "s/.*:\([0-9\.]*\)/\1/") +echo -n ".github/Dockerfile:" +grep -R nginx: .github/Dockerfile | egrep "[\"0-9]+" +colorNGTag build/docker-compose.yml $ngversion +colorNGTag patches/docker-compose.patch $ngversion +echo + +goversion=$(grep GO_VERSION -A 3 ../boulder/.github/workflows/release.yml | egrep "\- [\"0-9]+" | sed -e "s/\s*-\s*//" | sed -e "s/\"//g") +echo -n "../boulder/.github/workflows/release.yml" +grep GO_VERSION -A 3 ../boulder/.github/workflows/release.yml | egrep "\- [\"0-9]+" | sed -e "s/yml-/yml/" +colorGoVersion .github/workflows/release.yml $goversion +echo + diff --git a/install b/install index 6816472..73d0a7b 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="release-2023-12-04" +boulderTag="release-2024-01-08" # Feature flags flag_skip_redis=true diff --git a/mail-tester.go b/mail-tester.go index 4ee7457..16cda2b 100644 --- a/mail-tester.go +++ b/mail-tester.go @@ -56,7 +56,7 @@ type config struct { // during the SMTP connection (as opposed to the gRPC connections). SMTPTrustedRootFile string - Features map[string]bool + Features features.Config } Syslog cmd.SyslogConfig @@ -81,8 +81,8 @@ func main() { var c config err := cmd.ReadConfigFile(*configFile, &c) cmd.FailOnError(err, "Reading JSON config file into config structure") - err = features.Set(c.Mailer.Features) - cmd.FailOnError(err, "Failed to set feature flags") + + features.Set(c.Mailer.Features) scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.Mailer.DebugAddr) defer oTelShutdown(context.Background()) @@ -99,6 +99,8 @@ func main() { var resolver bdns.Client servers, err := bdns.NewStaticProvider(c.Mailer.DNSResolvers) cmd.FailOnError(err, "Couldn't parse static DNS server(s)") + tlsConfig, err := c.Mailer.TLS.Load(scope) + cmd.FailOnError(err, "TLS config") if !c.Mailer.DNSAllowLoopbackAddresses { r := bdns.New( dnsTimeout, @@ -106,10 +108,11 @@ func main() { scope, clk, dnsTries, - logger) + logger, + tlsConfig) resolver = r } else { - r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger) + r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger, tlsConfig) resolver = r } diff --git a/patches/bad-key-revoker_main.patch b/patches/bad-key-revoker_main.patch index 2b9ee74..1cc4e0c 100644 --- a/patches/bad-key-revoker_main.patch +++ b/patches/bad-key-revoker_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/bad-key-revoker/main.go b/cmd/bad-key-revoker/main.go -index e4e7b5a8..e0337a96 100644 +index e7015e0c8..860c3d0dd 100644 --- a/cmd/bad-key-revoker/main.go +++ b/cmd/bad-key-revoker/main.go @@ -18,6 +18,7 @@ import ( @@ -22,7 +22,7 @@ index e4e7b5a8..e0337a96 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 -@@ -462,6 +468,29 @@ func main() { +@@ -467,6 +473,30 @@ func main() { cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA") rac := rapb.NewRegistrationAuthorityClient(conn) @@ -42,17 +42,18 @@ index e4e7b5a8..e0337a96 100644 + scope, + clk, + dnsTries, -+ logger) ++ logger, ++ tlsConfig) + resolver = r + } else { -+ r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger) ++ r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger, tlsConfig) + resolver = r + } + var smtpRoots *x509.CertPool if config.BadKeyRevoker.Mailer.SMTPTrustedRootFile != "" { pem, err := os.ReadFile(config.BadKeyRevoker.Mailer.SMTPTrustedRootFile) -@@ -483,6 +512,7 @@ func main() { +@@ -488,6 +518,7 @@ func main() { config.BadKeyRevoker.Mailer.Username, smtpPassword, smtpRoots, diff --git a/patches/boulder-va_main.patch b/patches/boulder-va_main.patch index b3feb1e..e568406 100644 --- a/patches/boulder-va_main.patch +++ b/patches/boulder-va_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/boulder-va/main.go b/cmd/boulder-va/main.go -index 1c998bc97..0665bdf4b 100644 +index b28ec1134..78f5a7879 100644 --- a/cmd/boulder-va/main.go +++ b/cmd/boulder-va/main.go @@ -27,7 +27,8 @@ type Config struct { @@ -12,7 +12,7 @@ index 1c998bc97..0665bdf4b 100644 DNSTimeout config.Duration `validate:"required"` DNSAllowLoopbackAddresses bool -@@ -80,13 +81,18 @@ func main() { +@@ -79,7 +80,7 @@ func main() { } clk := cmd.Clock() @@ -21,16 +21,19 @@ index 1c998bc97..0665bdf4b 100644 cmd.Fail("Must specify dnsProvider") } - var servers bdns.ServerProvider -- servers, err = bdns.StartDynamicProvider(c.VA.DNSProvider, 60*time.Second) +@@ -88,8 +89,13 @@ func main() { + if features.Get().DOH { + proto = "tcp" + } +- servers, err = bdns.StartDynamicProvider(c.VA.DNSProvider, 60*time.Second, proto) - cmd.FailOnError(err, "Couldn't start dynamic DNS server resolver") + if len(c.VA.DNSResolvers) > 0 { + servers, err = bdns.NewStaticProvider(c.VA.DNSResolvers) + cmd.FailOnError(err, "Couldn't parse static DNS server(s)") + } else { -+ servers, err = bdns.StartDynamicProvider(c.VA.DNSProvider, 60*time.Second) ++ servers, err = bdns.StartDynamicProvider(c.VA.DNSProvider, 60*time.Second, proto) + cmd.FailOnError(err, "Couldn't start dynamic DNS server resolver") + } defer servers.Stop() - var resolver bdns.Client + tlsConfig, err := c.VA.TLS.Load(scope) diff --git a/patches/cert-checker_main.patch b/patches/cert-checker_main.patch index c91e633..09c2764 100644 --- a/patches/cert-checker_main.patch +++ b/patches/cert-checker_main.patch @@ -1,8 +1,8 @@ diff --git a/cmd/cert-checker/main.go b/cmd/cert-checker/main.go -index 03f66481f..17f0839a4 100644 +index 6cf2dee45..008f383d3 100644 --- a/cmd/cert-checker/main.go +++ b/cmd/cert-checker/main.go -@@ -108,6 +108,7 @@ type certChecker struct { +@@ -107,6 +107,7 @@ type certChecker struct { checkPeriod time.Duration acceptableValidityDurations map[time.Duration]bool logger blog.Logger @@ -10,7 +10,7 @@ index 03f66481f..17f0839a4 100644 } func newChecker(saDbMap certDB, -@@ -117,6 +118,7 @@ func newChecker(saDbMap certDB, +@@ -116,6 +117,7 @@ func newChecker(saDbMap certDB, period time.Duration, avd map[time.Duration]bool, logger blog.Logger, @@ -18,7 +18,7 @@ index 03f66481f..17f0839a4 100644 ) certChecker { precertGetter := func(ctx context.Context, serial string) ([]byte, error) { precertPb, err := sa.SelectPrecertificate(ctx, saDbMap, serial) -@@ -137,6 +139,7 @@ func newChecker(saDbMap certDB, +@@ -136,6 +138,7 @@ func newChecker(saDbMap certDB, checkPeriod: period, acceptableValidityDurations: avd, logger: logger, @@ -26,8 +26,8 @@ index 03f66481f..17f0839a4 100644 } } -@@ -412,7 +415,7 @@ func (c *certChecker) checkCert(ctx context.Context, cert core.Certificate, igno - err = c.pa.WillingToIssueWildcards([]identifier.ACMEIdentifier{id}) +@@ -410,7 +413,7 @@ func (c *certChecker) checkCert(ctx context.Context, cert core.Certificate, igno + err = c.pa.WillingToIssue([]string{name}) if err != nil { problems = append(problems, fmt.Sprintf("Policy Authority isn't willing to issue for '%s': %s", name, err)) - } else { @@ -35,7 +35,7 @@ index 03f66481f..17f0839a4 100644 // For defense-in-depth, even if the PA was willing to issue for a name // we double check it against a list of forbidden domains. This way even // if the hostnamePolicyFile malfunctions we will flag the forbidden -@@ -492,9 +495,10 @@ type Config struct { +@@ -490,9 +493,10 @@ type Config struct { Workers int `validate:"required,min=1"` // Deprecated: this is ignored, and cert checker always checks both expired and unexpired. @@ -49,7 +49,7 @@ index 03f66481f..17f0839a4 100644 // AcceptableValidityDurations is a list of durations which are // acceptable for certificates we issue. -@@ -562,6 +566,8 @@ func main() { +@@ -559,6 +563,8 @@ func main() { acceptableValidityDurations[ninetyDays] = true } @@ -58,7 +58,7 @@ index 03f66481f..17f0839a4 100644 // Validate PA config and set defaults if needed. cmd.FailOnError(config.PA.CheckChallenges(), "Invalid PA configuration") -@@ -602,6 +608,7 @@ func main() { +@@ -599,6 +605,7 @@ func main() { config.CertChecker.CheckPeriod.Duration, acceptableValidityDurations, logger, diff --git a/patches/crl-storer_main.patch b/patches/crl-storer_main.patch index ac1c910..dcacde0 100644 --- a/patches/crl-storer_main.patch +++ b/patches/crl-storer_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/crl-storer/main.go b/cmd/crl-storer/main.go -index d2fde00a8..410bbbd64 100644 +index 4dddfaa9f..8dcf40bbc 100644 --- a/cmd/crl-storer/main.go +++ b/cmd/crl-storer/main.go @@ -46,6 +46,9 @@ type Config struct { @@ -9,10 +9,10 @@ index d2fde00a8..410bbbd64 100644 + // If this is set, store the files locally instead of using (fake) S3 + LocalStorePath string + - Features map[string]bool + Features features.Config } -@@ -121,7 +124,7 @@ func main() { +@@ -129,7 +132,7 @@ func main() { } s3client := s3.NewFromConfig(awsConfig, s3opts...) diff --git a/patches/docker-compose-redis.patch b/patches/docker-compose-redis.patch index cd503da..0d70668 100644 --- a/patches/docker-compose-redis.patch +++ b/patches/docker-compose-redis.patch @@ -1,8 +1,8 @@ diff --git a/docker-compose.yml b/docker-compose.yml -index f6473c8ef..6ff3f70c6 100644 +index 6a918c2e2..c580176cd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml -@@ -23,8 +23,6 @@ services: +@@ -30,8 +30,6 @@ services: ipv4_address: 10.77.77.77 rednet: ipv4_address: 10.88.88.88 @@ -11,7 +11,7 @@ index f6473c8ef..6ff3f70c6 100644 consulnet: ipv4_address: 10.55.55.55 # Use consul as a backup to Docker's embedded DNS server. If there's a name -@@ -43,10 +41,6 @@ services: +@@ -50,10 +48,6 @@ services: depends_on: - bmysql - bproxysql @@ -22,7 +22,7 @@ index f6473c8ef..6ff3f70c6 100644 - bconsul - bjaeger entrypoint: test/entrypoint.sh -@@ -84,42 +78,6 @@ services: +@@ -91,42 +85,6 @@ services: aliases: - boulder-proxysql @@ -65,7 +65,7 @@ index f6473c8ef..6ff3f70c6 100644 bconsul: image: hashicorp/consul:1.15.4 volumes: -@@ -154,13 +112,6 @@ networks: +@@ -161,13 +119,6 @@ networks: config: - subnet: 10.88.88.0/24 diff --git a/patches/docker-compose.patch b/patches/docker-compose.patch index 18c8f5f..537daa5 100644 --- a/patches/docker-compose.patch +++ b/patches/docker-compose.patch @@ -1,17 +1,21 @@ diff --git a/docker-compose.yml b/docker-compose.yml -index 6ff3f70c6..74f1cf0f8 100644 +index c580176cd..aeb34b387 100644 --- a/docker-compose.yml +++ b/docker-compose.yml -@@ -1,20 +1,23 @@ +@@ -1,10 +1,11 @@ version: '3' +name: labca services: boulder: - # Should match one of the GO_DEV_VERSIONS in test/boulder-tools/tag_and_upload.sh. -- image: letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-go1.21.4_2023-11-09} -+ image: &boulder_image letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-go1.21.4_2023-11-09} - environment: - # To solve HTTP-01 and TLS-ALPN-01 challenges, change the IP in FAKE_DNS + # The `letsencrypt/boulder-tools:latest` tag is automatically built in local + # dev environments. In CI a specific BOULDER_TOOLS_TAG is passed, and it is + # pulled with `docker compose pull`. +- image: letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-latest} ++ image: &boulder_image letsencrypt/boulder-tools:${BOULDER_TOOLS_TAG:-go1.21.5_2023-12-11} + build: + context: test/boulder-tools/ + # Should match one of the GO_DEV_VERSIONS in test/boulder-tools/tag_and_upload.sh. +@@ -15,13 +16,15 @@ services: # to the IP address where your ACME client's solver is listening. # FAKE_DNS: 172.17.0.1 FAKE_DNS: 10.77.77.77 @@ -30,7 +34,7 @@ index 6ff3f70c6..74f1cf0f8 100644 - ./.gocache:/root/.cache/go-build:cached - ./.hierarchy:/hierarchy/:cached - ./.softhsm-tokens/:/var/lib/softhsm/tokens/:cached -@@ -34,20 +37,26 @@ services: +@@ -41,20 +44,26 @@ services: # TODO: Remove this when ServerAddress is deprecated in favor of SRV records # and DNSAuthority. dns: 10.55.55.10 @@ -65,7 +69,7 @@ index 6ff3f70c6..74f1cf0f8 100644 networks: bluenet: aliases: -@@ -61,22 +70,11 @@ services: +@@ -68,22 +77,11 @@ services: # small. command: mysqld --bind-address=0.0.0.0 --slow-query-log --log-output=TABLE --log-queries-not-using-indexes=ON logging: @@ -93,7 +97,7 @@ index 6ff3f70c6..74f1cf0f8 100644 bconsul: image: hashicorp/consul:1.15.4 -@@ -90,12 +88,73 @@ services: +@@ -97,12 +95,73 @@ services: rednet: ipv4_address: 10.88.88.10 command: "consul agent -dev -config-format=hcl -config-file=/test/consul/config.hcl" diff --git a/patches/expiration-mailer_main.patch b/patches/expiration-mailer_main.patch index 403c6d1..07b55e5 100644 --- a/patches/expiration-mailer_main.patch +++ b/patches/expiration-mailer_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/expiration-mailer/main.go b/cmd/expiration-mailer/main.go -index 1d7ccde3f..271813b5f 100644 +index e1014ebab..db289ca96 100644 --- a/cmd/expiration-mailer/main.go +++ b/cmd/expiration-mailer/main.go @@ -23,6 +23,7 @@ import ( @@ -10,7 +10,7 @@ index 1d7ccde3f..271813b5f 100644 "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/config" "github.com/letsencrypt/boulder/core" -@@ -38,7 +39,7 @@ import ( +@@ -39,7 +40,7 @@ import ( ) const ( @@ -18,8 +18,22 @@ index 1d7ccde3f..271813b5f 100644 + defaultExpirationSubject = "LabCA certificate expiration notice for domain {{.ExpirationSubject}}" ) - type regStore interface { -@@ -688,6 +689,11 @@ type Config struct { + var ( +@@ -161,8 +162,12 @@ func (m *mailer) sendNags(conn bmail.Conn, contacts []string, certs []*x509.Cert + if parsed.Scheme != "mailto" { + continue + } ++ pa, err := policy.New(nil, nil) ++ if err != nil { ++ return fmt.Errorf("cannot create policy authority implementation") ++ } + address := parsed.Opaque +- err = policy.ValidEmail(address) ++ err = pa.ValidEmail(address) + if err != nil { + m.log.Debugf("skipping invalid email %q: %s", address, err) + continue +@@ -698,6 +703,11 @@ type Config struct { TLS cmd.TLSConfig SAService *cmd.GRPCClientConfig @@ -31,7 +45,7 @@ index 1d7ccde3f..271813b5f 100644 // Path to a file containing a list of trusted root certificates for use // during the SMTP connection (as opposed to the gRPC connections). SMTPTrustedRootFile string -@@ -836,6 +842,29 @@ func main() { +@@ -851,6 +861,30 @@ func main() { cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") sac := sapb.NewStorageAuthorityClient(conn) @@ -51,17 +65,18 @@ index 1d7ccde3f..271813b5f 100644 + scope, + clk, + dnsTries, -+ logger) ++ logger, ++ tlsConfig) + resolver = r + } else { -+ r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger) ++ r := bdns.NewTest(dnsTimeout, servers, scope, clk, dnsTries, logger, tlsConfig) + resolver = r + } + var smtpRoots *x509.CertPool if c.Mailer.SMTPTrustedRootFile != "" { pem, err := os.ReadFile(c.Mailer.SMTPTrustedRootFile) -@@ -871,6 +900,7 @@ func main() { +@@ -886,6 +920,7 @@ func main() { c.Mailer.Username, smtpPassword, smtpRoots, diff --git a/patches/ocsp-responder_main.patch b/patches/ocsp-responder_main.patch index fccc0b2..2b710c3 100644 --- a/patches/ocsp-responder_main.patch +++ b/patches/ocsp-responder_main.patch @@ -1,5 +1,5 @@ diff --git a/cmd/ocsp-responder/main.go b/cmd/ocsp-responder/main.go -index fa19f679..a6e2835f 100644 +index cede54ee3..1360ed1d6 100644 --- a/cmd/ocsp-responder/main.go +++ b/cmd/ocsp-responder/main.go @@ -88,7 +88,7 @@ type Config struct { @@ -11,7 +11,7 @@ index fa19f679..a6e2835f 100644 // TLS client certificate, private key, and trusted root bundle. TLS cmd.TLSConfig `validate:"required_without=Source,structonly"` -@@ -153,7 +153,7 @@ as generated by Boulder's ceremony command. +@@ -162,7 +162,7 @@ as generated by Boulder's ceremony command. } source, err = responder.NewMemorySourceFromFile(filename, logger) cmd.FailOnError(err, fmt.Sprintf("Couldn't read file: %s", url.Path)) @@ -20,7 +20,7 @@ index fa19f679..a6e2835f 100644 // Set up the redis source and the combined multiplex source. rocspRWClient, err := rocsp_config.MakeClient(c.OCSPResponder.Redis, clk, scope) cmd.FailOnError(err, "Could not make redis client") -@@ -197,6 +197,19 @@ as generated by Boulder's ceremony command. +@@ -206,6 +206,19 @@ as generated by Boulder's ceremony command. source, err = redis_responder.NewCheckedRedisSource(rocspSource, dbMap, sac, scope, logger) cmd.FailOnError(err, "Could not create checkedRedis source") diff --git a/patches/policy_pa.patch b/patches/policy_pa.patch index f0f58f6..39d26ca 100644 --- a/patches/policy_pa.patch +++ b/patches/policy_pa.patch @@ -1,5 +1,5 @@ diff --git a/policy/pa.go b/policy/pa.go -index 86f79703d..59d42879a 100644 +index d872d5cbe..49daeb7d4 100644 --- a/policy/pa.go +++ b/policy/pa.go @@ -32,6 +32,8 @@ type AuthorityImpl struct { @@ -42,16 +42,16 @@ index 86f79703d..59d42879a 100644 pa.blocklistMu.Unlock() return nil } -@@ -205,7 +220,7 @@ var ( - // * exactly equal to an IANA registered TLD +@@ -203,7 +218,7 @@ var ( + // - exactly equal to an IANA registered TLD // - // It does _not_ check that the domain isn't on any PA blocked lists. --func ValidDomain(domain string) error { -+func (pa *AuthorityImpl) ValidDomain(domain string) error { + // It does NOT ensure that the domain is absent from any PA blocked lists. +-func ValidNonWildcardDomain(domain string) error { ++func (pa *AuthorityImpl) ValidNonWildcardDomain(domain string) error { if domain == "" { return errEmptyName } -@@ -281,6 +296,14 @@ func ValidDomain(domain string) error { +@@ -279,6 +294,14 @@ func ValidNonWildcardDomain(domain string) error { } } @@ -66,7 +66,28 @@ index 86f79703d..59d42879a 100644 // 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 { -@@ -308,7 +331,7 @@ var forbiddenMailDomains = map[string]bool{ +@@ -294,9 +317,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. +-func ValidDomain(domain string) error { ++func (pa *AuthorityImpl) ValidDomain(domain string) error { + if strings.Count(domain, "*") <= 0 { +- return ValidNonWildcardDomain(domain) ++ return pa.ValidNonWildcardDomain(domain) + } + + // Names containing more than one wildcard are invalid. +@@ -323,7 +346,7 @@ func ValidDomain(domain string) error { + if baseDomain == icannTLD { + return errICANNTLDWildcard + } +- return ValidNonWildcardDomain(baseDomain) ++ return pa.ValidNonWildcardDomain(baseDomain) + } + + // forbiddenMailDomains is a map of domain names we do not allow after the +@@ -341,7 +364,7 @@ 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). @@ -75,33 +96,42 @@ index 86f79703d..59d42879a 100644 email, err := mail.ParseAddress(address) if err != nil { if len(address) > 254 { -@@ -318,7 +341,7 @@ func ValidEmail(address string) error { +@@ -351,7 +374,7 @@ func ValidEmail(address string) error { } splitEmail := strings.SplitN(email.Address, "@", -1) domain := strings.ToLower(splitEmail[len(splitEmail)-1]) -- err = ValidDomain(domain) -+ err = pa.ValidDomain(domain) +- err = ValidNonWildcardDomain(domain) ++ err = pa.ValidNonWildcardDomain(domain) if err != nil { return berrors.InvalidEmailError( "contact email %q has invalid domain : %s", -@@ -358,11 +381,15 @@ func (pa *AuthorityImpl) willingToIssue(id identifier.ACMEIdentifier) error { - } - domain := id.Value - -- err := ValidDomain(domain) -+ err := pa.ValidDomain(domain) - if err != nil { - return err - } - -+ if ok, _ := pa.checkWhitelist(domain); ok { -+ return nil -+ } -+ - // Require no match against hostname block lists - err = pa.checkHostLists(domain) - if err != nil { -@@ -372,6 +399,31 @@ func (pa *AuthorityImpl) willingToIssue(id identifier.ACMEIdentifier) error { +@@ -416,7 +439,7 @@ func (pa *AuthorityImpl) WillingToIssue(domains []string) error { + for _, domain := range domains { + if strings.Count(domain, "*") > 0 { + // Domain contains a wildcard, check that it is valid. +- err := ValidDomain(domain) ++ err := pa.ValidDomain(domain) + if err != nil { + appendSubError(domain, err) + continue +@@ -433,12 +456,15 @@ func (pa *AuthorityImpl) WillingToIssue(domains []string) error { + } + } else { + // Validate that the domain is well-formed. +- err := ValidNonWildcardDomain(domain) ++ err := pa.ValidNonWildcardDomain(domain) + if err != nil { + appendSubError(domain, err) + continue + } + } ++ if ok, _ := pa.checkWhitelist(domain); ok { ++ return nil ++ } + // Require no match against hostname block lists + err := pa.checkHostLists(domain) + if err != nil { +@@ -471,6 +497,31 @@ func (pa *AuthorityImpl) WillingToIssue(domains []string) error { return nil } @@ -130,6 +160,6 @@ index 86f79703d..59d42879a 100644 + } +} + - // WillingToIssueWildcards is an extension of WillingToIssue that accepts DNS - // identifiers for well formed wildcard domains in addition to regular - // identifiers. + // checkWildcardHostList checks the wildcardExactBlocklist for a given domain. + // If the domain is not present on the list nil is returned, otherwise + // errPolicyForbidden is returned. diff --git a/patches/ra_ra.patch b/patches/ra_ra.patch index ab7d3f7..1d9387c 100644 --- a/patches/ra_ra.patch +++ b/patches/ra_ra.patch @@ -1,8 +1,8 @@ diff --git a/ra/ra.go b/ra/ra.go -index 3c2fb694b..1b7343dc8 100644 +index 7c62ad078..21bc601b4 100644 --- a/ra/ra.go +++ b/ra/ra.go -@@ -44,7 +44,6 @@ import ( +@@ -43,7 +43,6 @@ import ( "github.com/letsencrypt/boulder/issuance" blog "github.com/letsencrypt/boulder/log" "github.com/letsencrypt/boulder/metrics" @@ -10,7 +10,7 @@ index 3c2fb694b..1b7343dc8 100644 "github.com/letsencrypt/boulder/probs" pubpb "github.com/letsencrypt/boulder/publisher/proto" rapb "github.com/letsencrypt/boulder/ra/proto" -@@ -560,7 +559,7 @@ func (ra *RegistrationAuthorityImpl) validateContacts(contacts []string) error { +@@ -559,7 +558,7 @@ func (ra *RegistrationAuthorityImpl) validateContacts(contacts []string) error { contact, ) } diff --git a/patches/ratelimits_names.patch b/patches/ratelimits_names.patch index e5fdc25..d580f26 100644 --- a/patches/ratelimits_names.patch +++ b/patches/ratelimits_names.patch @@ -1,8 +1,8 @@ diff --git a/ratelimits/names.go b/ratelimits/names.go -index b0d581e76..a4774ae10 100644 +index 4a541d1e6..433aaa522 100644 --- a/ratelimits/names.go +++ b/ratelimits/names.go -@@ -135,7 +135,11 @@ func validateRegId(id string) error { +@@ -145,7 +145,11 @@ func validateRegId(id string) error { // validateDomain validates that the provided string is formatted 'domain', // where domain is a domain name. func validateDomain(id string) error { @@ -13,9 +13,22 @@ index b0d581e76..a4774ae10 100644 + } + err = pa.ValidDomain(id) if err != nil { - return fmt.Errorf("invalid domain, %q must be formatted 'domain'", id) + return fmt.Errorf("invalid domain, %q must be formatted 'domain': %w", id, err) } -@@ -150,8 +154,12 @@ func validateFQDNSet(id string) error { +@@ -166,7 +170,11 @@ func validateRegIdDomain(id string) error { + return fmt.Errorf( + "invalid regId, %q must be formatted 'regId:domain'", id) + } +- err = policy.ValidDomain(regIdDomain[1]) ++ pa, err := policy.New(nil, nil) ++ if err != nil { ++ return fmt.Errorf("cannot create policy authority implementation") ++ } ++ err = pa.ValidDomain(regIdDomain[1]) + if err != nil { + return fmt.Errorf( + "invalid domain, %q must be formatted 'regId:domain': %w", id, err) +@@ -182,8 +190,12 @@ func validateFQDNSet(id string) error { return fmt.Errorf( "invalid fqdnSet, %q must be formatted 'fqdnSet'", id) } @@ -28,4 +41,4 @@ index b0d581e76..a4774ae10 100644 + err = pa.ValidDomain(domain) if err != nil { return fmt.Errorf( - "invalid domain, %q must be formatted 'fqdnSet'", id) + "invalid domain, %q must be formatted 'fqdnSet': %w", id, err) diff --git a/patches/startservers.patch b/patches/startservers.patch index d03aa27..d52276f 100644 --- a/patches/startservers.patch +++ b/patches/startservers.patch @@ -1,8 +1,8 @@ diff --git a/test/startservers.py b/test/startservers.py -index a85339777..10fd2047e 100644 +index b5fc73439..135e6c9e4 100644 --- a/test/startservers.py +++ b/test/startservers.py -@@ -145,6 +145,9 @@ processes = [] +@@ -146,6 +146,9 @@ processes = [] challSrvProcess = None def setupHierarchy():