github.com/letsencrypt/boulder@v0.20251208.0/ra/ra_test.go (about)

     1  package ra
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/ecdsa"
     7  	"crypto/elliptic"
     8  	"crypto/rand"
     9  	"crypto/rsa"
    10  	"crypto/x509"
    11  	"crypto/x509/pkix"
    12  	"encoding/asn1"
    13  	"encoding/hex"
    14  	"encoding/json"
    15  	"encoding/pem"
    16  	"errors"
    17  	"fmt"
    18  	"math"
    19  	"math/big"
    20  	mrand "math/rand/v2"
    21  	"net/netip"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/go-jose/go-jose/v4"
    30  	"github.com/jmhodges/clock"
    31  	"github.com/prometheus/client_golang/prometheus"
    32  	"google.golang.org/grpc"
    33  	"google.golang.org/grpc/codes"
    34  	"google.golang.org/grpc/status"
    35  	"google.golang.org/protobuf/types/known/durationpb"
    36  	"google.golang.org/protobuf/types/known/emptypb"
    37  	"google.golang.org/protobuf/types/known/timestamppb"
    38  
    39  	"github.com/letsencrypt/boulder/allowlist"
    40  	capb "github.com/letsencrypt/boulder/ca/proto"
    41  	"github.com/letsencrypt/boulder/config"
    42  	"github.com/letsencrypt/boulder/core"
    43  	corepb "github.com/letsencrypt/boulder/core/proto"
    44  	"github.com/letsencrypt/boulder/ctpolicy"
    45  	"github.com/letsencrypt/boulder/ctpolicy/loglist"
    46  	berrors "github.com/letsencrypt/boulder/errors"
    47  	"github.com/letsencrypt/boulder/features"
    48  	"github.com/letsencrypt/boulder/goodkey"
    49  	bgrpc "github.com/letsencrypt/boulder/grpc"
    50  	"github.com/letsencrypt/boulder/identifier"
    51  	"github.com/letsencrypt/boulder/issuance"
    52  	blog "github.com/letsencrypt/boulder/log"
    53  	"github.com/letsencrypt/boulder/metrics"
    54  	"github.com/letsencrypt/boulder/mocks"
    55  	"github.com/letsencrypt/boulder/policy"
    56  	pubpb "github.com/letsencrypt/boulder/publisher/proto"
    57  	rapb "github.com/letsencrypt/boulder/ra/proto"
    58  	"github.com/letsencrypt/boulder/ratelimits"
    59  	"github.com/letsencrypt/boulder/revocation"
    60  	"github.com/letsencrypt/boulder/sa"
    61  	sapb "github.com/letsencrypt/boulder/sa/proto"
    62  	"github.com/letsencrypt/boulder/test"
    63  	isa "github.com/letsencrypt/boulder/test/inmem/sa"
    64  	"github.com/letsencrypt/boulder/test/vars"
    65  	"github.com/letsencrypt/boulder/va"
    66  	vapb "github.com/letsencrypt/boulder/va/proto"
    67  )
    68  
    69  // randomDomain creates a random domain name for testing.
    70  //
    71  // panics if crypto/rand.Rand.Read fails.
    72  func randomDomain() string {
    73  	var bytes [4]byte
    74  	_, err := rand.Read(bytes[:])
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	return fmt.Sprintf("%x.example.com", bytes[:])
    79  }
    80  
    81  // randomIPv6 creates a random IPv6 netip.Addr for testing. It uses a real IPv6
    82  // address range, not a test/documentation range.
    83  //
    84  // panics if crypto/rand.Rand.Read or netip.AddrFromSlice fails.
    85  func randomIPv6() netip.Addr {
    86  	var ipBytes [10]byte
    87  	_, err := rand.Read(ipBytes[:])
    88  	if err != nil {
    89  		panic(err)
    90  	}
    91  	ipPrefix, err := hex.DecodeString("2602080a600f")
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  	ip, ok := netip.AddrFromSlice(bytes.Join([][]byte{ipPrefix, ipBytes[:]}, nil))
    96  	if !ok {
    97  		panic("Couldn't parse random IP to netip.Addr")
    98  	}
    99  	return ip
   100  }
   101  
   102  func createPendingAuthorization(t *testing.T, sa sapb.StorageAuthorityClient, regID int64, ident identifier.ACMEIdentifier, exp time.Time) *corepb.Authorization {
   103  	t.Helper()
   104  
   105  	res, err := sa.NewOrderAndAuthzs(
   106  		context.Background(),
   107  		&sapb.NewOrderAndAuthzsRequest{
   108  			NewOrder: &sapb.NewOrderRequest{
   109  				RegistrationID: regID,
   110  				Expires:        timestamppb.New(exp),
   111  				Identifiers:    []*corepb.Identifier{ident.ToProto()},
   112  			},
   113  			NewAuthzs: []*sapb.NewAuthzRequest{
   114  				{
   115  					Identifier:     ident.ToProto(),
   116  					RegistrationID: regID,
   117  					Expires:        timestamppb.New(exp),
   118  					ChallengeTypes: []string{
   119  						string(core.ChallengeTypeHTTP01),
   120  						string(core.ChallengeTypeDNS01),
   121  						string(core.ChallengeTypeTLSALPN01)},
   122  					Token: core.NewToken(),
   123  				},
   124  			},
   125  		},
   126  	)
   127  	test.AssertNotError(t, err, "sa.NewOrderAndAuthzs failed")
   128  
   129  	return getAuthorization(t, fmt.Sprint(res.V2Authorizations[0]), sa)
   130  }
   131  
   132  func createFinalizedAuthorization(t *testing.T, saClient sapb.StorageAuthorityClient, regID int64, ident identifier.ACMEIdentifier, exp time.Time, chall core.AcmeChallenge, attemptedAt time.Time) int64 {
   133  	t.Helper()
   134  	pending := createPendingAuthorization(t, saClient, regID, ident, exp)
   135  	pendingID, err := strconv.ParseInt(pending.Id, 10, 64)
   136  	test.AssertNotError(t, err, "strconv.ParseInt failed")
   137  	_, err = saClient.FinalizeAuthorization2(context.Background(), &sapb.FinalizeAuthorizationRequest{
   138  		Id:          pendingID,
   139  		Status:      "valid",
   140  		Expires:     timestamppb.New(exp),
   141  		Attempted:   string(chall),
   142  		AttemptedAt: timestamppb.New(attemptedAt),
   143  	})
   144  	test.AssertNotError(t, err, "sa.FinalizeAuthorizations2 failed")
   145  	return pendingID
   146  }
   147  
   148  func getAuthorization(t *testing.T, id string, sa sapb.StorageAuthorityClient) *corepb.Authorization {
   149  	t.Helper()
   150  	idInt, err := strconv.ParseInt(id, 10, 64)
   151  	test.AssertNotError(t, err, "strconv.ParseInt failed")
   152  	dbAuthz, err := sa.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: idInt})
   153  	test.AssertNotError(t, err, "Could not fetch authorization from database")
   154  	return dbAuthz
   155  }
   156  
   157  func dnsChallIdx(t *testing.T, challenges []*corepb.Challenge) int64 {
   158  	t.Helper()
   159  	var challIdx int64
   160  	var set bool
   161  	for i, ch := range challenges {
   162  		if core.AcmeChallenge(ch.Type) == core.ChallengeTypeDNS01 {
   163  			challIdx = int64(i)
   164  			set = true
   165  			break
   166  		}
   167  	}
   168  	if !set {
   169  		t.Errorf("dnsChallIdx didn't find challenge of type DNS-01")
   170  	}
   171  	return challIdx
   172  }
   173  
   174  func numAuthorizations(o *corepb.Order) int {
   175  	return len(o.V2Authorizations)
   176  }
   177  
   178  // def is a test-only helper that returns the default validation profile
   179  // and is guaranteed to succeed because the validationProfile constructor
   180  // ensures that the default name has a corresponding profile.
   181  func (vp *validationProfiles) def() *validationProfile {
   182  	return vp.byName[vp.defaultName]
   183  }
   184  
   185  type DummyValidationAuthority struct {
   186  	doDCVRequest chan *vapb.PerformValidationRequest
   187  	doDCVError   error
   188  	doDCVResult  *vapb.ValidationResult
   189  
   190  	doCAARequest  chan *vapb.IsCAAValidRequest
   191  	doCAAError    error
   192  	doCAAResponse *vapb.IsCAAValidResponse
   193  }
   194  
   195  func (dva *DummyValidationAuthority) PerformValidation(ctx context.Context, req *vapb.PerformValidationRequest, _ ...grpc.CallOption) (*vapb.ValidationResult, error) {
   196  	dcvRes, err := dva.DoDCV(ctx, req)
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  	if dcvRes.Problem != nil {
   201  		return dcvRes, nil
   202  	}
   203  	caaResp, err := dva.DoCAA(ctx, &vapb.IsCAAValidRequest{
   204  		Identifier:       req.Identifier,
   205  		ValidationMethod: req.Challenge.Type,
   206  		AccountURIID:     req.Authz.RegID,
   207  		AuthzID:          req.Authz.Id,
   208  	})
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	return &vapb.ValidationResult{
   213  		Records: dcvRes.Records,
   214  		Problem: caaResp.Problem,
   215  	}, nil
   216  }
   217  
   218  func (dva *DummyValidationAuthority) IsCAAValid(ctx context.Context, req *vapb.IsCAAValidRequest, _ ...grpc.CallOption) (*vapb.IsCAAValidResponse, error) {
   219  	return nil, status.Error(codes.Unimplemented, "IsCAAValid not implemented")
   220  }
   221  
   222  func (dva *DummyValidationAuthority) DoDCV(ctx context.Context, req *vapb.PerformValidationRequest, _ ...grpc.CallOption) (*vapb.ValidationResult, error) {
   223  	dva.doDCVRequest <- req
   224  	return dva.doDCVResult, dva.doDCVError
   225  }
   226  
   227  func (dva *DummyValidationAuthority) DoCAA(ctx context.Context, req *vapb.IsCAAValidRequest, _ ...grpc.CallOption) (*vapb.IsCAAValidResponse, error) {
   228  	dva.doCAARequest <- req
   229  	return dva.doCAAResponse, dva.doCAAError
   230  }
   231  
   232  var (
   233  	// These values we simulate from the client
   234  	AccountKeyJSONA = []byte(`{
   235  		"kty":"RSA",
   236  		"n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
   237  		"e":"AQAB"
   238  	}`)
   239  	AccountKeyA = jose.JSONWebKey{}
   240  
   241  	AccountKeyJSONB = []byte(`{
   242  		"kty":"RSA",
   243  		"n":"z8bp-jPtHt4lKBqepeKF28g_QAEOuEsCIou6sZ9ndsQsEjxEOQxQ0xNOQezsKa63eogw8YS3vzjUcPP5BJuVzfPfGd5NVUdT-vSSwxk3wvk_jtNqhrpcoG0elRPQfMVsQWmxCAXCVRz3xbcFI8GTe-syynG3l-g1IzYIIZVNI6jdljCZML1HOMTTW4f7uJJ8mM-08oQCeHbr5ejK7O2yMSSYxW03zY-Tj1iVEebROeMv6IEEJNFSS4yM-hLpNAqVuQxFGetwtwjDMC1Drs1dTWrPuUAAjKGrP151z1_dE74M5evpAhZUmpKv1hY-x85DC6N0hFPgowsanmTNNiV75w",
   244  		"e":"AQAB"
   245  	}`)
   246  	AccountKeyB = jose.JSONWebKey{}
   247  
   248  	AccountKeyJSONC = []byte(`{
   249  		"kty":"RSA",
   250  		"n":"rFH5kUBZrlPj73epjJjyCxzVzZuV--JjKgapoqm9pOuOt20BUTdHqVfC2oDclqM7HFhkkX9OSJMTHgZ7WaVqZv9u1X2yjdx9oVmMLuspX7EytW_ZKDZSzL-sCOFCuQAuYKkLbsdcA3eHBK_lwc4zwdeHFMKIulNvLqckkqYB9s8GpgNXBDIQ8GjR5HuJke_WUNjYHSd8jY1LU9swKWsLQe2YoQUz_ekQvBvBCoaFEtrtRaSJKNLIVDObXFr2TLIiFiM0Em90kK01-eQ7ZiruZTKomll64bRFPoNo4_uwubddg3xTqur2vdF3NyhTrYdvAgTem4uC0PFjEQ1bK_djBQ",
   251  		"e":"AQAB"
   252  	}`)
   253  	AccountKeyC = jose.JSONWebKey{}
   254  
   255  	// These values we simulate from the client
   256  	AccountPrivateKeyJSON = []byte(`{
   257  		"kty":"RSA",
   258  		"n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
   259  		"e":"AQAB",
   260  		"d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
   261  		"p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
   262  		"q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
   263  		"dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
   264  		"dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
   265  		"qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU"
   266  	}`)
   267  	AccountPrivateKey = jose.JSONWebKey{}
   268  
   269  	ShortKeyJSON = []byte(`{
   270  		"e": "AQAB",
   271  		"kty": "RSA",
   272  		"n": "tSwgy3ORGvc7YJI9B2qqkelZRUC6F1S5NwXFvM4w5-M0TsxbFsH5UH6adigV0jzsDJ5imAechcSoOhAh9POceCbPN1sTNwLpNbOLiQQ7RD5mY_"
   273  		}`)
   274  
   275  	ShortKey = jose.JSONWebKey{}
   276  
   277  	ResponseIndex = 0
   278  
   279  	ExampleCSR = &x509.CertificateRequest{}
   280  
   281  	Identifier = "not-example.com"
   282  
   283  	log = blog.UseMock()
   284  )
   285  
   286  var ctx = context.Background()
   287  
   288  func initAuthorities(t *testing.T) (*DummyValidationAuthority, sapb.StorageAuthorityClient, *RegistrationAuthorityImpl, ratelimits.Source, clock.FakeClock, *corepb.Registration, func()) {
   289  	err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA)
   290  	test.AssertNotError(t, err, "Failed to unmarshal public JWK")
   291  	err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB)
   292  	test.AssertNotError(t, err, "Failed to unmarshal public JWK")
   293  	err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC)
   294  	test.AssertNotError(t, err, "Failed to unmarshal public JWK")
   295  
   296  	err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey)
   297  	test.AssertNotError(t, err, "Failed to unmarshal private JWK")
   298  
   299  	err = json.Unmarshal(ShortKeyJSON, &ShortKey)
   300  	test.AssertNotError(t, err, "Failed to unmarshal JWK")
   301  
   302  	fc := clock.NewFake()
   303  	// Set to some non-zero time.
   304  	fc.Set(time.Date(2020, 3, 4, 5, 0, 0, 0, time.UTC))
   305  
   306  	dbMap, err := sa.DBMapForTest(vars.DBConnSA)
   307  	if err != nil {
   308  		t.Fatalf("Failed to create dbMap: %s", err)
   309  	}
   310  	ssa, err := sa.NewSQLStorageAuthority(dbMap, dbMap, nil, 1, 0, fc, log, metrics.NoopRegisterer)
   311  	if err != nil {
   312  		t.Fatalf("Failed to create SA: %s", err)
   313  	}
   314  	sa := &isa.SA{Impl: ssa}
   315  
   316  	saDBCleanUp := test.ResetBoulderTestDatabase(t)
   317  
   318  	dummyVA := &DummyValidationAuthority{
   319  		doDCVRequest: make(chan *vapb.PerformValidationRequest, 1),
   320  		doCAARequest: make(chan *vapb.IsCAAValidRequest, 1),
   321  	}
   322  	va := va.RemoteClients{VAClient: dummyVA, CAAClient: dummyVA}
   323  
   324  	pa, err := policy.New(
   325  		map[identifier.IdentifierType]bool{
   326  			identifier.TypeDNS: true,
   327  			identifier.TypeIP:  true,
   328  		},
   329  		map[core.AcmeChallenge]bool{
   330  			core.ChallengeTypeHTTP01: true,
   331  			core.ChallengeTypeDNS01:  true,
   332  		},
   333  		blog.NewMock())
   334  	test.AssertNotError(t, err, "Couldn't create PA")
   335  	err = pa.LoadIdentPolicyFile("../test/ident-policy.yaml")
   336  	test.AssertNotError(t, err, "Couldn't set identifier policy")
   337  
   338  	stats := metrics.NoopRegisterer
   339  
   340  	ca := &mocks.MockCA{
   341  		PEM: eeCertPEM,
   342  	}
   343  	cleanUp := func() {
   344  		saDBCleanUp()
   345  	}
   346  
   347  	block, _ := pem.Decode(CSRPEM)
   348  	ExampleCSR, _ = x509.ParseCertificateRequest(block.Bytes)
   349  
   350  	test.AssertNotError(t, err, "Couldn't create initial IP")
   351  	registration, err := sa.NewRegistration(ctx, &corepb.Registration{
   352  		Key:    AccountKeyJSONA,
   353  		Status: string(core.StatusValid),
   354  	})
   355  	test.AssertNotError(t, err, "Failed to create initial registration")
   356  
   357  	ctp := ctpolicy.New(&mocks.PublisherClient{}, loglist.List{
   358  		{Name: "LogA1", Operator: "OperA", Url: "UrlA1", Key: []byte("KeyA1")},
   359  		{Name: "LogB1", Operator: "OperB", Url: "UrlB1", Key: []byte("KeyB1")},
   360  	}, nil, nil, 0, log, metrics.NoopRegisterer)
   361  
   362  	rlSource := ratelimits.NewInmemSource()
   363  	limiter, err := ratelimits.NewLimiter(fc, rlSource, stats)
   364  	test.AssertNotError(t, err, "making limiter")
   365  	txnBuilder, err := ratelimits.NewTransactionBuilderFromFiles("../test/config-next/ratelimit-defaults.yml", "", metrics.NoopRegisterer, log)
   366  	test.AssertNotError(t, err, "making transaction composer")
   367  
   368  	testKeyPolicy, err := goodkey.NewPolicy(nil, nil)
   369  	test.AssertNotError(t, err, "making keypolicy")
   370  
   371  	profiles := &validationProfiles{
   372  		defaultName: "test",
   373  		byName: map[string]*validationProfile{"test": {
   374  			pendingAuthzLifetime: 7 * 24 * time.Hour,
   375  			validAuthzLifetime:   300 * 24 * time.Hour,
   376  			orderLifetime:        7 * 24 * time.Hour,
   377  			maxNames:             100,
   378  			identifierTypes:      []identifier.IdentifierType{identifier.TypeDNS},
   379  		}},
   380  	}
   381  
   382  	ra := NewRegistrationAuthorityImpl(
   383  		fc, log, stats,
   384  		1, testKeyPolicy, limiter, txnBuilder, 100,
   385  		profiles, nil, 5*time.Minute, ctp, nil)
   386  	ra.SA = sa
   387  	ra.VA = va
   388  	ra.CA = ca
   389  	ra.PA = pa
   390  	return dummyVA, sa, ra, rlSource, fc, registration, cleanUp
   391  }
   392  
   393  func TestValidateContacts(t *testing.T) {
   394  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
   395  	defer cleanUp()
   396  
   397  	ansible := "ansible:earth.sol.milkyway.laniakea/letsencrypt"
   398  	validEmail := "mailto:admin@email.com"
   399  	otherValidEmail := "mailto:other-admin@email.com"
   400  	malformedEmail := "mailto:admin.com"
   401  	nonASCII := "mailto:seƱor@email.com"
   402  	unparsable := "mailto:a@email.com, b@email.com"
   403  	forbidden := "mailto:a@example.org"
   404  
   405  	err := ra.validateContacts([]string{})
   406  	test.AssertNotError(t, err, "No Contacts")
   407  
   408  	err = ra.validateContacts([]string{validEmail, otherValidEmail})
   409  	test.AssertError(t, err, "Too Many Contacts")
   410  
   411  	err = ra.validateContacts([]string{validEmail})
   412  	test.AssertNotError(t, err, "Valid Email")
   413  
   414  	err = ra.validateContacts([]string{malformedEmail})
   415  	test.AssertError(t, err, "Malformed Email")
   416  
   417  	err = ra.validateContacts([]string{ansible})
   418  	test.AssertError(t, err, "Unknown scheme")
   419  
   420  	err = ra.validateContacts([]string{""})
   421  	test.AssertError(t, err, "Empty URL")
   422  
   423  	err = ra.validateContacts([]string{nonASCII})
   424  	test.AssertError(t, err, "Non ASCII email")
   425  
   426  	err = ra.validateContacts([]string{unparsable})
   427  	test.AssertError(t, err, "Unparsable email")
   428  
   429  	err = ra.validateContacts([]string{forbidden})
   430  	test.AssertError(t, err, "Forbidden email")
   431  
   432  	err = ra.validateContacts([]string{"mailto:admin@localhost"})
   433  	test.AssertError(t, err, "Forbidden email")
   434  
   435  	err = ra.validateContacts([]string{"mailto:admin@example.not.a.iana.suffix"})
   436  	test.AssertError(t, err, "Forbidden email")
   437  
   438  	err = ra.validateContacts([]string{"mailto:admin@1.2.3.4"})
   439  	test.AssertError(t, err, "Forbidden email")
   440  
   441  	err = ra.validateContacts([]string{"mailto:admin@[1.2.3.4]"})
   442  	test.AssertError(t, err, "Forbidden email")
   443  
   444  	err = ra.validateContacts([]string{"mailto:admin@a.com?no-reminder-emails"})
   445  	test.AssertError(t, err, "No hfields in email")
   446  
   447  	err = ra.validateContacts([]string{"mailto:example@a.com?"})
   448  	test.AssertError(t, err, "No hfields in email")
   449  
   450  	err = ra.validateContacts([]string{"mailto:example@a.com#"})
   451  	test.AssertError(t, err, "No fragment")
   452  
   453  	err = ra.validateContacts([]string{"mailto:example@a.com#optional"})
   454  	test.AssertError(t, err, "No fragment")
   455  
   456  	// The registrations.contact field is VARCHAR(191). 175 'a' characters plus
   457  	// the prefix "mailto:" and the suffix "@a.com" makes exactly 191 bytes of
   458  	// encoded JSON. The correct size to hit our maximum DB field length.
   459  	var longStringBuf strings.Builder
   460  	longStringBuf.WriteString("mailto:")
   461  	for range 175 {
   462  		longStringBuf.WriteRune('a')
   463  	}
   464  	longStringBuf.WriteString("@a.com")
   465  
   466  	err = ra.validateContacts([]string{longStringBuf.String()})
   467  	test.AssertError(t, err, "Too long contacts")
   468  }
   469  
   470  func TestNewRegistration(t *testing.T) {
   471  	_, sa, ra, _, _, _, cleanUp := initAuthorities(t)
   472  	defer cleanUp()
   473  	acctKeyB, err := AccountKeyB.MarshalJSON()
   474  	test.AssertNotError(t, err, "failed to marshal account key")
   475  	input := &corepb.Registration{
   476  		Key: acctKeyB,
   477  	}
   478  
   479  	result, err := ra.NewRegistration(ctx, input)
   480  	if err != nil {
   481  		t.Fatalf("could not create new registration: %s", err)
   482  	}
   483  	test.AssertByteEquals(t, result.Key, acctKeyB)
   484  	test.Assert(t, result.Agreement == "", "Agreement didn't default empty")
   485  
   486  	reg, err := sa.GetRegistration(ctx, &sapb.RegistrationID{Id: result.Id})
   487  	test.AssertNotError(t, err, "Failed to retrieve registration")
   488  	test.AssertByteEquals(t, reg.Key, acctKeyB)
   489  }
   490  
   491  type mockSAFailsNewRegistration struct {
   492  	sapb.StorageAuthorityClient
   493  }
   494  
   495  func (sa *mockSAFailsNewRegistration) NewRegistration(_ context.Context, _ *corepb.Registration, _ ...grpc.CallOption) (*corepb.Registration, error) {
   496  	return &corepb.Registration{}, fmt.Errorf("too bad")
   497  }
   498  
   499  func TestNewRegistrationSAFailure(t *testing.T) {
   500  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
   501  	defer cleanUp()
   502  	ra.SA = &mockSAFailsNewRegistration{}
   503  	acctKeyB, err := AccountKeyB.MarshalJSON()
   504  	test.AssertNotError(t, err, "failed to marshal account key")
   505  	input := corepb.Registration{
   506  		Key: acctKeyB,
   507  	}
   508  	result, err := ra.NewRegistration(ctx, &input)
   509  	if err == nil {
   510  		t.Fatalf("NewRegistration should have failed when SA.NewRegistration failed %#v", result.Key)
   511  	}
   512  }
   513  
   514  func TestNewRegistrationNoFieldOverwrite(t *testing.T) {
   515  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
   516  	defer cleanUp()
   517  	acctKeyC, err := AccountKeyC.MarshalJSON()
   518  	test.AssertNotError(t, err, "failed to marshal account key")
   519  	input := &corepb.Registration{
   520  		Id:        23,
   521  		Key:       acctKeyC,
   522  		Agreement: "I agreed",
   523  	}
   524  
   525  	result, err := ra.NewRegistration(ctx, input)
   526  	test.AssertNotError(t, err, "Could not create new registration")
   527  	test.Assert(t, result.Id != 23, "ID shouldn't be set by user")
   528  	// TODO: Enable this test case once we validate terms agreement.
   529  	//test.Assert(t, result.Agreement != "I agreed", "Agreement shouldn't be set with invalid URL")
   530  }
   531  
   532  func TestNewRegistrationBadKey(t *testing.T) {
   533  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
   534  	defer cleanUp()
   535  	shortKey, err := ShortKey.MarshalJSON()
   536  	test.AssertNotError(t, err, "failed to marshal account key")
   537  	input := &corepb.Registration{
   538  		Key: shortKey,
   539  	}
   540  	_, err = ra.NewRegistration(ctx, input)
   541  	test.AssertError(t, err, "Should have rejected authorization with short key")
   542  }
   543  
   544  func TestPerformValidationExpired(t *testing.T) {
   545  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
   546  	defer cleanUp()
   547  
   548  	authz := createPendingAuthorization(t, sa, registration.Id, identifier.NewDNS("example.com"), fc.Now().Add(-2*time.Hour))
   549  
   550  	_, err := ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   551  		Authz:          authz,
   552  		ChallengeIndex: int64(ResponseIndex),
   553  	})
   554  	test.AssertError(t, err, "Updated expired authorization")
   555  }
   556  
   557  func TestPerformValidationAlreadyValid(t *testing.T) {
   558  	va, _, ra, _, _, registration, cleanUp := initAuthorities(t)
   559  	defer cleanUp()
   560  
   561  	// Create a finalized authorization
   562  	exp := ra.clk.Now().Add(365 * 24 * time.Hour)
   563  	authz := core.Authorization{
   564  		ID:             "1337",
   565  		Identifier:     identifier.NewDNS("not-example.com"),
   566  		RegistrationID: registration.Id,
   567  		Status:         "valid",
   568  		Expires:        &exp,
   569  		Challenges: []core.Challenge{
   570  			{
   571  				Token:  core.NewToken(),
   572  				Type:   core.ChallengeTypeHTTP01,
   573  				Status: core.StatusPending,
   574  			},
   575  		},
   576  	}
   577  	authzPB, err := bgrpc.AuthzToPB(authz)
   578  	test.AssertNotError(t, err, "bgrpc.AuthzToPB failed")
   579  
   580  	va.doDCVResult = &vapb.ValidationResult{
   581  		Records: []*corepb.ValidationRecord{
   582  			{
   583  				AddressUsed: []byte("192.168.0.1"),
   584  				Hostname:    "example.com",
   585  				Port:        "8080",
   586  				Url:         "http://example.com/",
   587  			},
   588  		},
   589  		Problem: nil,
   590  	}
   591  	va.doCAAResponse = &vapb.IsCAAValidResponse{Problem: nil}
   592  
   593  	// A subsequent call to perform validation should return nil due
   594  	// to being short-circuited because of valid authz reuse.
   595  	val, err := ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   596  		Authz:          authzPB,
   597  		ChallengeIndex: int64(ResponseIndex),
   598  	})
   599  	test.Assert(t, core.AcmeStatus(val.Status) == core.StatusValid, "Validation should have been valid")
   600  	test.AssertNotError(t, err, "Error was not nil, but should have been nil")
   601  }
   602  
   603  func TestPerformValidationSuccess(t *testing.T) {
   604  	va, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
   605  	defer cleanUp()
   606  
   607  	idents := identifier.ACMEIdentifiers{
   608  		identifier.NewDNS("example.com"),
   609  		identifier.NewIP(netip.MustParseAddr("192.168.0.1")),
   610  	}
   611  
   612  	for _, ident := range idents {
   613  		// We know this is OK because of TestNewAuthorization
   614  		authzPB := createPendingAuthorization(t, sa, registration.Id, ident, fc.Now().Add(12*time.Hour))
   615  
   616  		va.doDCVResult = &vapb.ValidationResult{
   617  			Records: []*corepb.ValidationRecord{
   618  				{
   619  					AddressUsed:   []byte("192.168.0.1"),
   620  					Hostname:      "example.com",
   621  					Port:          "8080",
   622  					Url:           "http://example.com/",
   623  					ResolverAddrs: []string{"rebound"},
   624  				},
   625  			},
   626  			Problem: nil,
   627  		}
   628  		va.doCAAResponse = &vapb.IsCAAValidResponse{Problem: nil}
   629  
   630  		now := fc.Now()
   631  		challIdx := dnsChallIdx(t, authzPB.Challenges)
   632  		authzPB, err := ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   633  			Authz:          authzPB,
   634  			ChallengeIndex: challIdx,
   635  		})
   636  		test.AssertNotError(t, err, "PerformValidation failed")
   637  
   638  		var vaRequest *vapb.PerformValidationRequest
   639  		select {
   640  		case r := <-va.doDCVRequest:
   641  			vaRequest = r
   642  		case <-time.After(time.Second):
   643  			t.Fatal("Timed out waiting for DummyValidationAuthority.PerformValidation to complete")
   644  		}
   645  
   646  		// Verify that the VA got the request, and it's the same as the others
   647  		test.AssertEquals(t, authzPB.Challenges[challIdx].Type, vaRequest.Challenge.Type)
   648  		test.AssertEquals(t, authzPB.Challenges[challIdx].Token, vaRequest.Challenge.Token)
   649  
   650  		// Sleep so the RA has a chance to write to the SA
   651  		time.Sleep(100 * time.Millisecond)
   652  
   653  		dbAuthzPB := getAuthorization(t, authzPB.Id, sa)
   654  		t.Log("dbAuthz:", dbAuthzPB)
   655  
   656  		// Verify that the responses are reflected
   657  		challIdx = dnsChallIdx(t, dbAuthzPB.Challenges)
   658  		challenge, err := bgrpc.PBToChallenge(dbAuthzPB.Challenges[challIdx])
   659  		test.AssertNotError(t, err, "Failed to marshall corepb.Challenge to core.Challenge.")
   660  
   661  		test.AssertNotNil(t, vaRequest.Challenge, "Request passed to VA has no challenge")
   662  		test.Assert(t, challenge.Status == core.StatusValid, "challenge was not marked as valid")
   663  
   664  		// The DB authz's expiry should be equal to the current time plus the
   665  		// configured authorization lifetime
   666  		test.AssertEquals(t, dbAuthzPB.Expires.AsTime(), now.Add(ra.profiles.def().validAuthzLifetime))
   667  
   668  		// Check that validated timestamp was recorded, stored, and retrieved
   669  		expectedValidated := fc.Now()
   670  		test.Assert(t, *challenge.Validated == expectedValidated, "Validated timestamp incorrect or missing")
   671  	}
   672  }
   673  
   674  // mockSAWithSyncPause is a mock sapb.StorageAuthorityClient that forwards all
   675  // method calls to an inner SA, but also performs a blocking write to a channel
   676  // when PauseIdentifiers is called to allow the tests to synchronize.
   677  type mockSAWithSyncPause struct {
   678  	sapb.StorageAuthorityClient
   679  	out chan<- *sapb.PauseRequest
   680  }
   681  
   682  func (msa mockSAWithSyncPause) PauseIdentifiers(ctx context.Context, req *sapb.PauseRequest, _ ...grpc.CallOption) (*sapb.PauseIdentifiersResponse, error) {
   683  	res, err := msa.StorageAuthorityClient.PauseIdentifiers(ctx, req)
   684  	msa.out <- req
   685  	return res, err
   686  }
   687  
   688  func TestPerformValidation_FailedValidationsTriggerPauseIdentifiersRatelimit(t *testing.T) {
   689  	va, sa, ra, rl, fc, registration, cleanUp := initAuthorities(t)
   690  	defer cleanUp()
   691  
   692  	features.Set(features.Config{AutomaticallyPauseZombieClients: true})
   693  	defer features.Reset()
   694  
   695  	// Replace the SA with one that will block when PauseIdentifiers is called.
   696  	pauseChan := make(chan *sapb.PauseRequest)
   697  	defer close(pauseChan)
   698  	ra.SA = mockSAWithSyncPause{
   699  		StorageAuthorityClient: ra.SA,
   700  		out:                    pauseChan,
   701  	}
   702  
   703  	// Set the default ratelimits to only allow one failed validation per 24
   704  	// hours before pausing.
   705  	txnBuilder, err := ratelimits.NewTransactionBuilder(ratelimits.LimitConfigs{
   706  		ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount.String(): &ratelimits.LimitConfig{
   707  			Burst:  1,
   708  			Count:  1,
   709  			Period: config.Duration{Duration: time.Hour * 24}},
   710  	}, nil, metrics.NoopRegisterer, blog.NewMock())
   711  	test.AssertNotError(t, err, "making transaction composer")
   712  	ra.txnBuilder = txnBuilder
   713  
   714  	// Set up a fake domain, authz, and bucket key to care about.
   715  	domain := randomDomain()
   716  	ident := identifier.NewDNS(domain)
   717  	authzPB := createPendingAuthorization(t, sa, registration.Id, ident, fc.Now().Add(12*time.Hour))
   718  	bucketKey, err := ratelimits.BuildBucketKey(ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, authzPB.RegistrationID, ident, nil, netip.Addr{})
   719  	test.AssertNotError(t, err, "building bucket key")
   720  
   721  	// Set the stored TAT to indicate that this bucket has exhausted its quota.
   722  	err = rl.BatchSet(context.Background(), map[string]time.Time{
   723  		bucketKey: fc.Now().Add(25 * time.Hour),
   724  	})
   725  	test.AssertNotError(t, err, "updating rate limit bucket")
   726  
   727  	// Now a failed validation should result in the identifier being paused
   728  	// due to the strict ratelimit.
   729  	va.doDCVResult = &vapb.ValidationResult{
   730  		Records: []*corepb.ValidationRecord{
   731  			{
   732  				AddressUsed:   []byte("192.168.0.1"),
   733  				Hostname:      domain,
   734  				Port:          "8080",
   735  				Url:           fmt.Sprintf("http://%s/", domain),
   736  				ResolverAddrs: []string{"rebound"},
   737  			},
   738  		},
   739  		Problem: nil,
   740  	}
   741  	va.doCAAResponse = &vapb.IsCAAValidResponse{
   742  		Problem: &corepb.ProblemDetails{
   743  			Detail: fmt.Sprintf("CAA invalid for %s", domain),
   744  		},
   745  	}
   746  
   747  	_, err = ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   748  		Authz:          authzPB,
   749  		ChallengeIndex: dnsChallIdx(t, authzPB.Challenges),
   750  	})
   751  	test.AssertNotError(t, err, "PerformValidation failed")
   752  
   753  	// Wait for the RA to finish processing the validation, and ensure that the paused
   754  	// account+identifier is what we expect.
   755  	paused := <-pauseChan
   756  	test.AssertEquals(t, len(paused.Identifiers), 1)
   757  	test.AssertEquals(t, paused.Identifiers[0].Value, domain)
   758  }
   759  
   760  // mockRLSourceWithSyncDelete is a mock ratelimits.Source that forwards all
   761  // method calls to an inner Source, but also performs a blocking write to a
   762  // channel when BatchDelete is called to allow the tests to synchronize.
   763  type mockRLSourceWithSyncDelete struct {
   764  	ratelimits.Source
   765  	out chan<- string
   766  }
   767  
   768  func (rl mockRLSourceWithSyncDelete) BatchDelete(ctx context.Context, bucketKeys []string) error {
   769  	err := rl.Source.BatchDelete(ctx, bucketKeys)
   770  	for _, bucketKey := range bucketKeys {
   771  		rl.out <- bucketKey
   772  	}
   773  	return err
   774  }
   775  
   776  func TestPerformValidation_FailedThenSuccessfulValidationResetsPauseIdentifiersRatelimit(t *testing.T) {
   777  	va, sa, ra, rl, fc, registration, cleanUp := initAuthorities(t)
   778  	defer cleanUp()
   779  
   780  	features.Set(features.Config{AutomaticallyPauseZombieClients: true})
   781  	defer features.Reset()
   782  
   783  	// Replace the rate limit source with one that will block when Delete is called.
   784  	keyChan := make(chan string)
   785  	defer close(keyChan)
   786  	limiter, err := ratelimits.NewLimiter(fc, mockRLSourceWithSyncDelete{
   787  		Source: rl,
   788  		out:    keyChan,
   789  	}, metrics.NoopRegisterer)
   790  	test.AssertNotError(t, err, "creating mock limiter")
   791  	ra.limiter = limiter
   792  
   793  	// Set up a fake domain, authz, and bucket key to care about.
   794  	domain := randomDomain()
   795  	ident := identifier.NewDNS(domain)
   796  	authzPB := createPendingAuthorization(t, sa, registration.Id, ident, fc.Now().Add(12*time.Hour))
   797  	bucketKey, err := ratelimits.BuildBucketKey(ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, authzPB.RegistrationID, ident, nil, netip.Addr{})
   798  	test.AssertNotError(t, err, "building bucket key")
   799  
   800  	// Set a stored TAT so that we can tell when it's been reset.
   801  	err = rl.BatchSet(context.Background(), map[string]time.Time{
   802  		bucketKey: fc.Now().Add(25 * time.Hour),
   803  	})
   804  	test.AssertNotError(t, err, "updating rate limit bucket")
   805  
   806  	va.doDCVResult = &vapb.ValidationResult{
   807  		Records: []*corepb.ValidationRecord{
   808  			{
   809  				AddressUsed:   []byte("192.168.0.1"),
   810  				Hostname:      domain,
   811  				Port:          "8080",
   812  				Url:           fmt.Sprintf("http://%s/", domain),
   813  				ResolverAddrs: []string{"rebound"},
   814  			},
   815  		},
   816  		Problem: nil,
   817  	}
   818  	va.doCAAResponse = &vapb.IsCAAValidResponse{Problem: nil}
   819  
   820  	_, err = ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   821  		Authz:          authzPB,
   822  		ChallengeIndex: dnsChallIdx(t, authzPB.Challenges),
   823  	})
   824  	test.AssertNotError(t, err, "PerformValidation failed")
   825  
   826  	// Wait for the RA to finish processesing the validation, and ensure that
   827  	// the reset bucket key is what we expect.
   828  	reset := <-keyChan
   829  	test.AssertEquals(t, reset, bucketKey)
   830  
   831  	// Verify that the bucket no longer exists (because the limiter reset has
   832  	// deleted it). This indicates the accountID:identifier bucket has regained
   833  	// capacity avoiding being inadvertently paused.
   834  	_, err = rl.Get(ctx, bucketKey)
   835  	test.AssertErrorIs(t, err, ratelimits.ErrBucketNotFound)
   836  }
   837  
   838  func TestPerformValidationVAError(t *testing.T) {
   839  	va, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
   840  	defer cleanUp()
   841  
   842  	authzPB := createPendingAuthorization(t, sa, registration.Id, identifier.NewDNS("example.com"), fc.Now().Add(12*time.Hour))
   843  
   844  	va.doDCVError = fmt.Errorf("Something went wrong")
   845  
   846  	challIdx := dnsChallIdx(t, authzPB.Challenges)
   847  	authzPB, err := ra.PerformValidation(ctx, &rapb.PerformValidationRequest{
   848  		Authz:          authzPB,
   849  		ChallengeIndex: challIdx,
   850  	})
   851  
   852  	test.AssertNotError(t, err, "PerformValidation completely failed")
   853  
   854  	var vaRequest *vapb.PerformValidationRequest
   855  	select {
   856  	case r := <-va.doDCVRequest:
   857  		vaRequest = r
   858  	case <-time.After(time.Second):
   859  		t.Fatal("Timed out waiting for DummyValidationAuthority.PerformValidation to complete")
   860  	}
   861  
   862  	// Verify that the VA got the request, and it's the same as the others
   863  	test.AssertEquals(t, authzPB.Challenges[challIdx].Type, vaRequest.Challenge.Type)
   864  	test.AssertEquals(t, authzPB.Challenges[challIdx].Token, vaRequest.Challenge.Token)
   865  
   866  	// Sleep so the RA has a chance to write to the SA
   867  	time.Sleep(100 * time.Millisecond)
   868  
   869  	dbAuthzPB := getAuthorization(t, authzPB.Id, sa)
   870  	t.Log("dbAuthz:", dbAuthzPB)
   871  
   872  	// Verify that the responses are reflected
   873  	challIdx = dnsChallIdx(t, dbAuthzPB.Challenges)
   874  	challenge, err := bgrpc.PBToChallenge(dbAuthzPB.Challenges[challIdx])
   875  	test.AssertNotError(t, err, "Failed to marshall corepb.Challenge to core.Challenge.")
   876  	test.Assert(t, challenge.Status == core.StatusInvalid, "challenge was not marked as invalid")
   877  	test.AssertContains(t, challenge.Error.String(), "Could not communicate with VA")
   878  	test.Assert(t, challenge.ValidationRecord == nil, "challenge had a ValidationRecord")
   879  
   880  	// Check that validated timestamp was recorded, stored, and retrieved
   881  	expectedValidated := fc.Now()
   882  	test.Assert(t, *challenge.Validated == expectedValidated, "Validated timestamp incorrect or missing")
   883  }
   884  
   885  func TestCertificateKeyNotEqualAccountKey(t *testing.T) {
   886  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
   887  	defer cleanUp()
   888  
   889  	exp := ra.clk.Now().Add(365 * 24 * time.Hour)
   890  
   891  	authzID := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("www.example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
   892  
   893  	order, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{
   894  		NewOrder: &sapb.NewOrderRequest{
   895  			RegistrationID:   registration.Id,
   896  			Expires:          timestamppb.New(exp),
   897  			Identifiers:      []*corepb.Identifier{identifier.NewDNS("www.example.com").ToProto()},
   898  			V2Authorizations: []int64{authzID},
   899  		},
   900  	})
   901  	test.AssertNotError(t, err, "Could not add test order with finalized authz IDs, ready status")
   902  
   903  	csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
   904  		// Registration has key == AccountKeyA
   905  		PublicKey:          AccountKeyA.Key,
   906  		SignatureAlgorithm: x509.SHA256WithRSA,
   907  		DNSNames:           []string{"www.example.com"},
   908  	}, AccountPrivateKey.Key)
   909  	test.AssertNotError(t, err, "Failed to sign CSR")
   910  
   911  	_, err = ra.FinalizeOrder(ctx, &rapb.FinalizeOrderRequest{
   912  		Order: &corepb.Order{
   913  			Status:         string(core.StatusReady),
   914  			Identifiers:    []*corepb.Identifier{identifier.NewDNS("www.example.com").ToProto()},
   915  			Id:             order.Id,
   916  			RegistrationID: registration.Id,
   917  		},
   918  		Csr: csrBytes,
   919  	})
   920  	test.AssertError(t, err, "Should have rejected cert with key = account key")
   921  	test.AssertEquals(t, err.Error(), "certificate public key must be different than account key")
   922  }
   923  
   924  func TestDeactivateAuthorization(t *testing.T) {
   925  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
   926  	defer cleanUp()
   927  
   928  	exp := ra.clk.Now().Add(365 * 24 * time.Hour)
   929  	authzID := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("not-example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
   930  	dbAuthzPB := getAuthorization(t, fmt.Sprint(authzID), sa)
   931  	_, err := ra.DeactivateAuthorization(ctx, dbAuthzPB)
   932  	test.AssertNotError(t, err, "Could not deactivate authorization")
   933  	deact, err := sa.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: authzID})
   934  	test.AssertNotError(t, err, "Could not get deactivated authorization with ID "+dbAuthzPB.Id)
   935  	test.AssertEquals(t, deact.Status, string(core.StatusDeactivated))
   936  }
   937  
   938  type mockSARecordingPauses struct {
   939  	sapb.StorageAuthorityClient
   940  	recv *sapb.PauseRequest
   941  }
   942  
   943  func (sa *mockSARecordingPauses) PauseIdentifiers(ctx context.Context, req *sapb.PauseRequest, _ ...grpc.CallOption) (*sapb.PauseIdentifiersResponse, error) {
   944  	sa.recv = req
   945  	return &sapb.PauseIdentifiersResponse{Paused: int64(len(req.Identifiers))}, nil
   946  }
   947  
   948  func (sa *mockSARecordingPauses) DeactivateAuthorization2(_ context.Context, _ *sapb.AuthorizationID2, _ ...grpc.CallOption) (*emptypb.Empty, error) {
   949  	return nil, nil
   950  }
   951  
   952  func TestDeactivateAuthorization_Pausing(t *testing.T) {
   953  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
   954  	defer cleanUp()
   955  
   956  	if ra.limiter == nil {
   957  		t.Skip("no redis limiter configured")
   958  	}
   959  
   960  	msa := mockSARecordingPauses{}
   961  	ra.SA = &msa
   962  
   963  	features.Set(features.Config{AutomaticallyPauseZombieClients: true})
   964  	defer features.Reset()
   965  
   966  	// Set the default ratelimits to only allow one failed validation per 24
   967  	// hours before pausing.
   968  	txnBuilder, err := ratelimits.NewTransactionBuilder(ratelimits.LimitConfigs{
   969  		ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount.String(): &ratelimits.LimitConfig{
   970  			Burst:  1,
   971  			Count:  1,
   972  			Period: config.Duration{Duration: time.Hour * 24}},
   973  	}, nil, metrics.NoopRegisterer, blog.NewMock())
   974  	test.AssertNotError(t, err, "making transaction composer")
   975  	ra.txnBuilder = txnBuilder
   976  
   977  	// The first deactivation of a pending authz should work and nothing should
   978  	// get paused.
   979  	_, err = ra.DeactivateAuthorization(ctx, &corepb.Authorization{
   980  		Id:             "1",
   981  		RegistrationID: registration.Id,
   982  		Identifier:     identifier.NewDNS("example.com").ToProto(),
   983  		Status:         string(core.StatusPending),
   984  	})
   985  	test.AssertNotError(t, err, "mock deactivation should work")
   986  	test.AssertBoxedNil(t, msa.recv, "shouldn't be a pause request yet")
   987  
   988  	// Deactivating a valid authz shouldn't increment any limits or pause anything.
   989  	_, err = ra.DeactivateAuthorization(ctx, &corepb.Authorization{
   990  		Id:             "2",
   991  		RegistrationID: registration.Id,
   992  		Identifier:     identifier.NewDNS("example.com").ToProto(),
   993  		Status:         string(core.StatusValid),
   994  	})
   995  	test.AssertNotError(t, err, "mock deactivation should work")
   996  	test.AssertBoxedNil(t, msa.recv, "deactivating valid authz should never pause")
   997  
   998  	// Deactivating a second pending authz should surpass the limit and result
   999  	// in a pause request.
  1000  	_, err = ra.DeactivateAuthorization(ctx, &corepb.Authorization{
  1001  		Id:             "3",
  1002  		RegistrationID: registration.Id,
  1003  		Identifier:     identifier.NewDNS("example.com").ToProto(),
  1004  		Status:         string(core.StatusPending),
  1005  	})
  1006  	test.AssertNotError(t, err, "mock deactivation should work")
  1007  	test.AssertNotNil(t, msa.recv, "should have recorded a pause request")
  1008  	test.AssertEquals(t, msa.recv.RegistrationID, registration.Id)
  1009  	test.AssertEquals(t, msa.recv.Identifiers[0].Value, "example.com")
  1010  }
  1011  
  1012  func TestDeactivateRegistration(t *testing.T) {
  1013  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  1014  	defer cleanUp()
  1015  
  1016  	// Deactivate failure because incomplete registration provided
  1017  	_, err := ra.DeactivateRegistration(context.Background(), &rapb.DeactivateRegistrationRequest{})
  1018  	test.AssertDeepEquals(t, err, fmt.Errorf("incomplete gRPC request message"))
  1019  
  1020  	// Deactivate success with valid registration
  1021  	got, err := ra.DeactivateRegistration(context.Background(), &rapb.DeactivateRegistrationRequest{RegistrationID: registration.Id})
  1022  	test.AssertNotError(t, err, "DeactivateRegistration failed")
  1023  	test.AssertEquals(t, got.Status, string(core.StatusDeactivated))
  1024  
  1025  	// Check db to make sure account is deactivated
  1026  	dbReg, err := ra.SA.GetRegistration(context.Background(), &sapb.RegistrationID{Id: registration.Id})
  1027  	test.AssertNotError(t, err, "GetRegistration failed")
  1028  	test.AssertEquals(t, dbReg.Status, string(core.StatusDeactivated))
  1029  }
  1030  
  1031  // noopCAA implements vapb.CAAClient, always returning nil
  1032  type noopCAA struct{}
  1033  
  1034  func (cr noopCAA) IsCAAValid(
  1035  	ctx context.Context,
  1036  	in *vapb.IsCAAValidRequest,
  1037  	opts ...grpc.CallOption,
  1038  ) (*vapb.IsCAAValidResponse, error) {
  1039  	return &vapb.IsCAAValidResponse{}, nil
  1040  }
  1041  
  1042  func (cr noopCAA) DoCAA(
  1043  	ctx context.Context,
  1044  	in *vapb.IsCAAValidRequest,
  1045  	opts ...grpc.CallOption,
  1046  ) (*vapb.IsCAAValidResponse, error) {
  1047  	return &vapb.IsCAAValidResponse{}, nil
  1048  }
  1049  
  1050  // caaRecorder implements vapb.CAAClient, always returning nil, but recording
  1051  // the names it was called for.
  1052  type caaRecorder struct {
  1053  	sync.Mutex
  1054  	names map[string]bool
  1055  }
  1056  
  1057  func (cr *caaRecorder) IsCAAValid(
  1058  	ctx context.Context,
  1059  	in *vapb.IsCAAValidRequest,
  1060  	opts ...grpc.CallOption,
  1061  ) (*vapb.IsCAAValidResponse, error) {
  1062  	cr.Lock()
  1063  	defer cr.Unlock()
  1064  	cr.names[in.Identifier.Value] = true
  1065  	return &vapb.IsCAAValidResponse{}, nil
  1066  }
  1067  
  1068  func (cr *caaRecorder) DoCAA(
  1069  	ctx context.Context,
  1070  	in *vapb.IsCAAValidRequest,
  1071  	opts ...grpc.CallOption,
  1072  ) (*vapb.IsCAAValidResponse, error) {
  1073  	cr.Lock()
  1074  	defer cr.Unlock()
  1075  	cr.names[in.Identifier.Value] = true
  1076  	return &vapb.IsCAAValidResponse{}, nil
  1077  }
  1078  
  1079  // Test that the right set of domain names have their CAA rechecked, based on
  1080  // their `Validated` (attemptedAt in the database) timestamp.
  1081  func TestRecheckCAADates(t *testing.T) {
  1082  	_, _, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1083  	defer cleanUp()
  1084  	recorder := &caaRecorder{names: make(map[string]bool)}
  1085  	ra.VA = va.RemoteClients{CAAClient: recorder}
  1086  	ra.profiles.def().validAuthzLifetime = 15 * time.Hour
  1087  
  1088  	recentValidated := fc.Now().Add(-1 * time.Hour)
  1089  	recentExpires := fc.Now().Add(15 * time.Hour)
  1090  	olderValidated := fc.Now().Add(-8 * time.Hour)
  1091  	olderExpires := fc.Now().Add(5 * time.Hour)
  1092  
  1093  	authzs := map[identifier.ACMEIdentifier]*core.Authorization{
  1094  		identifier.NewDNS("recent.com"): {
  1095  			Identifier: identifier.NewDNS("recent.com"),
  1096  			Expires:    &recentExpires,
  1097  			Challenges: []core.Challenge{
  1098  				{
  1099  					Status:    core.StatusValid,
  1100  					Type:      core.ChallengeTypeHTTP01,
  1101  					Token:     "exampleToken",
  1102  					Validated: &recentValidated,
  1103  				},
  1104  			},
  1105  		},
  1106  		identifier.NewDNS("older.com"): {
  1107  			Identifier: identifier.NewDNS("older.com"),
  1108  			Expires:    &olderExpires,
  1109  			Challenges: []core.Challenge{
  1110  				{
  1111  					Status:    core.StatusValid,
  1112  					Type:      core.ChallengeTypeHTTP01,
  1113  					Token:     "exampleToken",
  1114  					Validated: &olderValidated,
  1115  				},
  1116  			},
  1117  		},
  1118  		identifier.NewDNS("older2.com"): {
  1119  			Identifier: identifier.NewDNS("older2.com"),
  1120  			Expires:    &olderExpires,
  1121  			Challenges: []core.Challenge{
  1122  				{
  1123  					Status:    core.StatusValid,
  1124  					Type:      core.ChallengeTypeHTTP01,
  1125  					Token:     "exampleToken",
  1126  					Validated: &olderValidated,
  1127  				},
  1128  			},
  1129  		},
  1130  		identifier.NewDNS("wildcard.com"): {
  1131  			Identifier: identifier.NewDNS("wildcard.com"),
  1132  			Expires:    &olderExpires,
  1133  			Challenges: []core.Challenge{
  1134  				{
  1135  					Status:    core.StatusValid,
  1136  					Type:      core.ChallengeTypeHTTP01,
  1137  					Token:     "exampleToken",
  1138  					Validated: &olderValidated,
  1139  				},
  1140  			},
  1141  		},
  1142  		identifier.NewDNS("*.wildcard.com"): {
  1143  			Identifier: identifier.NewDNS("*.wildcard.com"),
  1144  			Expires:    &olderExpires,
  1145  			Challenges: []core.Challenge{
  1146  				{
  1147  					Status:    core.StatusValid,
  1148  					Type:      core.ChallengeTypeHTTP01,
  1149  					Token:     "exampleToken",
  1150  					Validated: &olderValidated,
  1151  				},
  1152  			},
  1153  		},
  1154  	}
  1155  	twoChallenges := map[identifier.ACMEIdentifier]*core.Authorization{
  1156  		identifier.NewDNS("twochallenges.com"): {
  1157  			ID:         "twochal",
  1158  			Identifier: identifier.NewDNS("twochallenges.com"),
  1159  			Expires:    &recentExpires,
  1160  			Challenges: []core.Challenge{
  1161  				{
  1162  					Status:    core.StatusValid,
  1163  					Type:      core.ChallengeTypeHTTP01,
  1164  					Token:     "exampleToken",
  1165  					Validated: &olderValidated,
  1166  				},
  1167  				{
  1168  					Status:    core.StatusValid,
  1169  					Type:      core.ChallengeTypeDNS01,
  1170  					Token:     "exampleToken",
  1171  					Validated: &olderValidated,
  1172  				},
  1173  			},
  1174  		},
  1175  	}
  1176  	noChallenges := map[identifier.ACMEIdentifier]*core.Authorization{
  1177  		identifier.NewDNS("nochallenges.com"): {
  1178  			ID:         "nochal",
  1179  			Identifier: identifier.NewDNS("nochallenges.com"),
  1180  			Expires:    &recentExpires,
  1181  			Challenges: []core.Challenge{},
  1182  		},
  1183  	}
  1184  	noValidationTime := map[identifier.ACMEIdentifier]*core.Authorization{
  1185  		identifier.NewDNS("novalidationtime.com"): {
  1186  			ID:         "noval",
  1187  			Identifier: identifier.NewDNS("novalidationtime.com"),
  1188  			Expires:    &recentExpires,
  1189  			Challenges: []core.Challenge{
  1190  				{
  1191  					Status:    core.StatusValid,
  1192  					Type:      core.ChallengeTypeHTTP01,
  1193  					Token:     "exampleToken",
  1194  					Validated: nil,
  1195  				},
  1196  			},
  1197  		},
  1198  	}
  1199  
  1200  	// NOTE: The names provided here correspond to authorizations in the
  1201  	// `mockSAWithRecentAndOlder`
  1202  	err := ra.checkAuthorizationsCAA(context.Background(), registration.Id, authzs, fc.Now())
  1203  	// We expect that there is no error rechecking authorizations for these names
  1204  	if err != nil {
  1205  		t.Errorf("expected nil err, got %s", err)
  1206  	}
  1207  
  1208  	// Should error if a authorization has `!= 1` challenge
  1209  	err = ra.checkAuthorizationsCAA(context.Background(), registration.Id, twoChallenges, fc.Now())
  1210  	test.AssertEquals(t, err.Error(), "authorization has incorrect number of challenges. 1 expected, 2 found for: id twochal")
  1211  
  1212  	// Should error if a authorization has `!= 1` challenge
  1213  	err = ra.checkAuthorizationsCAA(context.Background(), registration.Id, noChallenges, fc.Now())
  1214  	test.AssertEquals(t, err.Error(), "authorization has incorrect number of challenges. 1 expected, 0 found for: id nochal")
  1215  
  1216  	// Should error if authorization's challenge has no validated timestamp
  1217  	err = ra.checkAuthorizationsCAA(context.Background(), registration.Id, noValidationTime, fc.Now())
  1218  	test.AssertEquals(t, err.Error(), "authorization's challenge has no validated timestamp for: id noval")
  1219  
  1220  	// We expect that "recent.com" is not checked because its mock authorization
  1221  	// isn't expired
  1222  	if _, present := recorder.names["recent.com"]; present {
  1223  		t.Errorf("Rechecked CAA unnecessarily for recent.com")
  1224  	}
  1225  
  1226  	// We expect that "older.com" is checked
  1227  	if _, present := recorder.names["older.com"]; !present {
  1228  		t.Errorf("Failed to recheck CAA for older.com")
  1229  	}
  1230  
  1231  	// We expect that "older2.com" is checked
  1232  	if _, present := recorder.names["older2.com"]; !present {
  1233  		t.Errorf("Failed to recheck CAA for older2.com")
  1234  	}
  1235  
  1236  	// We expect that the "wildcard.com" domain (without the `*.` prefix) is checked.
  1237  	if _, present := recorder.names["wildcard.com"]; !present {
  1238  		t.Errorf("Failed to recheck CAA for wildcard.com")
  1239  	}
  1240  
  1241  	// We expect that "*.wildcard.com" is checked (with the `*.` prefix, because
  1242  	// it is stripped at a lower layer than we are testing)
  1243  	if _, present := recorder.names["*.wildcard.com"]; !present {
  1244  		t.Errorf("Failed to recheck CAA for *.wildcard.com")
  1245  	}
  1246  }
  1247  
  1248  type caaFailer struct{}
  1249  
  1250  func (cf *caaFailer) IsCAAValid(
  1251  	ctx context.Context,
  1252  	in *vapb.IsCAAValidRequest,
  1253  	opts ...grpc.CallOption,
  1254  ) (*vapb.IsCAAValidResponse, error) {
  1255  	cvrpb := &vapb.IsCAAValidResponse{}
  1256  	switch in.Identifier.Value {
  1257  	case "a.com":
  1258  		cvrpb.Problem = &corepb.ProblemDetails{
  1259  			Detail: "CAA invalid for a.com",
  1260  		}
  1261  	case "b.com":
  1262  	case "c.com":
  1263  		cvrpb.Problem = &corepb.ProblemDetails{
  1264  			Detail: "CAA invalid for c.com",
  1265  		}
  1266  	case "d.com":
  1267  		return nil, fmt.Errorf("Error checking CAA for d.com")
  1268  	default:
  1269  		return nil, fmt.Errorf("Unexpected test case")
  1270  	}
  1271  	return cvrpb, nil
  1272  }
  1273  
  1274  func (cf *caaFailer) DoCAA(
  1275  	ctx context.Context,
  1276  	in *vapb.IsCAAValidRequest,
  1277  	opts ...grpc.CallOption,
  1278  ) (*vapb.IsCAAValidResponse, error) {
  1279  	cvrpb := &vapb.IsCAAValidResponse{}
  1280  	switch in.Identifier.Value {
  1281  	case "a.com":
  1282  		cvrpb.Problem = &corepb.ProblemDetails{
  1283  			Detail: "CAA invalid for a.com",
  1284  		}
  1285  	case "b.com":
  1286  	case "c.com":
  1287  		cvrpb.Problem = &corepb.ProblemDetails{
  1288  			Detail: "CAA invalid for c.com",
  1289  		}
  1290  	case "d.com":
  1291  		return nil, fmt.Errorf("Error checking CAA for d.com")
  1292  	default:
  1293  		return nil, fmt.Errorf("Unexpected test case")
  1294  	}
  1295  	return cvrpb, nil
  1296  }
  1297  
  1298  func TestRecheckCAAEmpty(t *testing.T) {
  1299  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  1300  	defer cleanUp()
  1301  	err := ra.recheckCAA(context.Background(), nil)
  1302  	test.AssertNotError(t, err, "expected nil")
  1303  }
  1304  
  1305  func makeHTTP01Authorization(ident identifier.ACMEIdentifier) *core.Authorization {
  1306  	return &core.Authorization{
  1307  		Identifier: ident,
  1308  		Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
  1309  	}
  1310  }
  1311  
  1312  func TestRecheckCAASuccess(t *testing.T) {
  1313  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  1314  	defer cleanUp()
  1315  	ra.VA = va.RemoteClients{CAAClient: &noopCAA{}}
  1316  	authzs := []*core.Authorization{
  1317  		makeHTTP01Authorization(identifier.NewDNS("a.com")),
  1318  		makeHTTP01Authorization(identifier.NewDNS("b.com")),
  1319  		makeHTTP01Authorization(identifier.NewDNS("c.com")),
  1320  	}
  1321  	err := ra.recheckCAA(context.Background(), authzs)
  1322  	test.AssertNotError(t, err, "expected nil")
  1323  }
  1324  
  1325  func TestRecheckCAAFail(t *testing.T) {
  1326  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  1327  	defer cleanUp()
  1328  	ra.VA = va.RemoteClients{CAAClient: &caaFailer{}}
  1329  	authzs := []*core.Authorization{
  1330  		makeHTTP01Authorization(identifier.NewDNS("a.com")),
  1331  		makeHTTP01Authorization(identifier.NewDNS("b.com")),
  1332  		makeHTTP01Authorization(identifier.NewDNS("c.com")),
  1333  	}
  1334  	err := ra.recheckCAA(context.Background(), authzs)
  1335  
  1336  	test.AssertError(t, err, "expected err, got nil")
  1337  	var berr *berrors.BoulderError
  1338  	test.AssertErrorWraps(t, err, &berr)
  1339  	test.AssertErrorIs(t, berr, berrors.CAA)
  1340  	test.AssertEquals(t, len(berr.SubErrors), 2)
  1341  
  1342  	// We don't know whether the asynchronous a.com or c.com CAA recheck will fail
  1343  	// first. Whichever does will be mentioned in the top level problem detail.
  1344  	expectedDetailRegex := regexp.MustCompile(
  1345  		`Rechecking CAA for "(?:a\.com|c\.com)" and 1 more identifiers failed. Refer to sub-problems for more information`,
  1346  	)
  1347  	if !expectedDetailRegex.MatchString(berr.Detail) {
  1348  		t.Errorf("expected suberror detail to match expected regex, got %q", err)
  1349  	}
  1350  
  1351  	// There should be a sub error for both a.com and c.com with the correct type
  1352  	subErrMap := make(map[string]berrors.SubBoulderError, len(berr.SubErrors))
  1353  	for _, subErr := range berr.SubErrors {
  1354  		subErrMap[subErr.Identifier.Value] = subErr
  1355  	}
  1356  	subErrA, foundA := subErrMap["a.com"]
  1357  	subErrB, foundB := subErrMap["c.com"]
  1358  	test.AssertEquals(t, foundA, true)
  1359  	test.AssertEquals(t, foundB, true)
  1360  	test.AssertEquals(t, subErrA.Type, berrors.CAA)
  1361  	test.AssertEquals(t, subErrB.Type, berrors.CAA)
  1362  
  1363  	// Recheck CAA with just one bad authz
  1364  	authzs = []*core.Authorization{
  1365  		makeHTTP01Authorization(identifier.NewDNS("a.com")),
  1366  	}
  1367  	err = ra.recheckCAA(context.Background(), authzs)
  1368  	// It should error
  1369  	test.AssertError(t, err, "expected err from recheckCAA")
  1370  	// It should be a berror
  1371  	test.AssertErrorWraps(t, err, &berr)
  1372  	// There should be *no* suberrors because there was only one overall error
  1373  	test.AssertEquals(t, len(berr.SubErrors), 0)
  1374  }
  1375  
  1376  func TestRecheckCAAInternalServerError(t *testing.T) {
  1377  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  1378  	defer cleanUp()
  1379  	ra.VA = va.RemoteClients{CAAClient: &caaFailer{}}
  1380  	authzs := []*core.Authorization{
  1381  		makeHTTP01Authorization(identifier.NewDNS("a.com")),
  1382  		makeHTTP01Authorization(identifier.NewDNS("b.com")),
  1383  		makeHTTP01Authorization(identifier.NewDNS("d.com")),
  1384  	}
  1385  	err := ra.recheckCAA(context.Background(), authzs)
  1386  	test.AssertError(t, err, "expected err, got nil")
  1387  	test.AssertErrorIs(t, err, berrors.InternalServer)
  1388  }
  1389  
  1390  func TestRecheckSkipIPAddress(t *testing.T) {
  1391  	_, _, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1392  	defer cleanUp()
  1393  	ra.VA = va.RemoteClients{CAAClient: &caaFailer{}}
  1394  	ident := identifier.NewIP(netip.MustParseAddr("127.0.0.1"))
  1395  	olderValidated := fc.Now().Add(-8 * time.Hour)
  1396  	olderExpires := fc.Now().Add(5 * time.Hour)
  1397  	authzs := map[identifier.ACMEIdentifier]*core.Authorization{
  1398  		ident: {
  1399  			Identifier: ident,
  1400  			Expires:    &olderExpires,
  1401  			Challenges: []core.Challenge{
  1402  				{
  1403  					Status:    core.StatusValid,
  1404  					Type:      core.ChallengeTypeHTTP01,
  1405  					Token:     "exampleToken",
  1406  					Validated: &olderValidated,
  1407  				},
  1408  			},
  1409  		},
  1410  	}
  1411  	err := ra.checkAuthorizationsCAA(context.Background(), registration.Id, authzs, fc.Now())
  1412  	test.AssertNotError(t, err, "rechecking CAA for IP address, should have skipped")
  1413  }
  1414  
  1415  func TestRecheckInvalidIdentifierType(t *testing.T) {
  1416  	_, _, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1417  	defer cleanUp()
  1418  	ident := identifier.ACMEIdentifier{
  1419  		Type:  "fnord",
  1420  		Value: "well this certainly shouldn't have happened",
  1421  	}
  1422  	olderValidated := fc.Now().Add(-8 * time.Hour)
  1423  	olderExpires := fc.Now().Add(5 * time.Hour)
  1424  	authzs := map[identifier.ACMEIdentifier]*core.Authorization{
  1425  		ident: {
  1426  			Identifier: ident,
  1427  			Expires:    &olderExpires,
  1428  			Challenges: []core.Challenge{
  1429  				{
  1430  					Status:    core.StatusValid,
  1431  					Type:      core.ChallengeTypeHTTP01,
  1432  					Token:     "exampleToken",
  1433  					Validated: &olderValidated,
  1434  				},
  1435  			},
  1436  		},
  1437  	}
  1438  	err := ra.checkAuthorizationsCAA(context.Background(), registration.Id, authzs, fc.Now())
  1439  	test.AssertError(t, err, "expected err, got nil")
  1440  	test.AssertErrorIs(t, err, berrors.Malformed)
  1441  	test.AssertContains(t, err.Error(), "invalid identifier type")
  1442  }
  1443  
  1444  func TestNewOrder(t *testing.T) {
  1445  	_, _, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1446  	defer cleanUp()
  1447  
  1448  	now := fc.Now()
  1449  	orderA, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1450  		RegistrationID:         registration.Id,
  1451  		CertificateProfileName: "test",
  1452  		Identifiers: []*corepb.Identifier{
  1453  			identifier.NewDNS("b.com").ToProto(),
  1454  			identifier.NewDNS("a.com").ToProto(),
  1455  			identifier.NewDNS("a.com").ToProto(),
  1456  			identifier.NewDNS("C.COM").ToProto(),
  1457  		},
  1458  	})
  1459  	test.AssertNotError(t, err, "ra.NewOrder failed")
  1460  	test.AssertEquals(t, orderA.RegistrationID, registration.Id)
  1461  	test.AssertEquals(t, orderA.Expires.AsTime(), now.Add(ra.profiles.def().orderLifetime))
  1462  	test.AssertEquals(t, len(orderA.Identifiers), 3)
  1463  	test.AssertEquals(t, orderA.CertificateProfileName, "test")
  1464  	// We expect the order's identifier values to have been sorted,
  1465  	// deduplicated, and lowercased.
  1466  	test.AssertDeepEquals(t, orderA.Identifiers, []*corepb.Identifier{
  1467  		identifier.NewDNS("a.com").ToProto(),
  1468  		identifier.NewDNS("b.com").ToProto(),
  1469  		identifier.NewDNS("c.com").ToProto(),
  1470  	})
  1471  
  1472  	test.Assert(t, orderA.Id != 0, "order ID should not be zero")
  1473  	test.AssertEquals(t, numAuthorizations(orderA), 3)
  1474  
  1475  	_, err = ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1476  		RegistrationID: registration.Id,
  1477  		Identifiers:    []*corepb.Identifier{identifier.NewDNS("a").ToProto()},
  1478  	})
  1479  	test.AssertError(t, err, "NewOrder with invalid names did not error")
  1480  	test.AssertEquals(t, err.Error(), "Cannot issue for \"a\": Domain name needs at least one dot")
  1481  }
  1482  
  1483  // TestNewOrder_OrderReuse tests that subsequent requests by an ACME account to create
  1484  // an identical order results in only one order being created & subsequently
  1485  // reused.
  1486  func TestNewOrder_OrderReuse(t *testing.T) {
  1487  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  1488  	defer cleanUp()
  1489  
  1490  	// Create an initial order with regA and names
  1491  	idents := identifier.ACMEIdentifiers{
  1492  		identifier.NewDNS("zombo.com"),
  1493  		identifier.NewDNS("welcome.to.zombo.com"),
  1494  	}
  1495  
  1496  	orderReq := &rapb.NewOrderRequest{
  1497  		RegistrationID:         registration.Id,
  1498  		Identifiers:            idents.ToProtoSlice(),
  1499  		CertificateProfileName: "test",
  1500  	}
  1501  	firstOrder, err := ra.NewOrder(context.Background(), orderReq)
  1502  	test.AssertNotError(t, err, "Adding an initial order for regA failed")
  1503  
  1504  	// Create a second registration to reference
  1505  	acctKeyB, err := AccountKeyB.MarshalJSON()
  1506  	test.AssertNotError(t, err, "failed to marshal account key")
  1507  	input := &corepb.Registration{Key: acctKeyB}
  1508  	secondReg, err := ra.NewRegistration(context.Background(), input)
  1509  	test.AssertNotError(t, err, "Error creating a second test registration")
  1510  
  1511  	// Insert a second (albeit identical) profile to reference
  1512  	ra.profiles.byName["different"] = ra.profiles.def()
  1513  
  1514  	testCases := []struct {
  1515  		Name           string
  1516  		RegistrationID int64
  1517  		Identifiers    identifier.ACMEIdentifiers
  1518  		Profile        string
  1519  		ExpectReuse    bool
  1520  	}{
  1521  		{
  1522  			Name:           "Duplicate order, same regID",
  1523  			RegistrationID: registration.Id,
  1524  			Identifiers:    idents,
  1525  			Profile:        "test",
  1526  			// We expect reuse since the order matches firstOrder
  1527  			ExpectReuse: true,
  1528  		},
  1529  		{
  1530  			Name:           "Subset of order names, same regID",
  1531  			RegistrationID: registration.Id,
  1532  			Identifiers:    idents[:1],
  1533  			Profile:        "test",
  1534  			// We do not expect reuse because the order names don't match firstOrder
  1535  			ExpectReuse: false,
  1536  		},
  1537  		{
  1538  			Name:           "Superset of order names, same regID",
  1539  			RegistrationID: registration.Id,
  1540  			Identifiers:    append(idents, identifier.NewDNS("blog.zombo.com")),
  1541  			Profile:        "test",
  1542  			// We do not expect reuse because the order names don't match firstOrder
  1543  			ExpectReuse: false,
  1544  		},
  1545  		{
  1546  			Name:           "Missing profile, same regID",
  1547  			RegistrationID: registration.Id,
  1548  			Identifiers:    append(idents, identifier.NewDNS("blog.zombo.com")),
  1549  			// We do not expect reuse because the profile is missing
  1550  			ExpectReuse: false,
  1551  		},
  1552  		{
  1553  			Name:           "Missing profile, same regID",
  1554  			RegistrationID: registration.Id,
  1555  			Identifiers:    append(idents, identifier.NewDNS("blog.zombo.com")),
  1556  			Profile:        "different",
  1557  			// We do not expect reuse because a different profile is specified
  1558  			ExpectReuse: false,
  1559  		},
  1560  		{
  1561  			Name:           "Duplicate order, different regID",
  1562  			RegistrationID: secondReg.Id,
  1563  			Identifiers:    idents,
  1564  			Profile:        "test",
  1565  			// We do not expect reuse because the order regID differs from firstOrder
  1566  			ExpectReuse: false,
  1567  		},
  1568  		// TODO(#7324): Integrate certificate profile variance into this test.
  1569  	}
  1570  
  1571  	for _, tc := range testCases {
  1572  		t.Run(tc.Name, func(t *testing.T) {
  1573  			// Add the order for the test request
  1574  			order, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1575  				RegistrationID:         tc.RegistrationID,
  1576  				Identifiers:            tc.Identifiers.ToProtoSlice(),
  1577  				CertificateProfileName: tc.Profile,
  1578  			})
  1579  			test.AssertNotError(t, err, "NewOrder returned an unexpected error")
  1580  			test.AssertNotNil(t, order.Id, "NewOrder returned an order with a nil Id")
  1581  
  1582  			if tc.ExpectReuse {
  1583  				// If we expected order reuse for this testcase assert that the order
  1584  				// has the same ID as the firstOrder
  1585  				test.AssertEquals(t, order.Id, firstOrder.Id)
  1586  			} else {
  1587  				// Otherwise assert that the order doesn't have the same ID as the
  1588  				// firstOrder
  1589  				test.AssertNotEquals(t, order.Id, firstOrder.Id)
  1590  			}
  1591  		})
  1592  	}
  1593  }
  1594  
  1595  // TestNewOrder_OrderReuse_Expired tests that expired orders are not reused.
  1596  // This is not simply a test case in TestNewOrder_OrderReuse because it has
  1597  // side effects.
  1598  func TestNewOrder_OrderReuse_Expired(t *testing.T) {
  1599  	_, _, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1600  	defer cleanUp()
  1601  
  1602  	// Set the order lifetime to something short and known.
  1603  	ra.profiles.def().orderLifetime = time.Hour
  1604  
  1605  	// Create an initial order.
  1606  	extant, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1607  		RegistrationID: registration.Id,
  1608  		Identifiers: []*corepb.Identifier{
  1609  			identifier.NewDNS("a.com").ToProto(),
  1610  			identifier.NewDNS("b.com").ToProto(),
  1611  		},
  1612  	})
  1613  	test.AssertNotError(t, err, "creating test order")
  1614  
  1615  	// Transition the original order to status invalid by jumping forward in time
  1616  	// to when it has expired.
  1617  	fc.Set(extant.Expires.AsTime().Add(2 * time.Hour))
  1618  
  1619  	// Now a new order for the same names should not reuse the first one.
  1620  	new, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1621  		RegistrationID: registration.Id,
  1622  		Identifiers: []*corepb.Identifier{
  1623  			identifier.NewDNS("a.com").ToProto(),
  1624  			identifier.NewDNS("b.com").ToProto(),
  1625  		},
  1626  	})
  1627  	test.AssertNotError(t, err, "creating test order")
  1628  	test.AssertNotEquals(t, new.Id, extant.Id)
  1629  }
  1630  
  1631  // TestNewOrder_OrderReuse_Invalid tests that invalid orders are not reused.
  1632  // This is not simply a test case in TestNewOrder_OrderReuse because it has
  1633  // side effects.
  1634  func TestNewOrder_OrderReuse_Invalid(t *testing.T) {
  1635  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
  1636  	defer cleanUp()
  1637  
  1638  	// Create an initial order.
  1639  	extant, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1640  		RegistrationID: registration.Id,
  1641  		Identifiers: []*corepb.Identifier{
  1642  			identifier.NewDNS("a.com").ToProto(),
  1643  			identifier.NewDNS("b.com").ToProto(),
  1644  		},
  1645  	})
  1646  	test.AssertNotError(t, err, "creating test order")
  1647  
  1648  	// Transition the original order to status invalid by invalidating one of its
  1649  	// authorizations.
  1650  	_, err = sa.DeactivateAuthorization2(context.Background(), &sapb.AuthorizationID2{
  1651  		Id: extant.V2Authorizations[0],
  1652  	})
  1653  	test.AssertNotError(t, err, "deactivating test authorization")
  1654  
  1655  	// Now a new order for the same names should not reuse the first one.
  1656  	new, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1657  		RegistrationID: registration.Id,
  1658  		Identifiers: []*corepb.Identifier{
  1659  			identifier.NewDNS("a.com").ToProto(),
  1660  			identifier.NewDNS("b.com").ToProto(),
  1661  		},
  1662  	})
  1663  	test.AssertNotError(t, err, "creating test order")
  1664  	test.AssertNotEquals(t, new.Id, extant.Id)
  1665  }
  1666  
  1667  func TestNewOrder_AuthzReuse(t *testing.T) {
  1668  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
  1669  	defer cleanUp()
  1670  
  1671  	// Create three initial authzs by creating an initial order, then updating
  1672  	// the individual authz statuses.
  1673  	const (
  1674  		pending = "a-pending.com"
  1675  		valid   = "b-valid.com"
  1676  		invalid = "c-invalid.com"
  1677  	)
  1678  	extant, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1679  		RegistrationID: registration.Id,
  1680  		Identifiers: []*corepb.Identifier{
  1681  			identifier.NewDNS(pending).ToProto(),
  1682  			identifier.NewDNS(valid).ToProto(),
  1683  			identifier.NewDNS(invalid).ToProto(),
  1684  		},
  1685  	})
  1686  	test.AssertNotError(t, err, "creating test order")
  1687  	extantAuthzs := map[string]int64{
  1688  		// Take advantage of the fact that authz IDs are returned in the same order
  1689  		// as the lexicographically-sorted identifiers.
  1690  		pending: extant.V2Authorizations[0],
  1691  		valid:   extant.V2Authorizations[1],
  1692  		invalid: extant.V2Authorizations[2],
  1693  	}
  1694  	_, err = sa.FinalizeAuthorization2(context.Background(), &sapb.FinalizeAuthorizationRequest{
  1695  		Id:        extantAuthzs[valid],
  1696  		Status:    string(core.StatusValid),
  1697  		Attempted: "hello",
  1698  		Expires:   timestamppb.New(fc.Now().Add(48 * time.Hour)),
  1699  	})
  1700  	test.AssertNotError(t, err, "marking test authz as valid")
  1701  	_, err = sa.DeactivateAuthorization2(context.Background(), &sapb.AuthorizationID2{
  1702  		Id: extantAuthzs[invalid],
  1703  	})
  1704  	test.AssertNotError(t, err, "marking test authz as invalid")
  1705  
  1706  	// Create a second registration to reference later.
  1707  	acctKeyB, err := AccountKeyB.MarshalJSON()
  1708  	test.AssertNotError(t, err, "failed to marshal account key")
  1709  	input := &corepb.Registration{Key: acctKeyB}
  1710  	secondReg, err := ra.NewRegistration(context.Background(), input)
  1711  	test.AssertNotError(t, err, "Error creating a second test registration")
  1712  
  1713  	testCases := []struct {
  1714  		Name           string
  1715  		RegistrationID int64
  1716  		Identifier     identifier.ACMEIdentifier
  1717  		Profile        string
  1718  		ExpectReuse    bool
  1719  	}{
  1720  		{
  1721  			Name:           "Reuse pending authz",
  1722  			RegistrationID: registration.Id,
  1723  			Identifier:     identifier.NewDNS(pending),
  1724  			ExpectReuse:    false,
  1725  		},
  1726  		{
  1727  			Name:           "Reuse valid authz",
  1728  			RegistrationID: registration.Id,
  1729  			Identifier:     identifier.NewDNS(valid),
  1730  			ExpectReuse:    true,
  1731  		},
  1732  		{
  1733  			Name:           "Don't reuse invalid authz",
  1734  			RegistrationID: registration.Id,
  1735  			Identifier:     identifier.NewDNS(invalid),
  1736  			ExpectReuse:    false,
  1737  		},
  1738  		{
  1739  			Name:           "Don't reuse valid authz with wrong profile",
  1740  			RegistrationID: registration.Id,
  1741  			Identifier:     identifier.NewDNS(valid),
  1742  			Profile:        "test",
  1743  			ExpectReuse:    false,
  1744  		},
  1745  		{
  1746  			Name:           "Don't reuse valid authz from other acct",
  1747  			RegistrationID: secondReg.Id,
  1748  			Identifier:     identifier.NewDNS(valid),
  1749  			ExpectReuse:    false,
  1750  		},
  1751  	}
  1752  
  1753  	for _, tc := range testCases {
  1754  		t.Run(tc.Name, func(t *testing.T) {
  1755  			new, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1756  				RegistrationID:         tc.RegistrationID,
  1757  				Identifiers:            []*corepb.Identifier{tc.Identifier.ToProto()},
  1758  				CertificateProfileName: tc.Profile,
  1759  			})
  1760  			test.AssertNotError(t, err, "creating test order")
  1761  			test.AssertNotEquals(t, new.Id, extant.Id)
  1762  
  1763  			if tc.ExpectReuse {
  1764  				test.AssertEquals(t, new.V2Authorizations[0], extantAuthzs[tc.Identifier.Value])
  1765  			} else {
  1766  				test.AssertNotEquals(t, new.V2Authorizations[0], extantAuthzs[tc.Identifier.Value])
  1767  			}
  1768  		})
  1769  	}
  1770  }
  1771  
  1772  func TestNewOrder_ValidationProfiles(t *testing.T) {
  1773  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  1774  	defer cleanUp()
  1775  
  1776  	ra.profiles = &validationProfiles{
  1777  		defaultName: "one",
  1778  		byName: map[string]*validationProfile{
  1779  			"one": {
  1780  				pendingAuthzLifetime: 1 * 24 * time.Hour,
  1781  				validAuthzLifetime:   1 * 24 * time.Hour,
  1782  				orderLifetime:        1 * 24 * time.Hour,
  1783  				maxNames:             10,
  1784  				identifierTypes:      []identifier.IdentifierType{identifier.TypeDNS},
  1785  			},
  1786  			"two": {
  1787  				pendingAuthzLifetime: 2 * 24 * time.Hour,
  1788  				validAuthzLifetime:   2 * 24 * time.Hour,
  1789  				orderLifetime:        2 * 24 * time.Hour,
  1790  				maxNames:             10,
  1791  				identifierTypes:      []identifier.IdentifierType{identifier.TypeDNS},
  1792  			},
  1793  		},
  1794  	}
  1795  
  1796  	for _, tc := range []struct {
  1797  		name        string
  1798  		profile     string
  1799  		wantExpires time.Time
  1800  	}{
  1801  		{
  1802  			// A request with no profile should get an order and authzs with one-day lifetimes.
  1803  			name:        "no profile specified",
  1804  			profile:     "",
  1805  			wantExpires: ra.clk.Now().Add(1 * 24 * time.Hour),
  1806  		},
  1807  		{
  1808  			// A request for profile one should get an order and authzs with one-day lifetimes.
  1809  			name:        "profile one",
  1810  			profile:     "one",
  1811  			wantExpires: ra.clk.Now().Add(1 * 24 * time.Hour),
  1812  		},
  1813  		{
  1814  			// A request for profile two should get an order and authzs with one-day lifetimes.
  1815  			name:        "profile two",
  1816  			profile:     "two",
  1817  			wantExpires: ra.clk.Now().Add(2 * 24 * time.Hour),
  1818  		},
  1819  	} {
  1820  		t.Run(tc.name, func(t *testing.T) {
  1821  			order, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  1822  				RegistrationID:         registration.Id,
  1823  				Identifiers:            []*corepb.Identifier{identifier.NewDNS(randomDomain()).ToProto()},
  1824  				CertificateProfileName: tc.profile,
  1825  			})
  1826  			if err != nil {
  1827  				t.Fatalf("creating order: %s", err)
  1828  			}
  1829  			gotExpires := order.Expires.AsTime()
  1830  			if gotExpires != tc.wantExpires {
  1831  				t.Errorf("NewOrder(profile: %q).Expires = %s, expected %s", tc.profile, gotExpires, tc.wantExpires)
  1832  			}
  1833  
  1834  			authz, err := ra.GetAuthorization(context.Background(), &rapb.GetAuthorizationRequest{
  1835  				Id: order.V2Authorizations[0],
  1836  			})
  1837  			if err != nil {
  1838  				t.Fatalf("fetching test authz: %s", err)
  1839  			}
  1840  			gotExpires = authz.Expires.AsTime()
  1841  			if gotExpires != tc.wantExpires {
  1842  				t.Errorf("GetAuthorization(profile: %q).Expires = %s, expected %s", tc.profile, gotExpires, tc.wantExpires)
  1843  			}
  1844  		})
  1845  	}
  1846  }
  1847  
  1848  func TestNewOrder_ProfileSelectionAllowList(t *testing.T) {
  1849  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  1850  	defer cleanUp()
  1851  
  1852  	testCases := []struct {
  1853  		name              string
  1854  		profile           validationProfile
  1855  		expectErr         bool
  1856  		expectErrContains string
  1857  	}{
  1858  		{
  1859  			name:      "Allow all account IDs",
  1860  			profile:   validationProfile{allowList: nil},
  1861  			expectErr: false,
  1862  		},
  1863  		{
  1864  			name:              "Deny all but account Id 1337",
  1865  			profile:           validationProfile{allowList: allowlist.NewList([]int64{1337})},
  1866  			expectErr:         true,
  1867  			expectErrContains: "not permitted to use certificate profile",
  1868  		},
  1869  		{
  1870  			name:              "Deny all",
  1871  			profile:           validationProfile{allowList: allowlist.NewList([]int64{})},
  1872  			expectErr:         true,
  1873  			expectErrContains: "not permitted to use certificate profile",
  1874  		},
  1875  		{
  1876  			name:      "Allow registration ID",
  1877  			profile:   validationProfile{allowList: allowlist.NewList([]int64{registration.Id})},
  1878  			expectErr: false,
  1879  		},
  1880  	}
  1881  
  1882  	for _, tc := range testCases {
  1883  		t.Run(tc.name, func(t *testing.T) {
  1884  			tc.profile.maxNames = 1
  1885  			tc.profile.identifierTypes = []identifier.IdentifierType{identifier.TypeDNS}
  1886  			ra.profiles.byName = map[string]*validationProfile{
  1887  				"test": &tc.profile,
  1888  			}
  1889  
  1890  			orderReq := &rapb.NewOrderRequest{
  1891  				RegistrationID:         registration.Id,
  1892  				Identifiers:            []*corepb.Identifier{identifier.NewDNS(randomDomain()).ToProto()},
  1893  				CertificateProfileName: "test",
  1894  			}
  1895  			_, err := ra.NewOrder(context.Background(), orderReq)
  1896  
  1897  			if tc.expectErrContains != "" {
  1898  				test.AssertErrorIs(t, err, berrors.Unauthorized)
  1899  				test.AssertContains(t, err.Error(), tc.expectErrContains)
  1900  			} else {
  1901  				test.AssertNotError(t, err, "NewOrder failed")
  1902  			}
  1903  		})
  1904  	}
  1905  }
  1906  
  1907  func TestNewOrder_ProfileIdentifierTypes(t *testing.T) {
  1908  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  1909  	defer cleanUp()
  1910  
  1911  	testCases := []struct {
  1912  		name       string
  1913  		identTypes []identifier.IdentifierType
  1914  		idents     []*corepb.Identifier
  1915  		expectErr  string
  1916  	}{
  1917  		{
  1918  			name:       "Permit DNS, provide DNS names",
  1919  			identTypes: []identifier.IdentifierType{identifier.TypeDNS},
  1920  			idents:     []*corepb.Identifier{identifier.NewDNS(randomDomain()).ToProto(), identifier.NewDNS(randomDomain()).ToProto()},
  1921  		},
  1922  		{
  1923  			name:       "Permit IP, provide IPs",
  1924  			identTypes: []identifier.IdentifierType{identifier.TypeIP},
  1925  			idents:     []*corepb.Identifier{identifier.NewIP(randomIPv6()).ToProto(), identifier.NewIP(randomIPv6()).ToProto()},
  1926  		},
  1927  		{
  1928  			name:       "Permit DNS & IP, provide DNS & IP",
  1929  			identTypes: []identifier.IdentifierType{identifier.TypeDNS, identifier.TypeIP},
  1930  			idents:     []*corepb.Identifier{identifier.NewIP(randomIPv6()).ToProto(), identifier.NewDNS(randomDomain()).ToProto()},
  1931  		},
  1932  		{
  1933  			name:       "Permit DNS, provide IP",
  1934  			identTypes: []identifier.IdentifierType{identifier.TypeDNS},
  1935  			idents:     []*corepb.Identifier{identifier.NewIP(randomIPv6()).ToProto()},
  1936  			expectErr:  "Profile \"test\" does not permit ip type identifiers",
  1937  		},
  1938  		{
  1939  			name:       "Permit DNS, provide DNS & IP",
  1940  			identTypes: []identifier.IdentifierType{identifier.TypeDNS},
  1941  			idents:     []*corepb.Identifier{identifier.NewDNS(randomDomain()).ToProto(), identifier.NewIP(randomIPv6()).ToProto()},
  1942  			expectErr:  "Profile \"test\" does not permit ip type identifiers",
  1943  		},
  1944  		{
  1945  			name:       "Permit IP, provide DNS",
  1946  			identTypes: []identifier.IdentifierType{identifier.TypeIP},
  1947  			idents:     []*corepb.Identifier{identifier.NewDNS(randomDomain()).ToProto()},
  1948  			expectErr:  "Profile \"test\" does not permit dns type identifiers",
  1949  		},
  1950  		{
  1951  			name:       "Permit IP, provide DNS & IP",
  1952  			identTypes: []identifier.IdentifierType{identifier.TypeIP},
  1953  			idents:     []*corepb.Identifier{identifier.NewIP(randomIPv6()).ToProto(), identifier.NewDNS(randomDomain()).ToProto()},
  1954  			expectErr:  "Profile \"test\" does not permit dns type identifiers",
  1955  		},
  1956  	}
  1957  
  1958  	for _, tc := range testCases {
  1959  		t.Run(tc.name, func(t *testing.T) {
  1960  			var profile validationProfile
  1961  			profile.maxNames = 2
  1962  			profile.identifierTypes = tc.identTypes
  1963  			ra.profiles.byName = map[string]*validationProfile{
  1964  				"test": &profile,
  1965  			}
  1966  
  1967  			orderReq := &rapb.NewOrderRequest{
  1968  				RegistrationID:         registration.Id,
  1969  				Identifiers:            tc.idents,
  1970  				CertificateProfileName: "test",
  1971  			}
  1972  			_, err := ra.NewOrder(context.Background(), orderReq)
  1973  
  1974  			if tc.expectErr != "" {
  1975  				test.AssertErrorIs(t, err, berrors.RejectedIdentifier)
  1976  				test.AssertContains(t, err.Error(), tc.expectErr)
  1977  			} else {
  1978  				test.AssertNotError(t, err, "NewOrder failed")
  1979  			}
  1980  		})
  1981  	}
  1982  }
  1983  
  1984  // mockSAWithAuthzs has a GetValidAuthorizations2 method that returns the protobuf
  1985  // version of its authzs struct member. It also has a fake GetOrderForNames
  1986  // which always fails, and a fake NewOrderAndAuthzs which always succeeds, to
  1987  // facilitate the full execution of RA.NewOrder.
  1988  type mockSAWithAuthzs struct {
  1989  	sapb.StorageAuthorityClient
  1990  	authzs []*core.Authorization
  1991  }
  1992  
  1993  // GetOrderForNames is a mock which always returns NotFound so that NewOrder
  1994  // proceeds to attempt authz reuse instead of wholesale order reuse.
  1995  func (msa *mockSAWithAuthzs) GetOrderForNames(ctx context.Context, req *sapb.GetOrderForNamesRequest, _ ...grpc.CallOption) (*corepb.Order, error) {
  1996  	return nil, berrors.NotFoundError("no such order")
  1997  }
  1998  
  1999  // GetValidAuthorizations2 returns a _bizarre_ authorization for "*.zombo.com" that
  2000  // was validated by HTTP-01. This should never happen in real life since the
  2001  // name is a wildcard. We use this mock to test that we reject this bizarre
  2002  // situation correctly.
  2003  func (msa *mockSAWithAuthzs) GetValidAuthorizations2(ctx context.Context, req *sapb.GetValidAuthorizationsRequest, _ ...grpc.CallOption) (*sapb.Authorizations, error) {
  2004  	resp := &sapb.Authorizations{}
  2005  	for _, v := range msa.authzs {
  2006  		authzPB, err := bgrpc.AuthzToPB(*v)
  2007  		if err != nil {
  2008  			return nil, err
  2009  		}
  2010  		resp.Authzs = append(resp.Authzs, authzPB)
  2011  	}
  2012  	return resp, nil
  2013  }
  2014  
  2015  func (msa *mockSAWithAuthzs) GetAuthorization2(ctx context.Context, req *sapb.AuthorizationID2, _ ...grpc.CallOption) (*corepb.Authorization, error) {
  2016  	for _, authz := range msa.authzs {
  2017  		if authz.ID == fmt.Sprintf("%d", req.Id) {
  2018  			return bgrpc.AuthzToPB(*authz)
  2019  		}
  2020  	}
  2021  	return nil, berrors.NotFoundError("no such authz")
  2022  }
  2023  
  2024  // NewOrderAndAuthzs is a mock which just reflects the incoming request back,
  2025  // pretending to have created new db rows for the requested newAuthzs.
  2026  func (msa *mockSAWithAuthzs) NewOrderAndAuthzs(ctx context.Context, req *sapb.NewOrderAndAuthzsRequest, _ ...grpc.CallOption) (*corepb.Order, error) {
  2027  	authzIDs := req.NewOrder.V2Authorizations
  2028  	for range req.NewAuthzs {
  2029  		authzIDs = append(authzIDs, mrand.Int64())
  2030  	}
  2031  	return &corepb.Order{
  2032  		// Fields from the input new order request.
  2033  		RegistrationID:         req.NewOrder.RegistrationID,
  2034  		Expires:                req.NewOrder.Expires,
  2035  		Identifiers:            req.NewOrder.Identifiers,
  2036  		V2Authorizations:       authzIDs,
  2037  		CertificateProfileName: req.NewOrder.CertificateProfileName,
  2038  		// Mock new fields generated by the database transaction.
  2039  		Id:      mrand.Int64(),
  2040  		Created: timestamppb.Now(),
  2041  		// A new order is never processing because it can't have been finalized yet.
  2042  		BeganProcessing: false,
  2043  		Status:          string(core.StatusPending),
  2044  	}, nil
  2045  }
  2046  
  2047  // TestNewOrderAuthzReuseSafety checks that the RA's safety check for reusing an
  2048  // authorization for a new-order request with a wildcard name works correctly.
  2049  // We want to ensure that we never reuse a non-Wildcard authorization (e.g. one
  2050  // with more than just a DNS-01 challenge) for a wildcard name. See Issue #3420
  2051  // for background - this safety check was previously broken!
  2052  // https://github.com/letsencrypt/boulder/issues/3420
  2053  func TestNewOrderAuthzReuseSafety(t *testing.T) {
  2054  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  2055  	defer cleanUp()
  2056  
  2057  	ctx := context.Background()
  2058  	idents := identifier.ACMEIdentifiers{identifier.NewDNS("*.zombo.com")}
  2059  
  2060  	// Use a mock SA that always returns a valid HTTP-01 authz for the name
  2061  	// "zombo.com"
  2062  	expires := time.Now()
  2063  	ra.SA = &mockSAWithAuthzs{
  2064  		authzs: []*core.Authorization{
  2065  			{
  2066  				// A static fake ID we can check for in a unit test
  2067  				ID:             "1",
  2068  				Identifier:     identifier.NewDNS("*.zombo.com"),
  2069  				RegistrationID: registration.Id,
  2070  				// Authz is valid
  2071  				Status:  "valid",
  2072  				Expires: &expires,
  2073  				Challenges: []core.Challenge{
  2074  					// HTTP-01 challenge is valid
  2075  					{
  2076  						Type:   core.ChallengeTypeHTTP01, // The dreaded HTTP-01! X__X
  2077  						Status: core.StatusValid,
  2078  						Token:  core.NewToken(),
  2079  					},
  2080  					// DNS-01 challenge is pending
  2081  					{
  2082  						Type:   core.ChallengeTypeDNS01,
  2083  						Status: core.StatusPending,
  2084  						Token:  core.NewToken(),
  2085  					},
  2086  				},
  2087  			},
  2088  			{
  2089  				// A static fake ID we can check for in a unit test
  2090  				ID:             "2",
  2091  				Identifier:     identifier.NewDNS("zombo.com"),
  2092  				RegistrationID: registration.Id,
  2093  				// Authz is valid
  2094  				Status:  "valid",
  2095  				Expires: &expires,
  2096  				Challenges: []core.Challenge{
  2097  					// HTTP-01 challenge is valid
  2098  					{
  2099  						Type:   core.ChallengeTypeHTTP01,
  2100  						Status: core.StatusValid,
  2101  						Token:  core.NewToken(),
  2102  					},
  2103  					// DNS-01 challenge is pending
  2104  					{
  2105  						Type:   core.ChallengeTypeDNS01,
  2106  						Status: core.StatusPending,
  2107  						Token:  core.NewToken(),
  2108  					},
  2109  				},
  2110  			},
  2111  		},
  2112  	}
  2113  
  2114  	// Create an initial request with regA and names
  2115  	orderReq := &rapb.NewOrderRequest{
  2116  		RegistrationID: registration.Id,
  2117  		Identifiers:    idents.ToProtoSlice(),
  2118  	}
  2119  
  2120  	// Create an order for that request
  2121  	_, err := ra.NewOrder(ctx, orderReq)
  2122  	// It should fail
  2123  	test.AssertError(t, err, "Added an initial order for regA with invalid challenge(s)")
  2124  	test.AssertContains(t, err.Error(), "SA.GetAuthorizations returned a DNS wildcard authz (1) with invalid challenge(s)")
  2125  }
  2126  
  2127  func TestNewOrderWildcard(t *testing.T) {
  2128  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  2129  	defer cleanUp()
  2130  
  2131  	orderIdents := identifier.ACMEIdentifiers{
  2132  		identifier.NewDNS("example.com"),
  2133  		identifier.NewDNS("*.welcome.zombo.com"),
  2134  	}
  2135  	wildcardOrderRequest := &rapb.NewOrderRequest{
  2136  		RegistrationID: registration.Id,
  2137  		Identifiers:    orderIdents.ToProtoSlice(),
  2138  	}
  2139  
  2140  	order, err := ra.NewOrder(context.Background(), wildcardOrderRequest)
  2141  	test.AssertNotError(t, err, "NewOrder failed for a wildcard order request")
  2142  
  2143  	// We expect the order to be pending
  2144  	test.AssertEquals(t, order.Status, string(core.StatusPending))
  2145  	// We expect the order to have two identifiers
  2146  	test.AssertEquals(t, len(order.Identifiers), 2)
  2147  
  2148  	// We expect the order to have the identifiers we requested
  2149  	test.AssertDeepEquals(t,
  2150  		identifier.Normalize(identifier.FromProtoSlice(order.Identifiers)),
  2151  		identifier.Normalize(orderIdents))
  2152  	test.AssertEquals(t, numAuthorizations(order), 2)
  2153  
  2154  	// Check each of the authz IDs in the order
  2155  	for _, authzID := range order.V2Authorizations {
  2156  		// We should be able to retrieve the authz from the db without error
  2157  		authzPB, err := ra.SA.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: authzID})
  2158  		test.AssertNotError(t, err, "sa.GetAuthorization2 failed")
  2159  		authz, err := bgrpc.PBToAuthz(authzPB)
  2160  		test.AssertNotError(t, err, "bgrpc.PBToAuthz failed")
  2161  
  2162  		// We expect the authz is in Pending status
  2163  		test.AssertEquals(t, authz.Status, core.StatusPending)
  2164  
  2165  		name := authz.Identifier.Value
  2166  		switch name {
  2167  		case "*.welcome.zombo.com":
  2168  			// If the authz is for *.welcome.zombo.com, we expect that it only has one
  2169  			// pending challenge with DNS-01 type
  2170  			test.AssertEquals(t, len(authz.Challenges), 1)
  2171  			test.AssertEquals(t, authz.Challenges[0].Status, core.StatusPending)
  2172  			test.AssertEquals(t, authz.Challenges[0].Type, core.ChallengeTypeDNS01)
  2173  		case "example.com":
  2174  			// If the authz is for example.com, we expect it has normal challenges
  2175  			test.AssertEquals(t, len(authz.Challenges), 3)
  2176  		default:
  2177  			t.Fatalf("Received an authorization for a name not requested: %q", name)
  2178  		}
  2179  	}
  2180  
  2181  	// An order for a base domain and a wildcard for the same base domain should
  2182  	// return just 2 authz's, one for the wildcard with a DNS-01
  2183  	// challenge and one for the base domain with the normal challenges.
  2184  	orderIdents = identifier.ACMEIdentifiers{
  2185  		identifier.NewDNS("zombo.com"),
  2186  		identifier.NewDNS("*.zombo.com"),
  2187  	}
  2188  	wildcardOrderRequest = &rapb.NewOrderRequest{
  2189  		RegistrationID: registration.Id,
  2190  		Identifiers:    orderIdents.ToProtoSlice(),
  2191  	}
  2192  	order, err = ra.NewOrder(context.Background(), wildcardOrderRequest)
  2193  	test.AssertNotError(t, err, "NewOrder failed for a wildcard order request")
  2194  
  2195  	// We expect the order to be pending
  2196  	test.AssertEquals(t, order.Status, string(core.StatusPending))
  2197  	// We expect the order to have two identifiers
  2198  	test.AssertEquals(t, len(order.Identifiers), 2)
  2199  	// We expect the order to have the identifiers we requested
  2200  	test.AssertDeepEquals(t,
  2201  		identifier.Normalize(identifier.FromProtoSlice(order.Identifiers)),
  2202  		identifier.Normalize(orderIdents))
  2203  	test.AssertEquals(t, numAuthorizations(order), 2)
  2204  
  2205  	for _, authzID := range order.V2Authorizations {
  2206  		// We should be able to retrieve the authz from the db without error
  2207  		authzPB, err := ra.SA.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: authzID})
  2208  		test.AssertNotError(t, err, "sa.GetAuthorization2 failed")
  2209  		authz, err := bgrpc.PBToAuthz(authzPB)
  2210  		test.AssertNotError(t, err, "bgrpc.PBToAuthz failed")
  2211  		// We expect the authz is in Pending status
  2212  		test.AssertEquals(t, authz.Status, core.StatusPending)
  2213  		switch authz.Identifier.Value {
  2214  		case "zombo.com":
  2215  			// We expect that the base domain identifier auth has the normal number of
  2216  			// challenges
  2217  			test.AssertEquals(t, len(authz.Challenges), 3)
  2218  		case "*.zombo.com":
  2219  			// We expect that the wildcard identifier auth has only a pending
  2220  			// DNS-01 type challenge
  2221  			test.AssertEquals(t, len(authz.Challenges), 1)
  2222  			test.AssertEquals(t, authz.Challenges[0].Status, core.StatusPending)
  2223  			test.AssertEquals(t, authz.Challenges[0].Type, core.ChallengeTypeDNS01)
  2224  		default:
  2225  			t.Fatal("Unexpected authorization value returned from new-order")
  2226  		}
  2227  	}
  2228  
  2229  	// Make an order for a single domain, no wildcards. This will create a new
  2230  	// pending authz for the domain
  2231  	normalOrderReq := &rapb.NewOrderRequest{
  2232  		RegistrationID: registration.Id,
  2233  		Identifiers:    []*corepb.Identifier{identifier.NewDNS("everything.is.possible.zombo.com").ToProto()},
  2234  	}
  2235  	normalOrder, err := ra.NewOrder(context.Background(), normalOrderReq)
  2236  	test.AssertNotError(t, err, "NewOrder failed for a normal non-wildcard order")
  2237  
  2238  	test.AssertEquals(t, numAuthorizations(normalOrder), 1)
  2239  	// We expect the order is in Pending status
  2240  	test.AssertEquals(t, order.Status, string(core.StatusPending))
  2241  	var authz core.Authorization
  2242  	authzPB, err := ra.SA.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: normalOrder.V2Authorizations[0]})
  2243  	test.AssertNotError(t, err, "sa.GetAuthorization2 failed")
  2244  	authz, err = bgrpc.PBToAuthz(authzPB)
  2245  	test.AssertNotError(t, err, "bgrpc.PBToAuthz failed")
  2246  	// We expect the authz is in Pending status
  2247  	test.AssertEquals(t, authz.Status, core.StatusPending)
  2248  	// We expect the authz is for the identifier the correct domain
  2249  	test.AssertEquals(t, authz.Identifier.Value, "everything.is.possible.zombo.com")
  2250  	// We expect the authz has the normal # of challenges
  2251  	test.AssertEquals(t, len(authz.Challenges), 3)
  2252  
  2253  	// Now submit an order request for a wildcard of the domain we just created an
  2254  	// order for. We should **NOT** reuse the authorization from the previous
  2255  	// order since we now require a DNS-01 challenge for the `*.` prefixed name.
  2256  	orderIdents = identifier.ACMEIdentifiers{identifier.NewDNS("*.everything.is.possible.zombo.com")}
  2257  	wildcardOrderRequest = &rapb.NewOrderRequest{
  2258  		RegistrationID: registration.Id,
  2259  		Identifiers:    orderIdents.ToProtoSlice(),
  2260  	}
  2261  	order, err = ra.NewOrder(context.Background(), wildcardOrderRequest)
  2262  	test.AssertNotError(t, err, "NewOrder failed for a wildcard order request")
  2263  	// We expect the order is in Pending status
  2264  	test.AssertEquals(t, order.Status, string(core.StatusPending))
  2265  	test.AssertEquals(t, numAuthorizations(order), 1)
  2266  	// The authz should be a different ID than the previous authz
  2267  	test.AssertNotEquals(t, order.V2Authorizations[0], normalOrder.V2Authorizations[0])
  2268  	// We expect the authorization is available
  2269  	authzPB, err = ra.SA.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: order.V2Authorizations[0]})
  2270  	test.AssertNotError(t, err, "sa.GetAuthorization2 failed")
  2271  	authz, err = bgrpc.PBToAuthz(authzPB)
  2272  	test.AssertNotError(t, err, "bgrpc.PBToAuthz failed")
  2273  	// We expect the authz is in Pending status
  2274  	test.AssertEquals(t, authz.Status, core.StatusPending)
  2275  	// We expect the authz is for a identifier with the correct domain
  2276  	test.AssertEquals(t, authz.Identifier.Value, "*.everything.is.possible.zombo.com")
  2277  	// We expect the authz has only one challenge
  2278  	test.AssertEquals(t, len(authz.Challenges), 1)
  2279  	// We expect the one challenge is pending
  2280  	test.AssertEquals(t, authz.Challenges[0].Status, core.StatusPending)
  2281  	// We expect that the one challenge is a DNS01 type challenge
  2282  	test.AssertEquals(t, authz.Challenges[0].Type, core.ChallengeTypeDNS01)
  2283  
  2284  	// Submit an identical wildcard order request
  2285  	dupeOrder, err := ra.NewOrder(context.Background(), wildcardOrderRequest)
  2286  	test.AssertNotError(t, err, "NewOrder failed for a wildcard order request")
  2287  	// We expect the order is in Pending status
  2288  	test.AssertEquals(t, dupeOrder.Status, string(core.StatusPending))
  2289  	test.AssertEquals(t, numAuthorizations(dupeOrder), 1)
  2290  	// The authz should be the same ID as the previous order's authz. We already
  2291  	// checked that order.Authorizations[0] only has a DNS-01 challenge above so
  2292  	// we don't need to recheck that here.
  2293  	test.AssertEquals(t, dupeOrder.V2Authorizations[0], order.V2Authorizations[0])
  2294  }
  2295  
  2296  func TestNewOrderExpiry(t *testing.T) {
  2297  	_, _, ra, _, clk, registration, cleanUp := initAuthorities(t)
  2298  	defer cleanUp()
  2299  
  2300  	ctx := context.Background()
  2301  	idents := identifier.ACMEIdentifiers{identifier.NewDNS("zombo.com")}
  2302  
  2303  	// Set the order lifetime to 48 hours.
  2304  	ra.profiles.def().orderLifetime = 48 * time.Hour
  2305  
  2306  	// Use an expiry that is sooner than the configured order expiry but greater
  2307  	// than 24 hours away.
  2308  	fakeAuthzExpires := clk.Now().Add(35 * time.Hour)
  2309  
  2310  	// Use a mock SA that always returns a soon-to-be-expired valid authz for
  2311  	// "zombo.com".
  2312  	ra.SA = &mockSAWithAuthzs{
  2313  		authzs: []*core.Authorization{
  2314  			{
  2315  				// A static fake ID we can check for in a unit test
  2316  				ID:             "1",
  2317  				Identifier:     identifier.NewDNS("zombo.com"),
  2318  				RegistrationID: registration.Id,
  2319  				Expires:        &fakeAuthzExpires,
  2320  				Status:         "valid",
  2321  				Challenges: []core.Challenge{
  2322  					{
  2323  						Type:   core.ChallengeTypeHTTP01,
  2324  						Status: core.StatusValid,
  2325  						Token:  core.NewToken(),
  2326  					},
  2327  				},
  2328  			},
  2329  		},
  2330  	}
  2331  
  2332  	// Create an initial request with regA and names
  2333  	orderReq := &rapb.NewOrderRequest{
  2334  		RegistrationID: registration.Id,
  2335  		Identifiers:    idents.ToProtoSlice(),
  2336  	}
  2337  
  2338  	// Create an order for that request
  2339  	order, err := ra.NewOrder(ctx, orderReq)
  2340  	// It shouldn't fail
  2341  	test.AssertNotError(t, err, "Adding an order for regA failed")
  2342  	test.AssertEquals(t, numAuthorizations(order), 1)
  2343  	// It should be the fake near-expired-authz authz
  2344  	test.AssertEquals(t, order.V2Authorizations[0], int64(1))
  2345  	// The order's expiry should be the fake authz's expiry since it is sooner
  2346  	// than the order's own expiry.
  2347  	test.AssertEquals(t, order.Expires.AsTime(), fakeAuthzExpires)
  2348  
  2349  	// Set the order lifetime to be lower than the fakeAuthzLifetime
  2350  	ra.profiles.def().orderLifetime = 12 * time.Hour
  2351  	expectedOrderExpiry := clk.Now().Add(12 * time.Hour)
  2352  	// Create the order again
  2353  	order, err = ra.NewOrder(ctx, orderReq)
  2354  	// It shouldn't fail
  2355  	test.AssertNotError(t, err, "Adding an order for regA failed")
  2356  	test.AssertEquals(t, numAuthorizations(order), 1)
  2357  	// It should be the fake near-expired-authz authz
  2358  	test.AssertEquals(t, order.V2Authorizations[0], int64(1))
  2359  	// The order's expiry should be the order's own expiry since it is sooner than
  2360  	// the fake authz's expiry.
  2361  	test.AssertEquals(t, order.Expires.AsTime(), expectedOrderExpiry)
  2362  }
  2363  
  2364  func TestFinalizeOrder(t *testing.T) {
  2365  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
  2366  	defer cleanUp()
  2367  
  2368  	// Create one finalized authorization for not-example.com and one finalized
  2369  	// authorization for www.not-example.org
  2370  	now := ra.clk.Now()
  2371  	exp := now.Add(365 * 24 * time.Hour)
  2372  	authzIDA := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("not-example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
  2373  	authzIDB := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("www.not-example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
  2374  
  2375  	testKey, err := rsa.GenerateKey(rand.Reader, 2048)
  2376  	test.AssertNotError(t, err, "error generating test key")
  2377  
  2378  	policyForbidCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2379  		PublicKey:          testKey.PublicKey,
  2380  		SignatureAlgorithm: x509.SHA256WithRSA,
  2381  		DNSNames:           []string{"example.org"},
  2382  	}, testKey)
  2383  	test.AssertNotError(t, err, "Error creating policy forbid CSR")
  2384  
  2385  	oneDomainCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2386  		PublicKey:          testKey.PublicKey,
  2387  		SignatureAlgorithm: x509.SHA256WithRSA,
  2388  		DNSNames:           []string{"a.com"},
  2389  	}, testKey)
  2390  	test.AssertNotError(t, err, "Error creating CSR with one DNS name")
  2391  
  2392  	twoDomainCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2393  		PublicKey:          testKey.PublicKey,
  2394  		SignatureAlgorithm: x509.SHA256WithRSA,
  2395  		DNSNames:           []string{"a.com", "b.com"},
  2396  	}, testKey)
  2397  	test.AssertNotError(t, err, "Error creating CSR with two DNS names")
  2398  
  2399  	validCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2400  		PublicKey:          testKey.Public(),
  2401  		SignatureAlgorithm: x509.SHA256WithRSA,
  2402  		DNSNames:           []string{"not-example.com", "www.not-example.com"},
  2403  	}, testKey)
  2404  	test.AssertNotError(t, err, "Error creating CSR with authorized names")
  2405  
  2406  	expectedCert := &x509.Certificate{
  2407  		SerialNumber:          big.NewInt(0),
  2408  		Subject:               pkix.Name{CommonName: "not-example.com"},
  2409  		DNSNames:              []string{"not-example.com", "www.not-example.com"},
  2410  		PublicKey:             testKey.Public(),
  2411  		NotBefore:             now,
  2412  		BasicConstraintsValid: true,
  2413  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  2414  	}
  2415  	certDER, err := x509.CreateCertificate(rand.Reader, expectedCert, expectedCert, testKey.Public(), testKey)
  2416  	test.AssertNotError(t, err, "failed to construct test certificate")
  2417  	ra.CA.(*mocks.MockCA).PEM = pem.EncodeToMemory(&pem.Block{Bytes: certDER, Type: "CERTIFICATE"})
  2418  
  2419  	fakeRegID := int64(0xB00)
  2420  
  2421  	// NOTE(@cpu): We use unique `names` for each of these orders because
  2422  	// otherwise only *one* order is created & reused. The first test case to
  2423  	// finalize the order will put it into processing state and the other tests
  2424  	// will fail because you can't finalize an order that is already being
  2425  	// processed.
  2426  	// Add a new order for the fake reg ID
  2427  	fakeRegOrder, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  2428  		RegistrationID: registration.Id,
  2429  		Identifiers:    []*corepb.Identifier{identifier.NewDNS("001.example.com").ToProto()},
  2430  	})
  2431  	test.AssertNotError(t, err, "Could not add test order for fake reg ID order ID")
  2432  
  2433  	missingAuthzOrder, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  2434  		RegistrationID: registration.Id,
  2435  		Identifiers:    []*corepb.Identifier{identifier.NewDNS("002.example.com").ToProto()},
  2436  	})
  2437  	test.AssertNotError(t, err, "Could not add test order for missing authz order ID")
  2438  
  2439  	validatedOrder, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{
  2440  		NewOrder: &sapb.NewOrderRequest{
  2441  			RegistrationID: registration.Id,
  2442  			Expires:        timestamppb.New(exp),
  2443  			Identifiers: []*corepb.Identifier{
  2444  				identifier.NewDNS("not-example.com").ToProto(),
  2445  				identifier.NewDNS("www.not-example.com").ToProto(),
  2446  			},
  2447  			V2Authorizations: []int64{authzIDA, authzIDB},
  2448  		},
  2449  	})
  2450  	test.AssertNotError(t, err, "Could not add test order with finalized authz IDs, ready status")
  2451  
  2452  	testCases := []struct {
  2453  		Name           string
  2454  		OrderReq       *rapb.FinalizeOrderRequest
  2455  		ExpectedErrMsg string
  2456  		ExpectIssuance bool
  2457  	}{
  2458  		{
  2459  			Name: "No id in order",
  2460  			OrderReq: &rapb.FinalizeOrderRequest{
  2461  				Order: &corepb.Order{},
  2462  				Csr:   oneDomainCSR,
  2463  			},
  2464  			ExpectedErrMsg: "invalid order ID: 0",
  2465  		},
  2466  		{
  2467  			Name: "No account id in order",
  2468  			OrderReq: &rapb.FinalizeOrderRequest{
  2469  				Order: &corepb.Order{
  2470  					Id: 1,
  2471  				},
  2472  				Csr: oneDomainCSR,
  2473  			},
  2474  			ExpectedErrMsg: "invalid account ID: 0",
  2475  		},
  2476  		{
  2477  			Name: "No names in order",
  2478  			OrderReq: &rapb.FinalizeOrderRequest{
  2479  				Order: &corepb.Order{
  2480  					Id:             1,
  2481  					RegistrationID: 1,
  2482  					Status:         string(core.StatusReady),
  2483  					Identifiers:    []*corepb.Identifier{},
  2484  				},
  2485  				Csr: oneDomainCSR,
  2486  			},
  2487  			ExpectedErrMsg: "Order has no associated identifiers",
  2488  		},
  2489  		{
  2490  			Name: "Wrong order state (valid)",
  2491  			OrderReq: &rapb.FinalizeOrderRequest{
  2492  				Order: &corepb.Order{
  2493  					Id:             1,
  2494  					RegistrationID: 1,
  2495  					Status:         string(core.StatusValid),
  2496  					Identifiers:    []*corepb.Identifier{identifier.NewDNS("a.com").ToProto()},
  2497  				},
  2498  				Csr: oneDomainCSR,
  2499  			},
  2500  			ExpectedErrMsg: `Order's status ("valid") is not acceptable for finalization`,
  2501  		},
  2502  		{
  2503  			Name: "Wrong order state (pending)",
  2504  			OrderReq: &rapb.FinalizeOrderRequest{
  2505  				Order: &corepb.Order{
  2506  					Id:             1,
  2507  					RegistrationID: 1,
  2508  					Status:         string(core.StatusPending),
  2509  					Identifiers:    []*corepb.Identifier{identifier.NewDNS("a.com").ToProto()},
  2510  				},
  2511  				Csr: oneDomainCSR,
  2512  			},
  2513  			ExpectIssuance: false,
  2514  			ExpectedErrMsg: `Order's status ("pending") is not acceptable for finalization`,
  2515  		},
  2516  		{
  2517  			Name: "Invalid CSR",
  2518  			OrderReq: &rapb.FinalizeOrderRequest{
  2519  				Order: &corepb.Order{
  2520  					Id:             1,
  2521  					RegistrationID: 1,
  2522  					Status:         string(core.StatusReady),
  2523  					Identifiers:    []*corepb.Identifier{identifier.NewDNS("a.com").ToProto()},
  2524  				},
  2525  				Csr: []byte{0xC0, 0xFF, 0xEE},
  2526  			},
  2527  			ExpectedErrMsg: "unable to parse CSR: asn1: syntax error: truncated tag or length",
  2528  		},
  2529  		{
  2530  			Name: "CSR and Order with diff number of names",
  2531  			OrderReq: &rapb.FinalizeOrderRequest{
  2532  				Order: &corepb.Order{
  2533  					Id:             1,
  2534  					RegistrationID: 1,
  2535  					Status:         string(core.StatusReady),
  2536  					Identifiers: []*corepb.Identifier{
  2537  						identifier.NewDNS("a.com").ToProto(),
  2538  						identifier.NewDNS("b.com").ToProto(),
  2539  					},
  2540  				},
  2541  				Csr: oneDomainCSR,
  2542  			},
  2543  			ExpectedErrMsg: "CSR does not specify same identifiers as Order",
  2544  		},
  2545  		{
  2546  			Name: "CSR and Order with diff number of names (other way)",
  2547  			OrderReq: &rapb.FinalizeOrderRequest{
  2548  				Order: &corepb.Order{
  2549  					Id:             1,
  2550  					RegistrationID: 1,
  2551  					Status:         string(core.StatusReady),
  2552  					Identifiers:    []*corepb.Identifier{identifier.NewDNS("a.com").ToProto()},
  2553  				},
  2554  				Csr: twoDomainCSR,
  2555  			},
  2556  			ExpectedErrMsg: "CSR does not specify same identifiers as Order",
  2557  		},
  2558  		{
  2559  			Name: "CSR missing an order name",
  2560  			OrderReq: &rapb.FinalizeOrderRequest{
  2561  				Order: &corepb.Order{
  2562  					Id:             1,
  2563  					RegistrationID: 1,
  2564  					Status:         string(core.StatusReady),
  2565  					Identifiers:    []*corepb.Identifier{identifier.NewDNS("foobar.com").ToProto()},
  2566  				},
  2567  				Csr: oneDomainCSR,
  2568  			},
  2569  			ExpectedErrMsg: "CSR does not specify same identifiers as Order",
  2570  		},
  2571  		{
  2572  			Name: "CSR with policy forbidden name",
  2573  			OrderReq: &rapb.FinalizeOrderRequest{
  2574  				Order: &corepb.Order{
  2575  					Id:                1,
  2576  					RegistrationID:    1,
  2577  					Status:            string(core.StatusReady),
  2578  					Identifiers:       []*corepb.Identifier{identifier.NewDNS("example.org").ToProto()},
  2579  					Expires:           timestamppb.New(exp),
  2580  					CertificateSerial: "",
  2581  					BeganProcessing:   false,
  2582  				},
  2583  				Csr: policyForbidCSR,
  2584  			},
  2585  			ExpectedErrMsg: "Cannot issue for \"example.org\": The ACME server refuses to issue a certificate for this domain name, because it is forbidden by policy",
  2586  		},
  2587  		{
  2588  			Name: "Order with missing registration",
  2589  			OrderReq: &rapb.FinalizeOrderRequest{
  2590  				Order: &corepb.Order{
  2591  					Status:            string(core.StatusReady),
  2592  					Identifiers:       []*corepb.Identifier{identifier.NewDNS("a.com").ToProto()},
  2593  					Id:                fakeRegOrder.Id,
  2594  					RegistrationID:    fakeRegID,
  2595  					Expires:           timestamppb.New(exp),
  2596  					CertificateSerial: "",
  2597  					BeganProcessing:   false,
  2598  					Created:           timestamppb.New(now),
  2599  				},
  2600  				Csr: oneDomainCSR,
  2601  			},
  2602  			ExpectedErrMsg: fmt.Sprintf("registration with ID '%d' not found", fakeRegID),
  2603  		},
  2604  		{
  2605  			Name: "Order with missing authorizations",
  2606  			OrderReq: &rapb.FinalizeOrderRequest{
  2607  				Order: &corepb.Order{
  2608  					Status: string(core.StatusReady),
  2609  					Identifiers: []*corepb.Identifier{
  2610  						identifier.NewDNS("a.com").ToProto(),
  2611  						identifier.NewDNS("b.com").ToProto(),
  2612  					},
  2613  					Id:                missingAuthzOrder.Id,
  2614  					RegistrationID:    registration.Id,
  2615  					Expires:           timestamppb.New(exp),
  2616  					CertificateSerial: "",
  2617  					BeganProcessing:   false,
  2618  					Created:           timestamppb.New(now),
  2619  				},
  2620  				Csr: twoDomainCSR,
  2621  			},
  2622  			ExpectedErrMsg: "authorizations for these identifiers not found: a.com, b.com",
  2623  		},
  2624  		{
  2625  			Name: "Order with correct authorizations, ready status",
  2626  			OrderReq: &rapb.FinalizeOrderRequest{
  2627  				Order: validatedOrder,
  2628  				Csr:   validCSR,
  2629  			},
  2630  			ExpectIssuance: true,
  2631  		},
  2632  	}
  2633  
  2634  	for _, tc := range testCases {
  2635  		t.Run(tc.Name, func(t *testing.T) {
  2636  			_, result := ra.FinalizeOrder(context.Background(), tc.OrderReq)
  2637  			// If we don't expect issuance we expect an error
  2638  			if !tc.ExpectIssuance {
  2639  				// Check that the error happened and the message matches expected
  2640  				test.AssertError(t, result, "FinalizeOrder did not fail when expected to")
  2641  				test.AssertEquals(t, result.Error(), tc.ExpectedErrMsg)
  2642  			} else {
  2643  				// Otherwise we expect an issuance and no error
  2644  				test.AssertNotError(t, result, fmt.Sprintf("FinalizeOrder result was %#v, expected nil", result))
  2645  				// Check that the order now has a serial for the issued certificate
  2646  				updatedOrder, err := sa.GetOrder(
  2647  					context.Background(),
  2648  					&sapb.OrderRequest{Id: tc.OrderReq.Order.Id})
  2649  				test.AssertNotError(t, err, "Error getting order to check serial")
  2650  				test.AssertNotEquals(t, updatedOrder.CertificateSerial, "")
  2651  				test.AssertEquals(t, updatedOrder.Status, "valid")
  2652  				test.AssertEquals(t, updatedOrder.Expires.AsTime(), exp)
  2653  			}
  2654  		})
  2655  	}
  2656  }
  2657  
  2658  func TestFinalizeOrderWithMixedSANAndCN(t *testing.T) {
  2659  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
  2660  	defer cleanUp()
  2661  
  2662  	// Pick an expiry in the future
  2663  	now := ra.clk.Now()
  2664  	exp := now.Add(365 * 24 * time.Hour)
  2665  
  2666  	// Create one finalized authorization for the registration for not-example.com and
  2667  	// one finalized authorization for www.not-example.org
  2668  	authzIDA := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("not-example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
  2669  	authzIDB := createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("www.not-example.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
  2670  
  2671  	// Create a new order to finalize with names in SAN and CN
  2672  	mixedOrder, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{
  2673  		NewOrder: &sapb.NewOrderRequest{
  2674  			RegistrationID: registration.Id,
  2675  			Expires:        timestamppb.New(exp),
  2676  			Identifiers: []*corepb.Identifier{
  2677  				identifier.NewDNS("not-example.com").ToProto(),
  2678  				identifier.NewDNS("www.not-example.com").ToProto(),
  2679  			},
  2680  			V2Authorizations: []int64{authzIDA, authzIDB},
  2681  		},
  2682  	})
  2683  	test.AssertNotError(t, err, "Could not add test order with finalized authz IDs")
  2684  	testKey, err := rsa.GenerateKey(rand.Reader, 2048)
  2685  	test.AssertNotError(t, err, "error generating test key")
  2686  	mixedCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2687  		PublicKey:          testKey.PublicKey,
  2688  		SignatureAlgorithm: x509.SHA256WithRSA,
  2689  		Subject:            pkix.Name{CommonName: "not-example.com"},
  2690  		DNSNames:           []string{"www.not-example.com"},
  2691  	}, testKey)
  2692  	test.AssertNotError(t, err, "Could not create mixed CSR")
  2693  
  2694  	template := &x509.Certificate{
  2695  		SerialNumber:          big.NewInt(12),
  2696  		Subject:               pkix.Name{CommonName: "not-example.com"},
  2697  		DNSNames:              []string{"www.not-example.com", "not-example.com"},
  2698  		NotBefore:             time.Now(),
  2699  		BasicConstraintsValid: true,
  2700  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  2701  	}
  2702  	cert, err := x509.CreateCertificate(rand.Reader, template, template, testKey.Public(), testKey)
  2703  	test.AssertNotError(t, err, "Failed to create mixed cert")
  2704  
  2705  	ra.CA = &mocks.MockCA{
  2706  		PEM: pem.EncodeToMemory(&pem.Block{
  2707  			Bytes: cert,
  2708  		}),
  2709  	}
  2710  
  2711  	_, result := ra.FinalizeOrder(context.Background(), &rapb.FinalizeOrderRequest{Order: mixedOrder, Csr: mixedCSR})
  2712  	test.AssertNotError(t, result, "FinalizeOrder failed")
  2713  	// Check that the order now has a serial for the issued certificate
  2714  	updatedOrder, err := sa.GetOrder(
  2715  		context.Background(),
  2716  		&sapb.OrderRequest{Id: mixedOrder.Id})
  2717  	test.AssertNotError(t, err, "Error getting order to check serial")
  2718  	test.AssertNotEquals(t, updatedOrder.CertificateSerial, "")
  2719  	test.AssertEquals(t, updatedOrder.Status, "valid")
  2720  }
  2721  
  2722  func TestFinalizeOrderWildcard(t *testing.T) {
  2723  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
  2724  	defer cleanUp()
  2725  
  2726  	// Pick an expiry in the future
  2727  	now := ra.clk.Now()
  2728  	exp := now.Add(365 * 24 * time.Hour)
  2729  
  2730  	testKey, err := rsa.GenerateKey(rand.Reader, 2048)
  2731  	test.AssertNotError(t, err, "Error creating test RSA key")
  2732  	wildcardCSR, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2733  		PublicKey:          testKey.PublicKey,
  2734  		SignatureAlgorithm: x509.SHA256WithRSA,
  2735  		DNSNames:           []string{"*.zombo.com"},
  2736  	}, testKey)
  2737  	test.AssertNotError(t, err, "Error creating CSR with wildcard DNS name")
  2738  
  2739  	template := &x509.Certificate{
  2740  		SerialNumber:          big.NewInt(1337),
  2741  		NotBefore:             time.Now(),
  2742  		NotAfter:              time.Now().AddDate(0, 0, 1),
  2743  		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  2744  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  2745  		BasicConstraintsValid: true,
  2746  		Subject:               pkix.Name{CommonName: "*.zombo.com"},
  2747  		DNSNames:              []string{"*.zombo.com"},
  2748  	}
  2749  
  2750  	certBytes, err := x509.CreateCertificate(rand.Reader, template, template, testKey.Public(), testKey)
  2751  	test.AssertNotError(t, err, "Error creating test certificate")
  2752  
  2753  	certPEM := pem.EncodeToMemory(&pem.Block{
  2754  		Type:  "CERTIFICATE",
  2755  		Bytes: certBytes,
  2756  	})
  2757  
  2758  	// Set up a mock CA capable of giving back a cert for the wildcardCSR above
  2759  	ca := &mocks.MockCA{
  2760  		PEM: certPEM,
  2761  	}
  2762  	ra.CA = ca
  2763  
  2764  	// Create a new order for a wildcard domain
  2765  	orderIdents := identifier.ACMEIdentifiers{identifier.NewDNS("*.zombo.com")}
  2766  	test.AssertNotError(t, err, "Converting identifiers to DNS names")
  2767  	wildcardOrderRequest := &rapb.NewOrderRequest{
  2768  		RegistrationID: registration.Id,
  2769  		Identifiers:    orderIdents.ToProtoSlice(),
  2770  	}
  2771  	order, err := ra.NewOrder(context.Background(), wildcardOrderRequest)
  2772  	test.AssertNotError(t, err, "NewOrder failed for wildcard domain order")
  2773  
  2774  	// Create one standard finalized authorization for the registration for zombo.com
  2775  	_ = createFinalizedAuthorization(t, sa, registration.Id, identifier.NewDNS("zombo.com"), exp, core.ChallengeTypeHTTP01, ra.clk.Now())
  2776  
  2777  	// Finalizing the order should *not* work since the existing validated authz
  2778  	// is not a special DNS-01-Wildcard challenge authz, so the order will be
  2779  	// "pending" not "ready".
  2780  	finalizeReq := &rapb.FinalizeOrderRequest{
  2781  		Order: order,
  2782  		Csr:   wildcardCSR,
  2783  	}
  2784  	_, err = ra.FinalizeOrder(context.Background(), finalizeReq)
  2785  	test.AssertError(t, err, "FinalizeOrder did not fail for unauthorized "+
  2786  		"wildcard order")
  2787  	test.AssertEquals(t, err.Error(),
  2788  		`Order's status ("pending") is not acceptable for finalization`)
  2789  
  2790  	// Creating another order for the wildcard name
  2791  	validOrder, err := ra.NewOrder(context.Background(), wildcardOrderRequest)
  2792  	test.AssertNotError(t, err, "NewOrder failed for wildcard domain order")
  2793  	test.AssertEquals(t, numAuthorizations(validOrder), 1)
  2794  	// We expect to be able to get the authorization by ID
  2795  	_, err = sa.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: validOrder.V2Authorizations[0]})
  2796  	test.AssertNotError(t, err, "sa.GetAuthorization2 failed")
  2797  
  2798  	// Finalize the authorization with the challenge validated
  2799  	expires := now.Add(time.Hour * 24 * 7)
  2800  	_, err = sa.FinalizeAuthorization2(ctx, &sapb.FinalizeAuthorizationRequest{
  2801  		Id:          validOrder.V2Authorizations[0],
  2802  		Status:      string(core.StatusValid),
  2803  		Expires:     timestamppb.New(expires),
  2804  		Attempted:   string(core.ChallengeTypeDNS01),
  2805  		AttemptedAt: timestamppb.New(now),
  2806  	})
  2807  	test.AssertNotError(t, err, "sa.FinalizeAuthorization2 failed")
  2808  
  2809  	// Refresh the order so the SA sets its status
  2810  	validOrder, err = sa.GetOrder(ctx, &sapb.OrderRequest{
  2811  		Id: validOrder.Id,
  2812  	})
  2813  	test.AssertNotError(t, err, "Could not refresh valid order from SA")
  2814  
  2815  	// Now it should be possible to finalize the order
  2816  	finalizeReq = &rapb.FinalizeOrderRequest{
  2817  		Order: validOrder,
  2818  		Csr:   wildcardCSR,
  2819  	}
  2820  	_, err = ra.FinalizeOrder(context.Background(), finalizeReq)
  2821  	test.AssertNotError(t, err, "FinalizeOrder failed for authorized "+
  2822  		"wildcard order")
  2823  }
  2824  
  2825  func TestFinalizeOrderDisabledChallenge(t *testing.T) {
  2826  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
  2827  	defer cleanUp()
  2828  
  2829  	domain := randomDomain()
  2830  	ident := identifier.NewDNS(domain)
  2831  
  2832  	// Create a finalized authorization for that domain
  2833  	authzID := createFinalizedAuthorization(
  2834  		t, sa, registration.Id, ident, fc.Now().Add(24*time.Hour), core.ChallengeTypeHTTP01, fc.Now().Add(-1*time.Hour))
  2835  
  2836  	// Create an order that reuses that authorization
  2837  	order, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  2838  		RegistrationID: registration.Id,
  2839  		Identifiers:    []*corepb.Identifier{ident.ToProto()},
  2840  	})
  2841  	test.AssertNotError(t, err, "creating test order")
  2842  	test.AssertEquals(t, order.V2Authorizations[0], authzID)
  2843  
  2844  	// Create a CSR for this order
  2845  	testKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2846  	test.AssertNotError(t, err, "generating test key")
  2847  	csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2848  		PublicKey: testKey.PublicKey,
  2849  		DNSNames:  []string{domain},
  2850  	}, testKey)
  2851  	test.AssertNotError(t, err, "Error creating policy forbid CSR")
  2852  
  2853  	// Replace the Policy Authority with one which has this challenge type disabled
  2854  	pa, err := policy.New(
  2855  		map[identifier.IdentifierType]bool{
  2856  			identifier.TypeDNS: true,
  2857  			identifier.TypeIP:  true,
  2858  		},
  2859  		map[core.AcmeChallenge]bool{
  2860  			core.ChallengeTypeDNS01:     true,
  2861  			core.ChallengeTypeTLSALPN01: true,
  2862  		},
  2863  		ra.log)
  2864  	test.AssertNotError(t, err, "creating test PA")
  2865  	err = pa.LoadIdentPolicyFile("../test/ident-policy.yaml")
  2866  	test.AssertNotError(t, err, "loading test identifier policy")
  2867  	ra.PA = pa
  2868  
  2869  	// Now finalizing this order should fail
  2870  	_, err = ra.FinalizeOrder(context.Background(), &rapb.FinalizeOrderRequest{
  2871  		Order: order,
  2872  		Csr:   csr,
  2873  	})
  2874  	test.AssertError(t, err, "finalization should fail")
  2875  
  2876  	// Unfortunately we can't test for the PA's "which is now disabled" error
  2877  	// message directly, because the RA discards it and collects all invalid names
  2878  	// into a single more generic error message. But it does at least distinguish
  2879  	// between missing, expired, and invalid, so we can test for "invalid".
  2880  	test.AssertContains(t, err.Error(), "authorizations for these identifiers not valid")
  2881  }
  2882  
  2883  func TestFinalizeWithMustStaple(t *testing.T) {
  2884  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
  2885  	defer cleanUp()
  2886  
  2887  	ocspMustStapleExt := pkix.Extension{
  2888  		// RFC 7633: id-pe-tlsfeature OBJECT IDENTIFIER ::=  { id-pe 24 }
  2889  		Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24},
  2890  		// ASN.1 encoding of:
  2891  		// SEQUENCE
  2892  		//   INTEGER 5
  2893  		// where "5" is the status_request feature (RFC 6066)
  2894  		Value: []byte{0x30, 0x03, 0x02, 0x01, 0x05},
  2895  	}
  2896  
  2897  	domain := randomDomain()
  2898  
  2899  	authzID := createFinalizedAuthorization(
  2900  		t, sa, registration.Id, identifier.NewDNS(domain), fc.Now().Add(24*time.Hour), core.ChallengeTypeHTTP01, fc.Now().Add(-1*time.Hour))
  2901  
  2902  	order, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  2903  		RegistrationID: registration.Id,
  2904  		Identifiers:    []*corepb.Identifier{identifier.NewDNS(domain).ToProto()},
  2905  	})
  2906  	test.AssertNotError(t, err, "creating test order")
  2907  	test.AssertEquals(t, order.V2Authorizations[0], authzID)
  2908  
  2909  	testKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2910  	test.AssertNotError(t, err, "generating test key")
  2911  
  2912  	csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2913  		PublicKey:       testKey.Public(),
  2914  		DNSNames:        []string{domain},
  2915  		ExtraExtensions: []pkix.Extension{ocspMustStapleExt},
  2916  	}, testKey)
  2917  	test.AssertNotError(t, err, "creating must-staple CSR")
  2918  
  2919  	serial, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
  2920  	test.AssertNotError(t, err, "generating random serial number")
  2921  	template := &x509.Certificate{
  2922  		SerialNumber:          serial,
  2923  		Subject:               pkix.Name{CommonName: domain},
  2924  		DNSNames:              []string{domain},
  2925  		NotBefore:             fc.Now(),
  2926  		NotAfter:              fc.Now().Add(365 * 24 * time.Hour),
  2927  		BasicConstraintsValid: true,
  2928  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  2929  		ExtraExtensions:       []pkix.Extension{ocspMustStapleExt},
  2930  	}
  2931  	cert, err := x509.CreateCertificate(rand.Reader, template, template, testKey.Public(), testKey)
  2932  	test.AssertNotError(t, err, "creating certificate")
  2933  	ra.CA = &mocks.MockCA{
  2934  		PEM: pem.EncodeToMemory(&pem.Block{
  2935  			Bytes: cert,
  2936  			Type:  "CERTIFICATE",
  2937  		}),
  2938  	}
  2939  
  2940  	_, err = ra.FinalizeOrder(context.Background(), &rapb.FinalizeOrderRequest{
  2941  		Order: order,
  2942  		Csr:   csr,
  2943  	})
  2944  	test.AssertError(t, err, "finalization should fail")
  2945  	test.AssertContains(t, err.Error(), "no longer available")
  2946  }
  2947  
  2948  func TestIssueCertificateAuditLog(t *testing.T) {
  2949  	_, sa, ra, _, _, registration, cleanUp := initAuthorities(t)
  2950  	defer cleanUp()
  2951  
  2952  	// Make some valid authorizations for some names using different challenge types
  2953  	names := []string{"not-example.com", "www.not-example.com", "still.not-example.com", "definitely.not-example.com"}
  2954  	idents := identifier.ACMEIdentifiers{
  2955  		identifier.NewDNS("not-example.com"),
  2956  		identifier.NewDNS("www.not-example.com"),
  2957  		identifier.NewDNS("still.not-example.com"),
  2958  		identifier.NewDNS("definitely.not-example.com"),
  2959  	}
  2960  	exp := ra.clk.Now().Add(ra.profiles.def().orderLifetime)
  2961  	challs := []core.AcmeChallenge{core.ChallengeTypeHTTP01, core.ChallengeTypeDNS01, core.ChallengeTypeHTTP01, core.ChallengeTypeDNS01}
  2962  	var authzIDs []int64
  2963  	for i, ident := range idents {
  2964  		authzIDs = append(authzIDs, createFinalizedAuthorization(t, sa, registration.Id, ident, exp, challs[i], ra.clk.Now()))
  2965  	}
  2966  
  2967  	// Create a pending order for all of the names
  2968  	order, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{
  2969  		NewOrder: &sapb.NewOrderRequest{
  2970  			RegistrationID:   registration.Id,
  2971  			Expires:          timestamppb.New(exp),
  2972  			Identifiers:      idents.ToProtoSlice(),
  2973  			V2Authorizations: authzIDs,
  2974  		},
  2975  	})
  2976  	test.AssertNotError(t, err, "Could not add test order with finalized authz IDs")
  2977  
  2978  	// Generate a CSR covering the order names with a random RSA key
  2979  	testKey, err := rsa.GenerateKey(rand.Reader, 2048)
  2980  	test.AssertNotError(t, err, "error generating test key")
  2981  	csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  2982  		PublicKey:          testKey.PublicKey,
  2983  		SignatureAlgorithm: x509.SHA256WithRSA,
  2984  		Subject:            pkix.Name{CommonName: "not-example.com"},
  2985  		DNSNames:           names,
  2986  	}, testKey)
  2987  	test.AssertNotError(t, err, "Could not create test order CSR")
  2988  
  2989  	// Create a mock certificate for the fake CA to return
  2990  	template := &x509.Certificate{
  2991  		SerialNumber: big.NewInt(12),
  2992  		Subject: pkix.Name{
  2993  			CommonName: "not-example.com",
  2994  		},
  2995  		DNSNames:              names,
  2996  		NotBefore:             time.Now(),
  2997  		NotAfter:              time.Now().AddDate(0, 0, 1),
  2998  		BasicConstraintsValid: true,
  2999  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  3000  	}
  3001  	cert, err := x509.CreateCertificate(rand.Reader, template, template, testKey.Public(), testKey)
  3002  	test.AssertNotError(t, err, "Failed to create mock cert for test CA")
  3003  
  3004  	// Set up the RA's CA with a mock that returns the cert from above
  3005  	ra.CA = &mocks.MockCA{
  3006  		PEM: pem.EncodeToMemory(&pem.Block{
  3007  			Bytes: cert,
  3008  		}),
  3009  	}
  3010  
  3011  	// The mock cert needs to be parsed to get its notbefore/notafter dates
  3012  	parsedCerts, err := x509.ParseCertificates(cert)
  3013  	test.AssertNotError(t, err, "Failed to parse mock cert DER bytes")
  3014  	test.AssertEquals(t, len(parsedCerts), 1)
  3015  	parsedCert := parsedCerts[0]
  3016  
  3017  	// Cast the RA's mock log so we can ensure its cleared and can access the
  3018  	// matched log lines
  3019  	mockLog := ra.log.(*blog.Mock)
  3020  	mockLog.Clear()
  3021  
  3022  	// Finalize the order with the CSR
  3023  	order.Status = string(core.StatusReady)
  3024  	_, err = ra.FinalizeOrder(context.Background(), &rapb.FinalizeOrderRequest{
  3025  		Order: order,
  3026  		Csr:   csr,
  3027  	})
  3028  	test.AssertNotError(t, err, "Error finalizing test order")
  3029  
  3030  	// Get the logged lines from the audit logger
  3031  	loglines := mockLog.GetAllMatching("Certificate request - successful JSON=")
  3032  
  3033  	// There should be exactly 1 matching log line
  3034  	test.AssertEquals(t, len(loglines), 1)
  3035  	// Strip away the stuff before 'JSON='
  3036  	jsonContent := strings.TrimPrefix(loglines[0], "INFO: [AUDIT] Certificate request - successful JSON=")
  3037  
  3038  	// Unmarshal the JSON into a certificate request event object
  3039  	var event certificateRequestEvent
  3040  	err = json.Unmarshal([]byte(jsonContent), &event)
  3041  	// The JSON should unmarshal without error
  3042  	test.AssertNotError(t, err, "Error unmarshalling logged JSON issuance event")
  3043  	// The event should have no error
  3044  	test.AssertEquals(t, event.Error, "")
  3045  	// The event requester should be the expected reg ID
  3046  	test.AssertEquals(t, event.Requester, registration.Id)
  3047  	// The event order ID should be the expected order ID
  3048  	test.AssertEquals(t, event.OrderID, order.Id)
  3049  	// The event serial number should be the expected serial number
  3050  	test.AssertEquals(t, event.SerialNumber, core.SerialToString(template.SerialNumber))
  3051  	// The event verified fields should be the expected value
  3052  	test.AssertDeepEquals(t, event.VerifiedFields, []string{"subject.commonName", "subjectAltName"})
  3053  	// The event CommonName should match the expected common name
  3054  	test.AssertEquals(t, event.CommonName, "not-example.com")
  3055  	// The event identifiers should match the order identifiers
  3056  	test.AssertDeepEquals(t, identifier.Normalize(event.Identifiers), identifier.Normalize(identifier.FromProtoSlice(order.Identifiers)))
  3057  	// The event's NotBefore and NotAfter should match the cert's
  3058  	test.AssertEquals(t, event.NotBefore, parsedCert.NotBefore)
  3059  	test.AssertEquals(t, event.NotAfter, parsedCert.NotAfter)
  3060  
  3061  	// There should be one event Authorization entry for each name
  3062  	test.AssertEquals(t, len(event.Authorizations), len(names))
  3063  
  3064  	// Check the authz entry for each name
  3065  	for i, name := range names {
  3066  		authzEntry := event.Authorizations[name]
  3067  		// The authz entry should have the correct authz ID
  3068  		test.AssertEquals(t, authzEntry.ID, fmt.Sprintf("%d", authzIDs[i]))
  3069  		// The authz entry should have the correct challenge type
  3070  		test.AssertEquals(t, authzEntry.ChallengeType, challs[i])
  3071  	}
  3072  }
  3073  
  3074  func TestIssueCertificateCAACheckLog(t *testing.T) {
  3075  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
  3076  	defer cleanUp()
  3077  	ra.VA = va.RemoteClients{CAAClient: &noopCAA{}}
  3078  
  3079  	exp := fc.Now().Add(24 * time.Hour)
  3080  	recent := fc.Now().Add(-1 * time.Hour)
  3081  	older := fc.Now().Add(-8 * time.Hour)
  3082  
  3083  	// Make some valid authzs for four names. Half of them were validated
  3084  	// recently and half were validated in excess of our CAA recheck time.
  3085  	names := []string{
  3086  		"not-example.com",
  3087  		"www.not-example.com",
  3088  		"still.not-example.com",
  3089  		"definitely.not-example.com",
  3090  	}
  3091  	idents := identifier.NewDNSSlice(names)
  3092  	var authzIDs []int64
  3093  	for i, ident := range idents {
  3094  		attemptedAt := older
  3095  		if i%2 == 0 {
  3096  			attemptedAt = recent
  3097  		}
  3098  		authzIDs = append(authzIDs, createFinalizedAuthorization(t, sa, registration.Id, ident, exp, core.ChallengeTypeHTTP01, attemptedAt))
  3099  	}
  3100  
  3101  	// Create a pending order for all of the names.
  3102  	order, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{
  3103  		NewOrder: &sapb.NewOrderRequest{
  3104  			RegistrationID:   registration.Id,
  3105  			Expires:          timestamppb.New(exp),
  3106  			Identifiers:      idents.ToProtoSlice(),
  3107  			V2Authorizations: authzIDs,
  3108  		},
  3109  	})
  3110  	test.AssertNotError(t, err, "Could not add test order with finalized authz IDs")
  3111  
  3112  	// Generate a CSR covering the order names with a random RSA key.
  3113  	testKey, err := rsa.GenerateKey(rand.Reader, 2048)
  3114  	test.AssertNotError(t, err, "error generating test key")
  3115  	csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  3116  		PublicKey:          testKey.PublicKey,
  3117  		SignatureAlgorithm: x509.SHA256WithRSA,
  3118  		Subject:            pkix.Name{CommonName: "not-example.com"},
  3119  		DNSNames:           names,
  3120  	}, testKey)
  3121  	test.AssertNotError(t, err, "Could not create test order CSR")
  3122  
  3123  	// Create a mock certificate for the fake CA to return.
  3124  	template := &x509.Certificate{
  3125  		SerialNumber: big.NewInt(12),
  3126  		Subject: pkix.Name{
  3127  			CommonName: "not-example.com",
  3128  		},
  3129  		DNSNames:              names,
  3130  		NotBefore:             time.Now(),
  3131  		NotAfter:              time.Now().AddDate(0, 0, 1),
  3132  		BasicConstraintsValid: true,
  3133  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  3134  	}
  3135  	cert, err := x509.CreateCertificate(rand.Reader, template, template, testKey.Public(), testKey)
  3136  	test.AssertNotError(t, err, "Failed to create mock cert for test CA")
  3137  
  3138  	// Set up the RA's CA with a mock that returns the cert from above.
  3139  	ra.CA = &mocks.MockCA{
  3140  		PEM: pem.EncodeToMemory(&pem.Block{
  3141  			Bytes: cert,
  3142  		}),
  3143  	}
  3144  
  3145  	// Cast the RA's mock log so we can ensure its cleared and can access the
  3146  	// matched log lines.
  3147  	mockLog := ra.log.(*blog.Mock)
  3148  	mockLog.Clear()
  3149  
  3150  	// Finalize the order with the CSR.
  3151  	order.Status = string(core.StatusReady)
  3152  	_, err = ra.FinalizeOrder(context.Background(), &rapb.FinalizeOrderRequest{
  3153  		Order: order,
  3154  		Csr:   csr,
  3155  	})
  3156  	test.AssertNotError(t, err, "Error finalizing test order")
  3157  
  3158  	// Get the logged lines from the mock logger.
  3159  	loglines := mockLog.GetAllMatching("FinalizationCaaCheck JSON=")
  3160  	// There should be exactly 1 matching log line.
  3161  	test.AssertEquals(t, len(loglines), 1)
  3162  
  3163  	// Strip away the stuff before 'JSON='.
  3164  	jsonContent := strings.TrimPrefix(loglines[0], "INFO: FinalizationCaaCheck JSON=")
  3165  
  3166  	// Unmarshal the JSON into an event object.
  3167  	var event finalizationCAACheckEvent
  3168  	err = json.Unmarshal([]byte(jsonContent), &event)
  3169  	// The JSON should unmarshal without error.
  3170  	test.AssertNotError(t, err, "Error unmarshalling logged JSON issuance event.")
  3171  	// The event requester should be the expected registration ID.
  3172  	test.AssertEquals(t, event.Requester, registration.Id)
  3173  	// The event should have the expected number of Authzs where CAA was reused.
  3174  	test.AssertEquals(t, event.Reused, 2)
  3175  	// The event should have the expected number of Authzs where CAA was
  3176  	// rechecked.
  3177  	test.AssertEquals(t, event.Rechecked, 2)
  3178  }
  3179  
  3180  // TestUpdateMissingAuthorization tests the race condition where a challenge is
  3181  // updated to valid concurrently with another attempt to have the challenge
  3182  // updated. Previously this would return a `berrors.InternalServer` error when
  3183  // the row was found missing from `pendingAuthorizations` by the 2nd update
  3184  // since the 1st had already deleted it. We accept this may happen and now test
  3185  // for a `berrors.NotFound` error return.
  3186  //
  3187  // See https://github.com/letsencrypt/boulder/issues/3201
  3188  func TestUpdateMissingAuthorization(t *testing.T) {
  3189  	_, sa, ra, _, fc, registration, cleanUp := initAuthorities(t)
  3190  	defer cleanUp()
  3191  	ctx := context.Background()
  3192  
  3193  	authzPB := createPendingAuthorization(t, sa, registration.Id, identifier.NewDNS("example.com"), fc.Now().Add(12*time.Hour))
  3194  	authz, err := bgrpc.PBToAuthz(authzPB)
  3195  	test.AssertNotError(t, err, "failed to deserialize authz")
  3196  
  3197  	// Twiddle the authz to pretend its been validated by the VA
  3198  	authz.Challenges[0].Status = "valid"
  3199  	err = ra.recordValidation(ctx, authz.ID, fc.Now().Add(24*time.Hour), &authz.Challenges[0])
  3200  	test.AssertNotError(t, err, "ra.recordValidation failed")
  3201  
  3202  	// Try to record the same validation a second time.
  3203  	err = ra.recordValidation(ctx, authz.ID, fc.Now().Add(25*time.Hour), &authz.Challenges[0])
  3204  	test.AssertError(t, err, "ra.recordValidation didn't fail")
  3205  	test.AssertErrorIs(t, err, berrors.NotFound)
  3206  }
  3207  
  3208  func TestPerformValidationBadChallengeType(t *testing.T) {
  3209  	_, _, ra, _, fc, _, cleanUp := initAuthorities(t)
  3210  	defer cleanUp()
  3211  	pa, err := policy.New(map[identifier.IdentifierType]bool{}, map[core.AcmeChallenge]bool{}, blog.NewMock())
  3212  	test.AssertNotError(t, err, "Couldn't create PA")
  3213  	ra.PA = pa
  3214  
  3215  	exp := fc.Now().Add(10 * time.Hour)
  3216  	authz := core.Authorization{
  3217  		ID:             "1337",
  3218  		Identifier:     identifier.NewDNS("not-example.com"),
  3219  		RegistrationID: 1,
  3220  		Status:         "valid",
  3221  		Challenges: []core.Challenge{
  3222  			{
  3223  				Status: core.StatusValid,
  3224  				Type:   core.ChallengeTypeHTTP01,
  3225  				Token:  "exampleToken",
  3226  			},
  3227  		},
  3228  		Expires: &exp,
  3229  	}
  3230  	authzPB, err := bgrpc.AuthzToPB(authz)
  3231  	test.AssertNotError(t, err, "AuthzToPB failed")
  3232  
  3233  	_, err = ra.PerformValidation(context.Background(), &rapb.PerformValidationRequest{
  3234  		Authz:          authzPB,
  3235  		ChallengeIndex: 0,
  3236  	})
  3237  	test.AssertError(t, err, "ra.PerformValidation allowed a update to a authorization")
  3238  	test.AssertEquals(t, err.Error(), "challenge type \"http-01\" no longer allowed")
  3239  }
  3240  
  3241  type timeoutPub struct {
  3242  }
  3243  
  3244  func (mp *timeoutPub) SubmitToSingleCTWithResult(_ context.Context, _ *pubpb.Request, _ ...grpc.CallOption) (*pubpb.Result, error) {
  3245  	return nil, context.DeadlineExceeded
  3246  }
  3247  
  3248  func TestCTPolicyMeasurements(t *testing.T) {
  3249  	_, _, ra, _, _, _, cleanup := initAuthorities(t)
  3250  	defer cleanup()
  3251  
  3252  	ra.ctpolicy = ctpolicy.New(&timeoutPub{}, loglist.List{
  3253  		{Name: "LogA1", Operator: "OperA", Url: "UrlA1", Key: []byte("KeyA1")},
  3254  		{Name: "LogB1", Operator: "OperB", Url: "UrlB1", Key: []byte("KeyB1")},
  3255  	}, nil, nil, 0, log, metrics.NoopRegisterer)
  3256  
  3257  	_, cert := test.ThrowAwayCert(t, clock.NewFake())
  3258  	_, err := ra.GetSCTs(context.Background(), &rapb.SCTRequest{
  3259  		PrecertDER: cert.Raw,
  3260  	})
  3261  	test.AssertError(t, err, "GetSCTs should have failed when SCTs timed out")
  3262  	test.AssertContains(t, err.Error(), "failed to get 2 SCTs")
  3263  	test.AssertMetricWithLabelsEquals(t, ra.ctpolicyResults, prometheus.Labels{"result": "failure"}, 1)
  3264  }
  3265  
  3266  func TestWildcardOverlap(t *testing.T) {
  3267  	err := wildcardOverlap(identifier.ACMEIdentifiers{
  3268  		identifier.NewDNS("*.example.com"),
  3269  		identifier.NewDNS("*.example.net"),
  3270  	})
  3271  	if err != nil {
  3272  		t.Errorf("Got error %q, expected none", err)
  3273  	}
  3274  	err = wildcardOverlap(identifier.ACMEIdentifiers{
  3275  		identifier.NewDNS("*.example.com"),
  3276  		identifier.NewDNS("*.example.net"),
  3277  		identifier.NewDNS("www.example.com"),
  3278  	})
  3279  	if err == nil {
  3280  		t.Errorf("Got no error, expected one")
  3281  	}
  3282  	test.AssertErrorIs(t, err, berrors.Malformed)
  3283  
  3284  	err = wildcardOverlap(identifier.ACMEIdentifiers{
  3285  		identifier.NewDNS("*.foo.example.com"),
  3286  		identifier.NewDNS("*.example.net"),
  3287  		identifier.NewDNS("www.example.com"),
  3288  	})
  3289  	if err != nil {
  3290  		t.Errorf("Got error %q, expected none", err)
  3291  	}
  3292  }
  3293  
  3294  type MockCARecordingProfile struct {
  3295  	inner       *mocks.MockCA
  3296  	profileName string
  3297  }
  3298  
  3299  func (ca *MockCARecordingProfile) IssueCertificate(ctx context.Context, req *capb.IssueCertificateRequest, _ ...grpc.CallOption) (*capb.IssueCertificateResponse, error) {
  3300  	ca.profileName = req.CertProfileName
  3301  	return ca.inner.IssueCertificate(ctx, req)
  3302  }
  3303  
  3304  type mockSAWithFinalize struct {
  3305  	sapb.StorageAuthorityClient
  3306  }
  3307  
  3308  func (sa *mockSAWithFinalize) FinalizeOrder(ctx context.Context, req *sapb.FinalizeOrderRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) {
  3309  	return &emptypb.Empty{}, nil
  3310  }
  3311  
  3312  func (sa *mockSAWithFinalize) FQDNSetTimestampsForWindow(ctx context.Context, in *sapb.CountFQDNSetsRequest, opts ...grpc.CallOption) (*sapb.Timestamps, error) {
  3313  	return &sapb.Timestamps{
  3314  		Timestamps: []*timestamppb.Timestamp{
  3315  			timestamppb.Now(),
  3316  		},
  3317  	}, nil
  3318  }
  3319  
  3320  func TestIssueCertificateOuter(t *testing.T) {
  3321  	_, _, ra, _, fc, registration, cleanup := initAuthorities(t)
  3322  	defer cleanup()
  3323  	ra.SA = &mockSAWithFinalize{}
  3324  
  3325  	// Create a CSR to submit and a certificate for the fake CA to return.
  3326  	testKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  3327  	test.AssertNotError(t, err, "generating test key")
  3328  	csrDER, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{DNSNames: []string{"example.com"}}, testKey)
  3329  	test.AssertNotError(t, err, "creating test csr")
  3330  	csr, err := x509.ParseCertificateRequest(csrDER)
  3331  	test.AssertNotError(t, err, "parsing test csr")
  3332  	certDER, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
  3333  		SerialNumber:          big.NewInt(1),
  3334  		DNSNames:              []string{"example.com"},
  3335  		NotBefore:             fc.Now(),
  3336  		BasicConstraintsValid: true,
  3337  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  3338  	}, &x509.Certificate{}, testKey.Public(), testKey)
  3339  	test.AssertNotError(t, err, "creating test cert")
  3340  	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
  3341  
  3342  	for _, tc := range []struct {
  3343  		name        string
  3344  		profile     string
  3345  		wantProfile string
  3346  	}{
  3347  		{
  3348  			name:        "select default profile when none specified",
  3349  			wantProfile: "test", // matches ra.defaultProfileName
  3350  		},
  3351  		{
  3352  			name:        "default profile specified",
  3353  			profile:     "test",
  3354  			wantProfile: "test",
  3355  		},
  3356  		{
  3357  			name:        "other profile specified",
  3358  			profile:     "other",
  3359  			wantProfile: "other",
  3360  		},
  3361  	} {
  3362  		t.Run(tc.name, func(t *testing.T) {
  3363  			// Use a mock CA that will record the profile name and profile hash included
  3364  			// in the RA's request messages. Populate it with the cert generated above.
  3365  			mockCA := MockCARecordingProfile{inner: &mocks.MockCA{PEM: certPEM}}
  3366  			ra.CA = &mockCA
  3367  
  3368  			order := &corepb.Order{
  3369  				RegistrationID:         registration.Id,
  3370  				Expires:                timestamppb.New(fc.Now().Add(24 * time.Hour)),
  3371  				Identifiers:            []*corepb.Identifier{identifier.NewDNS("example.com").ToProto()},
  3372  				CertificateProfileName: tc.profile,
  3373  			}
  3374  
  3375  			order, err = ra.issueCertificateOuter(context.Background(), order, csr, certificateRequestEvent{})
  3376  
  3377  			// The resulting order should have new fields populated
  3378  			if order.Status != string(core.StatusValid) {
  3379  				t.Errorf("order.Status = %+v, want %+v", order.Status, core.StatusValid)
  3380  			}
  3381  			if order.CertificateSerial != core.SerialToString(big.NewInt(1)) {
  3382  				t.Errorf("CertificateSerial = %+v, want %+v", order.CertificateSerial, 1)
  3383  			}
  3384  
  3385  			// The recorded profile and profile hash should match what we expect.
  3386  			if mockCA.profileName != tc.wantProfile {
  3387  				t.Errorf("recorded profileName = %+v, want %+v", mockCA.profileName, tc.wantProfile)
  3388  			}
  3389  		})
  3390  	}
  3391  }
  3392  
  3393  func TestNewOrderMaxNames(t *testing.T) {
  3394  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  3395  	defer cleanUp()
  3396  
  3397  	ra.profiles.def().maxNames = 2
  3398  	_, err := ra.NewOrder(context.Background(), &rapb.NewOrderRequest{
  3399  		RegistrationID: 1,
  3400  		Identifiers: []*corepb.Identifier{
  3401  			identifier.NewDNS("a").ToProto(),
  3402  			identifier.NewDNS("b").ToProto(),
  3403  			identifier.NewDNS("c").ToProto(),
  3404  		},
  3405  	})
  3406  	test.AssertError(t, err, "NewOrder didn't fail with too many names in request")
  3407  	test.AssertEquals(t, err.Error(), "Order cannot contain more than 2 identifiers")
  3408  	test.AssertErrorIs(t, err, berrors.Malformed)
  3409  }
  3410  
  3411  // CSR generated by Go:
  3412  // * Random public key
  3413  // * CN = not-example.com
  3414  // * DNSNames = not-example.com, www.not-example.com
  3415  var CSRPEM = []byte(`
  3416  -----BEGIN CERTIFICATE REQUEST-----
  3417  MIICrjCCAZYCAQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMTD25vdC1leGFtcGxl
  3418  LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKT1B7UsonZuLOp7
  3419  qq2pw+COo0I9ZheuhN9ltu1+bAMWBYUb8KFPNGGp8Ygt6YCLjlnWOche7Fjb5lPj
  3420  hV6U2BkEt85mdaGTDg6mU3qjk2/cnZeAvJWW5ewYOBGxN/g/KHgdYZ+uhHH/PbGt
  3421  Wktcv5bRJ9Dxbjxsy7l8SLQ6fd/MF/3z6sBJzIHkcDupDOFdPN/Z0KOw7BOPHAbg
  3422  ghLJTmiESA1Ljxb8848bENlCz8pVizIu2Ilr4xBPtA5oUfO0FJKbT1T66JZoqwy/
  3423  drfrlHA7F6c8kYlAmwiOfWHzlWCkE1YuZPJrZQrt4tJ70rrPxV1qEGJDumzgcEbU
  3424  /aYYiBsCAwEAAaBCMEAGCSqGSIb3DQEJDjEzMDEwLwYDVR0RBCgwJoIPbm90LWV4
  3425  YW1wbGUuY29tghN3d3cubm90LWV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IB
  3426  AQBuFo5SHqN1lWmM6rKaOBXFezAdzZyGb9x8+5Zq/eh9pSxpn0MTOmq/u+sDHxsC
  3427  ywcshUO3P9//9u4ALtNn/jsJmSrElsTvG3SH5owl9muNEiOgf+6/rY/X8Zcnv/e0
  3428  Ar9r73BcCkjoAOFbr7xiLLYu5EaBQjSj6/m4ujwJTWS2SqobK5VfdpzmDp4wT3eB
  3429  V4FPLxyxxOLuWLzcBkDdLw/zh922HtR5fqk155Y4pj3WS9NnI/NMHmclrlfY/2P4
  3430  dJrBVM+qVbPTzM19QplMkiy7FxpDx6toUXDYM4KdKKV0+yX/zw/V0/Gb7K7yIjVB
  3431  wqjllqgMjN4nvHjiDXFx/kPY
  3432  -----END CERTIFICATE REQUEST-----
  3433  `)
  3434  
  3435  var eeCertPEM = []byte(`
  3436  -----BEGIN CERTIFICATE-----
  3437  MIIEfTCCAmWgAwIBAgISCr9BRk0C9OOGVke6CAa8F+AXMA0GCSqGSIb3DQEBCwUA
  3438  MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKDAdUZXN0IENBMRAwDgYDVQQDDAdUZXN0
  3439  IENBMB4XDTE2MDMyMDE4MTEwMFoXDTE2MDMyMDE5MTEwMFowHjEcMBoGA1UEAxMT
  3440  d3d3Lm5vdC1leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
  3441  ggEBAKT1B7UsonZuLOp7qq2pw+COo0I9ZheuhN9ltu1+bAMWBYUb8KFPNGGp8Ygt
  3442  6YCLjlnWOche7Fjb5lPjhV6U2BkEt85mdaGTDg6mU3qjk2/cnZeAvJWW5ewYOBGx
  3443  N/g/KHgdYZ+uhHH/PbGtWktcv5bRJ9Dxbjxsy7l8SLQ6fd/MF/3z6sBJzIHkcDup
  3444  DOFdPN/Z0KOw7BOPHAbgghLJTmiESA1Ljxb8848bENlCz8pVizIu2Ilr4xBPtA5o
  3445  UfO0FJKbT1T66JZoqwy/drfrlHA7F6c8kYlAmwiOfWHzlWCkE1YuZPJrZQrt4tJ7
  3446  0rrPxV1qEGJDumzgcEbU/aYYiBsCAwEAAaOBoTCBnjAdBgNVHSUEFjAUBggrBgEF
  3447  BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUIEr9ryJ0aJuD
  3448  CwBsCp7Eun8Hx4AwHwYDVR0jBBgwFoAUmiamd/N/8knrCb1QlhwB4WXCqaswLwYD
  3449  VR0RBCgwJoIPbm90LWV4YW1wbGUuY29tghN3d3cubm90LWV4YW1wbGUuY29tMA0G
  3450  CSqGSIb3DQEBCwUAA4ICAQBpGLrCt38Z+knbuE1ALEB3hqUQCAm1OPDW6HR+v2nO
  3451  f2ERxTwL9Cad++3vONxgB68+6KQeIf5ph48OGnS5DgO13mb2cxLlmM2IJpkbSFtW
  3452  VeRNFt/WxRJafpbKw2hgQNJ/sxEAsCyA+kVeh1oCxGQyPO7IIXtw5FecWfIiNNwM
  3453  mVM17uchtvsM5BRePvet9xZxrKOFnn6TQRs8vC4e59Y8h52On+L2Q/ytAa7j3+fb
  3454  7OYCe+yWypGeosekamZTMBjHFV3RRxsGdRATSuZkv1uewyUnEPmsy5Ow4doSYZKW
  3455  QmKjti+vv1YhAhFxPArob0SG3YOiFuKzZ9rSOhUtzSg01ml/kRyOiC7rfO7NRzHq
  3456  idhPUhu2QBmdJTLLOBQLvKDNDOHqDYwKdIHJ7pup2y0Fvm4T96q5bnrSdmz/QAlB
  3457  XVw08HWMcjeOeHYiHST3yxYfQivTNm2PlKfUACb7vcrQ6pYhOnVdYgJZm6gkV4Xd
  3458  K1HKja36snIevv/gSgsE7bGcBYLVCvf16o3IRt9K8CpDoSsWn0iAVcwUP2CyPLm4
  3459  QsqA1afjTUPKQTAgDKRecDPhrT1+FjtBwdpXetpRiBK0UE5exfnI4nszZ9+BYG1l
  3460  xGUhoOJp0T++nz6R3TX7Rwk7KmG6xX3vWr/MFu5A3c8fvkqj987Vti5BeBezCXfs
  3461  rA==
  3462  -----END CERTIFICATE-----
  3463  `)
  3464  
  3465  // mockSARevocation is a fake which includes all of the SA methods called in the
  3466  // course of a revocation. Its behavior can be customized by providing sets of
  3467  // issued (known) certs, already-revoked certs, and already-blocked keys. It
  3468  // also updates the sets of revoked certs and blocked keys when certain methods
  3469  // are called, to allow for more complex test logic.
  3470  type mockSARevocation struct {
  3471  	sapb.StorageAuthorityClient
  3472  
  3473  	known   map[string]*x509.Certificate
  3474  	revoked map[string]*corepb.CertificateStatus
  3475  	blocked []*sapb.AddBlockedKeyRequest
  3476  }
  3477  
  3478  func newMockSARevocation(known *x509.Certificate) *mockSARevocation {
  3479  	return &mockSARevocation{
  3480  		known:   map[string]*x509.Certificate{core.SerialToString(known.SerialNumber): known},
  3481  		revoked: make(map[string]*corepb.CertificateStatus),
  3482  		blocked: make([]*sapb.AddBlockedKeyRequest, 0),
  3483  	}
  3484  }
  3485  
  3486  func (msar *mockSARevocation) reset() {
  3487  	msar.revoked = make(map[string]*corepb.CertificateStatus)
  3488  	msar.blocked = make([]*sapb.AddBlockedKeyRequest, 0)
  3489  }
  3490  
  3491  func (msar *mockSARevocation) AddBlockedKey(_ context.Context, req *sapb.AddBlockedKeyRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) {
  3492  	msar.blocked = append(msar.blocked, req)
  3493  	return &emptypb.Empty{}, nil
  3494  }
  3495  
  3496  func (msar *mockSARevocation) GetSerialMetadata(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*sapb.SerialMetadata, error) {
  3497  	if cert, present := msar.known[req.Serial]; present {
  3498  		return &sapb.SerialMetadata{
  3499  			Serial:         req.Serial,
  3500  			RegistrationID: 1,
  3501  			Created:        timestamppb.New(cert.NotBefore),
  3502  			Expires:        timestamppb.New(cert.NotAfter),
  3503  		}, nil
  3504  	}
  3505  	return nil, berrors.UnknownSerialError()
  3506  }
  3507  
  3508  func (msar *mockSARevocation) GetLintPrecertificate(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.Certificate, error) {
  3509  	if cert, present := msar.known[req.Serial]; present {
  3510  		return &corepb.Certificate{Der: cert.Raw}, nil
  3511  	}
  3512  	return nil, berrors.UnknownSerialError()
  3513  }
  3514  
  3515  func (msar *mockSARevocation) GetCertificateStatus(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.CertificateStatus, error) {
  3516  	if status, present := msar.revoked[req.Serial]; present {
  3517  		return status, nil
  3518  	}
  3519  	if cert, present := msar.known[req.Serial]; present {
  3520  		return &corepb.CertificateStatus{
  3521  			Serial:   core.SerialToString(cert.SerialNumber),
  3522  			IssuerID: int64(issuance.IssuerNameID(cert)),
  3523  		}, nil
  3524  	}
  3525  	return nil, berrors.UnknownSerialError()
  3526  }
  3527  
  3528  func (msar *mockSARevocation) GetCertificate(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.Certificate, error) {
  3529  	var serialBytes [16]byte
  3530  	_, _ = rand.Read(serialBytes[:])
  3531  	serial := big.NewInt(0).SetBytes(serialBytes[:])
  3532  
  3533  	key, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
  3534  	if err != nil {
  3535  		return nil, err
  3536  	}
  3537  
  3538  	template := &x509.Certificate{
  3539  		SerialNumber:          serial,
  3540  		DNSNames:              []string{"revokememaybe.example.com"},
  3541  		NotBefore:             time.Now(),
  3542  		NotAfter:              time.Now().Add(6 * 24 * time.Hour),
  3543  		IssuingCertificateURL: []string{"http://localhost:4001/acme/issuer-cert/1234"},
  3544  		CRLDistributionPoints: []string{"http://example.com/123.crl"},
  3545  	}
  3546  
  3547  	testCertDER, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
  3548  	if err != nil {
  3549  		return nil, err
  3550  	}
  3551  
  3552  	return &corepb.Certificate{
  3553  		Der: testCertDER,
  3554  	}, nil
  3555  }
  3556  
  3557  func (msar *mockSARevocation) RevokeCertificate(_ context.Context, req *sapb.RevokeCertificateRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) {
  3558  	if _, present := msar.revoked[req.Serial]; present {
  3559  		return nil, berrors.AlreadyRevokedError("already revoked")
  3560  	}
  3561  	cert, present := msar.known[req.Serial]
  3562  	if !present {
  3563  		return nil, berrors.UnknownSerialError()
  3564  	}
  3565  	msar.revoked[req.Serial] = &corepb.CertificateStatus{
  3566  		Serial:        req.Serial,
  3567  		IssuerID:      int64(issuance.IssuerNameID(cert)),
  3568  		Status:        string(core.OCSPStatusRevoked),
  3569  		RevokedReason: req.Reason,
  3570  	}
  3571  	return &emptypb.Empty{}, nil
  3572  }
  3573  
  3574  func (msar *mockSARevocation) UpdateRevokedCertificate(_ context.Context, req *sapb.RevokeCertificateRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) {
  3575  	status, present := msar.revoked[req.Serial]
  3576  	if !present {
  3577  		return nil, errors.New("not already revoked")
  3578  	}
  3579  	if revocation.Reason(req.Reason) != revocation.KeyCompromise {
  3580  		return nil, errors.New("cannot re-revoke except for keyCompromise")
  3581  	}
  3582  	if present && revocation.Reason(status.RevokedReason) == revocation.KeyCompromise {
  3583  		return nil, berrors.AlreadyRevokedError("already revoked for keyCompromise")
  3584  	}
  3585  	msar.revoked[req.Serial].RevokedReason = req.Reason
  3586  	return &emptypb.Empty{}, nil
  3587  }
  3588  
  3589  func TestRevokeCertByApplicant_Subscriber(t *testing.T) {
  3590  	_, _, ra, _, clk, _, cleanUp := initAuthorities(t)
  3591  	defer cleanUp()
  3592  
  3593  	// Use the same self-signed cert as both issuer and issuee for revocation.
  3594  	_, cert := test.ThrowAwayCert(t, clk)
  3595  	cert.IsCA = true
  3596  	ic, err := issuance.NewCertificate(cert)
  3597  	test.AssertNotError(t, err, "failed to create issuer cert")
  3598  	ra.issuersByNameID = map[issuance.NameID]*issuance.Certificate{
  3599  		ic.NameID(): ic,
  3600  	}
  3601  	ra.SA = newMockSARevocation(cert)
  3602  
  3603  	// Revoking without a regID should fail.
  3604  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3605  		Cert:  cert.Raw,
  3606  		Code:  int64(revocation.Unspecified),
  3607  		RegID: 0,
  3608  	})
  3609  	test.AssertError(t, err, "should have failed with no RegID")
  3610  	test.AssertContains(t, err.Error(), "incomplete")
  3611  
  3612  	// Revoking for a disallowed reason should fail.
  3613  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3614  		Cert:  cert.Raw,
  3615  		Code:  int64(revocation.CertificateHold),
  3616  		RegID: 1,
  3617  	})
  3618  	test.AssertError(t, err, "should have failed with bad reasonCode")
  3619  	test.AssertContains(t, err.Error(), "disallowed revocation reason")
  3620  
  3621  	// Revoking with the correct regID should succeed.
  3622  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3623  		Cert:  cert.Raw,
  3624  		Code:  int64(revocation.Unspecified),
  3625  		RegID: 1,
  3626  	})
  3627  	test.AssertNotError(t, err, "should have succeeded")
  3628  
  3629  	// Revoking an already-revoked serial should fail.
  3630  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3631  		Cert:  cert.Raw,
  3632  		Code:  int64(revocation.Unspecified),
  3633  		RegID: 1,
  3634  	})
  3635  	test.AssertError(t, err, "should have failed with bad reasonCode")
  3636  	test.AssertContains(t, err.Error(), "already revoked")
  3637  }
  3638  
  3639  // mockSARevocationWithAuthzs embeds a mockSARevocation and so inherits all its
  3640  // methods, but also adds GetValidAuthorizations2 so that it can pretend to
  3641  // either be authorized or not for all of the names in the to-be-revoked cert.
  3642  type mockSARevocationWithAuthzs struct {
  3643  	*mockSARevocation
  3644  	authorized bool
  3645  }
  3646  
  3647  func (msa *mockSARevocationWithAuthzs) GetValidAuthorizations2(ctx context.Context, req *sapb.GetValidAuthorizationsRequest, _ ...grpc.CallOption) (*sapb.Authorizations, error) {
  3648  	authzs := &sapb.Authorizations{}
  3649  
  3650  	if !msa.authorized {
  3651  		return authzs, nil
  3652  	}
  3653  
  3654  	for _, ident := range req.Identifiers {
  3655  		authzs.Authzs = append(authzs.Authzs, &corepb.Authorization{Identifier: ident})
  3656  	}
  3657  
  3658  	return authzs, nil
  3659  }
  3660  
  3661  func TestRevokeCertByApplicant_Controller(t *testing.T) {
  3662  	_, _, ra, _, clk, _, cleanUp := initAuthorities(t)
  3663  	defer cleanUp()
  3664  
  3665  	// Use the same self-signed cert as both issuer and issuee for revocation.
  3666  	_, cert := test.ThrowAwayCert(t, clk)
  3667  	cert.IsCA = true
  3668  	ic, err := issuance.NewCertificate(cert)
  3669  	test.AssertNotError(t, err, "failed to create issuer cert")
  3670  	ra.issuersByNameID = map[issuance.NameID]*issuance.Certificate{
  3671  		ic.NameID(): ic,
  3672  	}
  3673  	mockSA := newMockSARevocation(cert)
  3674  
  3675  	// Revoking when the account doesn't have valid authzs for the name should fail.
  3676  	// We use RegID 2 here and below because the mockSARevocation believes regID 1
  3677  	// is the original issuer.
  3678  	ra.SA = &mockSARevocationWithAuthzs{mockSA, false}
  3679  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3680  		Cert:  cert.Raw,
  3681  		Code:  int64(revocation.Unspecified),
  3682  		RegID: 2,
  3683  	})
  3684  	test.AssertError(t, err, "should have failed with wrong RegID")
  3685  	test.AssertContains(t, err.Error(), "requester does not control all identifiers")
  3686  
  3687  	// Revoking when the account does have valid authzs for the name should succeed,
  3688  	// but override the revocation reason to cessationOfOperation.
  3689  	ra.SA = &mockSARevocationWithAuthzs{mockSA, true}
  3690  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3691  		Cert:  cert.Raw,
  3692  		Code:  int64(revocation.Unspecified),
  3693  		RegID: 2,
  3694  	})
  3695  	test.AssertNotError(t, err, "should have succeeded")
  3696  	test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)].RevokedReason, int64(revocation.CessationOfOperation))
  3697  }
  3698  
  3699  func TestRevokeCertByKey(t *testing.T) {
  3700  	_, _, ra, _, clk, _, cleanUp := initAuthorities(t)
  3701  	defer cleanUp()
  3702  
  3703  	// Use the same self-signed cert as both issuer and issuee for revocation.
  3704  	_, cert := test.ThrowAwayCert(t, clk)
  3705  	digest, err := core.KeyDigest(cert.PublicKey)
  3706  	test.AssertNotError(t, err, "core.KeyDigest failed")
  3707  	cert.IsCA = true
  3708  	ic, err := issuance.NewCertificate(cert)
  3709  	test.AssertNotError(t, err, "failed to create issuer cert")
  3710  	ra.issuersByNameID = map[issuance.NameID]*issuance.Certificate{
  3711  		ic.NameID(): ic,
  3712  	}
  3713  	mockSA := newMockSARevocation(cert)
  3714  	ra.SA = mockSA
  3715  
  3716  	// Revoking should work, but override the requested reason and block the key.
  3717  	_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
  3718  		Cert: cert.Raw,
  3719  	})
  3720  	test.AssertNotError(t, err, "should have succeeded")
  3721  	test.AssertEquals(t, len(mockSA.blocked), 1)
  3722  	test.Assert(t, bytes.Equal(digest[:], mockSA.blocked[0].KeyHash), "key hash mismatch")
  3723  	test.AssertEquals(t, mockSA.blocked[0].Source, "API")
  3724  	test.AssertEquals(t, len(mockSA.blocked[0].Comment), 0)
  3725  	test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)].RevokedReason, int64(revocation.KeyCompromise))
  3726  
  3727  	// Re-revoking should fail, because it is already revoked for keyCompromise.
  3728  	_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
  3729  		Cert: cert.Raw,
  3730  	})
  3731  	test.AssertError(t, err, "should have failed")
  3732  
  3733  	// Reset and have the Subscriber revoke for a different reason.
  3734  	// Then re-revoking using the key should work.
  3735  	mockSA.revoked = make(map[string]*corepb.CertificateStatus)
  3736  	_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
  3737  		Cert:  cert.Raw,
  3738  		Code:  int64(revocation.Unspecified),
  3739  		RegID: 1,
  3740  	})
  3741  	test.AssertNotError(t, err, "should have succeeded")
  3742  	_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
  3743  		Cert: cert.Raw,
  3744  	})
  3745  	test.AssertNotError(t, err, "should have succeeded")
  3746  }
  3747  
  3748  func TestAdministrativelyRevokeCertificate(t *testing.T) {
  3749  	_, _, ra, _, clk, _, cleanUp := initAuthorities(t)
  3750  	defer cleanUp()
  3751  
  3752  	// Use the same self-signed cert as both issuer and issuee for revocation.
  3753  	serial, cert := test.ThrowAwayCert(t, clk)
  3754  	digest, err := core.KeyDigest(cert.PublicKey)
  3755  	test.AssertNotError(t, err, "core.KeyDigest failed")
  3756  	cert.IsCA = true
  3757  	ic, err := issuance.NewCertificate(cert)
  3758  	test.AssertNotError(t, err, "failed to create issuer cert")
  3759  	ra.issuersByNameID = map[issuance.NameID]*issuance.Certificate{
  3760  		ic.NameID(): ic,
  3761  	}
  3762  	mockSA := newMockSARevocation(cert)
  3763  	ra.SA = mockSA
  3764  
  3765  	// Revoking with an empty request should fail immediately.
  3766  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{})
  3767  	test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed for nil request object")
  3768  
  3769  	// Revoking with no serial should fail immediately.
  3770  	mockSA.reset()
  3771  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3772  		Code:      int64(revocation.Unspecified),
  3773  		AdminName: "root",
  3774  	})
  3775  	test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with no cert or serial")
  3776  
  3777  	// Revoking without an admin name should fail immediately.
  3778  	mockSA.reset()
  3779  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3780  		Serial:    serial,
  3781  		Code:      int64(revocation.Unspecified),
  3782  		AdminName: "",
  3783  	})
  3784  	test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with empty string for `AdminName`")
  3785  
  3786  	// Revoking for a forbidden reason should fail immediately.
  3787  	mockSA.reset()
  3788  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3789  		Serial:    serial,
  3790  		Code:      int64(revocation.CertificateHold),
  3791  		AdminName: "root",
  3792  	})
  3793  	test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with forbidden revocation reason")
  3794  
  3795  	// Revoking a cert for an unspecified reason should work but not block the key.
  3796  	mockSA.reset()
  3797  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3798  		Serial:    serial,
  3799  		Code:      int64(revocation.Unspecified),
  3800  		AdminName: "root",
  3801  	})
  3802  	test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed")
  3803  	test.AssertEquals(t, len(mockSA.blocked), 0)
  3804  
  3805  	// Revoking a serial for an unspecified reason should work but not block the key.
  3806  	mockSA.reset()
  3807  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3808  		Serial:    serial,
  3809  		Code:      int64(revocation.Unspecified),
  3810  		AdminName: "root",
  3811  	})
  3812  	test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed")
  3813  	test.AssertEquals(t, len(mockSA.blocked), 0)
  3814  
  3815  	// Duplicate administrative revocation of a serial for any reason other than
  3816  	// keyCompromise should fail.
  3817  	// Note that we *don't* call reset() here, so it recognizes the duplicate.
  3818  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3819  		Serial:    serial,
  3820  		Code:      int64(revocation.Unspecified),
  3821  		AdminName: "root",
  3822  	})
  3823  	test.AssertError(t, err, "Should be revoked")
  3824  	test.AssertContains(t, err.Error(), "already revoked")
  3825  	test.AssertEquals(t, len(mockSA.blocked), 0)
  3826  
  3827  	// Revoking a cert for key compromise with skipBlockKey set should work but
  3828  	// not block the key.
  3829  	mockSA.reset()
  3830  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3831  		Serial:       serial,
  3832  		Code:         int64(revocation.KeyCompromise),
  3833  		AdminName:    "root",
  3834  		SkipBlockKey: true,
  3835  	})
  3836  	test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed")
  3837  	test.AssertEquals(t, len(mockSA.blocked), 0)
  3838  
  3839  	// Revoking a cert for key compromise should work and block the key.
  3840  	mockSA.reset()
  3841  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3842  		Serial:    serial,
  3843  		Code:      int64(revocation.KeyCompromise),
  3844  		AdminName: "root",
  3845  	})
  3846  	test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed")
  3847  	test.AssertEquals(t, len(mockSA.blocked), 1)
  3848  	test.Assert(t, bytes.Equal(digest[:], mockSA.blocked[0].KeyHash), "key hash mismatch")
  3849  	test.AssertEquals(t, mockSA.blocked[0].Source, "admin-revoker")
  3850  	test.AssertEquals(t, mockSA.blocked[0].Comment, "revoked by root")
  3851  	test.AssertEquals(t, mockSA.blocked[0].Added.AsTime(), clk.Now())
  3852  
  3853  	// Revoking a malformed cert for key compromise should fail because we don't
  3854  	// have the pubkey to block.
  3855  	mockSA.reset()
  3856  	_, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{
  3857  		Serial:    core.SerialToString(cert.SerialNumber),
  3858  		Code:      int64(revocation.KeyCompromise),
  3859  		AdminName: "root",
  3860  		Malformed: true,
  3861  	})
  3862  	test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with just serial for keyCompromise")
  3863  }
  3864  
  3865  // An authority that returns an error from NewOrderAndAuthzs if the
  3866  // "ReplacesSerial" field of the request is empty.
  3867  type mockNewOrderMustBeReplacementAuthority struct {
  3868  	mockSAWithAuthzs
  3869  }
  3870  
  3871  func (sa *mockNewOrderMustBeReplacementAuthority) NewOrderAndAuthzs(ctx context.Context, req *sapb.NewOrderAndAuthzsRequest, _ ...grpc.CallOption) (*corepb.Order, error) {
  3872  	if req.NewOrder.ReplacesSerial == "" {
  3873  		return nil, status.Error(codes.InvalidArgument, "NewOrder is not a replacement")
  3874  	}
  3875  	return &corepb.Order{
  3876  		Id:             1,
  3877  		RegistrationID: req.NewOrder.RegistrationID,
  3878  		Expires:        req.NewOrder.Expires,
  3879  		Status:         string(core.StatusPending),
  3880  		Created:        timestamppb.New(time.Now()),
  3881  		Identifiers:    req.NewOrder.Identifiers,
  3882  	}, nil
  3883  }
  3884  
  3885  func TestNewOrderReplacesSerialCarriesThroughToSA(t *testing.T) {
  3886  	_, _, ra, _, _, registration, cleanUp := initAuthorities(t)
  3887  	defer cleanUp()
  3888  
  3889  	exampleOrder := &rapb.NewOrderRequest{
  3890  		RegistrationID: registration.Id,
  3891  		Identifiers:    []*corepb.Identifier{identifier.NewDNS("example.com").ToProto()},
  3892  		ReplacesSerial: "1234",
  3893  	}
  3894  
  3895  	// Mock SA that returns an error from NewOrderAndAuthzs if the
  3896  	// "ReplacesSerial" field of the request is empty.
  3897  	ra.SA = &mockNewOrderMustBeReplacementAuthority{mockSAWithAuthzs{}}
  3898  
  3899  	_, err := ra.NewOrder(ctx, exampleOrder)
  3900  	test.AssertNotError(t, err, "order with ReplacesSerial should have succeeded")
  3901  }
  3902  
  3903  // newMockSAUnpauseAccount is a fake which includes all of the SA methods called
  3904  // in the course of an account unpause. Its behavior can be customized by
  3905  // providing the number of unpaused account identifiers to allow testing of
  3906  // various scenarios.
  3907  type mockSAUnpauseAccount struct {
  3908  	sapb.StorageAuthorityClient
  3909  	identsToUnpause int64
  3910  	receivedRegID   int64
  3911  }
  3912  
  3913  func (sa *mockSAUnpauseAccount) UnpauseAccount(_ context.Context, req *sapb.RegistrationID, _ ...grpc.CallOption) (*sapb.Count, error) {
  3914  	sa.receivedRegID = req.Id
  3915  	return &sapb.Count{Count: sa.identsToUnpause}, nil
  3916  }
  3917  
  3918  // TestUnpauseAccount tests that the RA's UnpauseAccount method correctly passes
  3919  // the requested RegID to the SA, and correctly passes the SA's count back to
  3920  // the caller.
  3921  func TestUnpauseAccount(t *testing.T) {
  3922  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  3923  	defer cleanUp()
  3924  
  3925  	mockSA := mockSAUnpauseAccount{identsToUnpause: 0}
  3926  	ra.SA = &mockSA
  3927  
  3928  	res, err := ra.UnpauseAccount(context.Background(), &rapb.UnpauseAccountRequest{
  3929  		RegistrationID: 1,
  3930  	})
  3931  	test.AssertNotError(t, err, "Should have been able to unpause account")
  3932  	test.AssertEquals(t, res.Count, int64(0))
  3933  	test.AssertEquals(t, mockSA.receivedRegID, int64(1))
  3934  
  3935  	mockSA.identsToUnpause = 50001
  3936  	res, err = ra.UnpauseAccount(context.Background(), &rapb.UnpauseAccountRequest{
  3937  		RegistrationID: 1,
  3938  	})
  3939  	test.AssertNotError(t, err, "Should have been able to unpause account")
  3940  	test.AssertEquals(t, res.Count, int64(50001))
  3941  }
  3942  
  3943  func TestGetAuthorization(t *testing.T) {
  3944  	_, _, ra, _, _, _, cleanup := initAuthorities(t)
  3945  	defer cleanup()
  3946  
  3947  	ra.SA = &mockSAWithAuthzs{
  3948  		authzs: []*core.Authorization{
  3949  			{
  3950  				ID:         "1",
  3951  				Identifier: identifier.NewDNS("example.com"),
  3952  				Status:     "valid",
  3953  				Challenges: []core.Challenge{
  3954  					{
  3955  						Type:   core.ChallengeTypeHTTP01,
  3956  						Status: core.StatusValid,
  3957  					},
  3958  				},
  3959  			},
  3960  		},
  3961  	}
  3962  
  3963  	// With HTTP01 enabled, GetAuthorization should pass the mock challenge through.
  3964  	pa, err := policy.New(
  3965  		map[identifier.IdentifierType]bool{
  3966  			identifier.TypeDNS: true,
  3967  			identifier.TypeIP:  true,
  3968  		},
  3969  		map[core.AcmeChallenge]bool{
  3970  			core.ChallengeTypeHTTP01: true,
  3971  			core.ChallengeTypeDNS01:  true,
  3972  		},
  3973  		blog.NewMock())
  3974  	test.AssertNotError(t, err, "Couldn't create PA")
  3975  	ra.PA = pa
  3976  	authz, err := ra.GetAuthorization(context.Background(), &rapb.GetAuthorizationRequest{Id: 1})
  3977  	test.AssertNotError(t, err, "should not fail")
  3978  	test.AssertEquals(t, len(authz.Challenges), 1)
  3979  	test.AssertEquals(t, authz.Challenges[0].Type, string(core.ChallengeTypeHTTP01))
  3980  
  3981  	// With HTTP01 disabled, GetAuthorization should filter out the mock challenge.
  3982  	pa, err = policy.New(
  3983  		map[identifier.IdentifierType]bool{
  3984  			identifier.TypeDNS: true,
  3985  			identifier.TypeIP:  true,
  3986  		},
  3987  		map[core.AcmeChallenge]bool{
  3988  			core.ChallengeTypeDNS01: true,
  3989  		},
  3990  		blog.NewMock())
  3991  	test.AssertNotError(t, err, "Couldn't create PA")
  3992  	ra.PA = pa
  3993  	authz, err = ra.GetAuthorization(context.Background(), &rapb.GetAuthorizationRequest{Id: 1})
  3994  	test.AssertNotError(t, err, "should not fail")
  3995  	test.AssertEquals(t, len(authz.Challenges), 0)
  3996  }
  3997  
  3998  type NoUpdateSA struct {
  3999  	sapb.StorageAuthorityClient
  4000  }
  4001  
  4002  func (sa *NoUpdateSA) UpdateRegistrationKey(_ context.Context, _ *sapb.UpdateRegistrationKeyRequest, _ ...grpc.CallOption) (*corepb.Registration, error) {
  4003  	return nil, fmt.Errorf("UpdateRegistrationKey() is mocked to always error")
  4004  }
  4005  
  4006  // mockSARecordingRegistration tests UpdateRegistrationKey.
  4007  type mockSARecordingRegistration struct {
  4008  	sapb.StorageAuthorityClient
  4009  	providedRegistrationID int64
  4010  	providedJwk            []byte
  4011  }
  4012  
  4013  // UpdateRegistrationKey records the registration ID and updated key provided.
  4014  func (sa *mockSARecordingRegistration) UpdateRegistrationKey(ctx context.Context, req *sapb.UpdateRegistrationKeyRequest, _ ...grpc.CallOption) (*corepb.Registration, error) {
  4015  	sa.providedRegistrationID = req.RegistrationID
  4016  	sa.providedJwk = req.Jwk
  4017  
  4018  	return &corepb.Registration{
  4019  		Id:  req.RegistrationID,
  4020  		Key: req.Jwk,
  4021  	}, nil
  4022  }
  4023  
  4024  // TestUpdateRegistrationKey tests that the RA's UpdateRegistrationKey method
  4025  // correctly requires a registration ID and key, passes them to the SA, and
  4026  // passes the updated Registration back to the caller.
  4027  func TestUpdateRegistrationKey(t *testing.T) {
  4028  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  4029  	defer cleanUp()
  4030  
  4031  	expectRegID := int64(1)
  4032  	expectJwk := AccountKeyJSONA
  4033  	mockSA := mockSARecordingRegistration{}
  4034  	ra.SA = &mockSA
  4035  
  4036  	_, err := ra.UpdateRegistrationKey(context.Background(), &rapb.UpdateRegistrationKeyRequest{})
  4037  	test.AssertError(t, err, "should not have been able to update registration key without a registration ID or key")
  4038  	test.AssertContains(t, err.Error(), "incomplete gRPC request message")
  4039  
  4040  	_, err = ra.UpdateRegistrationKey(context.Background(), &rapb.UpdateRegistrationKeyRequest{RegistrationID: expectRegID})
  4041  	test.AssertError(t, err, "should not have been able to update registration key without a key")
  4042  	test.AssertContains(t, err.Error(), "incomplete gRPC request message")
  4043  
  4044  	_, err = ra.UpdateRegistrationKey(context.Background(), &rapb.UpdateRegistrationKeyRequest{Jwk: expectJwk})
  4045  	test.AssertError(t, err, "should not have been able to update registration key without a registration ID")
  4046  	test.AssertContains(t, err.Error(), "incomplete gRPC request message")
  4047  
  4048  	res, err := ra.UpdateRegistrationKey(context.Background(), &rapb.UpdateRegistrationKeyRequest{
  4049  		RegistrationID: expectRegID,
  4050  		Jwk:            expectJwk,
  4051  	})
  4052  	test.AssertNotError(t, err, "should have been able to update registration key")
  4053  	test.AssertEquals(t, res.Id, expectRegID)
  4054  	test.AssertEquals(t, mockSA.providedRegistrationID, expectRegID)
  4055  	test.AssertDeepEquals(t, res.Key, expectJwk)
  4056  	test.AssertDeepEquals(t, mockSA.providedJwk, expectJwk)
  4057  
  4058  	// Switch to a mock SA that will always error if UpdateRegistrationKey() is
  4059  	// called.
  4060  	ra.SA = &NoUpdateSA{}
  4061  	_, err = ra.UpdateRegistrationKey(context.Background(), &rapb.UpdateRegistrationKeyRequest{
  4062  		RegistrationID: expectRegID,
  4063  		Jwk:            expectJwk,
  4064  	})
  4065  	test.AssertError(t, err, "should have received an error from the SA")
  4066  	test.AssertContains(t, err.Error(), "failed to update registration key")
  4067  	test.AssertContains(t, err.Error(), "mocked to always error")
  4068  }
  4069  
  4070  func TestCRLShard(t *testing.T) {
  4071  	var cdp []string
  4072  	n, err := crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4073  	if err == nil {
  4074  		t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
  4075  	}
  4076  
  4077  	cdp = []string{
  4078  		"https://example.com/123.crl",
  4079  		"https://example.net/123.crl",
  4080  	}
  4081  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4082  	if err == nil {
  4083  		t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
  4084  	}
  4085  
  4086  	cdp = []string{
  4087  		"https://example.com/abc",
  4088  	}
  4089  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4090  	if err == nil {
  4091  		t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
  4092  	}
  4093  
  4094  	cdp = []string{
  4095  		"example",
  4096  	}
  4097  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4098  	if err == nil {
  4099  		t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
  4100  	}
  4101  
  4102  	cdp = []string{
  4103  		"https://example.com/abc/-77.crl",
  4104  	}
  4105  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4106  	if err == nil {
  4107  		t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
  4108  	}
  4109  
  4110  	cdp = []string{
  4111  		"https://example.com/abc/123",
  4112  	}
  4113  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4114  	if err != nil || n != 123 {
  4115  		t.Errorf("crlShard(%+v) = %d, %s, want 123, nil", cdp, n, err)
  4116  	}
  4117  
  4118  	cdp = []string{
  4119  		"https://example.com/abc/123.crl",
  4120  	}
  4121  	n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
  4122  	if err != nil || n != 123 {
  4123  		t.Errorf("crlShard(%+v) = %d, %s, want 123, nil", cdp, n, err)
  4124  	}
  4125  }
  4126  
  4127  type mockSAWithOverrides struct {
  4128  	sapb.StorageAuthorityClient
  4129  	inserted *sapb.AddRateLimitOverrideRequest
  4130  }
  4131  
  4132  func (sa *mockSAWithOverrides) AddRateLimitOverride(ctx context.Context, req *sapb.AddRateLimitOverrideRequest, _ ...grpc.CallOption) (*sapb.AddRateLimitOverrideResponse, error) {
  4133  	sa.inserted = req
  4134  	return &sapb.AddRateLimitOverrideResponse{}, nil
  4135  }
  4136  
  4137  func TestAddRateLimitOverride(t *testing.T) {
  4138  	_, _, ra, _, _, _, cleanUp := initAuthorities(t)
  4139  	defer cleanUp()
  4140  
  4141  	mockSA := mockSAWithOverrides{}
  4142  	ra.SA = &mockSA
  4143  
  4144  	expectBucketKey := core.RandomString(10)
  4145  	ov := rapb.AddRateLimitOverrideRequest{
  4146  		LimitEnum: 1,
  4147  		BucketKey: expectBucketKey,
  4148  		Comment:   "insert",
  4149  		Period:    durationpb.New(time.Hour),
  4150  		Count:     100,
  4151  		Burst:     100,
  4152  	}
  4153  
  4154  	_, err := ra.AddRateLimitOverride(ctx, &ov)
  4155  	test.AssertNotError(t, err, "expected successful insert, got error")
  4156  	test.AssertEquals(t, mockSA.inserted.Override.LimitEnum, ov.LimitEnum)
  4157  	test.AssertEquals(t, mockSA.inserted.Override.BucketKey, expectBucketKey)
  4158  	test.AssertEquals(t, mockSA.inserted.Override.Comment, ov.Comment)
  4159  	test.AssertEquals(t, mockSA.inserted.Override.Period.AsDuration(), ov.Period.AsDuration())
  4160  	test.AssertEquals(t, mockSA.inserted.Override.Count, ov.Count)
  4161  	test.AssertEquals(t, mockSA.inserted.Override.Burst, ov.Burst)
  4162  }