diff --git a/.go-version b/.go-version index d8c40e539c..53cc1a6f92 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.23.6 +1.24.0 diff --git a/go.mod b/go.mod index 7611c0c8f6..2bf9add9b7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/spiffe/spire -go 1.23.6 +go 1.24.0 require ( cloud.google.com/go/iam v1.4.0 diff --git a/pkg/agent/plugin/nodeattestor/awsiid/iid_test.go b/pkg/agent/plugin/nodeattestor/awsiid/iid_test.go index 1e858e1e96..3786df1e5a 100644 --- a/pkg/agent/plugin/nodeattestor/awsiid/iid_test.go +++ b/pkg/agent/plugin/nodeattestor/awsiid/iid_test.go @@ -22,10 +22,10 @@ import ( "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor" nodeattestortest "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/test" "github.com/spiffe/spire/pkg/common/catalog" - "github.com/spiffe/spire/pkg/common/pemutil" "github.com/spiffe/spire/pkg/common/plugin/aws" "github.com/spiffe/spire/test/plugintest" "github.com/spiffe/spire/test/spiretest" + "github.com/spiffe/spire/test/testkey" "google.golang.org/grpc/codes" ) @@ -38,19 +38,7 @@ const ( ) var ( - signingKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBywIBAAJhAOn4rFLlxONpujl+q/h/kTQzZoqn1nQZbCKEyIPBWO6kkcSqIqON -aB3i+xyxgZNwkGEkLGRl/Uwasbp7O/sU43wh5ywWp/AG0iFe1RhwMd8LMq5ron6o -s2eql71hJKsGEwIDAQABAmEAoDa9YcKe8Q68C5TXE8He33z3Ealea3/hET4VxEsI -p9mfS6kpMQ+qpRSB2aMfVKP1mrAQ4/5TarrG1ZG3T/Mt9Oy1QHbzALvz2XObIvcR -0cnG353CLQK/nobvWcwAtac5AjEA9k+1a9R6eFaO3grl9yg5XY2+MboV4wjbsDS3 -s4+MivneTPwvK6eHxtoAlYCNOAslAjEA8yy0PJw3TLBK80DryF3r/Q4wd4uYeFhN -G6EBF0LccLB7GbKpcDHgnNjW/wObx+LXAjBeP4/G6+3U4CIYuojWMvEIaDVPp8m6 -LuiJGxLzxUjc4NF8Gb8e8CLXJxG0IxVmTXUCMQDSPJAG5rgYoUHrVPGEZU8llSLp -99J2GUFw5Z3f0nprIukKqqA606RxdjdKeoAwLDkCMCptc0jZR3VM4w1wnwvAe0FL -t61Ol/Q+OqWFX74JwsUU56FqPFm3Y9k7HxDILdedoQ== ------END RSA PRIVATE KEY-----`) - + signingKey = testkey.MustRSA2048() streamBuilder = nodeattestortest.ServerStream(aws.PluginName) ) @@ -180,15 +168,13 @@ func (s *Suite) buildDefaultIIDDocAndSig() (docBytes []byte, sigBytes []byte, si s.Require().NoError(err) rng := rand.Reader - key, err := pemutil.ParseRSAPrivateKey(signingKeyPEM) - s.Require().NoError(err) // doc signature docHash := sha256.Sum256(docBytes) - sig, err := rsa.SignPKCS1v15(rng, key, crypto.SHA256, docHash[:]) + sig, err := rsa.SignPKCS1v15(rng, signingKey, crypto.SHA256, docHash[:]) s.Require().NoError(err) - sigRSA2048 = s.generatePKCS7Signature(docBytes, key) + sigRSA2048 = s.generatePKCS7Signature(docBytes, signingKey) return docBytes, sig, sigRSA2048 } diff --git a/pkg/agent/plugin/nodeattestor/k8spsat/psat_test.go b/pkg/agent/plugin/nodeattestor/k8spsat/psat_test.go index 0e383d1f94..d9a986ca5b 100644 --- a/pkg/agent/plugin/nodeattestor/k8spsat/psat_test.go +++ b/pkg/agent/plugin/nodeattestor/k8spsat/psat_test.go @@ -13,27 +13,15 @@ import ( "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor" nodeattestortest "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/test" "github.com/spiffe/spire/pkg/common/catalog" - "github.com/spiffe/spire/pkg/common/pemutil" sat_common "github.com/spiffe/spire/pkg/common/plugin/k8s" "github.com/spiffe/spire/test/plugintest" "github.com/spiffe/spire/test/spiretest" + "github.com/spiffe/spire/test/testkey" "google.golang.org/grpc/codes" ) -var sampleKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBywIBAAJhAMB4gbT09H2RKXaxbu6IV9C3WY+pvkGAbrlQRIHLHwV3Xt1HchjX -c08v1VEoTBN2YTjhZJlDb/VUsNMJsmBFBBted5geRcbrDtXFlUJ8tQoQx1dWM4Aa -xcdULJ83A9ICKwIDAQABAmBR1asInrIphYQEtHJ/NzdnRd3tqHV9cjch0dAfA5dA -Ar4yBYOsrkaX37WqWSDnkYgN4FWYBWn7WxeotCtA5UQ3SM5hLld67rUqAm2dLrs1 -z8va6SwLzrPTu2+rmRgovFECMQDpbfPBRex7FY/xWu1pYv6X9XZ26SrC2Wc6RIpO -38AhKGjTFEMAPJQlud4e2+4I3KkCMQDTFLUvBSXokw2NvcNiM9Kqo5zCnCIkgc+C -hM3EzSh2jh4gZvRzPOhXYvNKgLx8+LMCMQDL4meXlpV45Fp3eu4GsJqi65jvP7VD -v1P0hs0vGyvbSkpUo0vqNv9G/FNQLNR6FRECMFXEMz5wxA91OOuf8HTFg9Lr+fUl -RcY5rJxm48kUZ12Mr3cQ/kCYvftL7HkYR/4rewIxANdritlIPu4VziaEhYZg7dvz -pG3eEhiqPxE++QHpwU78O+F1GznOPBvpZOB3GfyjNQ== ------END RSA PRIVATE KEY-----`) - var ( + sampleKey = testkey.MustRSA2048() streamBuilder = nodeattestortest.ServerStream(pluginName) ) @@ -168,11 +156,6 @@ func createPSAT(namespace, podName string) (string, error) { } func createSigner() (jose.Signer, error) { - sampleKey, err := pemutil.ParseRSAPrivateKey(sampleKeyPEM) - if err != nil { - return nil, err - } - sampleSigner, err := jose.NewSigner(jose.SigningKey{ Algorithm: jose.RS256, Key: sampleKey, diff --git a/pkg/common/plugin/x509pop/x509pop_test.go b/pkg/common/plugin/x509pop/x509pop_test.go index 518edf6961..05f4780993 100644 --- a/pkg/common/plugin/x509pop/x509pop_test.go +++ b/pkg/common/plugin/x509pop/x509pop_test.go @@ -1,50 +1,28 @@ package x509pop import ( - "crypto/ecdsa" "crypto/rand" - "crypto/rsa" "crypto/x509" "crypto/x509/pkix" - "encoding/pem" "math/big" "testing" "github.com/spiffe/go-spiffe/v2/spiffeid" "github.com/spiffe/spire/pkg/common/agentpathtemplate" + "github.com/spiffe/spire/test/testkey" "github.com/stretchr/testify/require" ) -const ( - testRSAKey = `-----BEGIN PRIVATE KEY----- -MIIB5QIBADANBgkqhkiG9w0BAQEFAASCAc8wggHLAgEAAmEAszTMHP/M0ETR5FjO -cUpKtxMc62olnUG2F4iSiNQ2n0YuFPRId+tDsiooNze3/WxJe5U4Ljbnw+LxYIAa -hrSbWWLbpE8ZofHmb+hNAmiXQcv40VMNtJlWHUm2O5DSsOzxAgMBAAECYCqaNpv+ -Q9aPRcafRhSwsKptJMbiaSbFZGCb2xokOQgMSxA4MrIvf9xvIThfSqI4h6mNuL0g -F4+7QbSCM9oMi4lVxqtu9ThBeUmvCuuolOdvpSjDV8Y8yRrm9d9rti1g8QIxAMlz -jmSLj5kjJfSVVEMXsLZkoESvymtI44+wBwRdIbKI3Jn2cDJ2VYPNsTEVXaZLRwIx -AOO7Ob6+ya1uNLeiVtsJmaHarKn/IExvzgvr9NfNAs2PifiFKLBERSf5zh8HOocy -BwIxAMDC9/+xo0hPX6Q3t5czdf4xL0JKS5B5AHafYzeDvhjN6PjR3O4MWStziReE -cEYNRQIxAMiaajmOUpWFWMbSJ/R2tnCO8j4lUMxESJrT1TArlWaCJKVYlwj+enTG -Zj2K3pGtDQIwcHg1MNxehdkTQ7qOPHce09enVjaM0+uXPKAOfSyM7jPMBn4cm/1K -qCrBUhzFaWeg ------END PRIVATE KEY-----` - testECDSAKey = `-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgMmjo28H7LEOxWD2t -74mWp5XPrZwzb/VyukdPxHGOoOOhRANCAARhpK2KSCTiyeNZzrB8c2eZ4K+yZGrp -4MpWREMXQMIwbP/QWGYXQ8GWhp16J6IYXkywB/SJnKPY+iV6Mnbxp31K ------END PRIVATE KEY-----` +var ( + testRSAKey = testkey.MustRSA2048() + testECDSAKey = testkey.MustEC256() ) func TestChallengeResponse(t *testing.T) { require := require.New(t) // load up RSA key and create a self-signed certificate over the public key - pemBlock, _ := pem.Decode([]byte(testRSAKey)) - require.NotNil(pemBlock) - privateKey, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes) - require.NoError(err) - rsaPrivateKey := privateKey.(*rsa.PrivateKey) + rsaPrivateKey := testRSAKey rsaPublicKey := &rsaPrivateKey.PublicKey rsaCert, err := createCertificate(rsaPrivateKey, rsaPublicKey) require.NoError(err) @@ -58,11 +36,7 @@ func TestChallengeResponse(t *testing.T) { require.NoError(err) // load up ECDSA key and create a self-signed certificate over the public key - pemBlock, _ = pem.Decode([]byte(testECDSAKey)) - require.NotNil(pemBlock) - privateKey, err = x509.ParsePKCS8PrivateKey(pemBlock.Bytes) - require.NoError(err) - ecdsaPrivateKey := privateKey.(*ecdsa.PrivateKey) + ecdsaPrivateKey := testECDSAKey ecdsaPublicKey := &ecdsaPrivateKey.PublicKey ecdsaCert, err := createCertificate(ecdsaPrivateKey, ecdsaPublicKey) require.NoError(err) diff --git a/pkg/server/authpolicy/policy_test.go b/pkg/server/authpolicy/policy_test.go index 04fb075145..af91e0a754 100644 --- a/pkg/server/authpolicy/policy_test.go +++ b/pkg/server/authpolicy/policy_test.go @@ -231,11 +231,11 @@ func TestPolicy(t *testing.T) { // Check with NewEngineFromConfigOrDefault regoFile := filepath.Join(tmpDir, "rego_file") - err = os.WriteFile(regoFile, []byte(tt.rego), 0600) + err = os.WriteFile(regoFile, []byte(tt.rego), 0o600) require.Nil(t, err, "failed to create rego_file") permsFile := filepath.Join(tmpDir, "perms_file") - err = os.WriteFile(permsFile, []byte(tt.jsonData), 0600) + err = os.WriteFile(permsFile, []byte(tt.jsonData), 0o600) require.Nil(t, err, "failed to create perms_file") ec := authpolicy.OpaEngineConfig{ @@ -274,20 +274,20 @@ func TestNewEngineFromConfig(t *testing.T) { // Create good policy/perms files validRegoFile := filepath.Join(tmpDir, "valid_rego_file") - err = os.WriteFile(validRegoFile, []byte(rego), 0600) + err = os.WriteFile(validRegoFile, []byte(rego), 0o600) require.Nil(t, err, "failed to create valid_rego_file") validPermsFile := filepath.Join(tmpDir, "valid_perms_file") - err = os.WriteFile(validPermsFile, []byte(jsonData), 0600) + err = os.WriteFile(validPermsFile, []byte(jsonData), 0o600) require.Nil(t, err, "failed to create valid_perms_file") // Create bad policy/perms files invalidRegoFile := filepath.Join(tmpDir, "invalid_rego_file") - err = os.WriteFile(invalidRegoFile, []byte("invalid rego"), 0600) + err = os.WriteFile(invalidRegoFile, []byte("invalid rego"), 0o600) require.Nil(t, err, "failed to create invalid_rego_file") invalidPermsFile := filepath.Join(tmpDir, "invalid_perms_file") - err = os.WriteFile(invalidPermsFile, []byte("{"), 0600) + err = os.WriteFile(invalidPermsFile, []byte("{"), 0o600) require.Nil(t, err, "failed to create invalid_perms_file") // Create permissions tmp file diff --git a/pkg/server/endpoints/bundle/internal/acmetest/ca.go b/pkg/server/endpoints/bundle/internal/acmetest/ca.go index 69fa8bff38..8100ec1990 100644 --- a/pkg/server/endpoints/bundle/internal/acmetest/ca.go +++ b/pkg/server/endpoints/bundle/internal/acmetest/ca.go @@ -38,28 +38,31 @@ package acmetest import ( "bytes" + "context" "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/json" "encoding/pem" "errors" "fmt" "io" - "log" "math/big" + "net" "net/http" "net/http/httptest" "path" - "sort" "strconv" "strings" "sync" + "testing" "time" "github.com/go-jose/go-jose/v4" @@ -80,60 +83,70 @@ var allowedJWTSignatureAlgorithms = []jose.SignatureAlgorithm{ // CAServer is a simple test server which implements ACME spec bits needed for testing. type CAServer struct { - URL string // server URL after it has been started - Roots *x509.CertPool // CA root certificates; initialized in NewCAServer - rootKey crypto.Signer rootCert []byte // DER encoding rootTemplate *x509.Certificate - server *httptest.Server - challengeTypes []string // supported challenge types - domainsWhitelist []string // only these domains are valid for issuing, unless empty + t *testing.T + server *httptest.Server + issuer pkix.Name + challengeTypes []string + url string + roots *x509.CertPool + eabRequired bool mu sync.Mutex - certCount int // number of issued certs - domainAddr map[string]string // domain name to addr:port resolution - authorizations map[string]*authorization // keyed by domain name - orders []*order // index is used as order ID - errors []error //nolint:structcheck,unused + certCount int // number of issued certs + acctRegistered bool // set once an account has been registered + domainAddr map[string]string // domain name to addr:port resolution + domainGetCert map[string]getCertificateFunc // domain name to GetCertificate function + domainHandler map[string]http.Handler // domain name to Handle function + validAuthz map[string]*authorization // valid authz, keyed by domain name + authorizations []*authorization // all authz, index is used as ID + orders []*order // index is used as order ID + errors []error // encountered client errors accountKeysMu sync.Mutex accountKeys map[string]any } -// NewCAServer creates a new ACME test server and starts serving requests. -// The returned CAServer issues certs signed with the CA roots -// available in the Roots field. -// -// The challengeTypes argument defines the supported ACME challenge types -// sent to a client in a response for a domain authorization. -// If domainsWhitelist is non-empty, the certs will be issued only for the specified -// list of domains. Otherwise, any domain name is allowed. -func NewCAServer(challengeTypes []string, domainsWhitelist []string) *CAServer { - var whitelist []string - for _, name := range domainsWhitelist { - whitelist = append(whitelist, name) - } - sort.Strings(whitelist) +type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) + +// NewCAServer creates a new ACME test server. The returned CAServer issues +// certs signed with the CA roots available in the Roots field. +func NewCAServer(t *testing.T) *CAServer { ca := &CAServer{ - challengeTypes: challengeTypes, - domainsWhitelist: whitelist, - domainAddr: make(map[string]string), - authorizations: make(map[string]*authorization), - accountKeys: make(map[string]any), + t: t, + challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"}, + domainAddr: make(map[string]string), + domainGetCert: make(map[string]getCertificateFunc), + domainHandler: make(map[string]http.Handler), + validAuthz: make(map[string]*authorization), + accountKeys: make(map[string]any), } + ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle)) + + r, err := rand.Int(rand.Reader, big.NewInt(1000000)) + if err != nil { + panic(fmt.Sprintf("rand.Int: %v", err)) + } + ca.issuer = pkix.Name{ + Organization: []string{"Test Acme Co"}, + CommonName: "Root CA " + r.String(), + } + + return ca +} + +func (ca *CAServer) generateRoot() { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) } tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{"Test Acme Co"}, - CommonName: "Root CA", - }, + SerialNumber: big.NewInt(1), + Subject: ca.issuer, NotBefore: time.Now(), NotAfter: time.Now().Add(365 * 24 * time.Hour), KeyUsage: x509.KeyUsageCertSign, @@ -148,40 +161,101 @@ func NewCAServer(challengeTypes []string, domainsWhitelist []string) *CAServer { if err != nil { panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) } - ca.Roots = x509.NewCertPool() - ca.Roots.AddCert(cert) + ca.roots = x509.NewCertPool() + ca.roots.AddCert(cert) ca.rootKey = key ca.rootCert = der ca.rootTemplate = tmpl +} + +// IssuerName sets the name of the issuing CA. +func (ca *CAServer) IssuerName(name pkix.Name) *CAServer { + if ca.url != "" { + panic("IssuerName must be called before Start") + } + ca.issuer = name + return ca +} + +// ChallengeTypes sets the supported challenge types. +func (ca *CAServer) ChallengeTypes(types ...string) *CAServer { + if ca.url != "" { + panic("ChallengeTypes must be called before Start") + } + ca.challengeTypes = types + return ca +} + +// URL returns the server address, after Start has been called. +func (ca *CAServer) URL() string { + if ca.url == "" { + panic("URL called before Start") + } + return ca.url +} + +// Roots returns a pool cointaining the CA root. +func (ca *CAServer) Roots() *x509.CertPool { + if ca.url == "" { + panic("Roots called before Start") + } + return ca.roots +} - ca.server = httptest.NewServer(http.HandlerFunc(ca.handle)) - ca.URL = ca.server.URL +// ExternalAccountRequired makes an EAB JWS required for account registration. +func (ca *CAServer) ExternalAccountRequired() *CAServer { + if ca.url != "" { + panic("ExternalAccountRequired must be called before Start") + } + ca.eabRequired = true return ca } -// Close shuts down the server and blocks until all outstanding -// requests on this server have completed. -func (ca *CAServer) Close() { - ca.server.Close() +// Start starts serving requests. The server address becomes available in the +// URL field. +func (ca *CAServer) Start() *CAServer { + if ca.url == "" { + ca.generateRoot() + ca.server.Start() + ca.t.Cleanup(ca.server.Close) + ca.url = ca.server.URL + } + return ca } -func (ca *CAServer) serverURL(format string, arg ...any) string { +func (ca *CAServer) serverURL(format string, arg ...interface{}) string { return ca.server.URL + fmt.Sprintf(format, arg...) } -func (ca *CAServer) addr(domain string) (string, error) { +func (ca *CAServer) addr(domain string) (string, bool) { ca.mu.Lock() defer ca.mu.Unlock() addr, ok := ca.domainAddr[domain] - if !ok { - return "", fmt.Errorf("CAServer: no addr resolution for %q", domain) - } - return addr, nil + return addr, ok +} + +func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) { + ca.mu.Lock() + defer ca.mu.Unlock() + f, ok := ca.domainGetCert[domain] + return f, ok +} + +func (ca *CAServer) getHandler(domain string) (http.Handler, bool) { + ca.mu.Lock() + defer ca.mu.Unlock() + h, ok := ca.domainHandler[domain] + return h, ok } -func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...any) { +func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) { s := fmt.Sprintf(format, a...) - log.Println(s) + // FORK DEVIATION FROM ORIGINAL CODE + // We intentionally comment out this line because + // TestACMEAuth/new-account-tos-not-accepted in pkg/server/endpoints/bundle/server_test.go + // tests a condition where an error is sent back to the client, + // and we don't want to fail the test prematurely before we can assert on the error condition. + // ca.t.Errorf(format, a...) http.Error(w, s, code) } @@ -193,16 +267,34 @@ func (ca *CAServer) Resolve(domain, addr string) { ca.domainAddr[domain] = addr } +// ResolveGetCertificate redirects TLS connections for domain to f when +// validating challenges for the domain authorization. +func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.domainGetCert[domain] = f +} + +// ResolveHandler redirects HTTP requests for domain to f when +// validating challenges for the domain authorization. +func (ca *CAServer) ResolveHandler(domain string, h http.Handler) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.domainHandler[domain] = h +} + type discovery struct { - NewNonce string `json:"newNonce"` - NewReg string `json:"newAccount"` - NewOrder string `json:"newOrder"` - NewAuthz string `json:"newAuthz"` - Meta discoveryMeta `json:"meta"` + NewNonce string `json:"newNonce"` + NewAccount string `json:"newAccount"` + NewOrder string `json:"newOrder"` + NewAuthz string `json:"newAuthz"` + + Meta discoveryMeta `json:"meta,omitempty"` } type discoveryMeta struct { - TermsOfService string `json:"termsOfService,omitempty"` + TermsOfService string `json:"termsOfService,omitempty"` + ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"` } type challenge struct { @@ -216,6 +308,7 @@ type authorization struct { Challenges []challenge `json:"challenges"` domain string + id int } type order struct { @@ -228,7 +321,7 @@ type order struct { } func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { - log.Printf("%s %s", r.Method, r.URL) + ca.t.Logf("%s %s", r.Method, r.URL) w.Header().Set("Replay-Nonce", "nonce") // TODO: Verify nonce header for all POST requests. @@ -239,12 +332,12 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { // Discovery request. case r.URL.Path == "/": resp := &discovery{ - NewNonce: ca.serverURL("/new-nonce"), - NewReg: ca.serverURL("/new-reg"), - NewOrder: ca.serverURL("/new-order"), - NewAuthz: ca.serverURL("/new-authz"), + NewNonce: ca.serverURL("/new-nonce"), + NewAccount: ca.serverURL("/new-account"), + NewOrder: ca.serverURL("/new-order"), Meta: discoveryMeta{ - TermsOfService: ca.serverURL("/tos"), + TermsOfService: ca.serverURL("/tos"), + ExternalAccountRequired: ca.eabRequired, }, } if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -257,19 +350,31 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { return // Client key registration request. - case r.URL.Path == "/new-reg": - // Fail the request unless terms are accepted + case r.URL.Path == "/new-account": + ca.mu.Lock() + defer ca.mu.Unlock() + if ca.acctRegistered { + ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented") + return + } + ca.acctRegistered = true + var req struct { - TermsOfServiceAgreed bool `json:"termsOfServiceAgreed"` + TermsOfServiceAgreed bool `json:"termsOfServiceAgreed"` + ExternalAccountBinding json.RawMessage } if err := ca.decodePayload(&req, r.Body); err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } if !req.TermsOfServiceAgreed { ca.httpErrorf(w, http.StatusBadRequest, "must agree to terms of service") return } + if ca.eabRequired && len(req.ExternalAccountBinding) == 0 { + ca.httpErrorf(w, http.StatusBadRequest, "registration failed: no JWS for EAB") + return + } // TODO: Check the user account key against a ca.accountKeys? w.Header().Set("Location", ca.serverURL("/accounts/1")) @@ -282,7 +387,7 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { Identifiers []struct{ Value string } } if err := ca.decodePayload(&req, r.Body); err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } ca.mu.Lock() @@ -290,7 +395,7 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { o := &order{Status: acme.StatusPending} for _, id := range req.Identifiers { z := ca.authz(id.Value) - o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%s", z.domain)) + o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id)) } orderID := len(ca.orders) ca.orders = append(ca.orders, o) @@ -306,56 +411,57 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { defer ca.mu.Unlock() o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/")) if err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } if err := json.NewEncoder(w).Encode(o); err != nil { panic(err) } - // Identifier authorization request. - case r.URL.Path == "/new-authz": - var req struct { - Identifier struct{ Value string } - } - if err := ca.decodePayload(&req, r.Body); err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) - return - } + // Accept challenge requests. + case strings.HasPrefix(r.URL.Path, "/challenge/"): + parts := strings.Split(r.URL.Path, "/") + typ, id := parts[len(parts)-2], parts[len(parts)-1] ca.mu.Lock() - defer ca.mu.Unlock() - z := ca.authz(req.Identifier.Value) - w.Header().Set("Location", ca.serverURL("/authz/%s", z.domain)) - w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(z); err != nil { - panic(fmt.Sprintf("new authz response: %v", err)) + supported := false + for _, suppTyp := range ca.challengeTypes { + if suppTyp == typ { + supported = true + } } - - // Accept tls-alpn-01 challenge type requests. - case strings.HasPrefix(r.URL.Path, "/challenge/tls-alpn-01/"): - domain := strings.TrimPrefix(r.URL.Path, "/challenge/tls-alpn-01/") - ca.mu.Lock() - _, exist := ca.authorizations[domain] + a, err := ca.storedAuthz(id) ca.mu.Unlock() - if !exist { - ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: no authz for %q", domain) + if !supported { + ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ) return } - go ca.validateChallenge("tls-alpn-01", domain) + if err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err) + return + } + ca.validateChallenge(a, typ) w.Write([]byte("{}")) // Get authorization status requests. case strings.HasPrefix(r.URL.Path, "/authz/"): - domain := strings.TrimPrefix(r.URL.Path, "/authz/") + var req struct{ Status string } + ca.decodePayload(&req, r.Body) + deactivate := req.Status == "deactivated" ca.mu.Lock() defer ca.mu.Unlock() - authz, ok := ca.authorizations[domain] - if !ok { - ca.httpErrorf(w, http.StatusNotFound, "no authz for %q", domain) + authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/")) + if err != nil { + ca.httpErrorf(w, http.StatusNotFound, "%v", err) return } + if deactivate { + // Note we don't invalidate authorized orders as we should. + authz.Status = "deactivated" + ca.t.Logf("authz %d is now %s", authz.id, authz.Status) + ca.updatePendingOrders() + } if err := json.NewEncoder(w).Encode(authz); err != nil { - panic(fmt.Sprintf("get authz for %q response: %v", domain, err)) + panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err)) } // Certificate issuance request. @@ -365,7 +471,7 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/") o, err := ca.storedOrder(orderID) if err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } if o.Status != acme.StatusReady { @@ -380,16 +486,7 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { b, _ := base64.RawURLEncoding.DecodeString(req.CSR) csr, err := x509.ParseCertificateRequest(b) if err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) - return - } - names := unique(append(csr.DNSNames, csr.Subject.CommonName)) - if err := ca.matchWhitelist(names); err != nil { - ca.httpErrorf(w, http.StatusUnauthorized, err.Error()) - return - } - if err := ca.authorized(names); err != nil { - ca.httpErrorf(w, http.StatusUnauthorized, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } // Issue the certificate. @@ -411,7 +508,7 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { defer ca.mu.Unlock() o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/")) if err != nil { - ca.httpErrorf(w, http.StatusBadRequest, err.Error()) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } if o.Status != acme.StatusValid { @@ -424,25 +521,6 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { } } -// matchWhitelist reports whether all dnsNames are whitelisted. -// The whitelist is provided in NewCAServer. -func (ca *CAServer) matchWhitelist(dnsNames []string) error { - if len(ca.domainsWhitelist) == 0 { - return nil - } - var nomatch []string - for _, name := range dnsNames { - i := sort.SearchStrings(ca.domainsWhitelist, name) - if i == len(ca.domainsWhitelist) || ca.domainsWhitelist[i] != name { - nomatch = append(nomatch, name) - } - } - if len(nomatch) > 0 { - return fmt.Errorf("matchWhitelist: some domains don't match: %q", nomatch) - } - return nil -} - // storedOrder retrieves a previously created order at index i. // It requires ca.mu to be locked. func (ca *CAServer) storedOrder(i string) (*order, error) { @@ -456,46 +534,50 @@ func (ca *CAServer) storedOrder(i string) (*order, error) { if idx > len(ca.orders)-1 { return nil, fmt.Errorf("storedOrder: no such order %d", idx) } + + ca.updatePendingOrders() return ca.orders[idx], nil } -// authz returns an existing authorization for the identifier or creates a new one. +// storedAuthz retrieves a previously created authz at index i. // It requires ca.mu to be locked. +func (ca *CAServer) storedAuthz(i string) (*authorization, error) { + idx, err := strconv.Atoi(i) + if err != nil { + return nil, fmt.Errorf("storedAuthz: %v", err) + } + if idx < 0 { + return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx) + } + if idx > len(ca.authorizations)-1 { + return nil, fmt.Errorf("storedAuthz: no such authz %d", idx) + } + return ca.authorizations[idx], nil +} + +// authz returns an existing valid authorization for the identifier or creates a +// new one. It requires ca.mu to be locked. func (ca *CAServer) authz(identifier string) *authorization { - authz, ok := ca.authorizations[identifier] + authz, ok := ca.validAuthz[identifier] if !ok { + authzId := len(ca.authorizations) authz = &authorization{ + id: authzId, domain: identifier, Status: acme.StatusPending, } for _, typ := range ca.challengeTypes { authz.Challenges = append(authz.Challenges, challenge{ Type: typ, - URI: ca.serverURL("/challenge/%s/%s", typ, authz.domain), - Token: challengeToken(authz.domain, typ), + URI: ca.serverURL("/challenge/%s/%d", typ, authzId), + Token: challengeToken(authz.domain, typ, authzId), }) } - ca.authorizations[authz.domain] = authz + ca.authorizations = append(ca.authorizations, authz) } return authz } -// authorized reports whether all authorizations for dnsNames have been satisfied. -// It requires ca.mu to be locked. -func (ca *CAServer) authorized(dnsNames []string) error { - var noauthz []string - for _, name := range dnsNames { - authz, ok := ca.authorizations[name] - if !ok || authz.Status != acme.StatusValid { - noauthz = append(noauthz, name) - } - } - if len(noauthz) > 0 { - return fmt.Errorf("CAServer: no authz for %q", noauthz) - } - return nil -} - // leafCert issues a new certificate. // It requires ca.mu to be locked. func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { @@ -516,79 +598,231 @@ func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err erro return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) } -// TODO: Only tls-alpn-01 is currently supported: implement http-01 and dns-01. -func (ca *CAServer) validateChallenge(typ, identifier string) { +// LeafCert issues a leaf certificate. +func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate { + if ca.url == "" { + panic("LeafCert called before Start") + } + + ca.mu.Lock() + defer ca.mu.Unlock() + var pk crypto.Signer + switch keyType { + case "RSA": + var err error + pk, err = rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + ca.t.Fatal(err) + } + case "ECDSA": + var err error + pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + ca.t.Fatal(err) + } + default: + panic("LeafCert: unknown key type") + } + ca.certCount++ // next leaf cert serial number + leaf := &x509.Certificate{ + SerialNumber: big.NewInt(int64(ca.certCount)), + Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + DNSNames: []string{name}, + BasicConstraintsValid: true, + } + der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey) + if err != nil { + ca.t.Fatal(err) + } + return &tls.Certificate{ + Certificate: [][]byte{der}, + PrivateKey: pk, + } +} + +func (ca *CAServer) validateChallenge(authz *authorization, typ string) { var err error switch typ { case "tls-alpn-01": - err = ca.verifyALPNChallenge(identifier) + err = ca.verifyALPNChallenge(authz) + case "http-01": + err = ca.verifyHTTPChallenge(authz) default: panic(fmt.Sprintf("validation of %q is not implemented", typ)) } ca.mu.Lock() defer ca.mu.Unlock() - authz := ca.authorizations[identifier] if err != nil { authz.Status = "invalid" } else { authz.Status = "valid" + ca.validAuthz[authz.domain] = authz } - log.Printf("validated %q for %q; authz status is now: %s", typ, identifier, authz.Status) + ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err) + ca.t.Logf("authz %d is now %s", authz.id, authz.Status) + + ca.updatePendingOrders() +} + +func (ca *CAServer) updatePendingOrders() { // Update all pending orders. // An order becomes "ready" if all authorizations are "valid". // An order becomes "invalid" if any authorization is "invalid". // Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6 -OrdersLoop: for i, o := range ca.orders { if o.Status != acme.StatusPending { continue } - var countValid int - for _, zurl := range o.AuthzURLs { - z, ok := ca.authorizations[path.Base(zurl)] - if !ok { - log.Printf("no authz %q for order %d", zurl, i) - continue OrdersLoop - } - if z.Status == acme.StatusInvalid { - o.Status = acme.StatusInvalid - log.Printf("order %d is now invalid", i) - continue OrdersLoop - } - if z.Status == acme.StatusValid { - countValid++ - } + + countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i) + if countInvalid > 0 { + o.Status = acme.StatusInvalid + ca.t.Logf("order %d is now invalid", i) + continue } if countValid == len(o.AuthzURLs) { o.Status = acme.StatusReady o.FinalizeURL = ca.serverURL("/new-cert/%d", i) - log.Printf("order %d is now ready", i) + ca.t.Logf("order %d is now ready", i) + } + } +} + +func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) { + for _, zurl := range urls { + z, err := ca.storedAuthz(path.Base(zurl)) + if err != nil { + ca.t.Logf("no authz %q for order %d", zurl, orderNum) + continue + } + if z.Status == acme.StatusInvalid { + countInvalid++ + } + if z.Status == acme.StatusValid { + countValid++ } } + return countValid, countInvalid } -func (ca *CAServer) verifyALPNChallenge(domain string) error { +func (ca *CAServer) verifyALPNChallenge(a *authorization) error { const acmeALPNProto = "acme-tls/1" - addr, err := ca.addr(domain) - if err != nil { - return err + addr, haveAddr := ca.addr(a.domain) + getCert, haveGetCert := ca.getCert(a.domain) + if !haveAddr && !haveGetCert { + return fmt.Errorf("no resolution information for %q", a.domain) } - conn, err := tls.Dial("tcp", addr, &tls.Config{ - ServerName: domain, - InsecureSkipVerify: true, - NextProtos: []string{acmeALPNProto}, - }) - if err != nil { - return err + if haveAddr && haveGetCert { + return fmt.Errorf("overlapping resolution information for %q", a.domain) + } + + var crt *x509.Certificate + switch { + case haveAddr: + conn, err := tls.Dial("tcp", addr, &tls.Config{ + ServerName: a.domain, + InsecureSkipVerify: true, + NextProtos: []string{acmeALPNProto}, + MinVersion: tls.VersionTLS12, + }) + if err != nil { + return err + } + if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { + return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) + } + if n := len(conn.ConnectionState().PeerCertificates); n != 1 { + return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) + } + crt = conn.ConnectionState().PeerCertificates[0] + case haveGetCert: + hello := &tls.ClientHelloInfo{ + ServerName: a.domain, + // TODO: support selecting ECDSA. + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, + SupportedProtos: []string{acme.ALPNProto}, + SupportedVersions: []uint16{tls.VersionTLS12}, + } + c, err := getCert(hello) + if err != nil { + return err + } + crt, err = x509.ParseCertificate(c.Certificate[0]) + if err != nil { + return err + } } - if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { - return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) + + if err := crt.VerifyHostname(a.domain); err != nil { + return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err) } - if n := len(conn.ConnectionState().PeerCertificates); n != 1 { - return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) + // See RFC 8737, Section 6.1. + oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} + for _, x := range crt.Extensions { + if x.Id.Equal(oid) { + // TODO: check the token. + return nil + } + } + return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found") +} + +func (ca *CAServer) verifyHTTPChallenge(a *authorization) error { + addr, haveAddr := ca.addr(a.domain) + handler, haveHandler := ca.getHandler(a.domain) + if !haveAddr && !haveHandler { + return fmt.Errorf("no resolution information for %q", a.domain) + } + if haveAddr && haveHandler { + return fmt.Errorf("overlapping resolution information for %q", a.domain) + } + + token := challengeToken(a.domain, "http-01", a.id) + path := "/.well-known/acme-challenge/" + token + + var body string + switch { + case haveAddr: + t := &http.Transport{ + DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, addr) + }, + } + req, err := http.NewRequest("GET", "http://"+a.domain+path, nil) + if err != nil { + return err + } + res, err := t.RoundTrip(req) + if err != nil { + return err + } + if res.StatusCode != http.StatusOK { + return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK) + } + b, err := io.ReadAll(res.Body) + if err != nil { + return err + } + body = string(b) + case haveHandler: + r := httptest.NewRequest("GET", path, nil) + r.Host = a.domain + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusOK { + return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) + } + body = w.Body.String() + } + + if !strings.HasPrefix(body, token) { + return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body) } - // TODO: verify conn.ConnectionState().PeerCertificates[0] return nil } @@ -654,8 +888,8 @@ func (ca *CAServer) setAccountKey(kid string, key any) { ca.accountKeys[kid] = key } -func challengeToken(domain, challType string) string { - return fmt.Sprintf("token-%s-%s", domain, challType) +func challengeToken(domain, challType string, authzID int) string { + return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID) } func unique(a []string) []string { diff --git a/pkg/server/endpoints/bundle/server_test.go b/pkg/server/endpoints/bundle/server_test.go index 7c22159386..9a5017c7c1 100644 --- a/pkg/server/endpoints/bundle/server_test.go +++ b/pkg/server/endpoints/bundle/server_test.go @@ -185,12 +185,12 @@ func TestDiskCertManagerAuth(t *testing.T) { serverCert, serverKey := createServerCertificate(t) serverCertPem := pemutil.EncodeCertificate(serverCert) - err := os.WriteFile(filepath.Join(dir, "server.crt"), serverCertPem, 0600) + err := os.WriteFile(filepath.Join(dir, "server.crt"), serverCertPem, 0o600) require.NoError(t, err) serverKeyPem, err := pemutil.EncodePKCS8PrivateKey(serverKey) require.NoError(t, err) - err = os.WriteFile(filepath.Join(dir, "server.key"), serverKeyPem, 0600) + err = os.WriteFile(filepath.Join(dir, "server.key"), serverKeyPem, 0o600) require.NoError(t, err) trustDomain := spiffeid.RequireTrustDomainFromString("domain.test") @@ -241,26 +241,26 @@ func TestACMEAuth(t *testing.T) { bundle := spiffebundle.New(trustDomain) km := fakeserverkeymanager.New(t) - ca := acmetest.NewCAServer([]string{"tls-alpn-01"}, []string{"domain.test"}) - - client := http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - RootCAs: ca.Roots, - ServerName: "domain.test", - MinVersion: tls.VersionTLS12, - }, - }, - } - // Perform the initial challenge to obtain a new certificate but without // the TOS being accepted. This should fail. We require the ToSAccepted // configurable to be set in order to function. t.Run("new-account-tos-not-accepted", func(t *testing.T) { + ca := acmetest.NewCAServer(t).Start() + + client := http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: ca.Roots(), + ServerName: "domain.test", + MinVersion: tls.VersionTLS12, + }, + }, + } + log, hook := test.NewNullLogger() addr, done := newTestServer(t, testGetter(bundle), ACMEAuth(log, km, ACMEConfig{ - DirectoryURL: ca.URL, + DirectoryURL: ca.URL(), DomainName: "domain.test", CacheDir: dir, Email: "admin@domain.test", @@ -281,8 +281,8 @@ func TestACMEAuth(t *testing.T) { assert.Equal(t, "ACME Terms of Service have not been accepted. See the `tos_accepted` configurable", entry.Message) assert.Equal(t, logrus.WarnLevel, entry.Level) assert.Equal(t, logrus.Fields{ - "directory_url": ca.URL, - "tos_url": ca.URL + "/tos", + "directory_url": ca.URL(), + "tos_url": ca.URL() + "/tos", "email": "admin@domain.test", }, entry.Data) } @@ -290,10 +290,22 @@ func TestACMEAuth(t *testing.T) { // Perform the initial challenge to obtain a new certificate. t.Run("initial", func(t *testing.T) { + ca := acmetest.NewCAServer(t).Start() + + client := http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: ca.Roots(), + ServerName: "domain.test", + MinVersion: tls.VersionTLS12, + }, + }, + } + log, hook := test.NewNullLogger() addr, done := newTestServer(t, testGetter(bundle), ACMEAuth(log, km, ACMEConfig{ - DirectoryURL: ca.URL, + DirectoryURL: ca.URL(), DomainName: "domain.test", CacheDir: dir, Email: "admin@domain.test", @@ -328,33 +340,19 @@ func TestACMEAuth(t *testing.T) { assert.Equal(t, "ACME Terms of Service accepted", entry.Message) assert.Equal(t, logrus.InfoLevel, entry.Level) assert.Equal(t, logrus.Fields{ - "directory_url": ca.URL, - "tos_url": ca.URL + "/tos", + "directory_url": ca.URL(), + "tos_url": ca.URL() + "/tos", "email": "admin@domain.test", }, entry.Data) } - }) - // Now test that the cached credentials are used. This test resolves the - // domain to bogus address so that the challenge would fail if it were tried - // as a way of telling that the challenge was not attempted - t.Run("cached", func(t *testing.T) { - log, _ := test.NewNullLogger() - addr, done := newTestServer(t, testGetter(bundle), - ACMEAuth(log, km, ACMEConfig{ - DirectoryURL: ca.URL, - DomainName: "domain.test", - CacheDir: dir, - Email: "admin@domain.test", - ToSAccepted: true, - }), - 5*time.Minute, - ) - defer done() + // Now test that the cached credentials are used. This test resolves the + // domain to bogus address so that the challenge would fail if it were tried + // as a way of telling that the challenge was not attempted ca.Resolve("domain.test", "127.0.0.1:0") - resp, err := client.Get(fmt.Sprintf("https://%s", addr)) + resp, err = client.Get(fmt.Sprintf("https://%s", addr)) require.NoError(t, err) resp.Body.Close() }) diff --git a/pkg/server/plugin/nodeattestor/k8spsat/psat_test.go b/pkg/server/plugin/nodeattestor/k8spsat/psat_test.go index 1d3cc0cadd..39d904cc96 100644 --- a/pkg/server/plugin/nodeattestor/k8spsat/psat_test.go +++ b/pkg/server/plugin/nodeattestor/k8spsat/psat_test.go @@ -22,12 +22,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/spiffe/go-spiffe/v2/spiffeid" "github.com/spiffe/spire/pkg/common/catalog" - "github.com/spiffe/spire/pkg/common/pemutil" sat_common "github.com/spiffe/spire/pkg/common/plugin/k8s" "github.com/spiffe/spire/pkg/server/plugin/nodeattestor" "github.com/spiffe/spire/proto/spire/common" "github.com/spiffe/spire/test/plugintest" "github.com/spiffe/spire/test/spiretest" + "github.com/spiffe/spire/test/testkey" "google.golang.org/grpc/codes" authv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" @@ -35,31 +35,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -var ( - fooKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBywIBAAJhAMB4gbT09H2RKXaxbu6IV9C3WY+pvkGAbrlQRIHLHwV3Xt1HchjX -c08v1VEoTBN2YTjhZJlDb/VUsNMJsmBFBBted5geRcbrDtXFlUJ8tQoQx1dWM4Aa -xcdULJ83A9ICKwIDAQABAmBR1asInrIphYQEtHJ/NzdnRd3tqHV9cjch0dAfA5dA -Ar4yBYOsrkaX37WqWSDnkYgN4FWYBWn7WxeotCtA5UQ3SM5hLld67rUqAm2dLrs1 -z8va6SwLzrPTu2+rmRgovFECMQDpbfPBRex7FY/xWu1pYv6X9XZ26SrC2Wc6RIpO -38AhKGjTFEMAPJQlud4e2+4I3KkCMQDTFLUvBSXokw2NvcNiM9Kqo5zCnCIkgc+C -hM3EzSh2jh4gZvRzPOhXYvNKgLx8+LMCMQDL4meXlpV45Fp3eu4GsJqi65jvP7VD -v1P0hs0vGyvbSkpUo0vqNv9G/FNQLNR6FRECMFXEMz5wxA91OOuf8HTFg9Lr+fUl -RcY5rJxm48kUZ12Mr3cQ/kCYvftL7HkYR/4rewIxANdritlIPu4VziaEhYZg7dvz -pG3eEhiqPxE++QHpwU78O+F1GznOPBvpZOB3GfyjNQ== ------END RSA PRIVATE KEY-----`) - barKeyPEM = []byte(`-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgOIAksqKX+ByhLcme -T7MXn5Qz58BJCSvvAyRoz7+7jXGhRANCAATUWB+7Xo/JyFuh1KQ6umUbihP+AGzy -da0ItHUJ/C5HElB5cSuyOAXDQbM5fuxJIefEVpodjqsQP6D0D8CPLJ5H ------END PRIVATE KEY-----`) - bazKeyPEM = []byte(`-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgpHVYFq6Z/LgGIG/X -+i+PWZEFjGVEUpjrMzlz95tDl4yhRANCAAQAc/I3bBO9XhgTTbLBuNA6XJBSvds9 -c4gThKYxugN3V398Eieoo2HTO2L7BBjTp5yh+EUtHQD52bFseBCnZT3d ------END PRIVATE KEY-----`) -) - func TestAttestorPlugin(t *testing.T) { spiretest.Run(t, new(AttestorSuite)) } @@ -90,24 +65,21 @@ type TokenData struct { func (s *AttestorSuite) SetupSuite() { var err error - s.fooKey, err = pemutil.ParseRSAPrivateKey(fooKeyPEM) - s.Require().NoError(err) + s.fooKey = testkey.MustRSA2048() s.fooSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.RS256, Key: s.fooKey, }, nil) s.Require().NoError(err) - s.barKey, err = pemutil.ParseECPrivateKey(barKeyPEM) - s.Require().NoError(err) + s.barKey = testkey.MustEC256() s.barSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.ES256, Key: s.barKey, }, nil) s.Require().NoError(err) - bazKey, err := pemutil.ParseECPrivateKey(bazKeyPEM) - s.Require().NoError(err) + bazKey := testkey.MustEC256() s.bazSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.ES256, Key: bazKey, diff --git a/pkg/server/plugin/nodeattestor/k8ssat/sat_test.go b/pkg/server/plugin/nodeattestor/k8ssat/sat_test.go index 40bdb38955..ed3c2e0e35 100644 --- a/pkg/server/plugin/nodeattestor/k8ssat/sat_test.go +++ b/pkg/server/plugin/nodeattestor/k8ssat/sat_test.go @@ -23,42 +23,17 @@ import ( "github.com/spiffe/go-spiffe/v2/spiffeid" agentstorev1 "github.com/spiffe/spire-plugin-sdk/proto/spire/hostservice/server/agentstore/v1" "github.com/spiffe/spire/pkg/common/catalog" - "github.com/spiffe/spire/pkg/common/pemutil" sat_common "github.com/spiffe/spire/pkg/common/plugin/k8s" "github.com/spiffe/spire/pkg/server/plugin/nodeattestor" "github.com/spiffe/spire/proto/spire/common" "github.com/spiffe/spire/test/fakes/fakeagentstore" "github.com/spiffe/spire/test/plugintest" "github.com/spiffe/spire/test/spiretest" + "github.com/spiffe/spire/test/testkey" "google.golang.org/grpc/codes" authv1 "k8s.io/api/authentication/v1" ) -var ( - fooKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBywIBAAJhAMB4gbT09H2RKXaxbu6IV9C3WY+pvkGAbrlQRIHLHwV3Xt1HchjX -c08v1VEoTBN2YTjhZJlDb/VUsNMJsmBFBBted5geRcbrDtXFlUJ8tQoQx1dWM4Aa -xcdULJ83A9ICKwIDAQABAmBR1asInrIphYQEtHJ/NzdnRd3tqHV9cjch0dAfA5dA -Ar4yBYOsrkaX37WqWSDnkYgN4FWYBWn7WxeotCtA5UQ3SM5hLld67rUqAm2dLrs1 -z8va6SwLzrPTu2+rmRgovFECMQDpbfPBRex7FY/xWu1pYv6X9XZ26SrC2Wc6RIpO -38AhKGjTFEMAPJQlud4e2+4I3KkCMQDTFLUvBSXokw2NvcNiM9Kqo5zCnCIkgc+C -hM3EzSh2jh4gZvRzPOhXYvNKgLx8+LMCMQDL4meXlpV45Fp3eu4GsJqi65jvP7VD -v1P0hs0vGyvbSkpUo0vqNv9G/FNQLNR6FRECMFXEMz5wxA91OOuf8HTFg9Lr+fUl -RcY5rJxm48kUZ12Mr3cQ/kCYvftL7HkYR/4rewIxANdritlIPu4VziaEhYZg7dvz -pG3eEhiqPxE++QHpwU78O+F1GznOPBvpZOB3GfyjNQ== ------END RSA PRIVATE KEY-----`) - barKeyPEM = []byte(`-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgOIAksqKX+ByhLcme -T7MXn5Qz58BJCSvvAyRoz7+7jXGhRANCAATUWB+7Xo/JyFuh1KQ6umUbihP+AGzy -da0ItHUJ/C5HElB5cSuyOAXDQbM5fuxJIefEVpodjqsQP6D0D8CPLJ5H ------END PRIVATE KEY-----`) - bazKeyPEM = []byte(`-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgpHVYFq6Z/LgGIG/X -+i+PWZEFjGVEUpjrMzlz95tDl4yhRANCAAQAc/I3bBO9XhgTTbLBuNA6XJBSvds9 -c4gThKYxugN3V398Eieoo2HTO2L7BBjTp5yh+EUtHQD52bFseBCnZT3d ------END PRIVATE KEY-----`) -) - func TestAttestorPlugin(t *testing.T) { spiretest.Run(t, new(AttestorSuite)) } @@ -80,24 +55,21 @@ type AttestorSuite struct { func (s *AttestorSuite) SetupSuite() { var err error - s.fooKey, err = pemutil.ParseRSAPrivateKey(fooKeyPEM) - s.Require().NoError(err) + s.fooKey = testkey.MustRSA2048() s.fooSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.RS256, Key: s.fooKey, }, nil) s.Require().NoError(err) - s.barKey, err = pemutil.ParseECPrivateKey(barKeyPEM) - s.Require().NoError(err) + s.barKey = testkey.MustEC256() s.barSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.ES256, Key: s.barKey, }, nil) s.Require().NoError(err) - bazKey, err := pemutil.ParseECPrivateKey(bazKeyPEM) - s.Require().NoError(err) + bazKey := testkey.MustEC256() s.bazSigner, err = jose.NewSigner(jose.SigningKey{ Algorithm: jose.ES256, Key: bazKey, diff --git a/test/fixture/nodeattestor/x509pop/generate.go b/test/fixture/nodeattestor/x509pop/generate.go index c4ccd1c4c3..dbc6ae5228 100644 --- a/test/fixture/nodeattestor/x509pop/generate.go +++ b/test/fixture/nodeattestor/x509pop/generate.go @@ -100,7 +100,7 @@ func createCertificate(key *rsa.PrivateKey, tmpl *x509.Certificate, parentKey *r } func generateRSAKey() *rsa.PrivateKey { - key, err := rsa.GenerateKey(rand.Reader, 768) //nolint: gosec // small key is to keep test fast... not a security feature + key, err := rsa.GenerateKey(rand.Reader, 2048) panice(err) return key } diff --git a/test/fixture/nodeattestor/x509pop/intermediate.pem b/test/fixture/nodeattestor/x509pop/intermediate.pem index 50b490ac7e..16f66f6802 100644 --- a/test/fixture/nodeattestor/x509pop/intermediate.pem +++ b/test/fixture/nodeattestor/x509pop/intermediate.pem @@ -1,10 +1,17 @@ -----BEGIN CERTIFICATE----- -MIIBaDCB86ADAgECAgNNXm8wDQYJKoZIhvcNAQELBQAwADAiGA8wMDAxMDEwMTAw -MDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAAMHwwDQYJKoZIhvcNAQEBBQADawAwaAJh -ALaWTeGivnnNjL964wNhM80p8b8yTa6mpq+rYj3L0UIYJHcPBQ7XB7o0+EWWEsKW -Qs5E5vY8p56aq0y4pU0SgIMioqThX+KcmLMgs1JoJ42ZE20eFYDVqcWfSJp4o4w+ -hQIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2FBvOaL0Mi7fy -W2QJimLBmz5PKTANBgkqhkiG9w0BAQsFAANhADOBJA7AEgjKU++fRmWauP8pR+Nk -v9nbj0mABiBA0GUX116MwKs/nWq56IgzCTzqRbLKMeQt+7AIdFNp4kcrEcKU57Vw -SWgH3QLhFGbXi61FGEfFvomk72ksIV6loR6lrg== +MIICszCCAZugAwIBAgIDTV5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMANo2N0Od2EOIc/OTnbVqtoyFK3WXPkS0cYVU4Gb54F2ziFHUzK +pThvrGWg7JS2W5wFOKbZmVJgMZAQHR5yS3Gio5qbi4wy7BZiBFPdrL0cltPr5rhj +J4Lz5W2LBv8Dzwt++/uad/nLk2p6+Vgu7Vi5WwBDtZ1bti5SdAYin2pJiiABLquD +leZlW8DJStQF+/fY0jlEtHIuQwWLQLNJy7vXs2CNvNsbZ8psw4i6jdKwszkZ9vbk +Gds4yz7re2UK+mkXbfB9gzR96hle2EnvZPJqTvVWOyeO9Hw8EwxaYKtnc5nNt7FE +vqGWbX5mQ89y+VG3+BK8XQ2EZyIcIwJxQIcCAwEAAaMyMDAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUiI0WI333r30GFI3h1ZfeTKYGOrcwDQYJKoZIhvcNAQEL +BQADggEBAFY9iuoed1Cgan9JfhSbDYc2ez9lSV4dCC56VKldgNcAH8ZP6sDscCkp ++EuayP22OAbFj8qMPRxP1moYaeuu+F7Nslar2xsonHWEH1ZjO5lwRwtAXhOKFD4F +rr9VXqdBaUVKx0lBHeLsfv0JbtXhsjMhcLubc9DU8dsuM5HTnf7UZ2pgI+v0ebH3 +/FYKNZ1gk36kURv2HmCZo4qlDcLC37OG4pMAbDKqRvBvFrQS1J4QVTkjbINEmVDY +a3604pKKBUJ6uWEcZeBNW7Y471MTfjtGfIISeYbZaESGuxUWa8FNM/MMFmqabe1q +8UxB5dpx8Pqm4KmxHPCjIZjKXrJL0GQ= -----END CERTIFICATE----- diff --git a/test/fixture/nodeattestor/x509pop/leaf-crt-bundle.pem b/test/fixture/nodeattestor/x509pop/leaf-crt-bundle.pem index 4c040fb9f5..17e65182f2 100644 --- a/test/fixture/nodeattestor/x509pop/leaf-crt-bundle.pem +++ b/test/fixture/nodeattestor/x509pop/leaf-crt-bundle.pem @@ -1,24 +1,38 @@ -----BEGIN CERTIFICATE----- -MIICFTCCAZ+gAwIBAgIGChssPU5fMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx +MIIDXzCCAkegAwIBAgIGChssPU5fMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowFTETMBEGA1UEAxMKQ09NTU9OTkFN -RTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDlTw9or+1nmNIvdmZACCj+3NLW0VpX -vx14+0j74/eMLI1QZaAe11kq4tqOfitQrM6h1cDgn3Vw97AvLdSrhfX/gYTGCuq+ -iw5k6b7n3OJwAZ/F2HH64Mjk1UWcGBZwwTUCAwEAAaOBxTCBwjAOBgNVHQ8BAf8E -BAMCB4AwHwYDVR0jBBgwFoAUNhQbzmi9DIu38ltkCYpiwZs+TykwgY4GA1UdEQSB -hjCBg4YqeDUwOXBvcDovL2V4YW1wbGUub3JnL2RhdGFjZW50ZXIvdXMtZWFzdC0x -hix4NTA5cG9wOi8vZXhhbXBsZS5vcmcvZW52aXJvbm1lbnQvcHJvZHVjdGlvboYn -eDUwOXBvcDovL2V4YW1wbGUub3JnL2tleS9wYXRoL3RvL3ZhbHVlMA0GCSqGSIb3 -DQEBCwUAA2EACXpd607HIbI8FUFjVBWugGUJOE2OSTHJ11tErBghIC+dmGUXa9x4 -gfBBRjw7oZFqtZgDodi6dLd05LwYjT31b+fBNDH3B2IKCG4jwFGkgJ4LE5S0BVIT -eoqivvzXS4cu +RTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKa0tXq7zFHgeakgdlO3 +pK7cWQS14stZzIhgtDX8jTWpSLaBSbbpAvCrM8osKHDcUhqC/UKUr2a2fIUsB7qF +OGcNfIivdCq1CIP/kXmsdOGDV0STKtJNs24WCA0pO+g4GEvP3ZAZKuiHrqoxGVuc +tmMCfZw11RMzNJVysX3oP6TZQMzDMX14iEkTedBUm+AFr3SX2TdoePHaLzMCIftr +9JDth5qds5eEtQ7ZnEOKKSf+ej4EcI00Km0Q3njvc4HwdPdpizzRObOZjBvBUy/U +9XePmu2tDGfZ19kRIuk7QSDMGWuV/xym32wOkEfU1xItytm899qDRpqULaBLriiW +wqcCAwEAAaOBxTCBwjAOBgNVHQ8BAf8EBAMCB4AwHwYDVR0jBBgwFoAUiI0WI333 +r30GFI3h1ZfeTKYGOrcwgY4GA1UdEQSBhjCBg4YqeDUwOXBvcDovL2V4YW1wbGUu +b3JnL2RhdGFjZW50ZXIvdXMtZWFzdC0xhix4NTA5cG9wOi8vZXhhbXBsZS5vcmcv +ZW52aXJvbm1lbnQvcHJvZHVjdGlvboYneDUwOXBvcDovL2V4YW1wbGUub3JnL2tl +eS9wYXRoL3RvL3ZhbHVlMA0GCSqGSIb3DQEBCwUAA4IBAQCgqrb7owFhuskaV8rL +hMzN7hz9mbjO14Kc9Bk1QgnToTkya/l3m69xYKuaccMqyuCtbW6xYGk2t7nSYVBd +FkN59gZWrEAeTLB6F+jDf0SBoaY3bphuYpgGoaIcpbHqyjr7Ix/g6wy3PXzjqCe1 ++7WVCkltFoQZBIhO6/50z7ez+yjjn90xRggIJ1V1qRiZmfnhQpNW1++9Nx8NDAk7 +5bLYQCuRIFglpfm/beRWp7h2VOHvycid4nOJAtETQpSHweAYrO/hOd8dXzmsFIO4 +MFshM8e83tuohXtGMmU6leU6nsABw1ApuCVTj11BpU8bBJ1AR4JqQOsx7s350fqo +wW1P -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIBaDCB86ADAgECAgNNXm8wDQYJKoZIhvcNAQELBQAwADAiGA8wMDAxMDEwMTAw -MDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAAMHwwDQYJKoZIhvcNAQEBBQADawAwaAJh -ALaWTeGivnnNjL964wNhM80p8b8yTa6mpq+rYj3L0UIYJHcPBQ7XB7o0+EWWEsKW -Qs5E5vY8p56aq0y4pU0SgIMioqThX+KcmLMgs1JoJ42ZE20eFYDVqcWfSJp4o4w+ -hQIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2FBvOaL0Mi7fy -W2QJimLBmz5PKTANBgkqhkiG9w0BAQsFAANhADOBJA7AEgjKU++fRmWauP8pR+Nk -v9nbj0mABiBA0GUX116MwKs/nWq56IgzCTzqRbLKMeQt+7AIdFNp4kcrEcKU57Vw -SWgH3QLhFGbXi61FGEfFvomk72ksIV6loR6lrg== +MIICszCCAZugAwIBAgIDTV5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMANo2N0Od2EOIc/OTnbVqtoyFK3WXPkS0cYVU4Gb54F2ziFHUzK +pThvrGWg7JS2W5wFOKbZmVJgMZAQHR5yS3Gio5qbi4wy7BZiBFPdrL0cltPr5rhj +J4Lz5W2LBv8Dzwt++/uad/nLk2p6+Vgu7Vi5WwBDtZ1bti5SdAYin2pJiiABLquD +leZlW8DJStQF+/fY0jlEtHIuQwWLQLNJy7vXs2CNvNsbZ8psw4i6jdKwszkZ9vbk +Gds4yz7re2UK+mkXbfB9gzR96hle2EnvZPJqTvVWOyeO9Hw8EwxaYKtnc5nNt7FE +vqGWbX5mQ89y+VG3+BK8XQ2EZyIcIwJxQIcCAwEAAaMyMDAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUiI0WI333r30GFI3h1ZfeTKYGOrcwDQYJKoZIhvcNAQEL +BQADggEBAFY9iuoed1Cgan9JfhSbDYc2ez9lSV4dCC56VKldgNcAH8ZP6sDscCkp ++EuayP22OAbFj8qMPRxP1moYaeuu+F7Nslar2xsonHWEH1ZjO5lwRwtAXhOKFD4F +rr9VXqdBaUVKx0lBHeLsfv0JbtXhsjMhcLubc9DU8dsuM5HTnf7UZ2pgI+v0ebH3 +/FYKNZ1gk36kURv2HmCZo4qlDcLC37OG4pMAbDKqRvBvFrQS1J4QVTkjbINEmVDY +a3604pKKBUJ6uWEcZeBNW7Y471MTfjtGfIISeYbZaESGuxUWa8FNM/MMFmqabe1q +8UxB5dpx8Pqm4KmxHPCjIZjKXrJL0GQ= -----END CERTIFICATE----- diff --git a/test/fixture/nodeattestor/x509pop/leaf-key.pem b/test/fixture/nodeattestor/x509pop/leaf-key.pem index 9fe15e6a65..7aa320fe10 100644 --- a/test/fixture/nodeattestor/x509pop/leaf-key.pem +++ b/test/fixture/nodeattestor/x509pop/leaf-key.pem @@ -1,13 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIB5QIBADANBgkqhkiG9w0BAQEFAASCAc8wggHLAgEAAmEA5U8PaK/tZ5jSL3Zm -QAgo/tzS1tFaV78dePtI++P3jCyNUGWgHtdZKuLajn4rUKzOodXA4J91cPewLy3U -q4X1/4GExgrqvosOZOm+59zicAGfxdhx+uDI5NVFnBgWcME1AgMBAAECYQDbSM+j -fRm6iBn36XG+qg8KKoI1i96pKso0d5lDyK1iDvjUeVq2I5nRuT7oJR+m9piUI0Bp -ZXuQYdbvNKQMneo6vfM2Q8RFzfbMErtyjDztD5qFTV339u3j7dbSMUCafcECMQDz -h4oQTR56B5to32oLOUBntubVVjVOJhqsYV2vGVijzNeFeN1TQZf5bf2DZHSeFGMC -MQDxDRnPL7781JoIEpozRw+NkAA3+x6fkoTms1p37ot1fiVt5PWOX9ZKpRCLLDPp -S4cCMGcAUdXZOGW2p/WwYQLEQUhcpL9gygT2uttkByLTHpmRPyrV1w6qtKOr8MjN -CUH/LwIxAN7KGPyhSIgth1/GsbaLCxjv6wPSmW8q4KLJSehnFYY2XSnA4CQC9/Bt -t2iqJiCNqQIwLd2tR9k8VmX+6cGbFK4tD/4i5HuNLtDizZ/DnYZcKqkR61gzr7Us -B69agNW/wxep +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmtLV6u8xR4Hmp +IHZTt6Su3FkEteLLWcyIYLQ1/I01qUi2gUm26QLwqzPKLChw3FIagv1ClK9mtnyF +LAe6hThnDXyIr3QqtQiD/5F5rHThg1dEkyrSTbNuFggNKTvoOBhLz92QGSroh66q +MRlbnLZjAn2cNdUTMzSVcrF96D+k2UDMwzF9eIhJE3nQVJvgBa90l9k3aHjx2i8z +AiH7a/SQ7YeanbOXhLUO2ZxDiikn/no+BHCNNCptEN5473OB8HT3aYs80TmzmYwb +wVMv1PV3j5rtrQxn2dfZESLpO0EgzBlrlf8cpt9sDpBH1NcSLcrZvPfag0aalC2g +S64olsKnAgMBAAECggEAEhVGHlMivbrw14S68SfZiFJEobstJ8vM4PpEchq8IpcD +WTC7E0lBVWPs0UBq/psXmOKeoEtKn4SqCzQUfooW7S7MVHNb0Yojq1XcrOslHpVF +sR2ZpohhL07afrr7UZxMHmUk7o2cVu7o5nM/Ae4E5saNY5V/UH7cdF2lnTfFN5dg +jgeK4V4O7qUlU6fi7dVYrb7kINzsa4qk03kjQa6pjTnOgY4fjyZMJugJefIpVqV2 +qiabJmk6KtstwBhrnd0vqhpEBvTHHBbvHjtcdC/PN15vQGfcreE0aJcpgpEpVxzn +JQ7XkyGwlFzNSnoO9bYHjWloS1Q3DDqMQHGF6hBGAQKBgQDY5FP4IrgACFBwBOhu +A9kx82kZFGnFxD6BnLqbKz+WIYkaIQ8PKe7j/8JWPB1i0D/RmY1K1v3ONqFd8vNc +90qHvf1DN5TGZCN4RebGQgeKkdI50Dt2PxMYuSuLAEObFfPv+AhkJGMq5b9fxFEO +qhjco35mntrg9cysL/VkMnA9AQKBgQDEw87fJqWV4C2qu8lIHzc9L6t/AJEb89g8 +HPXvpZNZ3aTlfEV25pYYB1eAuh98T8skrVmuAvk6rwXcYHSXFuq5W8eZimkjJ8ag +PC3IU6rL+c9vM3Ev+GHVkQ7Sb+lInuldod0Fq5/Lf2Gs665eJbblqVYFV0uxJGE3 +zBm0v4P3pwKBgDDI4s48WPDA7f7US8d7HB5tJqWaftQZ+QlETIDccHf/YQw8hVue +zfoArCCjcuSn/MLTbAF6bCo3BYLRQ8YUZXI03MOCu/cHzSafanILphCYDhYs7UMC +mvQDqnSggZRfkrfWLWUA/kFG3g3XZXgL8H2oVKUWdBsHjproSqTX54EBAoGBAJ9j +flCFndyqnFORiptBrh2CYAmhC+r4vFD1pMNb/ODvCoRbBmoqn6sXR2qfWqH4gTZU +tjCfeARxgu3htJAvoDRGhIl79W7k6aEjHnMIU3KoCcCqiyWwro+x0a/lt7N8Bs4y +MDhHrknKBfVtdPIO2vlvEp+A92+naJkqXChuexhBAoGAAkFMaDNgKMVGEP8vmY6G +hxqkuVQg0nWVMW7y7Svm6x++iSSZKMfemjw9PSBBP/NbeuM9P4buCvqyooGwdwm3 +fu3fm0eQlKvjqhsaA5AJlHR0cyvRU0+k/WwXyoNTZD9468cMAq0bio9OGUaxynea +tenMVkPXDcj3ggvU4J0waSw= -----END PRIVATE KEY----- diff --git a/test/fixture/nodeattestor/x509pop/leaf.pem b/test/fixture/nodeattestor/x509pop/leaf.pem index 04886daa08..737ea43a3f 100644 --- a/test/fixture/nodeattestor/x509pop/leaf.pem +++ b/test/fixture/nodeattestor/x509pop/leaf.pem @@ -1,14 +1,21 @@ -----BEGIN CERTIFICATE----- -MIICFTCCAZ+gAwIBAgIGChssPU5fMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx +MIIDXzCCAkegAwIBAgIGChssPU5fMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowFTETMBEGA1UEAxMKQ09NTU9OTkFN -RTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDlTw9or+1nmNIvdmZACCj+3NLW0VpX -vx14+0j74/eMLI1QZaAe11kq4tqOfitQrM6h1cDgn3Vw97AvLdSrhfX/gYTGCuq+ -iw5k6b7n3OJwAZ/F2HH64Mjk1UWcGBZwwTUCAwEAAaOBxTCBwjAOBgNVHQ8BAf8E -BAMCB4AwHwYDVR0jBBgwFoAUNhQbzmi9DIu38ltkCYpiwZs+TykwgY4GA1UdEQSB -hjCBg4YqeDUwOXBvcDovL2V4YW1wbGUub3JnL2RhdGFjZW50ZXIvdXMtZWFzdC0x -hix4NTA5cG9wOi8vZXhhbXBsZS5vcmcvZW52aXJvbm1lbnQvcHJvZHVjdGlvboYn -eDUwOXBvcDovL2V4YW1wbGUub3JnL2tleS9wYXRoL3RvL3ZhbHVlMA0GCSqGSIb3 -DQEBCwUAA2EACXpd607HIbI8FUFjVBWugGUJOE2OSTHJ11tErBghIC+dmGUXa9x4 -gfBBRjw7oZFqtZgDodi6dLd05LwYjT31b+fBNDH3B2IKCG4jwFGkgJ4LE5S0BVIT -eoqivvzXS4cu +RTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKa0tXq7zFHgeakgdlO3 +pK7cWQS14stZzIhgtDX8jTWpSLaBSbbpAvCrM8osKHDcUhqC/UKUr2a2fIUsB7qF +OGcNfIivdCq1CIP/kXmsdOGDV0STKtJNs24WCA0pO+g4GEvP3ZAZKuiHrqoxGVuc +tmMCfZw11RMzNJVysX3oP6TZQMzDMX14iEkTedBUm+AFr3SX2TdoePHaLzMCIftr +9JDth5qds5eEtQ7ZnEOKKSf+ej4EcI00Km0Q3njvc4HwdPdpizzRObOZjBvBUy/U +9XePmu2tDGfZ19kRIuk7QSDMGWuV/xym32wOkEfU1xItytm899qDRpqULaBLriiW +wqcCAwEAAaOBxTCBwjAOBgNVHQ8BAf8EBAMCB4AwHwYDVR0jBBgwFoAUiI0WI333 +r30GFI3h1ZfeTKYGOrcwgY4GA1UdEQSBhjCBg4YqeDUwOXBvcDovL2V4YW1wbGUu +b3JnL2RhdGFjZW50ZXIvdXMtZWFzdC0xhix4NTA5cG9wOi8vZXhhbXBsZS5vcmcv +ZW52aXJvbm1lbnQvcHJvZHVjdGlvboYneDUwOXBvcDovL2V4YW1wbGUub3JnL2tl +eS9wYXRoL3RvL3ZhbHVlMA0GCSqGSIb3DQEBCwUAA4IBAQCgqrb7owFhuskaV8rL +hMzN7hz9mbjO14Kc9Bk1QgnToTkya/l3m69xYKuaccMqyuCtbW6xYGk2t7nSYVBd +FkN59gZWrEAeTLB6F+jDf0SBoaY3bphuYpgGoaIcpbHqyjr7Ix/g6wy3PXzjqCe1 ++7WVCkltFoQZBIhO6/50z7ez+yjjn90xRggIJ1V1qRiZmfnhQpNW1++9Nx8NDAk7 +5bLYQCuRIFglpfm/beRWp7h2VOHvycid4nOJAtETQpSHweAYrO/hOd8dXzmsFIO4 +MFshM8e83tuohXtGMmU6leU6nsABw1ApuCVTj11BpU8bBJ1AR4JqQOsx7s350fqo +wW1P -----END CERTIFICATE----- diff --git a/test/fixture/nodeattestor/x509pop/root-crt.pem b/test/fixture/nodeattestor/x509pop/root-crt.pem index 9e36cb1bd5..4dfa6a1665 100644 --- a/test/fixture/nodeattestor/x509pop/root-crt.pem +++ b/test/fixture/nodeattestor/x509pop/root-crt.pem @@ -1,10 +1,17 @@ -----BEGIN CERTIFICATE----- -MIIBaDCB86ADAgECAgMaKzwwDQYJKoZIhvcNAQELBQAwADAiGA8wMDAxMDEwMTAw -MDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAAMHwwDQYJKoZIhvcNAQEBBQADawAwaAJh -ALKIawaz1D65b3PIiQX1hNw/P3ooQGP1TWA1ljPrbMNaeEknkXnLLqpvTNDiZuuy -XeQRMcfhQw40D5GOXF1bNqHT5eBDXL875Advg8oSAusz8c1KR+pHDFdaOsME+B6q -rwIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRk+dq09oRmca9H -e6WkMzIXYcEkdDANBgkqhkiG9w0BAQsFAANhADz62bzT/odKiqawXsOTSACyhMb/ -K+G2W/2TptH8T9onLJjbrxvuvoSR7mnneTXxaS572TTowz+6igsBdDhtdAd3bCmz -e4Ty1ihYDu4OjBwYF7FxpozumQ3hqCnYtraCgQ== +MIICszCCAZugAwIBAgIDGis8MA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKukyc1g/8xcNeaMo78B6l6sSFRtcalVUkIyFo799aNSBOwJVn5R +ITWU1McrRwj7VXL7p0F4wKNV4juHPUpfExihqxe9OGtKWpR8eSE/OofS13o5uMza +R/5hxRSib8gO19sdoYd3YdaOas61gy2lIB2vnIK84WG0mSiBY/IuN6sPBkiaPxPh +iJjcfT6JdFFdwvDUexktDogacxYk1KbAKcfd+1HSQMOixcMqWcMQcmMCRCqIQTJx +CGwDzdQO8OuqZdt1euOVEO40Jfg4+yXvgxtlrrFfO+epadLVk7Pk0yl2EHiIhRXr +TchHB4LQA/FpUSHjrRSRN7+XN+pnG8/+2msCAwEAAaMyMDAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUpZkJIF8hoZtmdEbeMq1VdLd6U0UwDQYJKoZIhvcNAQEL +BQADggEBADd+auJk+WvaBKKnnuVCo9UFcd8xekA1CpRunTmplCPtQF1iGmyx80L3 +HPLzIvi0OeBwnVSHmBfNEgzdoXYY+lqwxMHQWP0oEmYLRrLQmLnIGAbor7J0+4Go +lPYSCAEMwFV2udhIsZC+aQ3L94o/3sgzut7B/751b8IDN4HysRP0HZ1otibpNeRH +1+91zTZuHrkPs11EPjDiqUzlGF5renPaMQ/VGnUReb+T7JhIwB2lC376jHUZI67q +/sY5QGcDtaE1QjeXnmkezrDvOw6WyUDxPtEDjySd/5Q/sTXQu73WQ5mRP/r3vZrz +FkzS/4dA153/Tnq/IDGD1Tf2wt+Iu8Q= -----END CERTIFICATE----- diff --git a/test/fixture/nodeattestor/x509pop/svidexchange.pem b/test/fixture/nodeattestor/x509pop/svidexchange.pem index 18e9a5b373..936e7ad9ce 100644 --- a/test/fixture/nodeattestor/x509pop/svidexchange.pem +++ b/test/fixture/nodeattestor/x509pop/svidexchange.pem @@ -1,25 +1,39 @@ -----BEGIN CERTIFICATE----- -MIICQzCCAc2gAwIBAgIGChssPU5/MA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx +MIIDjTCCAnWgAwIBAgIGChssPU5/MA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowFTETMBEGA1UEAxMKQ09NTU9OTkFN -RTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDlTw9or+1nmNIvdmZACCj+3NLW0VpX -vx14+0j74/eMLI1QZaAe11kq4tqOfitQrM6h1cDgn3Vw97AvLdSrhfX/gYTGCuq+ -iw5k6b7n3OJwAZ/F2HH64Mjk1UWcGBZwwTUCAwEAAaOB8zCB8DAOBgNVHQ8BAf8E -BAMCB4AwHwYDVR0jBBgwFoAUNhQbzmi9DIu38ltkCYpiwZs+TykwgbwGA1UdEQSB -tDCBsYYsc3BpZmZlOi8vZXhhbXBsZS5vcmcvc3BpcmUtZXhjaGFuZ2UvdGVzdGhv -c3SGKng1MDlwb3A6Ly9leGFtcGxlLm9yZy9kYXRhY2VudGVyL3VzLWVhc3QtMYYs -eDUwOXBvcDovL2V4YW1wbGUub3JnL2Vudmlyb25tZW50L3Byb2R1Y3Rpb26GJ3g1 -MDlwb3A6Ly9leGFtcGxlLm9yZy9rZXkvcGF0aC90by92YWx1ZTANBgkqhkiG9w0B -AQsFAANhADcgsPZ6WdGKcwq7C8UoGjSmQz84+Gj4EP6+Yu+4DBydkTla5ZQUk2ck -lR+XLUclhAYuDxV46WLGGC2ppmueU4nDXFD0afbnc47P7t/zthYF+TxoaRmnKljd -NB/+3/o6AQ== +RTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKa0tXq7zFHgeakgdlO3 +pK7cWQS14stZzIhgtDX8jTWpSLaBSbbpAvCrM8osKHDcUhqC/UKUr2a2fIUsB7qF +OGcNfIivdCq1CIP/kXmsdOGDV0STKtJNs24WCA0pO+g4GEvP3ZAZKuiHrqoxGVuc +tmMCfZw11RMzNJVysX3oP6TZQMzDMX14iEkTedBUm+AFr3SX2TdoePHaLzMCIftr +9JDth5qds5eEtQ7ZnEOKKSf+ej4EcI00Km0Q3njvc4HwdPdpizzRObOZjBvBUy/U +9XePmu2tDGfZ19kRIuk7QSDMGWuV/xym32wOkEfU1xItytm899qDRpqULaBLriiW +wqcCAwEAAaOB8zCB8DAOBgNVHQ8BAf8EBAMCB4AwHwYDVR0jBBgwFoAUiI0WI333 +r30GFI3h1ZfeTKYGOrcwgbwGA1UdEQSBtDCBsYYsc3BpZmZlOi8vZXhhbXBsZS5v +cmcvc3BpcmUtZXhjaGFuZ2UvdGVzdGhvc3SGKng1MDlwb3A6Ly9leGFtcGxlLm9y +Zy9kYXRhY2VudGVyL3VzLWVhc3QtMYYseDUwOXBvcDovL2V4YW1wbGUub3JnL2Vu +dmlyb25tZW50L3Byb2R1Y3Rpb26GJ3g1MDlwb3A6Ly9leGFtcGxlLm9yZy9rZXkv +cGF0aC90by92YWx1ZTANBgkqhkiG9w0BAQsFAAOCAQEAsRNPe2CH/HvHqh1BmXip +pCmUN0kDR6l3xOaI3kF8+b2mFzg8xgHgBO/F0RHvS/tW4iXPft2gdRoLT5C1ZGH7 +0Ekb78hsqAp9toNWH87mliPM9DHAQOZaxMmE5fxhts3XNUszazOwCjXqvPa/ZFTC +E0o+3maUT+ilxqWT4mME+NByH5s3YohgsaGVPASMIOO9ZkUCjsWPM6+YLPBC4nCM +D27dC1XiUlfRYDBGwhGYUNZJQcaL2116qkT1W9+Q/xqLDsSsO0HuLPZpKmGuWcCU +PzcJc5BkbxptxY2K1KzwgCS71wz6NJ7J1DIxQDKD1xDnkJd+MJvsPN4qvpT03OWT +Aw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIBaDCB86ADAgECAgNNXm8wDQYJKoZIhvcNAQELBQAwADAiGA8wMDAxMDEwMTAw -MDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAAMHwwDQYJKoZIhvcNAQEBBQADawAwaAJh -ALaWTeGivnnNjL964wNhM80p8b8yTa6mpq+rYj3L0UIYJHcPBQ7XB7o0+EWWEsKW -Qs5E5vY8p56aq0y4pU0SgIMioqThX+KcmLMgs1JoJ42ZE20eFYDVqcWfSJp4o4w+ -hQIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2FBvOaL0Mi7fy -W2QJimLBmz5PKTANBgkqhkiG9w0BAQsFAANhADOBJA7AEgjKU++fRmWauP8pR+Nk -v9nbj0mABiBA0GUX116MwKs/nWq56IgzCTzqRbLKMeQt+7AIdFNp4kcrEcKU57Vw -SWgH3QLhFGbXi61FGEfFvomk72ksIV6loR6lrg== +MIICszCCAZugAwIBAgIDTV5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMANo2N0Od2EOIc/OTnbVqtoyFK3WXPkS0cYVU4Gb54F2ziFHUzK +pThvrGWg7JS2W5wFOKbZmVJgMZAQHR5yS3Gio5qbi4wy7BZiBFPdrL0cltPr5rhj +J4Lz5W2LBv8Dzwt++/uad/nLk2p6+Vgu7Vi5WwBDtZ1bti5SdAYin2pJiiABLquD +leZlW8DJStQF+/fY0jlEtHIuQwWLQLNJy7vXs2CNvNsbZ8psw4i6jdKwszkZ9vbk +Gds4yz7re2UK+mkXbfB9gzR96hle2EnvZPJqTvVWOyeO9Hw8EwxaYKtnc5nNt7FE +vqGWbX5mQ89y+VG3+BK8XQ2EZyIcIwJxQIcCAwEAAaMyMDAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUiI0WI333r30GFI3h1ZfeTKYGOrcwDQYJKoZIhvcNAQEL +BQADggEBAFY9iuoed1Cgan9JfhSbDYc2ez9lSV4dCC56VKldgNcAH8ZP6sDscCkp ++EuayP22OAbFj8qMPRxP1moYaeuu+F7Nslar2xsonHWEH1ZjO5lwRwtAXhOKFD4F +rr9VXqdBaUVKx0lBHeLsfv0JbtXhsjMhcLubc9DU8dsuM5HTnf7UZ2pgI+v0ebH3 +/FYKNZ1gk36kURv2HmCZo4qlDcLC37OG4pMAbDKqRvBvFrQS1J4QVTkjbINEmVDY +a3604pKKBUJ6uWEcZeBNW7Y471MTfjtGfIISeYbZaESGuxUWa8FNM/MMFmqabe1q +8UxB5dpx8Pqm4KmxHPCjIZjKXrJL0GQ= -----END CERTIFICATE----- diff --git a/test/fixture/nodeattestor/x509pop/svidreg.pem b/test/fixture/nodeattestor/x509pop/svidreg.pem index d105005713..65c626e409 100644 --- a/test/fixture/nodeattestor/x509pop/svidreg.pem +++ b/test/fixture/nodeattestor/x509pop/svidreg.pem @@ -1,21 +1,35 @@ -----BEGIN CERTIFICATE----- -MIIBrDCCATagAwIBAgIGChssPU5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx +MIIC9jCCAd6gAwIBAgIGChssPU5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAx MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowFTETMBEGA1UEAxMKQ09NTU9OTkFN -RTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDlTw9or+1nmNIvdmZACCj+3NLW0VpX -vx14+0j74/eMLI1QZaAe11kq4tqOfitQrM6h1cDgn3Vw97AvLdSrhfX/gYTGCuq+ -iw5k6b7n3OJwAZ/F2HH64Mjk1UWcGBZwwTUCAwEAAaNdMFswDgYDVR0PAQH/BAQD -AgeAMB8GA1UdIwQYMBaAFDYUG85ovQyLt/JbZAmKYsGbPk8pMCgGA1UdEQQhMB+G -HXNwaWZmZTovL2V4YW1wbGUub3JnL3NvbWVzdmlkMA0GCSqGSIb3DQEBCwUAA2EA -EihBZKPIogPRoxohOcm61SRe+8n9OMxORlMg6ovXKQd/nv1B1HF2X0BCxXcoHDae -MMKzAxmbPHlwmLw1Y5J1SkDLEyNb/ZYOWbVMpgfAdaXMVg1R/pW2aZThpjkUZel5 +RTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKa0tXq7zFHgeakgdlO3 +pK7cWQS14stZzIhgtDX8jTWpSLaBSbbpAvCrM8osKHDcUhqC/UKUr2a2fIUsB7qF +OGcNfIivdCq1CIP/kXmsdOGDV0STKtJNs24WCA0pO+g4GEvP3ZAZKuiHrqoxGVuc +tmMCfZw11RMzNJVysX3oP6TZQMzDMX14iEkTedBUm+AFr3SX2TdoePHaLzMCIftr +9JDth5qds5eEtQ7ZnEOKKSf+ej4EcI00Km0Q3njvc4HwdPdpizzRObOZjBvBUy/U +9XePmu2tDGfZ19kRIuk7QSDMGWuV/xym32wOkEfU1xItytm899qDRpqULaBLriiW +wqcCAwEAAaNdMFswDgYDVR0PAQH/BAQDAgeAMB8GA1UdIwQYMBaAFIiNFiN99699 +BhSN4dWX3kymBjq3MCgGA1UdEQQhMB+GHXNwaWZmZTovL2V4YW1wbGUub3JnL3Nv +bWVzdmlkMA0GCSqGSIb3DQEBCwUAA4IBAQAttoP6qX03+oPc4yF7OyBL2DeNuWG7 +Nr+jS8AgwAmWcF7gr02NnqrwmN1Nd1nHZIupXugLEEkTcstWYE8IpupAy8PTmwlX +rVtBlpNZLwahg+Vjb/96mY9ecwuGmAe/6eYzdYwQYYfIG9EMvh9hCSJtKHVYMOUd +wqvmkHXfiV+ud0UnUAYDKLXjjJ7+r0knzsJ/ZXMVQ9eJZWbALACjQJcE6AtUgeBv +8ILKNYqclOsRyuLZbNBPP8jMnQyjFrd8Xqm6ZC091nSrX9e5HuSPA5sP6DFk0yb1 +1J/hCkMIchF4mUUaZHbNfiCAdMGOBJqPORYGIGDhOjLBfvk8Hmq/up+m -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIBaDCB86ADAgECAgNNXm8wDQYJKoZIhvcNAQELBQAwADAiGA8wMDAxMDEwMTAw -MDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAAMHwwDQYJKoZIhvcNAQEBBQADawAwaAJh -ALaWTeGivnnNjL964wNhM80p8b8yTa6mpq+rYj3L0UIYJHcPBQ7XB7o0+EWWEsKW -Qs5E5vY8p56aq0y4pU0SgIMioqThX+KcmLMgs1JoJ42ZE20eFYDVqcWfSJp4o4w+ -hQIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2FBvOaL0Mi7fy -W2QJimLBmz5PKTANBgkqhkiG9w0BAQsFAANhADOBJA7AEgjKU++fRmWauP8pR+Nk -v9nbj0mABiBA0GUX116MwKs/nWq56IgzCTzqRbLKMeQt+7AIdFNp4kcrEcKU57Vw -SWgH3QLhFGbXi61FGEfFvomk72ksIV6loR6lrg== +MIICszCCAZugAwIBAgIDTV5vMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMANo2N0Od2EOIc/OTnbVqtoyFK3WXPkS0cYVU4Gb54F2ziFHUzK +pThvrGWg7JS2W5wFOKbZmVJgMZAQHR5yS3Gio5qbi4wy7BZiBFPdrL0cltPr5rhj +J4Lz5W2LBv8Dzwt++/uad/nLk2p6+Vgu7Vi5WwBDtZ1bti5SdAYin2pJiiABLquD +leZlW8DJStQF+/fY0jlEtHIuQwWLQLNJy7vXs2CNvNsbZ8psw4i6jdKwszkZ9vbk +Gds4yz7re2UK+mkXbfB9gzR96hle2EnvZPJqTvVWOyeO9Hw8EwxaYKtnc5nNt7FE +vqGWbX5mQ89y+VG3+BK8XQ2EZyIcIwJxQIcCAwEAAaMyMDAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUiI0WI333r30GFI3h1ZfeTKYGOrcwDQYJKoZIhvcNAQEL +BQADggEBAFY9iuoed1Cgan9JfhSbDYc2ez9lSV4dCC56VKldgNcAH8ZP6sDscCkp ++EuayP22OAbFj8qMPRxP1moYaeuu+F7Nslar2xsonHWEH1ZjO5lwRwtAXhOKFD4F +rr9VXqdBaUVKx0lBHeLsfv0JbtXhsjMhcLubc9DU8dsuM5HTnf7UZ2pgI+v0ebH3 +/FYKNZ1gk36kURv2HmCZo4qlDcLC37OG4pMAbDKqRvBvFrQS1J4QVTkjbINEmVDY +a3604pKKBUJ6uWEcZeBNW7Y471MTfjtGfIISeYbZaESGuxUWa8FNM/MMFmqabe1q +8UxB5dpx8Pqm4KmxHPCjIZjKXrJL0GQ= -----END CERTIFICATE----- diff --git a/test/testkey/keys.go b/test/testkey/keys.go index 6a407eccae..f9e18bedad 100644 --- a/test/testkey/keys.go +++ b/test/testkey/keys.go @@ -5,6 +5,8 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/rsa" + "crypto/x509" + "encoding/pem" "sync" "testing" @@ -23,34 +25,190 @@ func NewRSA2048(tb testing.TB) *rsa.PrivateKey { return keys.NewRSA2048(tb) } +func NewRSA2048PKCS1PEM(tb testing.TB) []byte { + key := NewRSA2048(tb) + keyDER := x509.MarshalPKCS1PrivateKey(key) + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: keyDER, + }) +} + +func NewRSA2048PKCS8PEM(tb testing.TB) []byte { + key := NewRSA2048(tb) + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func MustRSA2048() *rsa.PrivateKey { return keys.MustRSA2048() } +func MustRSA2048PKCS1PEM() []byte { + key := keys.MustRSA2048() + keyDER := x509.MarshalPKCS1PrivateKey(key) + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: keyDER, + }) +} + +func MustRSA2048PKCS8PEM() []byte { + key := keys.MustRSA2048() + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func NewRSA4096(tb testing.TB) *rsa.PrivateKey { return keys.NewRSA4096(tb) } +func NewRSA4096PKCS1PEM(tb testing.TB) []byte { + key := NewRSA4096(tb) + keyDER := x509.MarshalPKCS1PrivateKey(key) + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: keyDER, + }) +} + +func NewRSA4096PKCS8PEM(tb testing.TB) []byte { + key := NewRSA4096(tb) + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func MustRSA4096() *rsa.PrivateKey { return keys.MustRSA4096() } +func MustRSA4096PKCS1PEM() []byte { + key := keys.MustRSA4096() + keyDER := x509.MarshalPKCS1PrivateKey(key) + return pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: keyDER, + }) +} + +func MustRSA4096PKCS8PEM() []byte { + key := keys.MustRSA4096() + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func NewEC256(tb testing.TB) *ecdsa.PrivateKey { return keys.NewEC256(tb) } +func NewEC256PKCS1PEM(tb testing.TB) []byte { + key := NewEC256(tb) + keyDER, err := x509.MarshalECPrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: keyDER, + }) +} + +func NewEC256PKCS8PEM(tb testing.TB) []byte { + key := NewEC256(tb) + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func MustEC256() *ecdsa.PrivateKey { return keys.MustEC256() } +func MustEC256PKCS1PEM() []byte { + key := keys.MustEC256() + keyDER, err := x509.MarshalECPrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: keyDER, + }) +} + +func MustEC256PKCS8PEM() []byte { + key := keys.MustEC256() + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func NewEC384(tb testing.TB) *ecdsa.PrivateKey { return keys.NewEC384(tb) } +func NewEC384PKCS1PEM(tb testing.TB) []byte { + key := NewEC384(tb) + keyDER, err := x509.MarshalECPrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: keyDER, + }) +} + +func NewEC384PKCS8PEM(tb testing.TB) []byte { + key := NewEC384(tb) + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + require.NoError(tb, err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + func MustEC384() *ecdsa.PrivateKey { return keys.MustEC384() } +func MustEC384PKCS1PEM() []byte { + key := keys.MustEC384() + keyDER, err := x509.MarshalECPrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: keyDER, + }) +} + +func MustEC384PKCS8PEM() []byte { + key := keys.MustEC384() + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + check(err) + return pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyDER, + }) +} + type Keys struct { mtx sync.Mutex rsa2048Idx int diff --git a/test/tpmsimulator/simulator.go b/test/tpmsimulator/simulator.go index 04f6b05315..7857f93765 100644 --- a/test/tpmsimulator/simulator.go +++ b/test/tpmsimulator/simulator.go @@ -21,9 +21,7 @@ import ( "github.com/spiffe/spire/pkg/common/pemutil" ) -var ( - ErrUsingClosedSimulator = simulator.ErrUsingClosedSimulator -) +var ErrUsingClosedSimulator = simulator.ErrUsingClosedSimulator type TPMSimulator struct { *simulator.Simulator @@ -300,12 +298,11 @@ func (s *TPMSimulator) createEndorsementCertificate() (*x509.Certificate, error) return nil, fmt.Errorf("cannot generate root certificate: %w", err) } - ekHandle, ekPublicBlob, _, _, _, _, err := - tpm2.CreatePrimaryEx(s, tpm2.HandleEndorsement, - tpm2.PCRSelection{}, - s.endorsementHierarchyPassword, - "", - client.DefaultEKTemplateRSA()) + ekHandle, ekPublicBlob, _, _, _, _, err := tpm2.CreatePrimaryEx(s, tpm2.HandleEndorsement, + tpm2.PCRSelection{}, + s.endorsementHierarchyPassword, + "", + client.DefaultEKTemplateRSA()) if err != nil { return nil, fmt.Errorf("cannot generate endorsement key pair: %w", err) } @@ -352,8 +349,7 @@ func (s *TPMSimulator) createOrdinaryKey(keyType KeyType, parentKeyPassword, key return nil, nil, fmt.Errorf("unknown key type: %v", keyType) } - srkHandle, _, _, _, _, _, err := - tpm2.CreatePrimaryEx(s, tpm2.HandleOwner, tpm2.PCRSelection{}, s.ownerHierarchyPassword, parentKeyPassword, srkTemplate) + srkHandle, _, _, _, _, _, err := tpm2.CreatePrimaryEx(s, tpm2.HandleOwner, tpm2.PCRSelection{}, s.ownerHierarchyPassword, parentKeyPassword, srkTemplate) if err != nil { return nil, nil, fmt.Errorf("cannot create new storage root key: %w", err) } @@ -418,7 +414,7 @@ func createCertificate(key any, tmpl *x509.Certificate, parentKey *rsa.PrivateKe } func generateRSAKey() (*rsa.PrivateKey, error) { - return rsa.GenerateKey(rand.Reader, 768) //nolint: gosec // small key is to keep test fast... not a security feature + return rsa.GenerateKey(rand.Reader, 2048) } func defaultDevIDTemplateRSA() tpm2.Public {