@ -24,7 +24,7 @@ import (
"go.step.sm/crypto/pemutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/assert"
sassert "github.com/smallstep/assert"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority/config"
"github.com/smallstep/certificates/authority/policy"
@ -33,6 +33,8 @@ import (
"github.com/smallstep/certificates/db"
"github.com/smallstep/certificates/errs"
"github.com/smallstep/nosql/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
@ -80,25 +82,25 @@ func generateCertificate(t *testing.T, commonName string, sans []string, opts ..
t . Helper ( )
priv , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
assert. Fatal Error( t , err )
require. No Error( t , err )
cr , err := x509util . CreateCertificateRequest ( commonName , sans , priv )
assert. Fatal Error( t , err )
require. No Error( t , err )
template , err := x509util . NewCertificate ( cr )
assert. Fatal Error( t , err )
require. No Error( t , err )
cert := template . GetCertificate ( )
for _ , m := range opts {
switch m := m . ( type ) {
case provisioner . CertificateModifierFunc :
err = m . Modify ( cert , provisioner . SignOptions { } )
assert. Fatal Error( t , err )
require. No Error( t , err )
case signerFunc :
cert , err = m ( cert , priv . Public ( ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
default :
t. Fatalf ( "unknown type %T" , m )
require. Fail ( t , "" , "unknown type %T" , m )
}
}
@ -108,36 +110,36 @@ func generateCertificate(t *testing.T, commonName string, sans []string, opts ..
func generateRootCertificate ( t * testing . T ) ( * x509 . Certificate , crypto . Signer ) {
t . Helper ( )
priv , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
assert. Fatal Error( t , err )
require. No Error( t , err )
cr , err := x509util . CreateCertificateRequest ( "TestRootCA" , nil , priv )
assert. Fatal Error( t , err )
require. No Error( t , err )
data := x509util . CreateTemplateData ( "TestRootCA" , nil )
template , err := x509util . NewCertificate ( cr , x509util . WithTemplate ( x509util . DefaultRootTemplate , data ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
cert := template . GetCertificate ( )
cert , err = x509util . CreateCertificate ( cert , cert , priv . Public ( ) , priv )
assert. Fatal Error( t , err )
require. No Error( t , err )
return cert , priv
}
func generateIntermidiateCertificate ( t * testing . T , issuer * x509 . Certificate , signer crypto . Signer ) ( * x509 . Certificate , crypto . Signer ) {
t . Helper ( )
priv , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
assert. Fatal Error( t , err )
require. No Error( t , err )
cr , err := x509util . CreateCertificateRequest ( "TestIntermediateCA" , nil , priv )
assert. Fatal Error( t , err )
require. No Error( t , err )
data := x509util . CreateTemplateData ( "TestIntermediateCA" , nil )
template , err := x509util . NewCertificate ( cr , x509util . WithTemplate ( x509util . DefaultRootTemplate , data ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
cert := template . GetCertificate ( )
cert , err = x509util . CreateCertificate ( cert , issuer , priv . Public ( ) , signer )
assert. Fatal Error( t , err )
require. No Error( t , err )
return cert , priv
}
@ -192,9 +194,9 @@ func getCSR(t *testing.T, priv interface{}, opts ...func(*x509.CertificateReques
opt ( _csr )
}
csrBytes , err := x509 . CreateCertificateRequest ( rand . Reader , _csr , priv )
assert. Fatal Error( t , err )
require. No Error( t , err )
csr , err := x509 . ParseCertificateRequest ( csrBytes )
assert. Fatal Error( t , err )
require. No Error( t , err )
return csr
}
@ -239,10 +241,10 @@ func (e *testEnforcer) Enforce(cert *x509.Certificate) error {
func TestAuthority_Sign ( t * testing . T ) {
pub , priv , err := keyutil . GenerateDefaultKeyPair ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
a := testAuthority ( t )
assert. Fatal Error( t , err )
require. No Error( t , err )
a . config . AuthorityConfig . Template = & ASN1DN {
Country : "Tazmania" ,
Organization : "Acme Co" ,
@ -262,12 +264,12 @@ func TestAuthority_Sign(t *testing.T) {
// Create a token to get test extra opts.
p := a . config . AuthorityConfig . Provisioners [ 1 ] . ( * provisioner . JWK )
key , err := jose . ReadKey ( "testdata/secrets/step_cli_key_priv.jwk" , jose . WithPassword ( [ ] byte ( "pass" ) ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
token , err := generateToken ( "smallstep test" , "step-cli" , testAudiences . Sign [ 0 ] , [ ] string { "test.smallstep.com" } , time . Now ( ) , key )
assert. Fatal Error( t , err )
require. No Error( t , err )
ctx := provisioner . NewContextWithMethod ( context . Background ( ) , provisioner . SignMethod )
extraOpts , err := a . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
type signTest struct {
auth * Authority
@ -372,9 +374,9 @@ W5kR63lNVHBHgQmv5mA8YFsfrJHstaz5k727v2LMHEYIf5/3i16d5zhuxUoaPTYr
ZYtQ9Ot36qc =
-- -- - END CERTIFICATE REQUEST -- -- - `
block , _ := pem . Decode ( [ ] byte ( shortRSAKeyPEM ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
csr , err := x509 . ParseCertificateRequest ( block . Bytes )
assert. Fatal Error( t , err )
require. No Error( t , err )
return & signTest {
auth : a ,
@ -413,10 +415,10 @@ ZYtQ9Ot36qc=
X509 : & provisioner . X509Options { Template : ` {{ fail "fail message" }} ` } ,
}
testExtraOpts , err := testAuthority . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
testAuthority . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -442,10 +444,10 @@ ZYtQ9Ot36qc=
} ,
}
testExtraOpts , err := testAuthority . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
testAuthority . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -471,10 +473,10 @@ ZYtQ9Ot36qc=
} ,
}
testExtraOpts , err := testAuthority . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
testAuthority . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -492,7 +494,7 @@ ZYtQ9Ot36qc=
aa := testAuthority ( t )
aa . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -517,7 +519,7 @@ ZYtQ9Ot36qc=
} ) )
aa . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -537,7 +539,7 @@ ZYtQ9Ot36qc=
aa . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
fmt . Println ( crt . Subject )
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -549,7 +551,7 @@ ZYtQ9Ot36qc=
} ,
}
engine , err := policy . New ( options )
assert. Fatal Error( t , err )
require. No Error( t , err )
aa . policyEngine = engine
return & signTest {
auth : aa ,
@ -598,7 +600,7 @@ ZYtQ9Ot36qc=
_a := testAuthority ( t )
_a . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -617,7 +619,7 @@ ZYtQ9Ot36qc=
bcExt . Id = asn1 . ObjectIdentifier { 2 , 5 , 29 , 19 }
bcExt . Critical = false
bcExt . Value , err = asn1 . Marshal ( basicConstraints { IsCA : true , MaxPathLen : 4 } )
assert. Fatal Error( t , err )
require. No Error( t , err )
csr := getCSR ( t , priv , setExtraExtsCSR ( [ ] pkix . Extension {
bcExt ,
@ -632,7 +634,7 @@ ZYtQ9Ot36qc=
_a := testAuthority ( t )
_a . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -663,10 +665,10 @@ ZYtQ9Ot36qc=
} ` } ,
}
testExtraOpts , err := testAuthority . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
testAuthority . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -697,10 +699,10 @@ ZYtQ9Ot36qc=
} ` } ,
}
testExtraOpts , err := testAuthority . Authorize ( ctx , token )
assert. Fatal Error( t , err )
require. No Error( t , err )
testAuthority . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -737,7 +739,7 @@ ZYtQ9Ot36qc=
_a . config . AuthorityConfig . Template = & ASN1DN { }
_a . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject , pkix . Name { } )
s assert. Equals ( t , crt . Subject , pkix . Name { } )
return nil
} ,
}
@ -762,8 +764,8 @@ ZYtQ9Ot36qc=
aa . config . AuthorityConfig . Template = a . config . AuthorityConfig . Template
aa . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
assert. Equals ( t , crt . CRLDistributionPoints , [ ] string { "http://ca.example.org/leaf.crl" } )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . CRLDistributionPoints , [ ] string { "http://ca.example.org/leaf.crl" } )
return nil
} ,
}
@ -783,7 +785,7 @@ ZYtQ9Ot36qc=
aa . config . AuthorityConfig . Template = a . config . AuthorityConfig . Template
aa . db = & db . MockAuthDB {
MStoreCertificate : func ( crt * x509 . Certificate ) error {
assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , crt . Subject . CommonName , "smallstep test" )
return nil
} ,
}
@ -796,7 +798,7 @@ ZYtQ9Ot36qc=
} ,
}
engine , err := policy . New ( options )
assert. Fatal Error( t , err )
require. No Error( t , err )
aa . policyEngine = engine
return & signTest {
auth : aa ,
@ -816,13 +818,13 @@ ZYtQ9Ot36qc=
MStoreCertificateChain : func ( prov provisioner . Interface , certs ... * x509 . Certificate ) error {
p , ok := prov . ( attProvisioner )
if assert . True ( t , ok ) {
assert. Equals ( t , & provisioner . AttestationData {
s assert. Equals ( t , & provisioner . AttestationData {
PermanentIdentifier : "1234567890" ,
} , p . AttestationData ( ) )
}
if assert . Len ( t , 2 , certs ) {
assert. Equals ( t , certs [ 0 ] . Subject . CommonName , "smallstep test" )
assert. Equals ( t , certs [ 1 ] . Subject . CommonName , "smallstep Intermediate CA" )
if assert . Len ( t , certs , 2 ) {
s assert. Equals ( t , certs [ 0 ] . Subject . CommonName , "smallstep test" )
s assert. Equals ( t , certs [ 1 ] . Subject . CommonName , "smallstep Intermediate CA" )
}
return nil
} ,
@ -851,26 +853,26 @@ ZYtQ9Ot36qc=
if assert . NotNil ( t , tc . err , fmt . Sprintf ( "unexpected error: %s" , err ) ) {
assert . Nil ( t , certChain )
var sc render . StatusCodedError
assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
assert. Equals ( t , sc . StatusCode ( ) , tc . code )
assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
s assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
s assert. Equals ( t , sc . StatusCode ( ) , tc . code )
s assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
var ctxErr * errs . Error
assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
assert. Equals ( t , ctxErr . Details [ "csr" ] , tc . csr )
assert. Equals ( t , ctxErr . Details [ "signOptions" ] , tc . signOpts )
s assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
s assert. Equals ( t , ctxErr . Details [ "csr" ] , tc . csr )
s assert. Equals ( t , ctxErr . Details [ "signOptions" ] , tc . signOpts )
}
} else {
leaf := certChain [ 0 ]
intermediate := certChain [ 1 ]
if assert . Nil ( t , tc . err ) {
assert. Equals ( t , leaf . NotBefore , tc . notBefore )
assert. Equals ( t , leaf . NotAfter , tc . notAfter )
s assert. Equals ( t , leaf . NotBefore , tc . notBefore )
s assert. Equals ( t , leaf . NotAfter , tc . notAfter )
tmplt := a . config . AuthorityConfig . Template
if tc . csr . Subject . CommonName == "" {
assert. Equals ( t , leaf . Subject , pkix . Name { } )
s assert. Equals ( t , leaf . Subject , pkix . Name { } )
} else {
assert. Equals ( t , leaf . Subject . String ( ) ,
s assert. Equals ( t , leaf . Subject . String ( ) ,
pkix . Name {
Country : [ ] string { tmplt . Country } ,
Organization : [ ] string { tmplt . Organization } ,
@ -879,18 +881,18 @@ ZYtQ9Ot36qc=
Province : [ ] string { tmplt . Province } ,
CommonName : "smallstep test" ,
} . String ( ) )
assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" } )
s assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" } )
}
assert. Equals ( t , leaf . Issuer , intermediate . Subject )
assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
assert. Equals ( t , leaf . ExtKeyUsage , [ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageServerAuth , x509 . ExtKeyUsageClientAuth } )
s assert. Equals ( t , leaf . Issuer , intermediate . Subject )
s assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
s assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
s assert. Equals ( t , leaf . ExtKeyUsage , [ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageServerAuth , x509 . ExtKeyUsageClientAuth } )
issuer := getDefaultIssuer ( a )
subjectKeyID , err := generateSubjectKeyID ( pub )
assert. Fatal Error( t , err )
assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
require. No Error( t , err )
s assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
s assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
// Verify Provisioner OID
found := 0
@ -900,18 +902,18 @@ ZYtQ9Ot36qc=
found ++
val := stepProvisionerASN1 { }
_ , err := asn1 . Unmarshal ( ext . Value , & val )
assert. Fatal Error( t , err )
assert. Equals ( t , val . Type , provisionerTypeJWK )
assert. Equals ( t , val . Name , [ ] byte ( p . Name ) )
assert. Equals ( t , val . CredentialID , [ ] byte ( p . Key . KeyID ) )
require. No Error( t , err )
s assert. Equals ( t , val . Type , provisionerTypeJWK )
s assert. Equals ( t , val . Name , [ ] byte ( p . Name ) )
s assert. Equals ( t , val . CredentialID , [ ] byte ( p . Key . KeyID ) )
// Basic Constraints
case ext . Id . Equal ( asn1 . ObjectIdentifier ( [ ] int { 2 , 5 , 29 , 19 } ) ) :
val := basicConstraints { }
_ , err := asn1 . Unmarshal ( ext . Value , & val )
assert. Fatal Error( t , err )
require. No Error( t , err )
assert . False ( t , val . IsCA , false )
assert. Equals ( t , val . MaxPathLen , 0 )
s assert. Equals ( t , val . MaxPathLen , 0 )
// SAN extension
case ext . Id . Equal ( asn1 . ObjectIdentifier ( [ ] int { 2 , 5 , 29 , 17 } ) ) :
@ -922,11 +924,11 @@ ZYtQ9Ot36qc=
}
}
}
assert. Equals ( t , found , 1 )
s assert. Equals ( t , found , 1 )
realIntermediate , err := x509 . ParseCertificate ( issuer . Raw )
assert. Fatal Error( t , err )
assert. Equals ( t , intermediate , realIntermediate )
assert . Len ( t , tc. extensionsCount , leaf . Extensions )
require. No Error( t , err )
s assert. Equals ( t , intermediate , realIntermediate )
assert . Len ( t , leaf. Extensions , tc . extensionsCount )
}
}
} )
@ -1056,7 +1058,7 @@ func TestAuthority_Renew(t *testing.T) {
for name , genTestCase := range tests {
t . Run ( name , func ( t * testing . T ) {
tc , err := genTestCase ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
var certChain [ ] * x509 . Certificate
if tc . auth != nil {
@ -1068,19 +1070,19 @@ func TestAuthority_Renew(t *testing.T) {
if assert . NotNil ( t , tc . err , fmt . Sprintf ( "unexpected error: %s" , err ) ) {
assert . Nil ( t , certChain )
var sc render . StatusCodedError
assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
assert. Equals ( t , sc . StatusCode ( ) , tc . code )
assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
s assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
s assert. Equals ( t , sc . StatusCode ( ) , tc . code )
s assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
var ctxErr * errs . Error
assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . cert . SerialNumber . String ( ) )
s assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
s assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . cert . SerialNumber . String ( ) )
}
} else {
leaf := certChain [ 0 ]
intermediate := certChain [ 1 ]
if assert . Nil ( t , tc . err ) {
assert. Equals ( t , leaf . NotAfter . Sub ( leaf . NotBefore ) , tc . cert . NotAfter . Sub ( cert . NotBefore ) )
s assert. Equals ( t , leaf . NotAfter . Sub ( leaf . NotBefore ) , tc . cert . NotAfter . Sub ( cert . NotBefore ) )
assert . True ( t , leaf . NotBefore . After ( now . Add ( - 2 * time . Minute ) ) )
assert . True ( t , leaf . NotBefore . Before ( now . Add ( time . Minute ) ) )
@ -1090,30 +1092,30 @@ func TestAuthority_Renew(t *testing.T) {
assert . True ( t , leaf . NotAfter . Before ( expiry . Add ( time . Hour ) ) )
tmplt := a . config . AuthorityConfig . Template
assert. Equals ( t , leaf . RawSubject , tc . cert . RawSubject )
assert. Equals ( t , leaf . Subject . Country , [ ] string { tmplt . Country } )
assert. Equals ( t , leaf . Subject . Organization , [ ] string { tmplt . Organization } )
assert. Equals ( t , leaf . Subject . Locality , [ ] string { tmplt . Locality } )
assert. Equals ( t , leaf . Subject . StreetAddress , [ ] string { tmplt . StreetAddress } )
assert. Equals ( t , leaf . Subject . Province , [ ] string { tmplt . Province } )
assert. Equals ( t , leaf . Subject . CommonName , tmplt . CommonName )
assert. Equals ( t , leaf . Issuer , intermediate . Subject )
assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
assert. Equals ( t , leaf . ExtKeyUsage ,
s assert. Equals ( t , leaf . RawSubject , tc . cert . RawSubject )
s assert. Equals ( t , leaf . Subject . Country , [ ] string { tmplt . Country } )
s assert. Equals ( t , leaf . Subject . Organization , [ ] string { tmplt . Organization } )
s assert. Equals ( t , leaf . Subject . Locality , [ ] string { tmplt . Locality } )
s assert. Equals ( t , leaf . Subject . StreetAddress , [ ] string { tmplt . StreetAddress } )
s assert. Equals ( t , leaf . Subject . Province , [ ] string { tmplt . Province } )
s assert. Equals ( t , leaf . Subject . CommonName , tmplt . CommonName )
s assert. Equals ( t , leaf . Issuer , intermediate . Subject )
s assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
s assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
s assert. Equals ( t , leaf . ExtKeyUsage ,
[ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageServerAuth , x509 . ExtKeyUsageClientAuth } )
assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" , "test" } )
s assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" , "test" } )
subjectKeyID , err := generateSubjectKeyID ( leaf . PublicKey )
assert. Fatal Error( t , err )
assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
require. No Error( t , err )
s assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
// We did not change the intermediate before renewing.
authIssuer := getDefaultIssuer ( tc . auth )
if issuer . SerialNumber == authIssuer . SerialNumber {
assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
s assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
// Compare extensions: they can be in a different order
for _ , ext1 := range tc . cert . Extensions {
//skip SubjectKeyIdentifier
@ -1133,7 +1135,7 @@ func TestAuthority_Renew(t *testing.T) {
}
} else {
// We did change the intermediate before renewing.
assert. Equals ( t , leaf . AuthorityKeyId , authIssuer . SubjectKeyId )
s assert. Equals ( t , leaf . AuthorityKeyId , authIssuer . SubjectKeyId )
// Compare extensions: they can be in a different order
for _ , ext1 := range tc . cert . Extensions {
//skip SubjectKeyIdentifier
@ -1161,8 +1163,8 @@ func TestAuthority_Renew(t *testing.T) {
}
realIntermediate , err := x509 . ParseCertificate ( authIssuer . Raw )
assert. Fatal Error( t , err )
assert. Equals ( t , intermediate , realIntermediate )
require. No Error( t , err )
s assert. Equals ( t , intermediate , realIntermediate )
}
}
} )
@ -1171,7 +1173,7 @@ func TestAuthority_Renew(t *testing.T) {
func TestAuthority_Rekey ( t * testing . T ) {
pub , _ , err := keyutil . GenerateDefaultKeyPair ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
a := testAuthority ( t )
a . config . AuthorityConfig . Template = & ASN1DN {
@ -1261,7 +1263,7 @@ func TestAuthority_Rekey(t *testing.T) {
for name , genTestCase := range tests {
t . Run ( name , func ( t * testing . T ) {
tc , err := genTestCase ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
var certChain [ ] * x509 . Certificate
if tc . auth != nil {
@ -1273,19 +1275,19 @@ func TestAuthority_Rekey(t *testing.T) {
if assert . NotNil ( t , tc . err , fmt . Sprintf ( "unexpected error: %s" , err ) ) {
assert . Nil ( t , certChain )
var sc render . StatusCodedError
assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
assert. Equals ( t , sc . StatusCode ( ) , tc . code )
assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
s assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
s assert. Equals ( t , sc . StatusCode ( ) , tc . code )
s assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
var ctxErr * errs . Error
assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . cert . SerialNumber . String ( ) )
s assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
s assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . cert . SerialNumber . String ( ) )
}
} else {
leaf := certChain [ 0 ]
intermediate := certChain [ 1 ]
if assert . Nil ( t , tc . err ) {
assert. Equals ( t , leaf . NotAfter . Sub ( leaf . NotBefore ) , tc . cert . NotAfter . Sub ( cert . NotBefore ) )
s assert. Equals ( t , leaf . NotAfter . Sub ( leaf . NotBefore ) , tc . cert . NotAfter . Sub ( cert . NotBefore ) )
assert . True ( t , leaf . NotBefore . After ( now . Add ( - 2 * time . Minute ) ) )
assert . True ( t , leaf . NotBefore . Before ( now . Add ( time . Minute ) ) )
@ -1295,7 +1297,7 @@ func TestAuthority_Rekey(t *testing.T) {
assert . True ( t , leaf . NotAfter . Before ( expiry . Add ( time . Hour ) ) )
tmplt := a . config . AuthorityConfig . Template
assert. Equals ( t , leaf . Subject . String ( ) ,
s assert. Equals ( t , leaf . Subject . String ( ) ,
pkix . Name {
Country : [ ] string { tmplt . Country } ,
Organization : [ ] string { tmplt . Organization } ,
@ -1304,32 +1306,32 @@ func TestAuthority_Rekey(t *testing.T) {
Province : [ ] string { tmplt . Province } ,
CommonName : tmplt . CommonName ,
} . String ( ) )
assert. Equals ( t , leaf . Issuer , intermediate . Subject )
s assert. Equals ( t , leaf . Issuer , intermediate . Subject )
assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
assert. Equals ( t , leaf . ExtKeyUsage ,
s assert. Equals ( t , leaf . SignatureAlgorithm , x509 . ECDSAWithSHA256 )
s assert. Equals ( t , leaf . PublicKeyAlgorithm , x509 . ECDSA )
s assert. Equals ( t , leaf . ExtKeyUsage ,
[ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageServerAuth , x509 . ExtKeyUsageClientAuth } )
assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" , "test" } )
s assert. Equals ( t , leaf . DNSNames , [ ] string { "test.smallstep.com" , "test" } )
// Test Public Key and SubjectKeyId
expectedPK := tc . pk
if tc . pk == nil {
expectedPK = cert . PublicKey
}
assert. Equals ( t , leaf . PublicKey , expectedPK )
s assert. Equals ( t , leaf . PublicKey , expectedPK )
subjectKeyID , err := generateSubjectKeyID ( expectedPK )
assert. Fatal Error( t , err )
assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
require. No Error( t , err )
s assert. Equals ( t , leaf . SubjectKeyId , subjectKeyID )
if tc . pk == nil {
assert. Equals ( t , leaf . SubjectKeyId , cert . SubjectKeyId )
s assert. Equals ( t , leaf . SubjectKeyId , cert . SubjectKeyId )
}
// We did not change the intermediate before renewing.
authIssuer := getDefaultIssuer ( tc . auth )
if issuer . SerialNumber == authIssuer . SerialNumber {
assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
s assert. Equals ( t , leaf . AuthorityKeyId , issuer . SubjectKeyId )
// Compare extensions: they can be in a different order
for _ , ext1 := range tc . cert . Extensions {
//skip SubjectKeyIdentifier
@ -1349,7 +1351,7 @@ func TestAuthority_Rekey(t *testing.T) {
}
} else {
// We did change the intermediate before renewing.
assert. Equals ( t , leaf . AuthorityKeyId , authIssuer . SubjectKeyId )
s assert. Equals ( t , leaf . AuthorityKeyId , authIssuer . SubjectKeyId )
// Compare extensions: they can be in a different order
for _ , ext1 := range tc . cert . Extensions {
//skip SubjectKeyIdentifier
@ -1377,8 +1379,8 @@ func TestAuthority_Rekey(t *testing.T) {
}
realIntermediate , err := x509 . ParseCertificate ( authIssuer . Raw )
assert. Fatal Error( t , err )
assert. Equals ( t , intermediate , realIntermediate )
require. No Error( t , err )
s assert. Equals ( t , intermediate , realIntermediate )
}
}
} )
@ -1413,10 +1415,10 @@ func TestAuthority_GetTLSOptions(t *testing.T) {
for name , genTestCase := range tests {
t . Run ( name , func ( t * testing . T ) {
tc , err := genTestCase ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
opts := tc . auth . GetTLSOptions ( )
assert. Equals ( t , opts , tc . opts )
s assert. Equals ( t , opts , tc . opts )
} )
}
}
@ -1429,11 +1431,11 @@ func TestAuthority_Revoke(t *testing.T) {
now := time . Now ( ) . UTC ( )
jwk , err := jose . ReadKey ( "testdata/secrets/step_cli_key_priv.jwk" , jose . WithPassword ( [ ] byte ( "pass" ) ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
sig , err := jose . NewSigner ( jose . SigningKey { Algorithm : jose . ES256 , Key : jwk . Key } ,
( & jose . SignerOptions { } ) . WithType ( "JWT" ) . WithHeader ( "kid" , jwk . KeyID ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
a := testAuthority ( t )
@ -1472,7 +1474,7 @@ func TestAuthority_Revoke(t *testing.T) {
ID : "44" ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : a ,
@ -1486,9 +1488,9 @@ func TestAuthority_Revoke(t *testing.T) {
err : errors . New ( "authority.Revoke; no persistence layer configured" ) ,
code : http . StatusNotImplemented ,
checkErrDetails : func ( err * errs . Error ) {
assert. Equals ( t , err . Details [ "token" ] , raw )
assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
s assert. Equals ( t , err . Details [ "token" ] , raw )
s assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
s assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
} ,
}
} ,
@ -1512,7 +1514,7 @@ func TestAuthority_Revoke(t *testing.T) {
ID : "44" ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : _a ,
@ -1526,9 +1528,9 @@ func TestAuthority_Revoke(t *testing.T) {
err : errors . New ( "authority.Revoke: force" ) ,
code : http . StatusInternalServerError ,
checkErrDetails : func ( err * errs . Error ) {
assert. Equals ( t , err . Details [ "token" ] , raw )
assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
s assert. Equals ( t , err . Details [ "token" ] , raw )
s assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
s assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
} ,
}
} ,
@ -1552,7 +1554,7 @@ func TestAuthority_Revoke(t *testing.T) {
ID : "44" ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : _a ,
@ -1566,9 +1568,9 @@ func TestAuthority_Revoke(t *testing.T) {
err : errors . New ( "certificate with serial number 'sn' is already revoked" ) ,
code : http . StatusBadRequest ,
checkErrDetails : func ( err * errs . Error ) {
assert. Equals ( t , err . Details [ "token" ] , raw )
assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
s assert. Equals ( t , err . Details [ "token" ] , raw )
s assert. Equals ( t , err . Details [ "tokenID" ] , "44" )
s assert. Equals ( t , err . Details [ "provisionerID" ] , "step-cli:4UELJx8e0aS9m0CH3fZ0EB7D5aUPICb759zALHFejvc" )
} ,
}
} ,
@ -1591,7 +1593,7 @@ func TestAuthority_Revoke(t *testing.T) {
ID : "44" ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : _a ,
ctx : tlsRevokeCtx ,
@ -1607,7 +1609,7 @@ func TestAuthority_Revoke(t *testing.T) {
_a := testAuthority ( t , WithDatabase ( & db . MockAuthDB { } ) )
crt , err := pemutil . ReadCertificate ( "./testdata/certs/foo.crt" )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : _a ,
@ -1625,7 +1627,7 @@ func TestAuthority_Revoke(t *testing.T) {
_a := testAuthority ( t , WithDatabase ( & db . MockAuthDB { } ) )
crt , err := pemutil . ReadCertificate ( "./testdata/certs/foo.crt" )
assert. Fatal Error( t , err )
require. No Error( t , err )
// Filter out provisioner extension.
for i , ext := range crt . Extensions {
if ext . Id . Equal ( asn1 . ObjectIdentifier { 1 , 3 , 6 , 1 , 4 , 1 , 37476 , 9000 , 64 , 1 } ) {
@ -1650,7 +1652,7 @@ func TestAuthority_Revoke(t *testing.T) {
_a := testAuthority ( t , WithDatabase ( & db . MockAuthDB { } ) )
crt , err := pemutil . ReadCertificate ( "./testdata/certs/foo.crt" )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : _a ,
@ -1683,7 +1685,7 @@ func TestAuthority_Revoke(t *testing.T) {
ID : "44" ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
return test {
auth : a ,
ctx : provisioner . NewContextWithMethod ( context . Background ( ) , provisioner . SSHRevokeMethod ) ,
@ -1702,17 +1704,17 @@ func TestAuthority_Revoke(t *testing.T) {
if err := tc . auth . Revoke ( tc . ctx , tc . opts ) ; err != nil {
if assert . NotNil ( t , tc . err , fmt . Sprintf ( "unexpected error: %s" , err ) ) {
var sc render . StatusCodedError
assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
assert. Equals ( t , sc . StatusCode ( ) , tc . code )
assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
s assert. Fatal ( t , errors . As ( err , & sc ) , "error does not implement StatusCodedError interface" )
s assert. Equals ( t , sc . StatusCode ( ) , tc . code )
s assert. HasPrefix ( t , err . Error ( ) , tc . err . Error ( ) )
var ctxErr * errs . Error
assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . opts . Serial )
assert. Equals ( t , ctxErr . Details [ "reasonCode" ] , tc . opts . ReasonCode )
assert. Equals ( t , ctxErr . Details [ "reason" ] , tc . opts . Reason )
assert. Equals ( t , ctxErr . Details [ "MTLS" ] , tc . opts . MTLS )
assert. Equals ( t , ctxErr . Details [ "context" ] , provisioner . RevokeMethod . String ( ) )
s assert. Fatal ( t , errors . As ( err , & ctxErr ) , "error is not of type *errs.Error" )
s assert. Equals ( t , ctxErr . Details [ "serialNumber" ] , tc . opts . Serial )
s assert. Equals ( t , ctxErr . Details [ "reasonCode" ] , tc . opts . ReasonCode )
s assert. Equals ( t , ctxErr . Details [ "reason" ] , tc . opts . Reason )
s assert. Equals ( t , ctxErr . Details [ "MTLS" ] , tc . opts . MTLS )
s assert. Equals ( t , ctxErr . Details [ "context" ] , provisioner . RevokeMethod . String ( ) )
if tc . checkErrDetails != nil {
tc . checkErrDetails ( ctxErr )
@ -1814,13 +1816,11 @@ func TestAuthority_CRL(t *testing.T) {
validIssuer := "step-cli"
validAudience := testAudiences . Revoke
now := time . Now ( ) . UTC ( )
//
jwk , err := jose . ReadKey ( "testdata/secrets/step_cli_key_priv.jwk" , jose . WithPassword ( [ ] byte ( "pass" ) ) )
assert . FatalError ( t , err )
//
require . NoError ( t , err )
sig , err := jose . NewSigner ( jose . SigningKey { Algorithm : jose . ES256 , Key : jwk . Key } ,
( & jose . SignerOptions { } ) . WithType ( "JWT" ) . WithHeader ( "kid" , jwk . KeyID ) )
assert. Fatal Error( t , err )
require. No Error( t , err )
crlCtx := provisioner . NewContextWithMethod ( context . Background ( ) , provisioner . RevokeMethod )
@ -1865,7 +1865,7 @@ func TestAuthority_CRL(t *testing.T) {
auth : a ,
ctx : crlCtx ,
expected : nil ,
err : database. ErrNotFound ,
err : errors. New ( "authority.GetCertificateRevocationList: not found" ) ,
}
} ,
"ok/crl-full" : func ( ) test {
@ -1910,7 +1910,7 @@ func TestAuthority_CRL(t *testing.T) {
ID : sn ,
}
raw , err := jose . Signed ( sig ) . Claims ( cl ) . CompactSerialize ( )
assert. Fatal Error( t , err )
require. No Error( t , err )
err = a . Revoke ( crlCtx , & RevokeOptions {
Serial : sn ,
ReasonCode : reasonCode ,
@ -1918,7 +1918,7 @@ func TestAuthority_CRL(t *testing.T) {
OTT : raw ,
} )
assert. Fatal Error( t , err )
require. No Error( t , err )
ex = append ( ex , sn )
}
@ -1933,22 +1933,22 @@ func TestAuthority_CRL(t *testing.T) {
for name , f := range tests {
tc := f ( )
t . Run ( name , func ( t * testing . T ) {
if crlBytes , err := tc . auth . GetCertificateRevocationList ( ) ; err == nil {
crl , parseErr := x509 . ParseRevocationList ( crlBytes )
if parseErr != nil {
t . Errorf ( "x509.ParseCertificateRequest() error = %v, wantErr %v" , parseErr , nil )
crlInfo , err := tc . auth . GetCertificateRevocationList ( )
if tc . err != nil {
assert . EqualError ( t , err , tc . err . Error ( ) )
assert . Nil ( t , crlInfo )
return
}
crl , parseErr := x509 . ParseRevocationList ( crlInfo . Data )
require . NoError ( t , parseErr )
var cmpList [ ] string
for _ , c := range crl . RevokedCertificates {
for _ , c := range crl . RevokedCertificat eEntri es {
cmpList = append ( cmpList , c . SerialNumber . String ( ) )
}
assert . Equals ( t , cmpList , tc . expected )
} else {
assert . NotNil ( t , tc . err , err . Error ( ) )
}
assert . Equal ( t , tc . expected , cmpList )
} )
}
}