...

Source file src/github.com/letsencrypt/boulder/test/integration/crl_test.go

Documentation: github.com/letsencrypt/boulder/test/integration

     1  //go:build integration
     2  
     3  package integration
     4  
     5  import (
     6  	"database/sql"
     7  	"io"
     8  	"net/http"
     9  	"os"
    10  	"os/exec"
    11  	"path"
    12  	"path/filepath"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/jmhodges/clock"
    18  	"github.com/letsencrypt/boulder/core"
    19  	"github.com/letsencrypt/boulder/test"
    20  	"github.com/letsencrypt/boulder/test/vars"
    21  )
    22  
    23  // runUpdater executes the crl-updater binary with the -runOnce flag, and
    24  // returns when it completes.
    25  func runUpdater(t *testing.T, configFile string) {
    26  	t.Helper()
    27  
    28  	binPath, err := filepath.Abs("bin/boulder")
    29  	test.AssertNotError(t, err, "computing boulder binary path")
    30  
    31  	c := exec.Command(binPath, "crl-updater", "-config", configFile, "-debug-addr", ":8022", "-runOnce")
    32  	out, err := c.CombinedOutput()
    33  	for _, line := range strings.Split(string(out), "\n") {
    34  		// Print the updater's stdout for debugging, but only if the test fails.
    35  		t.Log(line)
    36  	}
    37  	test.AssertNotError(t, err, "crl-updater failed")
    38  }
    39  
    40  // TestCRLPipeline runs an end-to-end test of the crl issuance process, ensuring
    41  // that the correct number of properly-formed and validly-signed CRLs are sent
    42  // to our fake S3 service.
    43  func TestCRLPipeline(t *testing.T) {
    44  	// Basic setup.
    45  	fc := clock.NewFake()
    46  	configDir, ok := os.LookupEnv("BOULDER_CONFIG_DIR")
    47  	test.Assert(t, ok, "failed to look up test config directory")
    48  	configFile := path.Join(configDir, "crl-updater.json")
    49  
    50  	// Reset the "leasedUntil" column so that this test isn't dependent on state
    51  	// like priors runs of this test.
    52  	db, err := sql.Open("mysql", vars.DBConnSAIntegrationFullPerms)
    53  	test.AssertNotError(t, err, "opening database connection")
    54  	_, err = db.Exec(`UPDATE crlShards SET leasedUntil = ?`, fc.Now().Add(-time.Minute))
    55  	test.AssertNotError(t, err, "resetting leasedUntil column")
    56  
    57  	// Issue a test certificate and save its serial number.
    58  	client, err := makeClient()
    59  	test.AssertNotError(t, err, "creating acme client")
    60  	res, err := authAndIssue(client, nil, []string{random_domain()}, true)
    61  	test.AssertNotError(t, err, "failed to create test certificate")
    62  	cert := res.certs[0]
    63  	serial := core.SerialToString(cert.SerialNumber)
    64  
    65  	// Confirm that the cert does not yet show up as revoked in the CRLs.
    66  	runUpdater(t, configFile)
    67  	resp, err := http.Get("http://localhost:7890/query?serial=" + serial)
    68  	test.AssertNotError(t, err, "s3-test-srv GET /query failed")
    69  	test.AssertEquals(t, resp.StatusCode, 404)
    70  	resp.Body.Close()
    71  
    72  	// Revoke the certificate.
    73  	err = client.RevokeCertificate(client.Account, cert, client.PrivateKey, 5)
    74  	test.AssertNotError(t, err, "failed to revoke test certificate")
    75  
    76  	// Reset the "leasedUntil" column to prepare for another round of CRLs.
    77  	_, err = db.Exec(`UPDATE crlShards SET leasedUntil = ?`, fc.Now().Add(-time.Minute))
    78  	test.AssertNotError(t, err, "resetting leasedUntil column")
    79  
    80  	// Confirm that the cert now *does* show up in the CRLs.
    81  	runUpdater(t, configFile)
    82  	resp, err = http.Get("http://localhost:7890/query?serial=" + serial)
    83  	test.AssertNotError(t, err, "s3-test-srv GET /query failed")
    84  	test.AssertEquals(t, resp.StatusCode, 200)
    85  
    86  	// Confirm that the revoked certificate entry has the correct reason.
    87  	reason, err := io.ReadAll(resp.Body)
    88  	test.AssertNotError(t, err, "reading revocation reason")
    89  	test.AssertEquals(t, string(reason), "5")
    90  	resp.Body.Close()
    91  }
    92  

View as plain text