forked from TrueCloudLab/certificates
Verify CSR key fingerprint with attestation certificate key
This commit makes sure that the attestation certificate key matches the key used on the CSR on an ACME device attestation flow.
This commit is contained in:
parent
ec3be2359a
commit
6ba20209c2
9 changed files with 792 additions and 450 deletions
|
@ -8,15 +8,16 @@ import (
|
||||||
|
|
||||||
// Authorization representst an ACME Authorization.
|
// Authorization representst an ACME Authorization.
|
||||||
type Authorization struct {
|
type Authorization struct {
|
||||||
ID string `json:"-"`
|
ID string `json:"-"`
|
||||||
AccountID string `json:"-"`
|
AccountID string `json:"-"`
|
||||||
Token string `json:"-"`
|
Token string `json:"-"`
|
||||||
Identifier Identifier `json:"identifier"`
|
Identifier Identifier `json:"identifier"`
|
||||||
Status Status `json:"status"`
|
Status Status `json:"status"`
|
||||||
Challenges []*Challenge `json:"challenges"`
|
Challenges []*Challenge `json:"challenges"`
|
||||||
Wildcard bool `json:"wildcard"`
|
Wildcard bool `json:"wildcard"`
|
||||||
ExpiresAt time.Time `json:"expires"`
|
ExpiresAt time.Time `json:"expires"`
|
||||||
Error *Error `json:"error,omitempty"`
|
Fingerprint string `json:"fingerprint,omitempty"`
|
||||||
|
Error *Error `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToLog enables response logging.
|
// ToLog enables response logging.
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/fxamacker/cbor/v2"
|
"github.com/fxamacker/cbor/v2"
|
||||||
"go.step.sm/crypto/jose"
|
"go.step.sm/crypto/jose"
|
||||||
|
"go.step.sm/crypto/keyutil"
|
||||||
"go.step.sm/crypto/pemutil"
|
"go.step.sm/crypto/pemutil"
|
||||||
|
|
||||||
"github.com/smallstep/certificates/authority/provisioner"
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
@ -347,6 +348,13 @@ type attestationObject struct {
|
||||||
|
|
||||||
// TODO(bweeks): move attestation verification to a shared package.
|
// TODO(bweeks): move attestation verification to a shared package.
|
||||||
func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error {
|
func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error {
|
||||||
|
// Load authorization to store the key fingerprint.
|
||||||
|
az, err := db.GetAuthorization(ctx, ch.AuthorizationID)
|
||||||
|
if err != nil {
|
||||||
|
return WrapErrorISE(err, "error loading authorization")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse payload.
|
||||||
var p payloadType
|
var p payloadType
|
||||||
if err := json.Unmarshal(payload, &p); err != nil {
|
if err := json.Unmarshal(payload, &p); err != nil {
|
||||||
return WrapErrorISE(err, "error unmarshalling JSON")
|
return WrapErrorISE(err, "error unmarshalling JSON")
|
||||||
|
@ -385,7 +393,6 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
}
|
}
|
||||||
return WrapErrorISE(err, "error validating attestation")
|
return WrapErrorISE(err, "error validating attestation")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate nonce with SHA-256 of the token.
|
// Validate nonce with SHA-256 of the token.
|
||||||
if len(data.Nonce) != 0 {
|
if len(data.Nonce) != 0 {
|
||||||
sum := sha256.Sum256([]byte(ch.Token))
|
sum := sha256.Sum256([]byte(ch.Token))
|
||||||
|
@ -401,6 +408,9 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
if data.UDID != ch.Value && data.SerialNumber != ch.Value {
|
if data.UDID != ch.Value && data.SerialNumber != ch.Value {
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update attestation key fingerprint to compare against the CSR
|
||||||
|
az.Fingerprint = data.Fingerprint
|
||||||
case "step":
|
case "step":
|
||||||
data, err := doStepAttestationFormat(ctx, prov, ch, jwk, &att)
|
data, err := doStepAttestationFormat(ctx, prov, ch, jwk, &att)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -426,6 +436,9 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
)
|
)
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update attestation key fingerprint to compare against the CSR
|
||||||
|
az.Fingerprint = data.Fingerprint
|
||||||
default:
|
default:
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unexpected attestation object format"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unexpected attestation object format"))
|
||||||
}
|
}
|
||||||
|
@ -435,6 +448,15 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
ch.Error = nil
|
ch.Error = nil
|
||||||
ch.ValidatedAt = clock.Now().Format(time.RFC3339)
|
ch.ValidatedAt = clock.Now().Format(time.RFC3339)
|
||||||
|
|
||||||
|
// Store the fingerprint in the authorization.
|
||||||
|
//
|
||||||
|
// TODO: add method to update authorization and challenge atomically.
|
||||||
|
if az.Fingerprint != "" {
|
||||||
|
if err := db.UpdateAuthorization(ctx, az); err != nil {
|
||||||
|
return WrapErrorISE(err, "error updating authorization")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := db.UpdateChallenge(ctx, ch); err != nil {
|
if err := db.UpdateChallenge(ctx, ch); err != nil {
|
||||||
return WrapErrorISE(err, "error updating challenge")
|
return WrapErrorISE(err, "error updating challenge")
|
||||||
}
|
}
|
||||||
|
@ -471,6 +493,7 @@ type appleAttestationData struct {
|
||||||
UDID string
|
UDID string
|
||||||
SEPVersion string
|
SEPVersion string
|
||||||
Certificate *x509.Certificate
|
Certificate *x509.Certificate
|
||||||
|
Fingerprint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, att *attestationObject) (*appleAttestationData, error) {
|
func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, att *attestationObject) (*appleAttestationData, error) {
|
||||||
|
@ -527,6 +550,9 @@ func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challen
|
||||||
data := &appleAttestationData{
|
data := &appleAttestationData{
|
||||||
Certificate: leaf,
|
Certificate: leaf,
|
||||||
}
|
}
|
||||||
|
if data.Fingerprint, err = keyutil.Fingerprint(leaf.PublicKey); err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error calculating key fingerprint")
|
||||||
|
}
|
||||||
for _, ext := range leaf.Extensions {
|
for _, ext := range leaf.Extensions {
|
||||||
switch {
|
switch {
|
||||||
case ext.Id.Equal(oidAppleSerialNumber):
|
case ext.Id.Equal(oidAppleSerialNumber):
|
||||||
|
@ -572,6 +598,7 @@ var oidYubicoSerialNumber = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 41482, 3, 7}
|
||||||
type stepAttestationData struct {
|
type stepAttestationData struct {
|
||||||
Certificate *x509.Certificate
|
Certificate *x509.Certificate
|
||||||
SerialNumber string
|
SerialNumber string
|
||||||
|
Fingerprint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, jwk *jose.JSONWebKey, att *attestationObject) (*stepAttestationData, error) {
|
func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, jwk *jose.JSONWebKey, att *attestationObject) (*stepAttestationData, error) {
|
||||||
|
@ -667,6 +694,9 @@ func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challeng
|
||||||
data := &stepAttestationData{
|
data := &stepAttestationData{
|
||||||
Certificate: leaf,
|
Certificate: leaf,
|
||||||
}
|
}
|
||||||
|
if data.Fingerprint, err = keyutil.Fingerprint(leaf.PublicKey); err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error calculating key fingerprint")
|
||||||
|
}
|
||||||
for _, ext := range leaf.Extensions {
|
for _, ext := range leaf.Extensions {
|
||||||
if !ext.Id.Equal(oidYubicoSerialNumber) {
|
if !ext.Id.Equal(oidYubicoSerialNumber) {
|
||||||
continue
|
continue
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@ type dbAuthz struct {
|
||||||
Identifier acme.Identifier `json:"identifier"`
|
Identifier acme.Identifier `json:"identifier"`
|
||||||
Status acme.Status `json:"status"`
|
Status acme.Status `json:"status"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
Fingerprint string `json:"fingerprint,omitempty"`
|
||||||
ChallengeIDs []string `json:"challengeIDs"`
|
ChallengeIDs []string `json:"challengeIDs"`
|
||||||
Wildcard bool `json:"wildcard"`
|
Wildcard bool `json:"wildcard"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
@ -61,15 +62,16 @@ func (db *DB) GetAuthorization(ctx context.Context, id string) (*acme.Authorizat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &acme.Authorization{
|
return &acme.Authorization{
|
||||||
ID: dbaz.ID,
|
ID: dbaz.ID,
|
||||||
AccountID: dbaz.AccountID,
|
AccountID: dbaz.AccountID,
|
||||||
Identifier: dbaz.Identifier,
|
Identifier: dbaz.Identifier,
|
||||||
Status: dbaz.Status,
|
Status: dbaz.Status,
|
||||||
Challenges: chs,
|
Challenges: chs,
|
||||||
Wildcard: dbaz.Wildcard,
|
Wildcard: dbaz.Wildcard,
|
||||||
ExpiresAt: dbaz.ExpiresAt,
|
ExpiresAt: dbaz.ExpiresAt,
|
||||||
Token: dbaz.Token,
|
Token: dbaz.Token,
|
||||||
Error: dbaz.Error,
|
Fingerprint: dbaz.Fingerprint,
|
||||||
|
Error: dbaz.Error,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +99,7 @@ func (db *DB) CreateAuthorization(ctx context.Context, az *acme.Authorization) e
|
||||||
Identifier: az.Identifier,
|
Identifier: az.Identifier,
|
||||||
ChallengeIDs: chIDs,
|
ChallengeIDs: chIDs,
|
||||||
Token: az.Token,
|
Token: az.Token,
|
||||||
|
Fingerprint: az.Fingerprint,
|
||||||
Wildcard: az.Wildcard,
|
Wildcard: az.Wildcard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +114,8 @@ func (db *DB) UpdateAuthorization(ctx context.Context, az *acme.Authorization) e
|
||||||
}
|
}
|
||||||
|
|
||||||
nu := old.clone()
|
nu := old.clone()
|
||||||
|
|
||||||
nu.Status = az.Status
|
nu.Status = az.Status
|
||||||
|
nu.Fingerprint = az.Fingerprint
|
||||||
nu.Error = az.Error
|
nu.Error = az.Error
|
||||||
return db.save(ctx, old.ID, nu, old, "authz", authzTable)
|
return db.save(ctx, old.ID, nu, old, "authz", authzTable)
|
||||||
}
|
}
|
||||||
|
@ -136,15 +139,16 @@ func (db *DB) GetAuthorizationsByAccountID(ctx context.Context, accountID string
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
authzs = append(authzs, &acme.Authorization{
|
authzs = append(authzs, &acme.Authorization{
|
||||||
ID: dbaz.ID,
|
ID: dbaz.ID,
|
||||||
AccountID: dbaz.AccountID,
|
AccountID: dbaz.AccountID,
|
||||||
Identifier: dbaz.Identifier,
|
Identifier: dbaz.Identifier,
|
||||||
Status: dbaz.Status,
|
Status: dbaz.Status,
|
||||||
Challenges: nil, // challenges not required for current use case
|
Challenges: nil, // challenges not required for current use case
|
||||||
Wildcard: dbaz.Wildcard,
|
Wildcard: dbaz.Wildcard,
|
||||||
ExpiresAt: dbaz.ExpiresAt,
|
ExpiresAt: dbaz.ExpiresAt,
|
||||||
Token: dbaz.Token,
|
Token: dbaz.Token,
|
||||||
Error: dbaz.Error,
|
Fingerprint: dbaz.Fingerprint,
|
||||||
|
Error: dbaz.Error,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -473,6 +473,7 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
ChallengeIDs: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
|
Fingerprint: "fingerprint",
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -549,10 +550,11 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
{ID: "foo"},
|
{ID: "foo"},
|
||||||
{ID: "bar"},
|
{ID: "bar"},
|
||||||
},
|
},
|
||||||
Token: dbaz.Token,
|
Token: dbaz.Token,
|
||||||
Wildcard: dbaz.Wildcard,
|
Wildcard: dbaz.Wildcard,
|
||||||
ExpiresAt: dbaz.ExpiresAt,
|
ExpiresAt: dbaz.ExpiresAt,
|
||||||
Error: acme.NewError(acme.ErrorMalformedType, "malformed"),
|
Fingerprint: "fingerprint",
|
||||||
|
Error: acme.NewError(acme.ErrorMalformedType, "malformed"),
|
||||||
}
|
}
|
||||||
return test{
|
return test{
|
||||||
az: updAz,
|
az: updAz,
|
||||||
|
@ -582,6 +584,7 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
||||||
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
||||||
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
||||||
|
assert.Equals(t, dbNew.Fingerprint, dbaz.Fingerprint)
|
||||||
assert.Equals(t, dbNew.Error.Error(), acme.NewError(acme.ErrorMalformedType, "The request message was malformed").Error())
|
assert.Equals(t, dbNew.Error.Error(), acme.NewError(acme.ErrorMalformedType, "The request message was malformed").Error())
|
||||||
return nu, true, nil
|
return nu, true, nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ package acme
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/subtle"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/smallstep/certificates/authority/provisioner"
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
"go.step.sm/crypto/keyutil"
|
||||||
"go.step.sm/crypto/x509util"
|
"go.step.sm/crypto/x509util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -125,6 +127,27 @@ func (o *Order) UpdateStatus(ctx context.Context, db DB) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getKeyFingerprint returns a fingerprint from the list of authorizations. This
|
||||||
|
// fingerprint is used on the device-attest-01 flow to verify the attestation
|
||||||
|
// certificate public key with the CSR public key.
|
||||||
|
//
|
||||||
|
// There's no point on reading all the authorizations as there will be only one
|
||||||
|
// for a permanent identifier.
|
||||||
|
func (o *Order) getAuthorizationFingerprint(ctx context.Context, db DB) (string, error) {
|
||||||
|
for _, azID := range o.AuthorizationIDs {
|
||||||
|
az, err := db.GetAuthorization(ctx, azID)
|
||||||
|
if err != nil {
|
||||||
|
return "", WrapErrorISE(err, "error getting authorization %q", azID)
|
||||||
|
}
|
||||||
|
// There's no point on reading all the authorizations as there will
|
||||||
|
// be only one for a permanent identifier.
|
||||||
|
if az.Fingerprint != "" {
|
||||||
|
return az.Fingerprint, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
// Finalize signs a certificate if the necessary conditions for Order completion
|
// Finalize signs a certificate if the necessary conditions for Order completion
|
||||||
// have been met.
|
// have been met.
|
||||||
//
|
//
|
||||||
|
@ -150,6 +173,24 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques
|
||||||
return NewErrorISE("unexpected status %s for order %s", o.Status, o.ID)
|
return NewErrorISE("unexpected status %s for order %s", o.Status, o.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get key fingerprint if any. And then compare it with the CSR fingerprint.
|
||||||
|
//
|
||||||
|
// In device-attest-01 challenges we should check that the keys in the CSR
|
||||||
|
// and the attestation certificate are the same.
|
||||||
|
fingerprint, err := o.getAuthorizationFingerprint(ctx, db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fingerprint != "" {
|
||||||
|
fp, err := keyutil.Fingerprint(csr.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return WrapErrorISE(err, "error calculating key fingerprint")
|
||||||
|
}
|
||||||
|
if subtle.ConstantTimeCompare([]byte(fingerprint), []byte(fp)) == 0 {
|
||||||
|
return NewError(ErrorUnauthorizedType, "order %s csr does not match the attested key", o.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// canonicalize the CSR to allow for comparison
|
// canonicalize the CSR to allow for comparison
|
||||||
csr = canonicalize(csr)
|
csr = canonicalize(csr)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
|
@ -18,6 +19,7 @@ import (
|
||||||
"github.com/smallstep/assert"
|
"github.com/smallstep/assert"
|
||||||
"github.com/smallstep/certificates/authority"
|
"github.com/smallstep/certificates/authority"
|
||||||
"github.com/smallstep/certificates/authority/provisioner"
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
"go.step.sm/crypto/keyutil"
|
||||||
"go.step.sm/crypto/x509util"
|
"go.step.sm/crypto/x509util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -308,6 +310,14 @@ func (m *mockSignAuth) Revoke(context.Context, *authority.RevokeOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOrder_Finalize(t *testing.T) {
|
func TestOrder_Finalize(t *testing.T) {
|
||||||
|
mustSigner := func(kty, crv string, size int) crypto.Signer {
|
||||||
|
s, err := keyutil.GenerateSigner(kty, crv, size)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
type test struct {
|
type test struct {
|
||||||
o *Order
|
o *Order
|
||||||
err *Error
|
err *Error
|
||||||
|
@ -400,10 +410,18 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signer := mustSigner("EC", "P-256", 0)
|
||||||
|
fingerprint, err := keyutil.Fingerprint(signer.Public())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
csr := &x509.CertificateRequest{
|
csr := &x509.CertificateRequest{
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "a-different-identifier",
|
CommonName: "a-different-identifier",
|
||||||
},
|
},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
ExtraExtensions: []pkix.Extension{
|
ExtraExtensions: []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
@ -414,6 +432,29 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
return test{
|
return test{
|
||||||
o: o,
|
o: o,
|
||||||
csr: csr,
|
csr: csr,
|
||||||
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
switch id {
|
||||||
|
case "a":
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
case "b":
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Fingerprint: fingerprint,
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected authorization %s", id))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MockUpdateOrder: func(ctx context.Context, o *Order) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
err: &Error{
|
err: &Error{
|
||||||
Type: "urn:ietf:params:acme:error:badCSR",
|
Type: "urn:ietf:params:acme:error:badCSR",
|
||||||
Detail: "The CSR is unacceptable",
|
Detail: "The CSR is unacceptable",
|
||||||
|
@ -452,6 +493,11 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
return nil, errors.New("force")
|
return nil, errors.New("force")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
err: NewErrorISE("error retrieving authorization options from ACME provisioner: force"),
|
err: NewErrorISE("error retrieving authorization options from ACME provisioner: force"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -491,6 +537,11 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
err: NewErrorISE("error creating template options from ACME provisioner: error unmarshaling template data: invalid character 'o' in literal false (expecting 'a')"),
|
err: NewErrorISE("error creating template options from ACME provisioner: error unmarshaling template data: invalid character 'o' in literal false (expecting 'a')"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -532,6 +583,11 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
return nil, errors.New("force")
|
return nil, errors.New("force")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
err: NewErrorISE("error signing certificate for order oID: force"),
|
err: NewErrorISE("error signing certificate for order oID: force"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -578,6 +634,9 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
assert.Equals(t, cert.OrderID, o.ID)
|
assert.Equals(t, cert.OrderID, o.ID)
|
||||||
|
@ -632,6 +691,9 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -654,7 +716,7 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
err: NewErrorISE("error updating order oID: force"),
|
err: NewErrorISE("error updating order oID: force"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ok/permanent-identifier": func(t *testing.T) test {
|
"fail/csr-fingerprint": func(t *testing.T) test {
|
||||||
now := clock.Now()
|
now := clock.Now()
|
||||||
o := &Order{
|
o := &Order{
|
||||||
ID: "oID",
|
ID: "oID",
|
||||||
|
@ -666,10 +728,14 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signer := mustSigner("EC", "P-256", 0)
|
||||||
|
|
||||||
csr := &x509.CertificateRequest{
|
csr := &x509.CertificateRequest{
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "a-permanent-identifier",
|
CommonName: "a-permanent-identifier",
|
||||||
},
|
},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
ExtraExtensions: []pkix.Extension{
|
ExtraExtensions: []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
@ -679,7 +745,8 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
leaf := &x509.Certificate{
|
leaf := &x509.Certificate{
|
||||||
Subject: pkix.Name{CommonName: "a-permanent-identifier"},
|
Subject: pkix.Name{CommonName: "a-permanent-identifier"},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
ExtraExtensions: []pkix.Extension{
|
ExtraExtensions: []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
@ -709,6 +776,117 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Fingerprint: "other-fingerprint",
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
|
cert.ID = "certID"
|
||||||
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
assert.Equals(t, cert.OrderID, o.ID)
|
||||||
|
assert.Equals(t, cert.Leaf, leaf)
|
||||||
|
assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root})
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
MockUpdateOrder: func(ctx context.Context, updo *Order) error {
|
||||||
|
assert.Equals(t, updo.CertificateID, "certID")
|
||||||
|
assert.Equals(t, updo.Status, StatusValid)
|
||||||
|
assert.Equals(t, updo.ID, o.ID)
|
||||||
|
assert.Equals(t, updo.AccountID, o.AccountID)
|
||||||
|
assert.Equals(t, updo.ExpiresAt, o.ExpiresAt)
|
||||||
|
assert.Equals(t, updo.AuthorizationIDs, o.AuthorizationIDs)
|
||||||
|
assert.Equals(t, updo.Identifiers, o.Identifiers)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: NewError(ErrorUnauthorizedType, "order oID csr does not match the attested key"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ok/permanent-identifier": func(t *testing.T) test {
|
||||||
|
now := clock.Now()
|
||||||
|
o := &Order{
|
||||||
|
ID: "oID",
|
||||||
|
AccountID: "accID",
|
||||||
|
Status: StatusReady,
|
||||||
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
|
AuthorizationIDs: []string{"a", "b"},
|
||||||
|
Identifiers: []Identifier{
|
||||||
|
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
signer := mustSigner("EC", "P-256", 0)
|
||||||
|
fingerprint, err := keyutil.Fingerprint(signer.Public())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
csr := &x509.CertificateRequest{
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "a-permanent-identifier",
|
||||||
|
},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
|
ExtraExtensions: []pkix.Extension{
|
||||||
|
{
|
||||||
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
Value: []byte("a-permanent-identifier"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf := &x509.Certificate{
|
||||||
|
Subject: pkix.Name{CommonName: "a-permanent-identifier"},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
|
ExtraExtensions: []pkix.Extension{
|
||||||
|
{
|
||||||
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
Value: []byte("a-permanent-identifier"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
inter := &x509.Certificate{Subject: pkix.Name{CommonName: "inter"}}
|
||||||
|
root := &x509.Certificate{Subject: pkix.Name{CommonName: "root"}}
|
||||||
|
|
||||||
|
return test{
|
||||||
|
o: o,
|
||||||
|
csr: csr,
|
||||||
|
prov: &MockProvisioner{
|
||||||
|
MauthorizeSign: func(ctx context.Context, token string) ([]provisioner.SignOption, error) {
|
||||||
|
assert.Equals(t, token, "")
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
|
MgetOptions: func() *provisioner.Options {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ca: &mockSignAuth{
|
||||||
|
sign: func(_csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
|
assert.Equals(t, _csr, csr)
|
||||||
|
return []*x509.Certificate{leaf, inter, root}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
switch id {
|
||||||
|
case "a":
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
case "b":
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Fingerprint: fingerprint,
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected authorization %s", id))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -743,11 +921,19 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
{Type: "permanent-identifier", Value: "a-permanent-identifier"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signer := mustSigner("EC", "P-256", 0)
|
||||||
|
fingerprint, err := keyutil.Fingerprint(signer.Public())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
csr := &x509.CertificateRequest{
|
csr := &x509.CertificateRequest{
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "a-permanent-identifier",
|
CommonName: "a-permanent-identifier",
|
||||||
},
|
},
|
||||||
DNSNames: []string{"foo.internal"},
|
DNSNames: []string{"foo.internal"},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
ExtraExtensions: []pkix.Extension{
|
ExtraExtensions: []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
@ -757,7 +943,8 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
leaf := &x509.Certificate{
|
leaf := &x509.Certificate{
|
||||||
Subject: pkix.Name{CommonName: "a-permanent-identifier"},
|
Subject: pkix.Name{CommonName: "a-permanent-identifier"},
|
||||||
|
PublicKey: signer.Public(),
|
||||||
ExtraExtensions: []pkix.Extension{
|
ExtraExtensions: []pkix.Extension{
|
||||||
{
|
{
|
||||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3},
|
||||||
|
@ -792,6 +979,13 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{
|
||||||
|
ID: id,
|
||||||
|
Fingerprint: fingerprint,
|
||||||
|
Status: StatusValid,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -856,6 +1050,9 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -917,6 +1114,9 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -981,6 +1181,9 @@ func TestOrder_Finalize(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
db: &MockDB{
|
db: &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
MockCreateCertificate: func(ctx context.Context, cert *Certificate) error {
|
||||||
cert.ID = "certID"
|
cert.ID = "certID"
|
||||||
assert.Equals(t, cert.AccountID, o.AccountID)
|
assert.Equals(t, cert.AccountID, o.AccountID)
|
||||||
|
@ -1688,3 +1891,55 @@ func TestOrder_sans(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrder_getAuthorizationFingerprint(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
type fields struct {
|
||||||
|
AuthorizationIDs []string
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
db DB
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"ok", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
},
|
||||||
|
}}, "", false},
|
||||||
|
{"ok fingerprint", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
if id == "az1" {
|
||||||
|
return &Authorization{ID: id, Status: StatusValid}, nil
|
||||||
|
}
|
||||||
|
return &Authorization{ID: id, Fingerprint: "fingerprint", Status: StatusValid}, nil
|
||||||
|
},
|
||||||
|
}}, "fingerprint", false},
|
||||||
|
{"fail", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{
|
||||||
|
MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) {
|
||||||
|
return nil, errors.New("force")
|
||||||
|
},
|
||||||
|
}}, "", true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
o := &Order{
|
||||||
|
AuthorizationIDs: tt.fields.AuthorizationIDs,
|
||||||
|
}
|
||||||
|
got, err := o.getAuthorizationFingerprint(tt.args.ctx, tt.args.db)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Order.getAuthorizationFingerprint() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("Order.getAuthorizationFingerprint() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -12,7 +12,7 @@ require (
|
||||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3
|
github.com/Masterminds/sprig/v3 v3.2.3
|
||||||
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
||||||
github.com/aws/aws-sdk-go v1.44.185 // indirect
|
github.com/aws/aws-sdk-go v1.44.195 // indirect
|
||||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||||
github.com/fatih/color v1.9.0 // indirect
|
github.com/fatih/color v1.9.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.4.0
|
github.com/fxamacker/cbor/v2 v2.4.0
|
||||||
|
@ -43,7 +43,7 @@ require (
|
||||||
github.com/urfave/cli v1.22.12
|
github.com/urfave/cli v1.22.12
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352
|
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352
|
||||||
go.step.sm/cli-utils v0.7.5
|
go.step.sm/cli-utils v0.7.5
|
||||||
go.step.sm/crypto v0.23.2
|
go.step.sm/crypto v0.25.0
|
||||||
go.step.sm/linkedca v0.19.0
|
go.step.sm/linkedca v0.19.0
|
||||||
golang.org/x/crypto v0.5.0
|
golang.org/x/crypto v0.5.0
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/net v0.5.0
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -84,8 +84,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
|
||||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/aws/aws-sdk-go v1.44.185 h1:stasiou+Ucx2A0RyXRyPph4sLCBxVQK7DPPK8tNcl5g=
|
github.com/aws/aws-sdk-go v1.44.195 h1:d5xFL0N83Fpsq2LFiHgtBUHknCRUPGHdOlCWt/jtOJs=
|
||||||
github.com/aws/aws-sdk-go v1.44.185/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
github.com/aws/aws-sdk-go v1.44.195/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
@ -690,8 +690,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
|
||||||
go.step.sm/cli-utils v0.7.5 h1:jyp6X8k8mN1B0uWJydTid0C++8tQhm2kaaAdXKQQzdk=
|
go.step.sm/cli-utils v0.7.5 h1:jyp6X8k8mN1B0uWJydTid0C++8tQhm2kaaAdXKQQzdk=
|
||||||
go.step.sm/cli-utils v0.7.5/go.mod h1:taSsY8haLmXoXM3ZkywIyRmVij/4Aj0fQbNTlJvv71I=
|
go.step.sm/cli-utils v0.7.5/go.mod h1:taSsY8haLmXoXM3ZkywIyRmVij/4Aj0fQbNTlJvv71I=
|
||||||
go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0=
|
go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0=
|
||||||
go.step.sm/crypto v0.23.2 h1:XGmQH9Pkpxop47cjYlUhF10L5roPCbu1BCZXopbeW8I=
|
go.step.sm/crypto v0.25.0 h1:a+7sKyozZH9B30s0dHluygxreUxI1NtCBEmuNXx7a4k=
|
||||||
go.step.sm/crypto v0.23.2/go.mod h1:/IXGz8al8k7u7OV0RTWIi8TRVqO2FMyZVpedV+6Da6U=
|
go.step.sm/crypto v0.25.0/go.mod h1:kr1rzO6SzeQnLm6Zu6lNtksHZLiFe9k8LolSJNhoc94=
|
||||||
go.step.sm/linkedca v0.19.0 h1:xuagkR35wrJI2gnu6FAM+q3VmjwsHScvGcJsfZ0GdsI=
|
go.step.sm/linkedca v0.19.0 h1:xuagkR35wrJI2gnu6FAM+q3VmjwsHScvGcJsfZ0GdsI=
|
||||||
go.step.sm/linkedca v0.19.0/go.mod h1:b7vWPrHfYLEOTSUZitFEcztVCpTc+ileIN85CwEAluM=
|
go.step.sm/linkedca v0.19.0/go.mod h1:b7vWPrHfYLEOTSUZitFEcztVCpTc+ileIN85CwEAluM=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
|
Loading…
Reference in a new issue