Compare commits
38 Commits
Author | SHA1 | Date |
---|---|---|
|
a9ef40ef40 | |
|
455dc10734 | |
|
81e2be7c6b | |
|
dc4561673d | |
|
0be33f2139 | |
|
bb4fed2902 | |
|
00b5d41de5 | |
|
aa326b746d | |
|
68d6913607 | |
|
0beea6bbc8 | |
|
3bf80d78fb | |
|
c7de9b5377 | |
|
9720677383 | |
|
3c1b79fef5 | |
|
e3774ace37 | |
|
81c5e7da3f | |
|
3228b9f043 | |
|
c9a1c338ef | |
|
71632fca2a | |
|
44475437d9 | |
|
050d6bfaa4 | |
|
74ede875c7 | |
|
33f069ceca | |
|
458a2f893f | |
|
b7910d3af2 | |
|
ec51e0c7aa | |
|
6b2e90b018 | |
|
94e7cf40dc | |
|
5379b3607f | |
|
2725e23db1 | |
|
e28a1f1a49 | |
|
a4a566ca29 | |
|
b3cddddec0 | |
|
539bddf7fd | |
|
9485ff8805 | |
|
26ed67742e | |
|
2c7b293242 | |
|
95a2e64a4a |
|
@ -0,0 +1,15 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
groups:
|
||||
aws-sdk-go:
|
||||
patterns:
|
||||
- "github.com/aws/aws-sdk-go-v2"
|
||||
- "github.com/aws/aws-sdk-go-v2/*"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
|
@ -13,14 +13,14 @@ permissions:
|
|||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
go-version: 1.24.2
|
||||
- uses: actions/checkout@v4
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||
version: latest
|
||||
|
@ -30,6 +30,7 @@ jobs:
|
|||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
# args: --issues-exit-code=0
|
||||
args: --timeout=10m
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
|
|
|
@ -13,12 +13,12 @@ permissions:
|
|||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
go-version: 1.24.2
|
||||
- run: ./build-release.sh
|
||||
# Upload to S3:
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
|
|
|
@ -11,15 +11,15 @@ on:
|
|||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
go-version: 1.24.2
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
|
|
@ -10,10 +10,10 @@ on:
|
|||
|
||||
jobs:
|
||||
try-release:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
go-version: 1.24.2
|
||||
- run: ./build-release.sh
|
||||
|
|
|
@ -1,19 +1,37 @@
|
|||
version: "2"
|
||||
linters:
|
||||
disable-all: true
|
||||
default: none
|
||||
enable:
|
||||
- gofmt
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- wastedassign
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:[FS]?[Pp]rint*,io:Write,os:Remove,net/http:Write,net:Write,encoding/binary:Write
|
||||
settings:
|
||||
gosec:
|
||||
excludes:
|
||||
- G404
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
|
57
README.md
57
README.md
|
@ -2,7 +2,57 @@
|
|||
|
||||
[](https://github.com/letsencrypt/crl-monitor/actions/workflows/test.yml?query=branch%3Amain)
|
||||
|
||||
CRL-Monitor monitors CRLs
|
||||
CRL-Monitor monitors CRLs.
|
||||
|
||||
It issues certificates, revokes them, and then looks for them to appear in CRLs.
|
||||
Each component runs as an AWS Lambda.
|
||||
|
||||
The `churner` runs periodically. On each run it issues a certificate, fetches and lints
|
||||
the certificate's CRL URL, revokes the certificate, and stores its serial number and metadata
|
||||
for the `checker` to later verify that it shows up as revoked. It also checks previously
|
||||
seen serials. If they haven't shown up in a CRL after a reasonable amount of time, `checker`
|
||||
produces an error.
|
||||
|
||||
The `checker` runs in response to the upload of each new CRL shard in S3. It diffs the newly
|
||||
uploaded CRL shard against its previous version and verifies:
|
||||
|
||||
- New CRL has a later date and higher CRL number than the previous version.
|
||||
- New CRL passes lints.
|
||||
- For any serials removed between the old shard and the new one:
|
||||
- The certificate is expired (based on fetching it by serial from Let's Encrypt).
|
||||
- For any serials added (if the certificate was issued by the churner):
|
||||
- The certificate's CRLDistributionPoint matches the CRL shard's IssuingDistributionPoint.
|
||||
|
||||
The `checker` also removes from database any certificates it sees, to indicate that their
|
||||
revocation has been published, so the `churner` won't alert about them
|
||||
It then marks as completed (deletes) any `churner`-issued certificates that show up on
|
||||
the new CRL.
|
||||
|
||||
## Build and Deployment
|
||||
|
||||
This repository has two binaries named `checker` and two binaries named `churner`. The
|
||||
binaries under `cmd` are for local use and testing. The binaries under `lambda` are for
|
||||
deployment to AWS Lambda. The key difference is that the `lambda/` binaries register a
|
||||
lambda handler ([`lambda.StartWithOptions()`]), which AWS then calls. That
|
||||
[handler can return errors], and we have separate Cloudwatch monitoring that alerts when
|
||||
any errors are detected.
|
||||
|
||||
The lambda binaries are built by a release workflow on GitHub Actions triggered by uploading
|
||||
a release tag (starting with `v`). Those binaries are uploaded to S3 under a versioned path.
|
||||
They are then deployed to Lambda using Terraform (in another repository).
|
||||
|
||||
[`lambda.StartWithOptions()`]: https://pkg.go.dev/github.com/aws/aws-lambda-go/lambda#StartWithOptions
|
||||
[handler can return errors]: https://docs.aws.amazon.com/lambda/latest/dg/foundation-progmodel.html
|
||||
|
||||
## Testing
|
||||
|
||||
Most of the tests are unittests and can be run with:
|
||||
|
||||
go test ./...
|
||||
|
||||
There is also an integration test for DynamoDB code. To run this, install Java and run:
|
||||
|
||||
./db/run_integration_test.sh
|
||||
|
||||
## Architecture Diagram
|
||||
|
||||
|
@ -17,6 +67,7 @@ sequenceDiagram
|
|||
loop timer
|
||||
activate churn
|
||||
churn->>ca: Issue certificate
|
||||
churn->>ca: Fetch CRL
|
||||
churn->>ca: Revoke certificate
|
||||
churn->>ddb: Store certificate metadata
|
||||
ddb->>churn: Get previous revoked serials
|
||||
|
@ -31,10 +82,10 @@ sequenceDiagram
|
|||
checker->>s3: Read current CRL
|
||||
checker->>s3: Read previous CRL
|
||||
Note over checker: Alert if CRL<br />fails linting
|
||||
loop all removed serials
|
||||
loop random selection of serials
|
||||
checker->>ca: Get Certificate
|
||||
end
|
||||
Note over checker: Alert if CRL had any<br />serials leave early
|
||||
Note over checker: Alert if CRL had<br />serials leave early
|
||||
checker->>ddb: Get revoked serials
|
||||
checker->>ddb: Delete seen serials
|
||||
deactivate checker
|
||||
|
|
|
@ -4,19 +4,17 @@ import (
|
|||
"context"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
"github.com/letsencrypt/boulder/crl/checker"
|
||||
"github.com/letsencrypt/boulder/crl/idp"
|
||||
|
||||
"github.com/letsencrypt/crl-monitor/checker/earlyremoval"
|
||||
"github.com/letsencrypt/crl-monitor/checker/expiry"
|
||||
|
@ -58,37 +56,28 @@ func New(database *db.Database, storage *storage.Storage, fetcher earlyremoval.F
|
|||
}
|
||||
|
||||
func NewFromEnv(ctx context.Context) (*Checker, error) {
|
||||
cfg, err := config.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating AWS config: %w", err)
|
||||
}
|
||||
|
||||
boulderBaseURL := BoulderBaseURL.MustRead("Boulder endpoint to fetch certificates from")
|
||||
dynamoTable := DynamoTableEnv.MustRead("DynamoDB table name")
|
||||
dynamoEndpoint, customEndpoint := DynamoEndpointEnv.LookupEnv()
|
||||
dynamoEndpoint, _ := DynamoEndpointEnv.LookupEnv()
|
||||
crlAgeLimit, hasAgeLimit := CRLAgeLimit.LookupEnv()
|
||||
issuerPaths := IssuerPaths.MustRead("Colon (:) separated list of paths to PEM-formatted CRL issuer certificates")
|
||||
|
||||
maxFetch := 0
|
||||
maxFetchString, hasMaxFetch := BoulderMaxFetch.LookupEnv()
|
||||
if hasMaxFetch {
|
||||
var err error
|
||||
maxFetch, err = strconv.Atoi(maxFetchString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing %s as int (%s): %v", BoulderMaxFetch, maxFetchString, err)
|
||||
}
|
||||
}
|
||||
|
||||
if customEndpoint {
|
||||
cfg.EndpointResolverWithOptions = aws.EndpointResolverWithOptionsFunc(db.StaticResolver(dynamoEndpoint)) // nolint:staticcheck // SA1019
|
||||
}
|
||||
|
||||
database, err := db.New(dynamoTable, &cfg)
|
||||
database, err := db.New(ctx, dynamoTable, dynamoEndpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("database setup: %w", err)
|
||||
}
|
||||
|
||||
baf := expiry.BoulderAPIFetcher{
|
||||
Client: http.DefaultClient,
|
||||
BaseURL: boulderBaseURL,
|
||||
}
|
||||
|
||||
|
@ -110,7 +99,7 @@ func NewFromEnv(ctx context.Context) (*Checker, error) {
|
|||
issuers = append(issuers, issuer)
|
||||
}
|
||||
|
||||
return New(database, storage.New(cfg), &baf, maxFetch, ageLimitDuration, issuers), nil
|
||||
return New(database, storage.New(ctx), &baf, maxFetch, ageLimitDuration, issuers), nil
|
||||
}
|
||||
|
||||
// The Checker handles fetching and linting CRLs.
|
||||
|
@ -124,18 +113,57 @@ type Checker struct {
|
|||
issuers map[string]*x509.Certificate
|
||||
}
|
||||
|
||||
// crlSummary is a subset of fields from *x509.RevocationList
|
||||
// useful for logging, plus the number of entries and some metadata.
|
||||
type crlSummary struct {
|
||||
Number *big.Int
|
||||
NumEntries int
|
||||
ThisUpdate time.Time
|
||||
NextUpdate time.Time
|
||||
URL string
|
||||
StorageKey storage.Key
|
||||
}
|
||||
|
||||
func summary(crl *x509.RevocationList, key storage.Key) crlSummary {
|
||||
// If getIDP fails, we will just log ""
|
||||
idp, _ := getIDP(crl)
|
||||
return crlSummary{
|
||||
ThisUpdate: crl.ThisUpdate,
|
||||
NextUpdate: crl.NextUpdate,
|
||||
Number: crl.Number,
|
||||
NumEntries: len(crl.RevokedCertificateEntries),
|
||||
URL: idp,
|
||||
StorageKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
type crlsSummary struct {
|
||||
Old, New crlSummary
|
||||
}
|
||||
|
||||
func logSummary(old *x509.RevocationList, oldStorageKey storage.Key, new *x509.RevocationList, newStorageKey storage.Key) crlsSummary {
|
||||
return crlsSummary{
|
||||
Old: summary(old, oldStorageKey),
|
||||
New: summary(new, newStorageKey),
|
||||
}
|
||||
}
|
||||
|
||||
// Check fetches a CRL and its previous version. It runs lints on the CRL, checks for early removal, and removes any
|
||||
// certificates we're waiting for out of the database.
|
||||
func (c *Checker) Check(ctx context.Context, bucket, object string, startingVersion *string) error {
|
||||
// Read the current CRL shard
|
||||
crlDER, version, err := c.storage.Fetch(ctx, bucket, object, startingVersion)
|
||||
crlDER, version, err := c.storage.Fetch(ctx, storage.Key{
|
||||
Bucket: bucket,
|
||||
Object: object,
|
||||
Version: startingVersion,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
crl, err := x509.ParseRevocationList(crlDER)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing current crl: %v", err)
|
||||
return fmt.Errorf("parsing current crl: %v", err)
|
||||
}
|
||||
log.Printf("loaded CRL number %d (len %d) from %s version %s", crl.Number, len(crl.RevokedCertificateEntries), object, version)
|
||||
|
||||
|
@ -150,26 +178,41 @@ func (c *Checker) Check(ctx context.Context, bucket, object string, startingVers
|
|||
}
|
||||
log.Printf("crl %d successfully linted", crl.Number)
|
||||
|
||||
// And the previous:
|
||||
prevVersion, err := c.storage.Previous(ctx, bucket, object, version)
|
||||
_, err = getIDP(crl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prevDER, _, err := c.storage.Fetch(ctx, bucket, object, &prevVersion)
|
||||
curKey := storage.Key{
|
||||
Bucket: bucket,
|
||||
Object: object,
|
||||
Version: &version,
|
||||
}
|
||||
// And the previous:
|
||||
prevVersion, err := c.storage.Previous(ctx, curKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prevKey := curKey
|
||||
prevKey.Version = &prevVersion
|
||||
|
||||
prevDER, _, err := c.storage.Fetch(ctx, prevKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prev, err := x509.ParseRevocationList(prevDER)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing previous crl: %v", err)
|
||||
return fmt.Errorf("parsing previous crl: %v", err)
|
||||
}
|
||||
log.Printf("loaded previous CRL number %d (len %d) from version %s", prev.Number, len(prev.RevokedCertificateEntries), prevVersion)
|
||||
|
||||
context := logSummary(prev, prevKey, crl, curKey)
|
||||
|
||||
earlyRemoved, err := earlyremoval.Check(ctx, c.fetcher, c.maxFetch, prev, crl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check for early removal: %v", err)
|
||||
return fmt.Errorf("checking for early removal: %v. context: %+v", err, context)
|
||||
}
|
||||
|
||||
if len(earlyRemoved) != 0 {
|
||||
|
@ -179,7 +222,7 @@ func (c *Checker) Check(ctx context.Context, bucket, object string, startingVers
|
|||
}
|
||||
|
||||
// Certificates removed early! This is very bad.
|
||||
return fmt.Errorf("early removal of %d certificates detected! First %d: %v", len(earlyRemoved), len(sample), sample)
|
||||
return fmt.Errorf("early removal of %d certificates detected! First %d: %v. context: %+v", len(earlyRemoved), len(sample), sample, context)
|
||||
}
|
||||
|
||||
return c.lookForSeenCerts(ctx, crl)
|
||||
|
@ -190,20 +233,31 @@ func (c *Checker) Check(ctx context.Context, bucket, object string, startingVers
|
|||
func (c *Checker) lookForSeenCerts(ctx context.Context, crl *x509.RevocationList) error {
|
||||
unseenCerts, err := c.db.GetAllCerts(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read from db: %v", err)
|
||||
return fmt.Errorf("getting all certs from DB: %v", err)
|
||||
}
|
||||
var seenSerials [][]byte
|
||||
var errs []error
|
||||
for _, seen := range crl.RevokedCertificateEntries {
|
||||
if metadata, ok := unseenCerts[db.NewCertKey(seen.SerialNumber).SerialString()]; ok {
|
||||
idp, err := getIDP(crl)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
if metadata.CRLDistributionPoint != "" && metadata.CRLDistributionPoint != idp {
|
||||
errs = append(errs, fmt.Errorf("cert %x on CRL %q has non-matching CRLDistributionPoint %q",
|
||||
seen.SerialNumber, idp, metadata.CRLDistributionPoint))
|
||||
continue
|
||||
}
|
||||
seenSerials = append(seenSerials, metadata.SerialNumber)
|
||||
}
|
||||
}
|
||||
|
||||
err = c.db.DeleteSerials(ctx, seenSerials)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete from db: %v", err)
|
||||
errs = append(errs, fmt.Errorf("deleting %d serials from DB: %v", len(seenSerials), err))
|
||||
}
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// issuerForObject takes an s3 object path, extracts the issuer prefix, and returns the right x509.Certificate
|
||||
|
@ -220,3 +274,14 @@ func (c *Checker) issuerForObject(object string) (*x509.Certificate, error) {
|
|||
|
||||
return issuer, nil
|
||||
}
|
||||
|
||||
func getIDP(crl *x509.RevocationList) (string, error) {
|
||||
idps, err := idp.GetIDPURIs(crl.Extensions)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("extracting IssuingDistributionPoint URIs: %v", err)
|
||||
}
|
||||
if len(idps) == 1 {
|
||||
return idps[0], nil
|
||||
}
|
||||
return "", fmt.Errorf("CRL had incorrect number of IssuingDistributionPoint URIs: %s", idps)
|
||||
}
|
||||
|
|
|
@ -31,13 +31,17 @@ func TestCheck(t *testing.T) {
|
|||
issuerName := nameID(issuer)
|
||||
shouldBeGood := fmt.Sprintf("%s/should-be-good.crl", issuerName)
|
||||
earlyRemoval := fmt.Sprintf("%s/early-removal.crl", issuerName)
|
||||
shouldBeGoodIDP := fmt.Sprintf("http://idp/%s", shouldBeGood)
|
||||
earlyRemovalIDP := fmt.Sprintf("http://idp/%s", earlyRemoval)
|
||||
certificatesHaveCRLDP := fmt.Sprintf("%s/certificates-have-crldp.crl", issuerName)
|
||||
shouldBeGoodURL := fmt.Sprintf("http://idp/%s", shouldBeGood)
|
||||
earlyRemovalURL := fmt.Sprintf("http://idp/%s", earlyRemoval)
|
||||
certificatesHaveCRLDPURL := fmt.Sprintf("http://idp/%s", certificatesHaveCRLDP)
|
||||
|
||||
crl1der := testdata.MakeCRL(t, &testdata.CRL1, shouldBeGoodIDP, issuer, key)
|
||||
crl2der := testdata.MakeCRL(t, &testdata.CRL2, shouldBeGoodIDP, issuer, key)
|
||||
crl3der := testdata.MakeCRL(t, &testdata.CRL3, earlyRemovalIDP, issuer, key)
|
||||
crl4der := testdata.MakeCRL(t, &testdata.CRL4, earlyRemovalIDP, issuer, key)
|
||||
crl1der := testdata.MakeCRL(t, &testdata.CRL1, shouldBeGoodURL, issuer, key)
|
||||
crl2der := testdata.MakeCRL(t, &testdata.CRL2, shouldBeGoodURL, issuer, key)
|
||||
crl3der := testdata.MakeCRL(t, &testdata.CRL3, earlyRemovalURL, issuer, key)
|
||||
crl4der := testdata.MakeCRL(t, &testdata.CRL4, earlyRemovalURL, issuer, key)
|
||||
crl6der := testdata.MakeCRL(t, &testdata.CRL6, certificatesHaveCRLDPURL, issuer, key)
|
||||
crl7der := testdata.MakeCRL(t, &testdata.CRL7, certificatesHaveCRLDPURL, issuer, key)
|
||||
|
||||
data := map[string][]storagemock.MockObject{
|
||||
shouldBeGood: {
|
||||
|
@ -60,6 +64,16 @@ func TestCheck(t *testing.T) {
|
|||
Data: crl3der,
|
||||
},
|
||||
},
|
||||
certificatesHaveCRLDP: {
|
||||
{
|
||||
VersionID: "the-current-version",
|
||||
Data: crl7der, // CRL6 has serial 4213, which has a CRLDP
|
||||
},
|
||||
{
|
||||
VersionID: "the-previous-version",
|
||||
Data: crl6der,
|
||||
},
|
||||
},
|
||||
}
|
||||
bucket := "crl-test"
|
||||
|
||||
|
@ -74,11 +88,12 @@ func TestCheck(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
|
||||
// Watch the first revoked cert's serial
|
||||
// Insert some serials in the "unseen-certificates" table to be checked.
|
||||
serial := testdata.CRL1.RevokedCertificateEntries[0].SerialNumber
|
||||
require.NoError(t, checker.db.AddCert(ctx, &x509.Certificate{SerialNumber: serial}, testdata.Now))
|
||||
shouldNotBeSeen := big.NewInt(12345)
|
||||
require.NoError(t, checker.db.AddCert(ctx, &x509.Certificate{SerialNumber: shouldNotBeSeen}, testdata.Now))
|
||||
mismatchCRLDistributionPoint := big.NewInt(4213)
|
||||
|
||||
require.NoError(t, checker.Check(ctx, bucket, shouldBeGood, nil))
|
||||
|
||||
|
@ -92,6 +107,15 @@ func TestCheck(t *testing.T) {
|
|||
|
||||
// The "early-removal" object should error on a certificate removed early
|
||||
require.ErrorContains(t, checker.Check(ctx, bucket, earlyRemoval, nil), "early removal of 1 certificates detected!")
|
||||
|
||||
require.NoError(t, checker.db.AddCert(ctx, &x509.Certificate{
|
||||
SerialNumber: mismatchCRLDistributionPoint,
|
||||
CRLDistributionPoints: []string{
|
||||
"http://example.com",
|
||||
},
|
||||
}, testdata.Now))
|
||||
// The "certificates-have-crldp" object should error because the certificate CRL is a mismatch
|
||||
require.ErrorContains(t, checker.Check(ctx, bucket, certificatesHaveCRLDP, nil), "has non-matching CRLDistributionPoint")
|
||||
}
|
||||
|
||||
func Test_nameID(t *testing.T) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"crypto/x509"
|
||||
"log"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/crl/checker"
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
"crypto/x509"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"math/rand/v2"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -68,9 +68,8 @@ func TestSample(t *testing.T) {
|
|||
require.Empty(t, sample([]int{}, 999))
|
||||
|
||||
var data []int
|
||||
// Generate a random array for tests. Insecure RNG is fine.
|
||||
// #nosec G404
|
||||
length := 100 + rand.Intn(300)
|
||||
// Generate a random array for tests.
|
||||
length := 100 + rand.IntN(300)
|
||||
for i := 0; i < length; i++ {
|
||||
data = append(data, i)
|
||||
}
|
||||
|
|
|
@ -5,80 +5,41 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/crl-monitor/retryhttp"
|
||||
)
|
||||
|
||||
type BoulderAPIFetcher struct {
|
||||
Client *http.Client
|
||||
BaseURL string
|
||||
}
|
||||
|
||||
func (baf *BoulderAPIFetcher) getBody(ctx context.Context, url string) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "CRL-Monitor/0.1")
|
||||
resp, err := baf.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("http status %d (%s)", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// getWithRetries is a simple wrapper around client.Do that will retry on a fixed backoff schedule
|
||||
func (baf *BoulderAPIFetcher) getWithRetries(ctx context.Context, url string) ([]byte, error) {
|
||||
// A fixed sequence of retries. We start with 0 seconds, retrying
|
||||
// immediately, and increase a few seconds between each retry. The final
|
||||
// value is zero so that we don't sleep before returning the final error.
|
||||
var err error
|
||||
for _, backoff := range []int{0, 1, 1, 2, 3, 0} {
|
||||
var body []byte
|
||||
body, err = baf.getBody(ctx, url)
|
||||
if err == nil {
|
||||
return body, nil
|
||||
}
|
||||
time.Sleep(time.Duration(backoff) * time.Second)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// FetchNotAfter downloads a certificate, parses it, and returns the NotAfter on
|
||||
// it. It uses a non-acme path to download a certificate unauthenticated by
|
||||
// serial. So it is specific to Boulder's API, not a generic ACME API client.
|
||||
func (baf *BoulderAPIFetcher) FetchNotAfter(ctx context.Context, serial *big.Int) (time.Time, error) {
|
||||
// The baseURL is followed by a hex-encoded serial
|
||||
url := fmt.Sprintf("%s/%036x", baf.BaseURL, serial)
|
||||
url := fmt.Sprintf("%s/%s", baf.BaseURL, formatSerial(serial))
|
||||
|
||||
body, err := baf.getWithRetries(ctx, url)
|
||||
body, err := retryhttp.Get(ctx, url)
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("error fetching NotAfter for serial %d: %w", serial, err)
|
||||
return time.Time{}, fmt.Errorf("fetching NotAfter for serial %s: %w", formatSerial(serial), err)
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(body)
|
||||
if block == nil {
|
||||
return time.Time{}, fmt.Errorf("error parsing PEM for serial %d: %s", serial, string(body))
|
||||
return time.Time{}, fmt.Errorf("parsing PEM for serial %s: %s", formatSerial(serial), string(body))
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("error parsing certificate for serial %d: %w", serial, err)
|
||||
return time.Time{}, fmt.Errorf("parsing certificate for serial %s: %s", formatSerial(serial), err)
|
||||
}
|
||||
|
||||
return cert.NotAfter, nil
|
||||
}
|
||||
|
||||
func formatSerial(serial *big.Int) string {
|
||||
return fmt.Sprintf("%036x", serial)
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ func TestBoulderAPIFetcher(t *testing.T) {
|
|||
res.Write([]byte(testCert))
|
||||
}))
|
||||
|
||||
fetcher := BoulderAPIFetcher{BaseURL: testServer.URL + somePrefix, Client: http.DefaultClient}
|
||||
fetcher := BoulderAPIFetcher{BaseURL: testServer.URL + somePrefix}
|
||||
|
||||
serial := new(big.Int)
|
||||
serial.SetString(serialhex, 16)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -36,7 +35,7 @@ func TestBoulderAPI(t *testing.T) {
|
|||
} {
|
||||
t.Run(tc.subdomain, func(t *testing.T) {
|
||||
baseURL := fmt.Sprintf("https://%s.api.letsencrypt.org/get/cert", tc.subdomain)
|
||||
baf := BoulderAPIFetcher{Client: http.DefaultClient, BaseURL: baseURL}
|
||||
baf := BoulderAPIFetcher{BaseURL: baseURL}
|
||||
|
||||
serial := new(big.Int)
|
||||
serial.SetString(tc.serial, 16)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK
|
||||
a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO
|
||||
VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw
|
||||
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw
|
||||
i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
|
||||
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C
|
||||
2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+
|
||||
bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG
|
||||
6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV
|
||||
XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO
|
||||
koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq
|
||||
cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI
|
||||
E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e
|
||||
K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX
|
||||
GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL
|
||||
sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd
|
||||
VQD9F6Na/+zmXCc=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G
|
||||
h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV
|
||||
6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw
|
||||
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj
|
||||
v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
|
||||
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc
|
||||
MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL
|
||||
pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp
|
||||
eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH
|
||||
pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7
|
||||
s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu
|
||||
h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv
|
||||
YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8
|
||||
ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0
|
||||
LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+
|
||||
EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY
|
||||
Ig46v9mFmBvyH04=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVzCCAj+gAwIBAgIRAKp18eYrjwoiCWbTi7/UuqEwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCRTcwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARB6AST
|
||||
CFh/vjcwDMCgQer+VtqEkz7JANurZxLP+U9TCeioL6sp5Z8VRvRbYk4P1INBmbef
|
||||
QHJFHCxcSjKmwtvGBWpl/9ra8HW0QDsUaJW2qOJqceJ0ZVFT3hbUHifBM/2jgfgw
|
||||
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSuSJ7chx1EoG/aouVgdAR4
|
||||
wpwAgDAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
|
||||
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAjx66fDdLk5ywFn3CzA1w1qfylHUD
|
||||
aEf0QZpXcJseddJGSfbUUOvbNR9N/QQ16K1lXl4VFyhmGXDT5Kdfcr0RvIIVrNxF
|
||||
h4lqHtRRCP6RBRstqbZ2zURgqakn/Xip0iaQL0IdfHBZr396FgknniRYFckKORPG
|
||||
yM3QKnd66gtMst8I5nkRQlAg/Jb+Gc3egIvuGKWboE1G89NTsN9LTDD3PLj0dUMr
|
||||
OIuqVjLB8pEC6yk9enrlrqjXQgkLEYhXzq7dLafv5Vkig6Gl0nuuqjqfp0Q1bi1o
|
||||
yVNAlXe6aUXw92CcghC9bNsKEO1+M52YY5+ofIXlS/SEQbvVYYBLZ5yeiglV6t3S
|
||||
M6H+vTG0aP9YHzLn/KVOHzGQfXDP7qM5tkf+7diZe7o2fw6O7IvN6fsQXEQQj8TJ
|
||||
UXJxv2/uJhcuy/tSDgXwHM8Uk34WNbRT7zGTGkQRX0gsbjAea/jYAoWv0ZvQRwpq
|
||||
Pe79D/i7Cep8qWnA+7AE/3B3S/3dEEYmc0lpe1366A/6GEgk3ktr9PEoQrLChs6I
|
||||
tu3wnNLB2euC8IKGLQFpGtOO/2/hiAKjyajaBP25w1jF0Wl8Bbqne3uZ2q1GyPFJ
|
||||
YRmT7/OXpmOH/FVLtwS+8ng1cAmpCujPwteJZNcDG0sF2n/sc0+SQf49fdyUK0ty
|
||||
+VUwFj9tmWxyR/M=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
|
||||
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
|
||||
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
|
||||
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
|
||||
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
|
||||
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
|
||||
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
|
||||
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
|
||||
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
|
||||
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
|
||||
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
|
||||
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
|
||||
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
|
||||
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
|
||||
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
|
||||
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
|
||||
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
|
||||
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
|
||||
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
|
||||
u1igv3OefnWjSQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVjCCAj6gAwIBAgIQPxMQ4JDWqro5xbc4i97cEzANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQswCQYDVQQDEwJFOTB2MBAGByqGSM49AgEGBSuBBAAiA2IABKBc3EWf
|
||||
O6zmAqlYSV0MFToiAnzppo1ZSJfbXGjprjBkydFbYBekcgrlJEmt5787R4P1grbP
|
||||
tgd3oUBlfoMzWHihpjXWkojvlceMmUYqvVbQc39pCD3RiYjDCr7WpuIqc6OB+DCB
|
||||
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
|
||||
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFF130U2sTSJ4WbKGWY5DHLdk
|
||||
WRNBMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
|
||||
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
|
||||
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
|
||||
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBXnLSlc0Gensx9lwlwHOuj6gafwSHI
|
||||
Ex4AhPjD6aMOCfuMP5iEn3Mb1QadTZafQ075SWQo1npjZyaH5M1N8cewGo2/2fjc
|
||||
z+2joCAeXBxTAbIiOIbaJwjgeUXQAFtpb7OffZdj7fmN5dAplWuau3ssY7vhmMfI
|
||||
zxMW7ILj0Uwj99AGtg6YQmo5UVFJbLu41sTpLXFP4eeI5L+cbsHxgMnXaHB7G1Wl
|
||||
Htlyp2iDlfzHdR28GBf05Ztex/S/kwFP3TUD5udUpaGZ/wAM8Vz0PnES0YN9Pwkg
|
||||
fz1kxBO37E1nmGtF8mBVzBvGAiVL2AfgDn6eaKuerWrbtXEBCp0JawPcJRYRRu3e
|
||||
lp1fqkvihMKBwXwA4xjM4BOvbGDPr9zkFN8NTwvL2sOuLDRlX6ZV6ILJ3uEMuJ17
|
||||
8b+fUymtArsbbSsbcCW8yb95gy9corS6RLCND8GU5+ampNzgNx0+PP7QFP4/eqLC
|
||||
68CJNOctb5eDwbGsmF1vrfltenYU375le6FZILjP8O69hD3BPrNIie8VlrqBSiDg
|
||||
M+ZF/E4uwcNxU62tYmKs9/WZyMJAR084fkEwXOw322x6OCwzyemZVq3kYKFg0y/m
|
||||
E9NYU8ijBkUBB3uW1AC4btGCOSo9cnEz9TlRO1HOo7DMZkuuz5K0Rcal0LGLL11d
|
||||
KsApwwSJLRbh7A==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL
|
||||
YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a
|
||||
/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4
|
||||
FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR
|
||||
mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3
|
||||
DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
|
||||
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
|
||||
AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5
|
||||
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
|
||||
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
|
||||
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
|
||||
AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo
|
||||
zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd
|
||||
u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9
|
||||
1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0
|
||||
GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh
|
||||
1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ
|
||||
QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N
|
||||
4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz
|
||||
rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei
|
||||
RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx
|
||||
KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFBjCCAu6gAwIBAgIRAIp9PhPWLzDvI4a9KQdrNPgwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDEMMAoGA1UEAxMDUjExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAuoe8XBsAOcvKCs3UZxD5ATylTqVhyybKUvsVAbe5KPUoHu0nsyQYOWcJ
|
||||
DAjs4DqwO3cOvfPlOVRBDE6uQdaZdN5R2+97/1i9qLcT9t4x1fJyyXJqC4N0lZxG
|
||||
AGQUmfOx2SLZzaiSqhwmej/+71gFewiVgdtxD4774zEJuwm+UE1fj5F2PVqdnoPy
|
||||
6cRms+EGZkNIGIBloDcYmpuEMpexsr3E+BUAnSeI++JjF5ZsmydnS8TbKF5pwnnw
|
||||
SVzgJFDhxLyhBax7QG0AtMJBP6dYuC/FXJuluwme8f7rsIU5/agK70XEeOtlKsLP
|
||||
Xzze41xNG/cLJyuqC0J3U095ah2H2QIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
|
||||
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
|
||||
/wIBADAdBgNVHQ4EFgQUxc9GpOr0w8B6bJXELbBeki8m47kwHwYDVR0jBBgwFoAU
|
||||
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
|
||||
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
|
||||
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
|
||||
AQELBQADggIBAE7iiV0KAxyQOND1H/lxXPjDj7I3iHpvsCUf7b632IYGjukJhM1y
|
||||
v4Hz/MrPU0jtvfZpQtSlET41yBOykh0FX+ou1Nj4ScOt9ZmWnO8m2OG0JAtIIE38
|
||||
01S0qcYhyOE2G/93ZCkXufBL713qzXnQv5C/viOykNpKqUgxdKlEC+Hi9i2DcaR1
|
||||
e9KUwQUZRhy5j/PEdEglKg3l9dtD4tuTm7kZtB8v32oOjzHTYw+7KdzdZiw/sBtn
|
||||
UfhBPORNuay4pJxmY/WrhSMdzFO2q3Gu3MUBcdo27goYKjL9CTF8j/Zz55yctUoV
|
||||
aneCWs/ajUX+HypkBTA+c8LGDLnWO2NKq0YD/pnARkAnYGPfUDoHR9gVSp/qRx+Z
|
||||
WghiDLZsMwhN1zjtSC0uBWiugF3vTNzYIEFfaPG7Ws3jDrAMMYebQ95JQ+HIBD/R
|
||||
PBuHRTBpqKlyDnkSHDHYPiNX3adPoPAcgdF3H2/W0rmoswMWgTlLn1Wu0mrks7/q
|
||||
pdWfS6PJ1jty80r2VKsM/Dj3YIDfbjXKdaFU5C+8bhfJGqU3taKauuz0wHVGT3eo
|
||||
6FlWkWYtbt4pgdamlwVeZEW+LM7qZEJEsMNPrfC03APKmZsJgpWCDWOKZvkZcvjV
|
||||
uYkQ4omYCTX5ohy+knMjdOmdH9c7SpqEWBDC86fiNex+O0XOMEZSa8DA
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFBjCCAu6gAwIBAgIRAMISMktwqbSRcdxA9+KFJjwwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDEMMAoGA1UEAxMDUjEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEA2pgodK2+lP474B7i5Ut1qywSf+2nAzJ+Npfs6DGPpRONC5kuHs0BUT1M
|
||||
5ShuCVUxqqUiXXL0LQfCTUA83wEjuXg39RplMjTmhnGdBO+ECFu9AhqZ66YBAJpz
|
||||
kG2Pogeg0JfT2kVhgTU9FPnEwF9q3AuWGrCf4yrqvSrWmMebcas7dA8827JgvlpL
|
||||
Thjp2ypzXIlhZZ7+7Tymy05v5J75AEaz/xlNKmOzjmbGGIVwx1Blbzt05UiDDwhY
|
||||
XS0jnV6j/ujbAKHS9OMZTfLuevYnnuXNnC2i8n+cF63vEzc50bTILEHWhsDp7CH4
|
||||
WRt/uTp8n1wBnWIEwii9Cq08yhDsGwIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
|
||||
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
|
||||
/wIBADAdBgNVHQ4EFgQUALUp8i2ObzHom0yteD763OkM0dIwHwYDVR0jBBgwFoAU
|
||||
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
|
||||
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
|
||||
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
|
||||
AQELBQADggIBAI910AnPanZIZTKS3rVEyIV29BWEjAK/duuz8eL5boSoVpHhkkv3
|
||||
4eoAeEiPdZLj5EZ7G2ArIK+gzhTlRQ1q4FKGpPPaFBSpqV/xbUb5UlAXQOnkHn3m
|
||||
FVj+qYv87/WeY+Bm4sN3Ox8BhyaU7UAQ3LeZ7N1X01xxQe4wIAAE3JVLUCiHmZL+
|
||||
qoCUtgYIFPgcg350QMUIWgxPXNGEncT921ne7nluI02V8pLUmClqXOsCwULw+PVO
|
||||
ZCB7qOMxxMBoCUeL2Ll4oMpOSr5pJCpLN3tRA2s6P1KLs9TSrVhOk+7LX28NMUlI
|
||||
usQ/nxLJID0RhAeFtPjyOCOscQBA53+NRjSCak7P4A5jX7ppmkcJECL+S0i3kXVU
|
||||
y5Me5BbrU8973jZNv/ax6+ZK6TM8jWmimL6of6OrX7ZU6E2WqazzsFrLG3o2kySb
|
||||
zlhSgJ81Cl4tv3SbYiYXnJExKQvzf83DYotox3f0fwv7xln1A2ZLplCb0O+l/AK0
|
||||
YE0DS2FPxSAHi0iwMfW2nNHJrXcY3LLHD77gRgje4Eveubi2xxa+Nmk/hmhLdIET
|
||||
iVDFanoCrMVIpQ59XWHkzdFmoHXHBV7oibVjGSO7ULSQ7MJ1Nz51phuDJSgAIU7A
|
||||
0zrLnOrAj/dfrlEWRhCvAgbuwLZX1A2sjNjXoPOHbsPiy+lO1KF8/XY7
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFBTCCAu2gAwIBAgIQWgDyEtjUtIDzkkFX6imDBTANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQwwCgYDVQQDEwNSMTMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQClZ3CN0FaBZBUXYc25BtStGZCMJlA3mBZjklTb2cyEBZPs0+wIG6BgUUNI
|
||||
fSvHSJaetC3ancgnO1ehn6vw1g7UDjDKb5ux0daknTI+WE41b0VYaHEX/D7YXYKg
|
||||
L7JRbLAaXbhZzjVlyIuhrxA3/+OcXcJJFzT/jCuLjfC8cSyTDB0FxLrHzarJXnzR
|
||||
yQH3nAP2/Apd9Np75tt2QnDr9E0i2gB3b9bJXxf92nUupVcM9upctuBzpWjPoXTi
|
||||
dYJ+EJ/B9aLrAek4sQpEzNPCifVJNYIKNLMc6YjCR06CDgo28EdPivEpBHXazeGa
|
||||
XP9enZiVuppD0EqiFwUBBDDTMrOPAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
|
||||
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
|
||||
AgEAMB0GA1UdDgQWBBTnq58PLDOgU9NeT3jIsoQOO9aSMzAfBgNVHSMEGDAWgBR5
|
||||
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
|
||||
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
|
||||
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
|
||||
AQsFAAOCAgEAUTdYUqEimzW7TbrOypLqCfL7VOwYf/Q79OH5cHLCZeggfQhDconl
|
||||
k7Kgh8b0vi+/XuWu7CN8n/UPeg1vo3G+taXirrytthQinAHGwc/UdbOygJa9zuBc
|
||||
VyqoH3CXTXDInT+8a+c3aEVMJ2St+pSn4ed+WkDp8ijsijvEyFwE47hulW0Ltzjg
|
||||
9fOV5Pmrg/zxWbRuL+k0DBDHEJennCsAen7c35Pmx7jpmJ/HtgRhcnz0yjSBvyIw
|
||||
6L1QIupkCv2SBODT/xDD3gfQQyKv6roV4G2EhfEyAsWpmojxjCUCGiyg97FvDtm/
|
||||
NK2LSc9lybKxB73I2+P2G3CaWpvvpAiHCVu30jW8GCxKdfhsXtnIy2imskQqVZ2m
|
||||
0Pmxobb28Tucr7xBK7CtwvPrb79os7u2XP3O5f9b/H66GNyRrglRXlrYjI1oGYL/
|
||||
f4I1n/Sgusda6WvA6C190kxjU15Y12mHU4+BxyR9cx2hhGS9fAjMZKJss28qxvz6
|
||||
Axu4CaDmRNZpK/pQrXF17yXCXkmEWgvSOEZy6Z9pcbLIVEGckV/iVeq0AOo2pkg9
|
||||
p4QRIy0tK2diRENLSF2KysFwbY6B26BFeFs3v1sYVRhFW9nLkOrQVporCS0KyZmf
|
||||
wVD89qSTlnctLcZnIavjKsKUu1nA1iU0yYMdYepKR7lWbnwhdx3ewok=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFBjCCAu6gAwIBAgIRAL7zc3iocCqewKR6uSGlBqswDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDEMMAoGA1UEAxMDUjE0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAzWhUbJkv1MTfFF7ihLylp5jaitXVng6yEeruE71/c0TLq/bZ438PLiPN
|
||||
r3I1qp66HaqOANbQ6ETg0SjuBbWng7VLHG4M1vQnx40EyXb4MnqeiwIucbyfEras
|
||||
GfTsS7E0ulC7uJ3G80OeAGQl76Rvq/qOYOR8n9VofZfbSKiQkHjUE4yP18YKub7E
|
||||
y8L0i7+WibZd7OYLtcGDxZwgr56r5iSYSVFl6c4ihop2I81g2BkBGPYLygDSktVW
|
||||
Vz1/cnjHH+u7ubt5hhlw/GwsOaJfIjrFhw3KafQJyvJxanpfCSSTShzR9whLTSKV
|
||||
lH2A1761dHaceWkBRqcV3HkuFIGIlQIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
|
||||
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
|
||||
/wIBADAdBgNVHQ4EFgQU5RCV2LYMUdencjVjClRobgZT+PswHwYDVR0jBBgwFoAU
|
||||
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
|
||||
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
|
||||
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
|
||||
AQELBQADggIBACA3LtFXH8eQXLovPGzp7c2XE0/jmEp7tokiecuSdHfIUoMMYLjI
|
||||
TpCNbi92Czp+qraLmp0eLy6QEE5wnvMe5f9fgE24yk8EpsLw0JEr9L8tqWUXC1Kp
|
||||
jsT3ydhbWR70i4gElBvXnjGJc6HnU80veqABHEOU8TuAVwerBqH479ZLZSX+ezAf
|
||||
n9QcYiU9r8kVMbeSoSiQY39L6QK/3w4lmMZ9XoGM+9YhJldIbpBNgikoNgcOp3ya
|
||||
QxsfsE6ixjBZ/G6OSdi7KY41a/QdzeIiSy4dDV8R4pYF9FEhogpU/T/fD9tE7gEO
|
||||
81vGLOyhUSlI2EzsJeH0lAt9NIN5CPtcooj9ZV3gkuYwhQMdhiBM/giI1CX+3JUh
|
||||
w6zKwXr3EjiY4Emw12U6ACaMSJxFxakt1zjmBn/DNgx0rP4WyeSJrewrQsYjW9Us
|
||||
bpO7GGrbADy72exibqrULU3Hp/PWHdXn+j3dKweU5ZL5li67ckqf1ixqQtoQuyjb
|
||||
F4+flbcU7AdHYnNHNUHMz5TWXYKWP6fFk9PSggS8DmYtYozN3npRSCHTC56Rxa81
|
||||
ApdD9Ab0dF7fOvlnmniGxfqCRSh/RMGGEaTxdAfhp/m/yaR4xtm8VTAn8d65h/3D
|
||||
fKOGZ34UnvZmJ/bHqnU4zkLWc51iC1i9OIQWzoePK6qNPUq7k+oKUMSj
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEljCCAn6gAwIBAgIQRzEp1D1mDiVVv4b1zlB56jANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowUjELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSEwHwYDVQQD
|
||||
ExgoU1RBR0lORykgUHNldWRvIFBsdW0gRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
|
||||
AATljbbcV+mqWZa3g+z0bDOuBpZOtbi48iK9rjLtPdRU0WsgVp53MW3nXFU6qVYV
|
||||
zEYaYd6PSmec0Tj3R5zEp5/F+cuOjTdh3AkTMzYm1tkflocPBN5APHYZ+76WxZad
|
||||
q+WjggEAMIH9MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYI
|
||||
KwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU/EbRAUNfu3um
|
||||
PTBorhG64LxtydMwHwYDVR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYI
|
||||
KwYBBQUHAQEEKjAoMCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iu
|
||||
b3JnLzATBgNVHSAEDDAKMAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRw
|
||||
Oi8vc3RnLXgxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAAtCGn4iG
|
||||
cupruhkCTcoDqSIVTFgVR8JJ3GvGL7SYwIc4Fn0As66nQgnkATIzF5+gFb+CXEQD
|
||||
qR2Jo+R38OeT7lQ1rNDcaJcbY6hL8cNRku3QlcfdYODZ5pgTVH04gTZUJISZKLjD
|
||||
kMMcQIDZlF7iYqTvmHbn2ISSKorsJ3QKAvWhHwMoJtocSz3VeDJIep5QtbHnoXh1
|
||||
/dyDx7sp8RuhC0eO9ElTgDtiA2V6JxigLPzqcnibBBR4bFLGtMNE4EvOOD/Fkd0L
|
||||
hdGDbAMNd+O06n+b0rgmDvg75IgOV6fpDrdZFoiNfCckOEJh9v10uYt4pTc3B6lf
|
||||
zI/X3EWP1H4VJmsYuy+OA29jPeP831sAObZtd3RWv0LQPrMfx6FCmy4AaeYEMvul
|
||||
FrF6OX+JbssE+bn83F+sGEMZu/eVBwwKh3db7+2UduMdTOb8DePE3Aqlg9zofS8X
|
||||
9fJXrrp+PPrdQyvM3e8DxuioWa9GLG30yD9WD6WTlSiiOrdWGOzisWpW4shFoL8u
|
||||
0EfmeLVU4JVbauhOYZASQXABNeXewe9lqJWwfqaARYpRjyf+jRibn22H5NVK4Vog
|
||||
l55Iq1rUgjc8r493NaNrlNwG7va7Ztkch5lJ3oL/FEVlVSK4snTbgb0b5qjQz3SA
|
||||
i7rA/8QRZvOLnKNtdEUlDZNrzkZwHNluLGw=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIElzCCAn+gAwIBAgIQJtklZLQLsngwp0DD4clbajANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowUzELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSIwIAYDVQQD
|
||||
ExkoU1RBR0lORykgRmFsc2UgRmVubmVsIEU2MHYwEAYHKoZIzj0CAQYFK4EEACID
|
||||
YgAE7mIshEAbfnZhXHmCLThagBq8wNKY84YkUynY83vBo8FGIFdBQ7xQV3NrPkhi
|
||||
dMXyW4aQcADxF/skAnZAsvnjxR+oCnYZAtBXgeE+WFA6FE7/fr/ecbTglsAgp59e
|
||||
ADZDo4IBADCB/TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIG
|
||||
CCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFKF0GgZtULeG
|
||||
LUoswX60jYhJbM0WMB8GA1UdIwQYMBaAFLXzZfL+sAqSH/s8ffNEoKxjJcMUMDYG
|
||||
CCsGAQUFBwEBBCowKDAmBggrBgEFBQcwAoYaaHR0cDovL3N0Zy14MS5pLmxlbmNy
|
||||
Lm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwKwYDVR0fBCQwIjAgoB6gHIYaaHR0
|
||||
cDovL3N0Zy14MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcNAQELBQADggIBAFGjOrc+
|
||||
GlZYCuxNKS9u+4l6pDux++Cg3FX3hR0QhCZPKORxnua9dJlles5NBcIf5W1Y2OW7
|
||||
1El+oq+0cCS39bqfG3d+9sRbqnLlqB9xysRfpGPmY2IRQ4YFurIzurFw/TshoGGw
|
||||
L74VtBgmxeO1fhP8OWJfnMB3EILdz6hxEqbQtCmU/2ejQTQEK6cQtBj33a+MUI7i
|
||||
YnRP+OTL1M81tmZRkUWY7WItMGDPIabhXfHqvqYXh0huxqUDls0VjC52xpiK6e2F
|
||||
+ZxouwmBwQlxSL9pJWMvhRGJdFCIBulQPm/0tbt2seBxkFKWIYmouDh+28swkTSl
|
||||
f8mV0KGmEVmPka5CQkgSg4btNHUoZ1xwt++f4N12AapSfPDYVyJ69c9fw+kbFTFa
|
||||
9G1keN75SIJovWWhy4XUEcGkInDM4GyyEff1kpeEeZaOQZe2UojnptfmqLf0qDj6
|
||||
n02ABUdDiHhQT7Za634b0pxKAPXW2pSFflrGZc2e+pKpIG4ui/80uq8AGybeHda1
|
||||
Dl7iS2Msv4wpBii4j1Qs8gXAb7yI9ozS2weCmu5oqDN4SnYZBYoirT8seUia62aw
|
||||
XMVzkkQUsjRQz2oqQsTUZxtDuIU0VCNYPY0UgeSLjdzo+cUIbaoO6M8rAK42tq/1
|
||||
jJ+0RltUFPHxLXxi0LIAV0tFJxEJVUbpv7Nt
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEmzCCAoOgAwIBAgIQR1zhS092VJ8XK2pNm/t1gDANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowVzELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSYwJAYDVQQD
|
||||
Ex0oU1RBR0lORykgUHV6emxpbmcgUGFyc25pcCBFNzB2MBAGByqGSM49AgEGBSuB
|
||||
BAAiA2IABHu5ddBGjP6Ky/vtPVXikXyYxd8+ua+vISFBc3hJ1Iz/zme8T3C7BQsc
|
||||
U3WslRgVeI6c2CpEn2pB+5xb2PRVY8u8RoyrtKV7Q0gcUbQ5bMHYJc1Zubn4tcWt
|
||||
+tAkzx5JoqOCAQAwgf0wDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUF
|
||||
BwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSkD5QL
|
||||
RGNqmamg2YxmQ7FP3LAsRjAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXD
|
||||
FDA2BggrBgEFBQcBAQQqMCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5s
|
||||
ZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCsGA1UdHwQkMCIwIKAeoByG
|
||||
Gmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBk
|
||||
ws0hFFdRM6HYbbeSV+sAX3qiH0GSQCAS3le8ZdEDw0vdLQUqNA8dYd4t2P0tjFg5
|
||||
3ZVr8MFDQvP0zMyTAROT7SB4/8yG9QTWV9uQ4fMjwRh474EWvdXDMPVIw1W9FhiF
|
||||
NatXQD9o6Dg3Q91puWUxMOwiux+XkpMRHpFQ/6kHC9O4whjYqvZOYZaRwg0aiAg4
|
||||
SOnorJMeo2215nAsFWidfJF7WzfUQHRWsmSdJumUf6SSYl2hhB11nFTSHQG75uaG
|
||||
qz27J/XSP+QiF0BBBR5iK7x2W7vOFG1UTFAredh7SAkJehlHfnNcrFLHGPvkRLb1
|
||||
gW6BZH7tl2DB3auMuP5MdFytEq88HG83eerp4WRBZ8RL+R3nXDo6fCv1SMr6mzA5
|
||||
lsytrmDDuWSSRsn/rSkx78h+JtDfBrAz+QAVYa7I49nKRLyhc9RjOGTGpZh2LLbi
|
||||
Q09bTBIgSN14ZiCBbet8vH5c+PeDRZnBbSZrJn9Ju14m43Z1rmOOcd4VoG1wjD2X
|
||||
Q3DrM3K1TMn6DWq7Ks1sb+XkoMVKqi++M4bip3PUxdNNfj+ekovaaK1JJsjEDgCp
|
||||
f6V+ThZrDT72tmOYrus7oQXDglKZ2rJWON5LB/kK5Z9Nn7/uMShxuwxp5rwHf5zb
|
||||
AQlfAKgotEgPQfmzftRHvTab4vAx+D2u8+NHlzitJg==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEnjCCAoagAwIBAgIQIVQn1mKkfC7iT9ENPR8UEzANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowWjELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSkwJwYDVQQD
|
||||
EyAoU1RBR0lORykgTXlzdGVyaW91cyBNdWxiZXJyeSBFODB2MBAGByqGSM49AgEG
|
||||
BSuBBAAiA2IABBOvNirv3KX1VMRKbraNVeIX+G72tT9sFZArUXk/3HeA3/mVxG4D
|
||||
psHwhPQz23gyMwlv1EyWfrMQfcLXy51NQjUG6YHckZZXTqLcVmxyjdBl4aIbdPB2
|
||||
jtFJDRqB/nzYcKOCAQAwgf0wDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG
|
||||
AQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTJ
|
||||
QZNCSNGMFwaR8vI50qAfp7vbOTAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCs
|
||||
YyXDFDA2BggrBgEFBQcBAQQqMCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEu
|
||||
aS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCsGA1UdHwQkMCIwIKAe
|
||||
oByGGmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMA0GCSqGSIb3DQEBCwUAA4IC
|
||||
AQAiXF9HjYcmXFtrsRtT1ZwTTicTgRRAAHZmBGR7v/82qzzZmWCkDA1n7HbQxwOa
|
||||
MFNrXE9duNYYBMtFtrekiWnOq9wzmlVEdj3ZijJqdIyr9B3ZgRuVnKp4AKFWeGuc
|
||||
O8ae6iPmnNR0guY6f8uJzSn4jY14U+jtVSehVG6f4eHr6NrW45Eq3oPjjG+q1y77
|
||||
P7+Luns5iYJnY1eny+RzDJAUx/tMvQh7afAqdAZU6owoXXs+GHDBRbGUEEAozwar
|
||||
2BmR9HFaIgv613YbUxRjkuHZhUuGfViFvMytTma8zLPTax3VM3XnaJc4j3/1JL8B
|
||||
TBD49tskTZATwlZ30/NJ44BJjnHjbWbFMnFa2l7oOMpUZAmbYWDFg2zRESWHiJK2
|
||||
H6zCXkpyO5wqt3v1me5tXr8pytfIBOZX+D0o3NZgiQYMey4kretvisaheVgXx41e
|
||||
PVZO8aSl7nNC3STza2p2IDKiv7tLw9/aGgA+QJ8meue4ls0ZYbI/AX6nEIoT9YDg
|
||||
tzb+o/HC1a5n7D8zOQIYqmPQ334PT4wTeaB/wX+1SPRcsZlFwC195vWJoaGbjLSR
|
||||
eP/do0ZDlnnERlTn+Kcs77Yu7/B3JYP4eBOHi0/0Dluodaour255DEg7f/izTk+L
|
||||
Tm7oHiUHLtyYrDmi3MvCE/QZX9NUPs2uvctKIe8EZzJkdg==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkzCCAnugAwIBAgIQcmKs2kNXy4VFPKWbHytyTzANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowTzELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MR4wHAYDVQQD
|
||||
ExUoU1RBR0lORykgRmFrZSBGaWcgRTkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASG
|
||||
0H2j3VkxrFBiCmXKVfEGCGBIE+yLLfyhXE1sjgbHRvmv/LA8HPvocPO3S13qs7FF
|
||||
8xzguhOXOPFX/8QyVecqfd2ObEBA5rurkihNvL4gPksOc0jne3R9Ny3LS0LbKvGj
|
||||
ggEAMIH9MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYB
|
||||
BQUHAwEwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUjt3lqPew2dGlcdT/
|
||||
ijj51jsCbVcwHwYDVR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYIKwYB
|
||||
BQUHAQEEKjAoMCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iub3Jn
|
||||
LzATBgNVHSAEDDAKMAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8v
|
||||
c3RnLXgxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAQ0HW4n723Xzs
|
||||
5Yitnb3omoQ8OUauWJQDnzoid3WwDrSsptbIie6YFbhSBXlhTM+2IEeR4WfJIjxa
|
||||
lFciPuTGqv/5NBlHiNN3vZZfpEmDKTdBNy2EBxLbOS+BNvpzGyVJ14edgfiBawwM
|
||||
y33qrym9MyN3siOnifxeEUtqz/Rhjqqwve/5QFSewQxEMSj6Qf3aXg6OLgy/CxPC
|
||||
rICwghNB4l1xE8uySnKyQwwxJFMK26YwjVlF00GBi6lvA21rp2dnu5QtV4s9Jd5k
|
||||
HHB8tVq8LBr8MEQgzw5PPUWIA5wYmavwsOlb5McqMvjAmum44LaXKU1hLbAsULjo
|
||||
RO0/Rc+E7fAHLYDX5TfSdkRWJNoU2jPYUcRWtkTS8dOLXUg8nEhc3sAXUV6nnnPE
|
||||
+AmAvAGwdpfnb9keSH7zKvth+KV1V5eKO8zw6Xa1UGpSASedm3DO6PAfFzYeUzm3
|
||||
N7rSg0NQsw/U7HnLII/drATvjbBAGtLobMEogbYya11Q/m6ZjyMVLpDZUYn0vNlk
|
||||
IL4p2shL4z+Wiv9GaUX3tXVk8hBKWgs2/wYMWMd98tAbkBcUYJ3zeUt7EOft46NS
|
||||
Gcf0dcHPaEuFTT6wZJcwBf4oUm3Okf7k5I79NLqbqxD9aWBh10i/+J9J2Vg1ILXZ
|
||||
Zr3MA+MggU3jj6YscJtJGQ/4clsnURg=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFTTCCAzWgAwIBAgIRAIEbJZNMRe313pPFbPDf1AQwDQYJKoZIhvcNAQELBQAw
|
||||
ZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
|
||||
cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRlbmQg
|
||||
UGVhciBYMTAeFw0yNDAzMTMwMDAwMDBaFw0yNzAzMTIyMzU5NTlaMFoxCzAJBgNV
|
||||
BAYTAlVTMSAwHgYDVQQKExcoU1RBR0lORykgTGV0J3MgRW5jcnlwdDEpMCcGA1UE
|
||||
AxMgKFNUQUdJTkcpIENvdW50ZXJmZWl0IENhc2hldyBSMTAwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCa8zRfthw5T4/n9kt2iuNxb4zt78rR3ZygeZvp
|
||||
GGx8nMdU7jqCLeOqkuqhKBvBV823fvA0bYg3JaCiFsyB6Idry8eVZLFJp3BtBZFX
|
||||
pbAb7+QCYLAZrUl5rX3G9VoTG/x4Q8a9pN57CI34bmJlKaaefSLoeeAOArk8fcV3
|
||||
/MkTQHWG+heh9ex0ogr3kDQQOSm+dI14hz75eHuiV26kory+tDDBN1re76Qf8RRt
|
||||
NxnngYZFrbJ9IOovFJa28weGOVXekOL4JJ7/VdFMMceXQze8M+0qnkaaj+HNRYQx
|
||||
z0N1geD3clT/xrme3gL0y5xAKjX6eq4dXdJuau0h90VFTc3DAgMBAAGjggEAMIH9
|
||||
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
|
||||
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUpFJG6lioj2jYt7GQ0UpCSo9r
|
||||
KHEwHwYDVR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYIKwYBBQUHAQEE
|
||||
KjAoMCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iub3JnLzATBgNV
|
||||
HSAEDDAKMAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3RnLXgx
|
||||
LmMubGVuY3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAHhpGt8p6QJk8fnM0zOS5
|
||||
AEUultcQP/20NSCdBpIxAfownd+ylUzH2s1prl8T9rhKzTm4xZ+NBqPEDAd/1p5e
|
||||
1PYqR8bNnKJcTAAkjBYvKo5br0ng6GUkCQTqJ3atbAvx2bghdfrULF6+u+f4o288
|
||||
Jo6o1kN2Jf1mTXTKi2GRJ5JerChn0dls28Mzx8QS3mWfFFSu+QuGwtxLty7ySzWE
|
||||
TH+lNMa8U6MbtSvoWf8OYzNUZ7Bih6JKnuo4ueG7zRir2go8ygNdZoWHhmk84c35
|
||||
ABH8dKX+fKNDK6xzeygtbguJN2/D1n72RQK8w7gXjT7ptphEoxmxe+ZSQ1XEoKUv
|
||||
I/Xy2D8F/5+b4Uxg8xSNev/N+E9F/env3Pp7zQJt/L4dhnUMoqqbAOifOE8l/CdN
|
||||
QHKv1OJkNYiaJ+xfx+Z9wUw4zRvjuD23EK42GjCfsK0JNuHb98LAmDBF+Xfq+PlH
|
||||
OGZTLlmnM72Jmjvi5IJ/uo5pM2QbmauUMle4tZwq11ipRs0BggZY0fHFK/7AxXj/
|
||||
j3PQZAbnLSo/9x/YUK6aR1NGZYBScfwFCfbEMNuXB1KJJvn/eQP7TbVSrqsrsHpk
|
||||
AAzAHvDkhUpctdN8Bfjjylj4p9D0zGpqz7RMd4EKnC+K6waARt3+cY05nzq7uF34
|
||||
4eamtcAi8f6h3h9vQlcWOAg=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFTTCCAzWgAwIBAgIRAOOuDiVgQFyATegPOxfOa5IwDQYJKoZIhvcNAQELBQAw
|
||||
ZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
|
||||
cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRlbmQg
|
||||
UGVhciBYMTAeFw0yNDAzMTMwMDAwMDBaFw0yNzAzMTIyMzU5NTlaMFoxCzAJBgNV
|
||||
BAYTAlVTMSAwHgYDVQQKExcoU1RBR0lORykgTGV0J3MgRW5jcnlwdDEpMCcGA1UE
|
||||
AxMgKFNUQUdJTkcpIFdhbm5hYmUgV2F0ZXJjcmVzcyBSMTEwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCVYHwe2gxMv9Jh/d1BgocW3am5E/iBOrLkyENg
|
||||
RqLmVl6vNRXgoKpPjtP40Mv17Z2LlYhRsneaK9gdSNmNTxJlY8viqs9dk4XwKJxD
|
||||
Pfl/vJBW4M/nJzFwS30qu7VF8jSfyF82Q7KkLl5NxJ39Y5yvQFzHjL3YCO8coMG5
|
||||
v72DDgWzc+9wk2ncoXiB3/3mVg4RtD1w1xPpdjtSh5keB7jqgnD2/I75OLBzamy6
|
||||
NL9nguaEc8cX8CdnpoCCQI8/Fz9qhPtJjP+O/RHCugWVkSptuCRra8tcnJTGHRiN
|
||||
r/GyYsHZZ4jZ76hbJjxapwf24E8RAVzuMRsw/nS6/hUJ8lqPAgMBAAGjggEAMIH9
|
||||
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
|
||||
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUE8vX9q6d/GlCZNZcfCPMhflH
|
||||
x7YwHwYDVR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYIKwYBBQUHAQEE
|
||||
KjAoMCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iub3JnLzATBgNV
|
||||
HSAEDDAKMAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3RnLXgx
|
||||
LmMubGVuY3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAeD9pt5sWtXEQyF94RMzo
|
||||
lF+uip+ODYaNxPEJG/93xtxPc6QC0bsC9QIgv6dBk+s1LUf5ulIlJZQ1UlkLgTH4
|
||||
HzHi37O4ivcbSHpILcgD0hKnftv0E8o9SNAaIcO7DKNmbeWQ6cPlfOlRtpcIXYoc
|
||||
95wY9AipN0/ken5KxDxdxTSKuWS7Ae+ZWh7hmLdfDc5C85o2omLvM/6Ovmp0xUSP
|
||||
U/xFR1fk0kRmM975smehEOXSHOJ24zFaY6BnMUWa67yLawbxUj0AqzGmohdqz7Lu
|
||||
DhtKd9oXJgRzacFzuMSQluN0ivwKIzirpLR/AJoz4nHXIaDQRyfaA3jr1VYpK+bA
|
||||
poIXAjgxR/vEFtbEHw7fNO3FKRCddvyJ0vh+OKIrY0nrbGUoyRlPlKF/9XrQ3UJo
|
||||
Zc708mBBjzqijXdUQ0TB1/irAAQ7O/6i+ThQxElt77gYWzv2/8sSoagzqRKXOqLJ
|
||||
ckNJQIA39t4HMIFgqxDLRuRNtooFUeoOvocDWTQr80bUp6357cBtAl7ypcOzrPK6
|
||||
m5cuuyZfQ7zdh5ufcfMdFbgjwfeN8d442EzBnLxoMA9T2Igfn7KOhFl3znZ+WJhS
|
||||
h+oyBS8PrKUKB2Xo9pnXma6123xyFPDapnuK3iiNpGJfI0sULCqjEodYG+aGyfCz
|
||||
ZFLWftbU683YxZCOddgYxHI=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFSjCCAzKgAwIBAgIQG+VMtXt5SUBCqOW+UHI8WTANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowWDELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MScwJQYDVQQD
|
||||
Ex4oU1RBR0lORykgUmlkZGxpbmcgUmh1YmFyYiBSMTIwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQDYHSGRScFq1U7sAS8YfqaA2I/hnt1bHeDT3/lnQcQ4
|
||||
U24ic0bSHmDECLIgQh8b4HhKG0G5X9P7+8JQgWQbizkNJYps3IOwhqiG0FmPvR1m
|
||||
/byeEtidU0aVtAQoLNIkHulaw1l3nCIBGtL5ZGGKzOGP39VRNp2iV4a1TIGnb0/F
|
||||
z08FWhvkAxaX6WP8HH9aFvvsnjH14D+O24WBJjqHe5V8+IiLoxM9EcRCgOk3oAS2
|
||||
VngAnoSqkqeHKoIIz8t761lEk34Ln8qhEEHCxaX44Y4glllbLQL1fN1tEUiV7Gfw
|
||||
W4JU644Em2RkzHr5G/rD6aam6EXgmIq4Nucj9IENjN7hAgMBAAGjggEAMIH9MA4G
|
||||
A1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYD
|
||||
VR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU9kMDkS9mJa+FJd3kZNFpfsuiHNkw
|
||||
HwYDVR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYIKwYBBQUHAQEEKjAo
|
||||
MCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iub3JnLzATBgNVHSAE
|
||||
DDAKMAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3RnLXgxLmMu
|
||||
bGVuY3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEArPTkhI92+dUqNgxVitYi/w8z
|
||||
xwOXR6rhiJvKaoOFhA8DxqUaQ12eIVrhIN8LSQq2+O/Su3+VQaLXuQoeh/RBts6m
|
||||
GQS56fTuf6Q7Sb49olfNQjkdV+BqxkUzyWl7j/GAGumpZxGPLRmfUT0BV1jq+2Yd
|
||||
HKjvo3smWPEBnx/XMQ+p+fXh3xL1ATgB+eFtgQ/mQkVLMDUWGrcHUy78LTVgTZmt
|
||||
eWhTubOipgNVJi19FHi3cYdsPTM3JOCAGahsXOYV30sU+9TKw+fEG1RgjucVAiPC
|
||||
VxoyT/xiQ28tJ+MjWodlhrdWlTmiLHm6uBqJV8cEh6v0DwlI6BdnbCqM44d+jsO9
|
||||
QjlPiG6uGX9LEYaVmgIA3cplNBdWZ3KdYNnxh+bVFz9aO8j1G5kDTNldx6nMP+u5
|
||||
t1rA0iHIVMhXbY2JALAbO6/kH8XWmghsC81Xr5PzJEnROKZ65daBItHambNl+JJc
|
||||
mj84Iqe4HIjgOn2/BbfQHu/YfQx8gZGl5nXarDkGtI3IS4jb9OPfJZEErnizRVAV
|
||||
KsqiDk04Teh3BZX/w2prXHGCdsxCbbQgfximi0Q/Ug1xE0HCmmdTq/ZgYb2zdu3m
|
||||
s6Sg00ivj7b0LaPtVGt1eEFqX+6OofleMic4uZgiazH/87j0EhBquPEmNPeXEMq1
|
||||
SIKYbiG+Lshx0NWHFGE=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFSTCCAzGgAwIBAgIRALFHDgDyoK1a9jgJ6YGyNZEwDQYJKoZIhvcNAQELBQAw
|
||||
ZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
|
||||
cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRlbmQg
|
||||
UGVhciBYMTAeFw0yNDAzMTMwMDAwMDBaFw0yNzAzMTIyMzU5NTlaMFYxCzAJBgNV
|
||||
BAYTAlVTMSAwHgYDVQQKExcoU1RBR0lORykgTGV0J3MgRW5jcnlwdDElMCMGA1UE
|
||||
AxMcKFNUQUdJTkcpIFRlbnVvdXMgVG9tYXRvIFIxMzCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBALCK+fGStcR61BnRaS432a3MFb/OABZls4n5dFDskT7N
|
||||
rxbmnWFE+fr2AajUqfrQvi0gkCVc2VUHZBvCNSo2SNRIsqSDqMv+pnvsUlHFsAWk
|
||||
Nn0m38txlWHe4yNiCCBIG5FhtwAoRsrxq7+DucvurSfM19jdV0Xo7yEHwljJGBpF
|
||||
VmAc1oCHfXSW4MXgNTgFw9AFS3YQuiwR3xpYWb2sdnS2gsXQtqTi9GSPrJCeS5+U
|
||||
qQeJVXuYqOdA0R4hCBhaCSX0e8qibY9+CwOmUCtUPDu6/GT0qLFAw+4TUwioo4oW
|
||||
XEM9w+1k8QMK2C1+8k7eS7Gb6Mr7fy8hKUmjOw9tAYkCAwEAAaOCAQAwgf0wDgYD
|
||||
VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNV
|
||||
HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQ+NI/KKXMrEFgZoev4u6nEXmTm0TAf
|
||||
BgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXDFDA2BggrBgEFBQcBAQQqMCgw
|
||||
JgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5sZW5jci5vcmcvMBMGA1UdIAQM
|
||||
MAowCAYGZ4EMAQIBMCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9zdGcteDEuYy5s
|
||||
ZW5jci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQAqeimaSzd5wkNwYXId1a0J/pE9
|
||||
oGu37UCH4S0vkEJhzat3yRUIdokC4ixAuNVEaX7XzkeSfQnVQBL5SDlmoVXE4/Dn
|
||||
7UWKGOk83EQq5+49hINQ9pjcUXI7ENxbyz+ZNjSy7UrL9B6N/ZHy8/GKRgm2cd13
|
||||
GwbB4wJA5VS1ge5rPy+3rJfMuszdCSy8v/LlS2zyoPtPt7CvVfsy8mac3jrJdfMM
|
||||
9Ugd4uU8riB0AZ5yY7dE5H8LF49qtm1qJ5Vdp//4Xva4Wkd7YSbEKRSgpF7Y0B9U
|
||||
SCfhwVyw1cxOWudA/RG8bFaSet5ORxhIygRdeDwROZNY/sduoHloJekGbxTRB9QC
|
||||
qdXLY0xPcDjiZliKzft8XG71UpJ9Ld7+mq1wx9igojcSh6ZACaeyhbAh7S6EcvGT
|
||||
pv6C1YZADh6KlWJBnrCVeaSdrFx3CwZUDtk16YQHcYpL1fK99hZx9ka4awChReDu
|
||||
EEFAju96zpPV2SuSb0fs6Z2L8TrGwMmlUOe39H8sMKCLUnqdXhnrRcWMWlpg5wVc
|
||||
Tkka73Ald6uRLQJBQhttRYEtDsy2WvuGP5xkFOrSgxG/EdVmDf00ueO7MJOW31mT
|
||||
zeCBmfQzFGWbBaOWBvl014IAjONFt5VjyDwI9NExsrgcIdo91+4R5qV92aPXqC+H
|
||||
1ihc7aoA6ccL6q+Rag==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFRzCCAy+gAwIBAgIQM1SWpsbRGJEvfzrEKJM61TANBgkqhkiG9w0BAQsFADBm
|
||||
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
|
||||
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
|
||||
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowVTELMAkGA1UE
|
||||
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSQwIgYDVQQD
|
||||
ExsoU1RBR0lORykgTm90IE5lY3RhcmluZSBSMTQwggEiMA0GCSqGSIb3DQEBAQUA
|
||||
A4IBDwAwggEKAoIBAQCU1OyKAowg7M1LoMHUIa5HOTH85yvIkqiFffue3hSJkJFc
|
||||
IMeaQzc76CZ8k6XnYzSeGwBqMJsy5OK9uKxvzFYNP58br2+L9FDM417Sr5JAEoVa
|
||||
0oOZgUhj9+/YPmhbIWkvkDtbqYXX+HLVEtJWFOGeXquHaF72NMAUTJd5AW6tezjG
|
||||
AJwYKy2Dn1HICxZ9Xa+I2rO+XrUJk4ksy3cjaKhJgqqYHVQd4Rbea1KLJBJXnOyH
|
||||
eDe/iMO+ktnaJOXopX+FXv39V35VUslhFm0JoFJniy7BzWTu0IqYs1fi+6o1Pbgi
|
||||
/+QPUI/Vy5Ji/iLTnuRPnL35T3Jhlfhjpmc/nG4xAgMBAAGjggEAMIH9MA4GA1Ud
|
||||
DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0T
|
||||
AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUTdM2YmiVBflkEg783eAsH4ErrPYwHwYD
|
||||
VR0jBBgwFoAUtfNl8v6wCpIf+zx980SgrGMlwxQwNgYIKwYBBQUHAQEEKjAoMCYG
|
||||
CCsGAQUFBzAChhpodHRwOi8vc3RnLXgxLmkubGVuY3Iub3JnLzATBgNVHSAEDDAK
|
||||
MAgGBmeBDAECATArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3RnLXgxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEARVtr23kJ3bcVULo/8gB1QzJIjUKs
|
||||
qkigEk9FIPx28PHMDpwvGRDGWjYQ4HIThqwugycxgeueFJtnV3L65vAowc/Xk3MG
|
||||
KKL+pPwj5nf6xd82+Ga+PBV2WGrwhYkfs9i56xB9iH1He7e21v5U4B4CTrb63LLK
|
||||
mfoz5OIA7/tWupHccgmFpwEZuzracr9z9KpBWnvv9j2xNHxolNl/cH6X2DAltMNn
|
||||
AXpeW6c6/eke4wIAhbGaOb8f1JnayJl5VfzlCEVOjTolvPtXtKxIyu0G7cuBkatJ
|
||||
BU1S5V5JbO4gf9W8OwuaJv2M3vhfnIuH+JOoAHJmLkb6CmRAXiqj0C4hA10YgCZw
|
||||
ko3b4zhVCFMpk/yQPVCdIA65xTcvhxmShKbwAODBQTiZxkOIMtqm7fFXU+AJBRju
|
||||
057TkaF7tro2ADGHa82tSmnfqArWAeHLMk7sQ4ENHgzd9h85NtloVEiTEmD+3Z2v
|
||||
pfWpmvm4do6FNbeBxMM7Ytt0xAYmz5divUxkPvo4Q5gtcSnWRDH5nrIfniMshD3a
|
||||
m2K0OFUq3k35TB7eUkMQ5SQ7lYEfeQAQ4QuWOeVXTGvOOP6zG0JBkuN7VQSOHNom
|
||||
jVPRtCbul4dmPLxM4+Dqs/Sa4bN9aRF0AAvz5K1316kWTwEPUjo7iatGwk61cBy+
|
||||
kUaGFBEQvWad/V8=
|
||||
-----END CERTIFICATE-----
|
|
@ -70,6 +70,28 @@ var CRL5 = x509.RevocationList{
|
|||
RevokedCertificateEntries: nil,
|
||||
}
|
||||
|
||||
// CRL6 contains serial 4213, which will have a CRLDistributionPoint
|
||||
// that doesn't match the CRL.
|
||||
var CRL6 = x509.RevocationList{
|
||||
ThisUpdate: Now.Add(4 * time.Hour),
|
||||
NextUpdate: Now.Add(24 * time.Hour),
|
||||
Number: big.NewInt(1),
|
||||
RevokedCertificateEntries: []x509.RevocationListEntry{
|
||||
{SerialNumber: big.NewInt(4213), RevocationTime: Now},
|
||||
},
|
||||
}
|
||||
|
||||
// CRL7 also contains serial 4213, which will have a CRLDistributionPoint
|
||||
// that doesn't match the CRL.
|
||||
var CRL7 = x509.RevocationList{
|
||||
ThisUpdate: Now.Add(5 * time.Hour),
|
||||
NextUpdate: Now.Add(25 * time.Hour),
|
||||
Number: big.NewInt(2),
|
||||
RevokedCertificateEntries: []x509.RevocationListEntry{
|
||||
{SerialNumber: big.NewInt(4213), RevocationTime: Now},
|
||||
},
|
||||
}
|
||||
|
||||
func MakeIssuer(t *testing.T) (*x509.Certificate, crypto.Signer) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -2,25 +2,29 @@ package churner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
mathrand "math/rand/v2"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/libdns/route53"
|
||||
"github.com/mholt/acmez"
|
||||
"github.com/mholt/acmez/acme"
|
||||
"go.uber.org/zap"
|
||||
"github.com/mholt/acmez/v3"
|
||||
"github.com/mholt/acmez/v3/acme"
|
||||
|
||||
"github.com/letsencrypt/boulder/crl/checker"
|
||||
"github.com/letsencrypt/crl-monitor/cmd"
|
||||
"github.com/letsencrypt/crl-monitor/db"
|
||||
"github.com/letsencrypt/crl-monitor/retryhttp"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -46,21 +50,20 @@ type Churner struct {
|
|||
// `baseDomain` should be a domain name that the `dnsProvider` can create/delete
|
||||
// records for. The certs will be issued from the CA at `acmeDirectory`.
|
||||
// The resulting serials are stored into `db`
|
||||
func New(baseDomain string, acmeDirectory string, dnsProvider certmagic.ACMEDNSProvider, db *db.Database, cutoff time.Time) (*Churner, error) {
|
||||
zapLogger, err := zap.NewProduction()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func New(baseDomain string, acmeDirectory string, dnsProvider certmagic.DNSProvider, db *db.Database, cutoff time.Time) (*Churner, error) {
|
||||
slogger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
|
||||
acmeClient := acmez.Client{
|
||||
Client: &acme.Client{
|
||||
Directory: acmeDirectory,
|
||||
Logger: zapLogger,
|
||||
Logger: slogger,
|
||||
},
|
||||
ChallengeSolvers: map[string]acmez.Solver{
|
||||
acme.ChallengeTypeDNS01: &certmagic.DNS01Solver{
|
||||
DNSProvider: dnsProvider,
|
||||
PropagationDelay: 60 * time.Second, // Route53 docs say 60 seconds in normal conditions
|
||||
DNSManager: certmagic.DNSManager{
|
||||
DNSProvider: dnsProvider,
|
||||
PropagationDelay: 60 * time.Second, // Route53 docs say 60 seconds in normal conditions,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -77,7 +80,7 @@ func NewFromEnv(ctx context.Context) (*Churner, error) {
|
|||
baseDomain := BaseDomainEnv.MustRead("Base domain to issue certificates under")
|
||||
acmeDirectory := ACMEDirectoryEnv.MustRead("ACME directory URL")
|
||||
dynamoTable := DynamoTableEnv.MustRead("DynamoDB table name")
|
||||
dynamoEndpoint, customEndpoint := DynamoEndpointEnv.LookupEnv()
|
||||
dynamoEndpoint, _ := DynamoEndpointEnv.LookupEnv()
|
||||
|
||||
revokeDeadline, err := time.ParseDuration(RevokeDeadline.MustRead("Deadline for revoked certs to appear in CRL, as a duration before the current time"))
|
||||
if err != nil {
|
||||
|
@ -86,16 +89,7 @@ func NewFromEnv(ctx context.Context) (*Churner, error) {
|
|||
|
||||
cutoff := time.Now().Add(-1 * revokeDeadline)
|
||||
|
||||
cfg, err := config.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating AWS config: %v", err)
|
||||
}
|
||||
|
||||
if customEndpoint {
|
||||
cfg.EndpointResolverWithOptions = aws.EndpointResolverWithOptionsFunc(db.StaticResolver(dynamoEndpoint)) // nolint:staticcheck // SA1019
|
||||
}
|
||||
|
||||
database, err := db.New(dynamoTable, &cfg)
|
||||
database, err := db.New(ctx, dynamoTable, dynamoEndpoint)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in database setup: %v", err)
|
||||
}
|
||||
|
@ -126,27 +120,81 @@ func (c *Churner) RegisterAccount(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Churner) retryObtain(ctx context.Context, certPrivateKey crypto.Signer, sans []string) ([]acme.Certificate, error) {
|
||||
csr, err := acmez.NewCSR(certPrivateKey, sans)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params, err := acmez.OrderParametersFromCSR(c.acmeAccount, csr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var certificates []acme.Certificate
|
||||
for retry := 0; retry < 5; retry++ {
|
||||
certificates, err = c.acmeClient.ObtainCertificate(ctx, params)
|
||||
if err != nil {
|
||||
log.Printf("error obtaining certificate on retry %d: %v", retry, err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
return certificates, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Churn issues a certificate, revokes it, and stores the result in DynamoDB
|
||||
func (c *Churner) Churn(ctx context.Context) error {
|
||||
// Generate either an ecdsa or rsa private key
|
||||
certPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
certPrivateKey, err := randomKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certificates, err := c.acmeClient.ObtainCertificate(ctx, c.acmeAccount, certPrivateKey, randDomains(c.baseDomain))
|
||||
certificates, err := c.retryObtain(ctx, certPrivateKey, randDomains(c.baseDomain))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// certificates contains all the possible cert chains. We only care about
|
||||
// the cert, so we just take the first one and parse it.
|
||||
// certificates contains all the possible cert chains. We don't
|
||||
// care about alternate chains, but we do care about getting
|
||||
// the parent of the certificate we just got, so we can validate its CRL.
|
||||
firstChain := certificates[0].ChainPEM
|
||||
block, _ := pem.Decode(firstChain)
|
||||
block, remaining := pem.Decode(firstChain)
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
block, _ = pem.Decode(remaining)
|
||||
issuer, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the certificate has any CRLDistributionPoints, check that they can be fetched,
|
||||
// parsed, verified, and linted. We don't try to check for revocation at this stage
|
||||
// because it may be several hours before a new CRL is uploaded that reflects the
|
||||
// revocation we're about to do. Contrariwise, we check for non-revocation, since
|
||||
// we're fetching the CRL before revoking.
|
||||
for _, url := range cert.CRLDistributionPoints {
|
||||
body, err := retryhttp.Get(ctx, url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching CRL %q from CRLDistributionPoint of certificate %036x: %s",
|
||||
url, cert.SerialNumber, err)
|
||||
}
|
||||
crl, err := x509.ParseRevocationList(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching CRL %q from CRLDistributionPoint of certificate %036x: %s",
|
||||
url, cert.SerialNumber, err)
|
||||
}
|
||||
err = checker.Validate(crl, issuer, 24*time.Hour)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range crl.RevokedCertificateEntries {
|
||||
if entry.SerialNumber.Cmp(cert.SerialNumber) == 0 {
|
||||
return fmt.Errorf("certificate %x was found on CRL %s before it was revoked", cert.SerialNumber, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = c.acmeClient.RevokeCertificate(ctx, c.acmeAccount, cert, c.acmeAccount.PrivateKey, acme.ReasonCessationOfOperation)
|
||||
if err != nil {
|
||||
|
@ -156,16 +204,19 @@ func (c *Churner) Churn(ctx context.Context) error {
|
|||
return c.db.AddCert(ctx, cert, time.Now())
|
||||
}
|
||||
|
||||
// randomKey generates either an ecdsa or rsa private key
|
||||
func randomKey() (crypto.Signer, error) {
|
||||
if mathrand.IntN(2) == 0 {
|
||||
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
} else {
|
||||
return rsa.GenerateKey(rand.Reader, 2048)
|
||||
}
|
||||
}
|
||||
|
||||
// randDomains picks the domains to include on the certificate.
|
||||
// We put a single domain which includes the current time and a random value.
|
||||
func randDomains(baseDomain string) []string {
|
||||
randomSuffix := make([]byte, 2)
|
||||
_, err := rand.Read(randomSuffix)
|
||||
if err != nil {
|
||||
// Something has to go terribly wrong for this
|
||||
panic(fmt.Sprintf("random read failed: %v", err))
|
||||
}
|
||||
domain := fmt.Sprintf("r%dz%x.%s", time.Now().Unix(), randomSuffix, baseDomain)
|
||||
domain := fmt.Sprintf("r%dz%x.%s", time.Now().Unix(), mathrand.Uint32(), baseDomain)
|
||||
return []string{domain}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestRandDomains(t *testing.T) {
|
|||
base := "revoked.invalid"
|
||||
domains := randDomains(base)
|
||||
require.Len(t, domains, 1)
|
||||
require.Regexp(t, regexp.MustCompile(`r[0-9]{10}z[0-9a-f]{4}\.`+regexp.QuoteMeta(base)), domains[0])
|
||||
require.Regexp(t, regexp.MustCompile(`r[0-9]{10}z[0-9a-f]+\.`+regexp.QuoteMeta(base)), domains[0])
|
||||
|
||||
second := randDomains(base)
|
||||
require.NotEqual(t, domains, second, "Domains should be different each invocation")
|
||||
|
|
49
db/db.go
49
db/db.go
|
@ -4,10 +4,12 @@ import (
|
|||
"context"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
|
||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
|
||||
|
@ -25,10 +27,19 @@ type Database struct {
|
|||
Dynamo ddb
|
||||
}
|
||||
|
||||
func New(table string, cfg *aws.Config) (*Database, error) {
|
||||
func New(ctx context.Context, table, dynamoEndpoint string) (*Database, error) {
|
||||
cfg, err := config.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating AWS config: %v", err)
|
||||
}
|
||||
|
||||
return &Database{
|
||||
Table: table,
|
||||
Dynamo: dynamodb.NewFromConfig(*cfg),
|
||||
Table: table,
|
||||
Dynamo: dynamodb.NewFromConfig(cfg, func(o *dynamodb.Options) {
|
||||
if dynamoEndpoint != "" {
|
||||
o.BaseEndpoint = aws.String(dynamoEndpoint)
|
||||
}
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -36,7 +47,8 @@ func New(table string, cfg *aws.Config) (*Database, error) {
|
|||
// That is the CertKey plus the revocation time today.
|
||||
type CertMetadata struct {
|
||||
CertKey
|
||||
RevocationTime time.Time `dynamodbav:"RT,unixtime"`
|
||||
RevocationTime time.Time `dynamodbav:"RT,unixtime"`
|
||||
CRLDistributionPoint string `dynamodbav:"DP,string,omitempty"`
|
||||
}
|
||||
|
||||
// CertKey is the DynamoDB primary key, which is the serial number.
|
||||
|
@ -56,9 +68,19 @@ func (ck CertKey) SerialString() string {
|
|||
|
||||
// AddCert inserts the metadata for monitoring
|
||||
func (db *Database) AddCert(ctx context.Context, certificate *x509.Certificate, revocationTime time.Time) error {
|
||||
var crlDistributionPoint string
|
||||
// TODO: Once all issued certificates have a CRLDistributionPoint, error out when
|
||||
// the extension is absent.
|
||||
if len(certificate.CRLDistributionPoints) > 0 {
|
||||
crlDistributionPoint = certificate.CRLDistributionPoints[0]
|
||||
}
|
||||
if len(certificate.CRLDistributionPoints) > 1 {
|
||||
return fmt.Errorf("too many CRLDistributionPoints in certificate: %d", len(certificate.CRLDistributionPoints))
|
||||
}
|
||||
item, err := attributevalue.MarshalMap(CertMetadata{
|
||||
CertKey: NewCertKey(certificate.SerialNumber),
|
||||
RevocationTime: revocationTime,
|
||||
CertKey: NewCertKey(certificate.SerialNumber),
|
||||
RevocationTime: revocationTime,
|
||||
CRLDistributionPoint: crlDistributionPoint,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -98,7 +120,7 @@ func (db *Database) GetAllCerts(ctx context.Context) (map[string]CertMetadata, e
|
|||
|
||||
certs := make(map[string]CertMetadata, len(certList))
|
||||
for _, cert := range certList {
|
||||
certs[cert.CertKey.SerialString()] = cert
|
||||
certs[cert.SerialString()] = cert
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
@ -130,16 +152,3 @@ func (db *Database) DeleteSerials(ctx context.Context, serialNumbers [][]byte) e
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StaticResolver is used in test and dev to use the local dynamodb
|
||||
func StaticResolver(url string) func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
|
||||
return func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
|
||||
if service != dynamodb.ServiceID {
|
||||
return aws.Endpoint{}, &aws.EndpointNotFoundError{}
|
||||
}
|
||||
return aws.Endpoint{
|
||||
PartitionID: "aws",
|
||||
URL: url,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -69,3 +70,57 @@ func smoketest(t *testing.T, handle *db.Database) {
|
|||
}
|
||||
require.Equal(t, expected, remaining)
|
||||
}
|
||||
|
||||
func TestAddCertCRLDP(t *testing.T) {
|
||||
handle := mock.NewMockedDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
revocationTime := time.Now().Add(100 * time.Hour)
|
||||
|
||||
int111 := big.NewInt(111)
|
||||
int4s := big.NewInt(444444)
|
||||
int60s := big.NewInt(606060)
|
||||
|
||||
err := handle.AddCert(ctx, &x509.Certificate{
|
||||
SerialNumber: int111,
|
||||
}, revocationTime)
|
||||
if err != nil {
|
||||
t.Errorf("inserting plain cert: %s", err)
|
||||
}
|
||||
|
||||
err = handle.AddCert(ctx, &x509.Certificate{
|
||||
SerialNumber: int4s,
|
||||
CRLDistributionPoints: []string{
|
||||
"http://example.com/crl",
|
||||
"http://example.net/crl",
|
||||
},
|
||||
}, revocationTime)
|
||||
if err == nil {
|
||||
t.Errorf("inserting cert with two CRLDistributionPoints: got success, want error")
|
||||
}
|
||||
|
||||
err = handle.AddCert(ctx, &x509.Certificate{
|
||||
SerialNumber: int60s,
|
||||
CRLDistributionPoints: []string{
|
||||
"http://example.com/crl",
|
||||
},
|
||||
}, revocationTime)
|
||||
if err != nil {
|
||||
t.Errorf("inserting cert with one CRLDistributionPoint: %s", err)
|
||||
}
|
||||
|
||||
results, err := handle.GetAllCerts(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("getting all certs: %s", err)
|
||||
}
|
||||
|
||||
serialString := fmt.Sprintf("%036x", int60s)
|
||||
metadata, ok := results[serialString]
|
||||
if !ok {
|
||||
t.Errorf("getting all certs: expected entry for %s, got %+v", serialString, metadata)
|
||||
}
|
||||
|
||||
if metadata.CRLDistributionPoint != "http://example.com/crl" {
|
||||
t.Errorf("CRL for %s = %q, want %q", serialString, metadata.CRLDistributionPoint, "http://example.com/crl")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,10 @@ import (
|
|||
// run most tests outside the db package.
|
||||
func TestIntegrationDynamoDB(t *testing.T) {
|
||||
cfg := aws.NewConfig()
|
||||
cfg.EndpointResolverWithOptions = aws.EndpointResolverWithOptionsFunc(db.StaticResolver("http://localhost:8000"))
|
||||
cfg.Credentials = aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
|
||||
return aws.Credentials{AccessKeyID: "Bogus", SecretAccessKey: "Bogus"}, nil
|
||||
})
|
||||
handle, err := db.New("unseen-certificates", cfg)
|
||||
handle, err := db.New(context.Background(), "unseen-certificates", "http://localhost:8000")
|
||||
require.NoError(t, err)
|
||||
|
||||
smoketest(t, handle)
|
||||
|
|
101
go.mod
101
go.mod
|
@ -1,65 +1,68 @@
|
|||
module github.com/letsencrypt/crl-monitor
|
||||
|
||||
go 1.21
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.21.4
|
||||
toolchain go1.24.2
|
||||
|
||||
require (
|
||||
github.com/aws/aws-lambda-go v1.43.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.1
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.12.12
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.6
|
||||
github.com/caddyserver/certmagic v0.20.0
|
||||
github.com/letsencrypt/boulder v0.0.0-20231211192339-8cd1e60abfcd
|
||||
github.com/libdns/route53 v1.3.3
|
||||
github.com/mholt/acmez v1.2.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.26.0
|
||||
github.com/aws/aws-lambda-go v1.49.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.4
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.16
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.2
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.3
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.80.2
|
||||
github.com/caddyserver/certmagic v0.21.7
|
||||
github.com/letsencrypt/boulder v0.0.0-20240424004736-7ee5b469a6a9
|
||||
github.com/libdns/route53 v1.5.1
|
||||
github.com/mholt/acmez/v3 v3.1.2
|
||||
github.com/stretchr/testify v1.10.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.69 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.35 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21 // indirect
|
||||
github.com/aws/smithy-go v1.22.2 // indirect
|
||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/miekg/dns v1.1.57 // indirect
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/libdns/libdns v0.2.2 // indirect
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230620154423-38c92ad2d5c6 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300 // indirect
|
||||
github.com/zmap/zlint/v3 v3.5.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
github.com/weppos/publicsuffix-go v0.30.3-0.20240411085455-21202160c2ed // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c // indirect
|
||||
github.com/zmap/zlint/v3 v3.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
246
go.sum
246
go.sum
|
@ -1,71 +1,60 @@
|
|||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/aws/aws-lambda-go v1.43.0 h1:Tdu7SnMB5bD+CbdnSq1Dg4sM68vEuGIDcQFZ+IjUfx0=
|
||||
github.com/aws/aws-lambda-go v1.43.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.8/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.21/go.mod h1:+jPQiVPz1diRnjj6VGqWcLK6EzNmQ42l7J3OqGTLsSY=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.1 h1:z6DqMxclFGL3Zfo+4Q0rLnAZ6yVkzCRxhRMsiRQnD1o=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.1/go.mod h1:ZB+CuKHRbb5v5F0oJtGdhFTelmrxd4iWO1lf0rQwSAg=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.20/go.mod h1:xtZnXErtbZ8YGXC3+8WfajpMBn5Ga/3ojZdxHq6iI8o=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.12 h1:v/WgB8NxprNvr5inKIiVVrXPuuTegM+K8nncFkr1usU=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.12/go.mod h1:X21k0FjEJe+/pauud82HYiQbEr9jRKY3kXEIQ4hXeTQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.12.12 h1:6p4l8wc8QMRSg8Yb6qfmiJpkfwyJtcljmGH6hcxz/ik=
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.12.12/go.mod h1:mzvoVQGD+ivawg984kcM2zd7oCFcknJ0uWTaR19lqEs=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.2/go.mod h1:cDh1p6XkSGSwSRIArWRc6+UqAQ7x4alQ0QfpVR6f+co=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32/go.mod h1:RudqOgadTWdcS3t/erPQo24pcVEoYyqj/kKW5Vya21I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26/go.mod h1:vq86l7956VgFr0/FWQ2BWnK07QC3WYsepKzy33qqY5U=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.33/go.mod h1:zG2FcwjQarWaqXSCGpgcr3RSjZ6dHGguZSppUL0XR7Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6 h1:kSdpnPOZL9NG5QHoKL5rTsdY+J+77hr+vqVMsPeyNe0=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6/go.mod h1:o7TD9sjdgrl8l/g2a2IkYjuhxjPy9DMP2sWo7piaRBQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.5 h1:ekyZDC/JMR4s/64oT9KsOnYWfGr03ebkwgHwe3iX9rA=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.5/go.mod h1:T461RxBmf94zuOuIUifdy5Zim3DJTo0X4nXE3vodXQI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10 h1:h8uweImUHGgyNKrxIUwpPs6XiH0a6DJ17hSJvFLgPAo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10/go.mod h1:LZKVtMBiZfdvUWgwg61Qo6kyAmE5rn9Dw36AqnycvG8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.26/go.mod h1:Bd4C/4PkVGubtNe5iMXu5BNnaBi/9t/UsFspPt4ram8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.27.7/go.mod h1:Jhu94omkrksnqX6Xs4Qo10eA1Fx+2NYKjZMU4GvZLp0=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5 h1:WVQIKVwv56JY+I0b2fFeRGCTSi/Xupa87z7y8HZ6l5g=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5/go.mod h1:F9El48+5Tf+TkYJB/6M9H7oqXw9Mr9eVetwJ6SUql7g=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.6 h1:bkmlzokzTJyrFNA0J+EPlsF8x4/wp+9D45HTHO/ZUiY=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.6/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.8/go.mod h1:GNIveDnP+aE3jujyUSH5aZ/rktsTM5EvtKnCqBZawdw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.8/go.mod h1:44qFP1g7pfd+U+sQHLPalAPKnyfTZjJsYR4xIwsJy5o=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.9/go.mod h1:yyW88BEPXA2fGFyI2KCcZC3dNpiT0CZAHaF+i656/tQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 h1:5UYvv8JUvllZsRnfrcMQ+hJ9jNICmcgKPAO1CER25Wg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU=
|
||||
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
|
||||
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
|
||||
github.com/aws/aws-lambda-go v1.49.0 h1:z4VhTqkFZPM3xpEtTqWqRqsRH4TZBMJqTkRiBPYLqIQ=
|
||||
github.com/aws/aws-lambda-go v1.49.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.16 h1:XkruGnXX1nEZ+Nyo9v84TzsX+nj86icbFAeust6uo8A=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.16/go.mod h1:uCW7PNjGwZ5cOGZ5jr8vCWrYkGIhPoTNV23Q/tpHKzg=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.69 h1:8B8ZQboRc3uaIKjshve/XlvJ570R7BKNy3gftSbS178=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.69/go.mod h1:gPME6I8grR1jCqBFEGthULiolzf/Sexq/Wy42ibKK9c=
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.2 h1:Nl1i1+ZtpafH5DHr4LYpAgPwvWjDc3bfPlcZpLw3ffQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.2/go.mod h1:P9puVqIaBsnqbUcfDOIk0dsKaa7jckuRxwBbg6NzF9Y=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31 h1:oQWSGexYasNpYp4epLGZxxjsDo8BMBh6iNWkTXQvkwk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31/go.mod h1:nc332eGUU+djP3vrMI6blS0woaCfHTe3KiSQUVTMRq0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.35 h1:th/m+Q18CkajTw1iqx2cKkLCij/uz8NMwJFPK91p2ug=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.35/go.mod h1:dkJuf0a1Bc8HAA0Zm2MoTGm/WDC18Td9vSbrQ1+VqE8=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.3 h1:2FCJAT5wyPs5JjAFoLgaEB0MIiWvXiJ0T6PZiKDkJoo=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.3/go.mod h1:rUOhTo9+gtTYTMnGD+xiiks/2Z8vssPP+uSMNhJBbmI=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.5 h1:JSQ8/BuqZHaeE/kVgimmjHZ27wTKjYHujo6Oo6M1Iv4=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.5/go.mod h1:4iQhABsZl371BGh/fJq/qJcHzxoNX3kHTmhOXQWYhjU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.3 h1:VHPZakq2L7w+RLzV54LmQavbvheFaR2u1NomJRSEfcU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.3/go.mod h1:DX1e/lkbsAt0MkY3NgLYuH4jQvRfw8MYxTe9feR7aXM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.16 h1:TLsOzHW9zlJoMgjcKQI/7bolyv/DL0796y4NigWgaw8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.16/go.mod h1:mNoiR5qsO9TxXZ6psjjQ3M+Zz7hURFTumXHF+UKjyAU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16 h1:/ldKrPPXTC421bTNWrUIpq3CxwHwRI/kpc+jPUTJocM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16/go.mod h1:5vkf/Ws0/wgIMJDQbjI4p2op86hNW6Hie5QtebrDgT8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.16 h1:2HuI7vWKhFWsBhIr2Zq8KfFZT6xqaId2XXnXZjkbEuc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.16/go.mod h1:BrwWnsfbFtFeRjdx0iM1ymvlqDX1Oz68JsQaibX/wG8=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3 h1:MmLCRqP4U4Cw9gJ4bNrCG0mWqEtBlmAVleyelcHARMU=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3/go.mod h1:AMPjK2YnRh0YgOID3PqhJA1BRNfXDfGOnSsKHtAe8yA=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.80.2 h1:T6Wu+8E2LeTUqzqQ/Bh1EoFNj1u4jUyveMgmTlu9fDU=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.80.2/go.mod h1:chSY8zfqmS0OnhZoO/hpPx/BHfAIL80m77HwhRLYScY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4 h1:EU58LP8ozQDVroOEyAfcq0cGc5R/FTZjVoYJ6tvby3w=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4/go.mod h1:CrtOgCcysxMvrCoHnvNAD7PHWclmoFG78Q2xLK0KKcs=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2 h1:XB4z0hbQtpmBnb1FQYvKaCM7UsS6Y/u8jVBwIUGeCTk=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2/go.mod h1:hwRpqkRxnQ58J9blRDrB4IanlXCpcKmsC83EhG77upg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21 h1:nyLjs8sYJShFYj6aiyjCBI3EcLn1udWrQTjEF+SOXB0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21/go.mod h1:EhdxtZ+g84MSGrSrHzZiUm9PYiZkrADNja15wtRJSJo=
|
||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
||||
github.com/caddyserver/certmagic v0.21.7 h1:66KJioPFJwttL43KYSWk7ErSmE6LfaJgCQuhm8Sg6fg=
|
||||
github.com/caddyserver/certmagic v0.21.7/go.mod h1:LCPG3WLxcnjVKl/xpjzM0gqh0knrKKKiO5WVttX2eEI=
|
||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
|
@ -73,21 +62,22 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/certificate-transparency-go v1.1.6 h1:SW5K3sr7ptST/pIvNkSVWMiJqemRmkjJPPT0jzXdOOY=
|
||||
github.com/google/certificate-transparency-go v1.1.6/go.mod h1:0OJjOsOk+wj6aYQgP7FU0ioQ0AJUmnWPFMqTjQeazPQ=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
|
@ -95,11 +85,9 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
|
|||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=
|
||||
github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
|
@ -108,27 +96,27 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/letsencrypt/boulder v0.0.0-20231211192339-8cd1e60abfcd h1:HvHfvGkozQ5EL7qNEfCLB+A0fhQJiibkxJc4BNX/Eiw=
|
||||
github.com/letsencrypt/boulder v0.0.0-20231211192339-8cd1e60abfcd/go.mod h1:wMTwTuF8RTqUheknqYBAXMMoTI2t5OwqPpAV9F324Rg=
|
||||
github.com/letsencrypt/boulder v0.0.0-20240424004736-7ee5b469a6a9 h1:1WzTMHK3XWzzXu9y7NzvuwNClO3n0qN15Aoje5LRcF4=
|
||||
github.com/letsencrypt/boulder v0.0.0-20240424004736-7ee5b469a6a9/go.mod h1:CtAtcgvLkR5K75e/MrIvIlMnCiC4/+Wu2U8ipjUDaSQ=
|
||||
github.com/letsencrypt/pkcs11key/v4 v4.0.0 h1:qLc/OznH7xMr5ARJgkZCCWk+EomQkiNTOoOF5LAgagc=
|
||||
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
|
||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/libdns/route53 v1.3.3 h1:16sTxbbRGm0zODz0p0aVHHIyTqtHzEn3j0s4dGzQvNI=
|
||||
github.com/libdns/route53 v1.3.3/go.mod h1:n1Xy55lpfdxMIx4CVWAM16GQac+/OZcnm1xBjMyhZAo=
|
||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/libdns/route53 v1.5.1 h1:dkdcc2CKY/EHBBzAKqE0Cko7MKR8uVJ3GvpzwKu/UKM=
|
||||
github.com/libdns/route53 v1.5.1/go.mod h1:joT4hKmaTNKHEwb7GmZ65eoDz1whTu7KKYPS8ZqIh6Q=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
|
||||
|
@ -139,9 +127,8 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
|
|||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
|
@ -150,19 +137,17 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY=
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230620154423-38c92ad2d5c6 h1:kNn7cjQYeNjKUflvFFCxFeyS7ENcDdfPmkhFpgd0G/A=
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230620154423-38c92ad2d5c6/go.mod h1:wdMq89hDN07Zqr0yqYAXIBTJXl4MEELx+HYHOZdf5gM=
|
||||
github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE=
|
||||
github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222/go.mod h1:s41lQh6dIsDWIC1OWh7ChWJXLH0zkJ9KHZVqA7vHyuQ=
|
||||
github.com/weppos/publicsuffix-go v0.30.3-0.20240411085455-21202160c2ed h1:2SVbw+/Q/si5J66tuM12841RSkH/3Q4TQpiUkUctBgY=
|
||||
github.com/weppos/publicsuffix-go v0.30.3-0.20240411085455-21202160c2ed/go.mod h1:L9gKhYxnlc2z0fQFyL/6Y9YLnObLkmErfCYMuwgXIX8=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
|
@ -171,17 +156,19 @@ github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54t
|
|||
github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk=
|
||||
github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
|
||||
github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
|
||||
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300 h1:DZH5n7L3L8RxKdSyJHZt7WePgwdhHnPhQFdQSJaHF+o=
|
||||
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2fe2nV9KXsa9AyQBFZGzygVPovsZR+Rl5w=
|
||||
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c h1:U1b4THKcgOpJ+kILupuznNwPiURtwVW3e9alJvji9+s=
|
||||
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c/go.mod h1:GSDpFDD4TASObxvfZfvpZZ3OWHIUHMlhVWlkOe4ewVk=
|
||||
github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8=
|
||||
github.com/zmap/zlint/v3 v3.5.0 h1:Eh2B5t6VKgVH0DFmTwOqE50POvyDhUaU9T2mJOe1vfQ=
|
||||
github.com/zmap/zlint/v3 v3.5.0/go.mod h1:JkNSrsDJ8F4VRtBZcYUQSvnWFL7utcjDIn+FE64mlBI=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
github.com/zmap/zlint/v3 v3.6.0 h1:vTEaDRtYN0d/1Ax60T+ypvbLQUHwHxbvYRnUMVr35ug=
|
||||
github.com/zmap/zlint/v3 v3.6.0/go.mod h1:NVgiIWssgzp0bNl8P4Gz94NHV2ep/4Jyj9V69uTmZyg=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -189,34 +176,37 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP
|
|||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -232,16 +222,22 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -250,15 +246,16 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
|
||||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
|
@ -266,18 +263,15 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.1 h1:qEzJlIDmG9q5VO0M/o8tGS65QMHMS1w01TQJB1VPJ4U=
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.1/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -2,11 +2,11 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-lambda-go/events"
|
||||
"github.com/aws/aws-lambda-go/lambda"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
"github.com/letsencrypt/crl-monitor/checker"
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ func HandleRequest(c *checker.Checker) func(ctx context.Context, event events.S3
|
|||
var err error
|
||||
for _, record := range event.Records {
|
||||
record := record
|
||||
err = multierr.Append(err, c.Check(ctx, record.S3.Bucket.Name, record.S3.Object.Key, &record.S3.Object.VersionID))
|
||||
err = errors.Join(err, c.Check(ctx, record.S3.Bucket.Name, record.S3.Object.Key, &record.S3.Object.VersionID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package retryhttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getBody(ctx context.Context, url string) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "CRL-Monitor/0.1")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("http status %d (%s)", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// Get is a simple wrapper around http.Client.Do that will retry on a fixed backoff schedule
|
||||
func Get(ctx context.Context, url string) ([]byte, error) {
|
||||
// A fixed exponential backoff schedule. The final value is zero so that we don't sleep before
|
||||
// returning the final error.
|
||||
var err error
|
||||
for _, backoff := range []int{1000, 1250, 1562, 1953, 2441, 3051, 3814, 4768, 5960, 7450, 9313, 11641, 0} {
|
||||
var body []byte
|
||||
body, err = getBody(ctx, url)
|
||||
if err == nil {
|
||||
return body, nil
|
||||
}
|
||||
time.Sleep(time.Duration(backoff) * time.Millisecond)
|
||||
}
|
||||
return nil, err
|
||||
}
|
|
@ -4,8 +4,9 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
)
|
||||
|
||||
|
@ -19,8 +20,19 @@ type Storage struct {
|
|||
S3Client s3client
|
||||
}
|
||||
|
||||
func New(awsConfig aws.Config) *Storage {
|
||||
s3Client := s3.NewFromConfig(awsConfig)
|
||||
// The parameters used to fetch a unique item from storage.
|
||||
type Key struct {
|
||||
Bucket, Object string
|
||||
Version *string
|
||||
}
|
||||
|
||||
func New(ctx context.Context) *Storage {
|
||||
cfg, err := config.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating AWS config: %v", err)
|
||||
}
|
||||
|
||||
s3Client := s3.NewFromConfig(cfg)
|
||||
return &Storage{S3Client: s3Client}
|
||||
}
|
||||
|
||||
|
@ -28,29 +40,32 @@ func New(awsConfig aws.Config) *Storage {
|
|||
// The bucket and object names are required.
|
||||
// If version is nil, the current version is returned.
|
||||
// Returns the retrieved DER CRL bytes and what VersionID it was.
|
||||
func (s *Storage) Fetch(ctx context.Context, bucket, object string, version *string) ([]byte, string, error) {
|
||||
func (s *Storage) Fetch(ctx context.Context, key Key) ([]byte, string, error) {
|
||||
resp, err := s.S3Client.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &object,
|
||||
VersionId: version,
|
||||
Bucket: &key.Bucket,
|
||||
Key: &key.Object,
|
||||
VersionId: key.Version,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error retrieving CRL %s %s version %v: %w", bucket, object, version, err)
|
||||
return nil, "", fmt.Errorf("retrieving CRL %s %s version %v: %w", key.Bucket, key.Object, key.Version, err)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error reading CRL %s %s version %v: %w", bucket, object, version, err)
|
||||
return nil, "", fmt.Errorf("reading CRL %s %s version %v: %w", key.Bucket, key.Object, key.Version, err)
|
||||
}
|
||||
|
||||
return body, *resp.VersionId, err
|
||||
}
|
||||
|
||||
// Previous returns the previous version of a CRL shard, which can then be fetched.
|
||||
func (s *Storage) Previous(ctx context.Context, bucket, object, version string) (string, error) {
|
||||
func (s *Storage) Previous(ctx context.Context, key Key) (string, error) {
|
||||
if key.Version == nil {
|
||||
return "", fmt.Errorf("Previous called with no Version")
|
||||
}
|
||||
resp, err := s.S3Client.ListObjectVersions(ctx, &s3.ListObjectVersionsInput{
|
||||
Bucket: &bucket,
|
||||
Prefix: &object,
|
||||
Bucket: &key.Bucket,
|
||||
Prefix: &key.Object,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -64,14 +79,14 @@ func (s *Storage) Previous(ctx context.Context, bucket, object, version string)
|
|||
break
|
||||
}
|
||||
|
||||
if v.VersionId != nil && *v.VersionId == version {
|
||||
if v.VersionId != nil && *v.VersionId == *key.Version {
|
||||
// This is the version of interest; select the next one
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!found || prevVersion == nil) && resp.IsTruncated != nil && *resp.IsTruncated {
|
||||
return "", fmt.Errorf("too many versions and pagination not implemented! %s %s %s", bucket, object, version)
|
||||
return "", fmt.Errorf("too many versions and pagination not implemented! %+v", key)
|
||||
}
|
||||
|
||||
if !found {
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/letsencrypt/crl-monitor/storage"
|
||||
"github.com/letsencrypt/crl-monitor/storage/mock"
|
||||
)
|
||||
|
||||
func TestStorage(t *testing.T) {
|
||||
storage := mock.New(t, "somebucket", map[string][]mock.MockObject{
|
||||
mockStorage := mock.New(t, "somebucket", map[string][]mock.MockObject{
|
||||
"123/0.crl": {
|
||||
{VersionID: "111", Data: []byte{0xaa, 0xbb}},
|
||||
{VersionID: "222", Data: []byte{0xcc, 0xdd}},
|
||||
|
@ -56,7 +57,11 @@ func TestStorage(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
crl, version, err := storage.Fetch(context.Background(), "somebucket", tt.object, tt.version)
|
||||
crl, version, err := mockStorage.Fetch(context.Background(), storage.Key{
|
||||
Bucket: "somebucket",
|
||||
Object: tt.object,
|
||||
Version: tt.version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.expectedVer, version)
|
||||
require.Equal(t, tt.expectedCRL, crl)
|
||||
|
@ -87,7 +92,11 @@ func TestStorage(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
version, err := storage.Previous(context.Background(), "somebucket", tt.object, tt.version)
|
||||
version, err := mockStorage.Previous(context.Background(), storage.Key{
|
||||
Bucket: "somebucket",
|
||||
Object: tt.object,
|
||||
Version: &tt.version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.expectedVer, version)
|
||||
})
|
||||
|
@ -113,7 +122,11 @@ func TestStorage(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
version, err := storage.Previous(context.Background(), "somebucket", tt.object, tt.version)
|
||||
version, err := mockStorage.Previous(context.Background(), storage.Key{
|
||||
Bucket: "somebucket",
|
||||
Object: tt.object,
|
||||
Version: &tt.version,
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "", version)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue