mirror of
https://github.com/smallstep/certificates.git
synced 2024-10-31 03:20:16 +00:00
Add public methods to retrieve the provisioner extensions.
This commit is contained in:
parent
236caaa735
commit
4690fa64ed
@ -179,7 +179,7 @@ func TestACME_AuthorizeSign(t *testing.T) {
|
|||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeACME))
|
assert.Equals(t, v.Type, TypeACME)
|
||||||
assert.Equals(t, v.Name, tc.p.GetName())
|
assert.Equals(t, v.Name, tc.p.GetName())
|
||||||
assert.Equals(t, v.CredentialID, "")
|
assert.Equals(t, v.CredentialID, "")
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
@ -677,7 +677,7 @@ func TestAWS_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeAWS))
|
assert.Equals(t, v.Type, TypeAWS)
|
||||||
assert.Equals(t, v.Name, tt.aws.GetName())
|
assert.Equals(t, v.Name, tt.aws.GetName())
|
||||||
assert.Equals(t, v.CredentialID, tt.aws.Accounts[0])
|
assert.Equals(t, v.CredentialID, tt.aws.Accounts[0])
|
||||||
assert.Len(t, 2, v.KeyValuePairs)
|
assert.Len(t, 2, v.KeyValuePairs)
|
||||||
|
@ -506,7 +506,7 @@ func TestAzure_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeAzure))
|
assert.Equals(t, v.Type, TypeAzure)
|
||||||
assert.Equals(t, v.Name, tt.azure.GetName())
|
assert.Equals(t, v.Name, tt.azure.GetName())
|
||||||
assert.Equals(t, v.CredentialID, tt.azure.TenantID)
|
assert.Equals(t, v.CredentialID, tt.azure.TenantID)
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
@ -152,8 +152,8 @@ func (c *Collection) LoadByToken(token *jose.JSONWebToken, claims *jose.Claims)
|
|||||||
// proper id to load the provisioner.
|
// proper id to load the provisioner.
|
||||||
func (c *Collection) LoadByCertificate(cert *x509.Certificate) (Interface, bool) {
|
func (c *Collection) LoadByCertificate(cert *x509.Certificate) (Interface, bool) {
|
||||||
for _, e := range cert.Extensions {
|
for _, e := range cert.Extensions {
|
||||||
if e.Id.Equal(stepOIDProvisioner) {
|
if e.Id.Equal(StepOIDProvisioner) {
|
||||||
var provisioner stepProvisionerASN1
|
var provisioner extensionASN1
|
||||||
if _, err := asn1.Unmarshal(e.Value, &provisioner); err != nil {
|
if _, err := asn1.Unmarshal(e.Value, &provisioner); err != nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,17 @@ func TestCollection_LoadByToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCollection_LoadByCertificate(t *testing.T) {
|
func TestCollection_LoadByCertificate(t *testing.T) {
|
||||||
|
mustExtension := func(typ Type, name, credentialID string) pkix.Extension {
|
||||||
|
e := Extension{
|
||||||
|
Type: typ, Name: name, CredentialID: credentialID,
|
||||||
|
}
|
||||||
|
ext, err := e.ToExtension()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return ext
|
||||||
|
}
|
||||||
|
|
||||||
p1, err := generateJWK()
|
p1, err := generateJWK()
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
p2, err := generateOIDC()
|
p2, err := generateOIDC()
|
||||||
@ -159,30 +170,21 @@ func TestCollection_LoadByCertificate(t *testing.T) {
|
|||||||
byName.Store(p2.GetName(), p2)
|
byName.Store(p2.GetName(), p2)
|
||||||
byName.Store(p3.GetName(), p3)
|
byName.Store(p3.GetName(), p3)
|
||||||
|
|
||||||
ok1Ext, err := createProvisionerExtension(1, p1.Name, p1.Key.KeyID)
|
|
||||||
assert.FatalError(t, err)
|
|
||||||
ok2Ext, err := createProvisionerExtension(2, p2.Name, p2.ClientID)
|
|
||||||
assert.FatalError(t, err)
|
|
||||||
ok3Ext, err := createProvisionerExtension(int(TypeACME), p3.Name, "")
|
|
||||||
assert.FatalError(t, err)
|
|
||||||
notFoundExt, err := createProvisionerExtension(1, "foo", "bar")
|
|
||||||
assert.FatalError(t, err)
|
|
||||||
|
|
||||||
ok1Cert := &x509.Certificate{
|
ok1Cert := &x509.Certificate{
|
||||||
Extensions: []pkix.Extension{ok1Ext},
|
Extensions: []pkix.Extension{mustExtension(1, p1.Name, p1.Key.KeyID)},
|
||||||
}
|
}
|
||||||
ok2Cert := &x509.Certificate{
|
ok2Cert := &x509.Certificate{
|
||||||
Extensions: []pkix.Extension{ok2Ext},
|
Extensions: []pkix.Extension{mustExtension(2, p2.Name, p2.ClientID)},
|
||||||
}
|
}
|
||||||
ok3Cert := &x509.Certificate{
|
ok3Cert := &x509.Certificate{
|
||||||
Extensions: []pkix.Extension{ok3Ext},
|
Extensions: []pkix.Extension{mustExtension(TypeACME, p3.Name, "")},
|
||||||
}
|
}
|
||||||
notFoundCert := &x509.Certificate{
|
notFoundCert := &x509.Certificate{
|
||||||
Extensions: []pkix.Extension{notFoundExt},
|
Extensions: []pkix.Extension{mustExtension(1, "foo", "bar")},
|
||||||
}
|
}
|
||||||
badCert := &x509.Certificate{
|
badCert := &x509.Certificate{
|
||||||
Extensions: []pkix.Extension{
|
Extensions: []pkix.Extension{
|
||||||
{Id: stepOIDProvisioner, Critical: false, Value: []byte("foobar")},
|
{Id: StepOIDProvisioner, Critical: false, Value: []byte("foobar")},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
authority/provisioner/extension.go
Normal file
73
authority/provisioner/extension.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package provisioner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// StepOIDRoot is the root OID for smallstep.
|
||||||
|
StepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64}
|
||||||
|
|
||||||
|
// StepOIDProvisioner is the OID for the provisioner extension.
|
||||||
|
StepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(StepOIDRoot, 1)...)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extension is the Go representation of the provisioner extension.
|
||||||
|
type Extension struct {
|
||||||
|
Type Type
|
||||||
|
Name string
|
||||||
|
CredentialID string
|
||||||
|
KeyValuePairs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type extensionASN1 struct {
|
||||||
|
Type int
|
||||||
|
Name []byte
|
||||||
|
CredentialID []byte
|
||||||
|
KeyValuePairs []string `asn1:"optional,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals the extension using encoding/asn1.
|
||||||
|
func (e *Extension) Marshal() ([]byte, error) {
|
||||||
|
return asn1.Marshal(extensionASN1{
|
||||||
|
Type: int(e.Type),
|
||||||
|
Name: []byte(e.Name),
|
||||||
|
CredentialID: []byte(e.CredentialID),
|
||||||
|
KeyValuePairs: e.KeyValuePairs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToExtension returns the pkix.Extension representation of the provisioner
|
||||||
|
// extension.
|
||||||
|
func (e *Extension) ToExtension() (pkix.Extension, error) {
|
||||||
|
b, err := e.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return pkix.Extension{}, err
|
||||||
|
}
|
||||||
|
return pkix.Extension{
|
||||||
|
Id: StepOIDProvisioner,
|
||||||
|
Value: b,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProvisionerExtension goes through all the certificate extensions and
|
||||||
|
// returns the provisioner extension (1.3.6.1.4.1.37476.9000.64.1).
|
||||||
|
func GetProvisionerExtension(cert *x509.Certificate) (*Extension, bool) {
|
||||||
|
for _, e := range cert.Extensions {
|
||||||
|
if e.Id.Equal(StepOIDProvisioner) {
|
||||||
|
var provisioner extensionASN1
|
||||||
|
if _, err := asn1.Unmarshal(e.Value, &provisioner); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return &Extension{
|
||||||
|
Type: Type(provisioner.Type),
|
||||||
|
Name: string(provisioner.Name),
|
||||||
|
CredentialID: string(provisioner.CredentialID),
|
||||||
|
KeyValuePairs: provisioner.KeyValuePairs,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
158
authority/provisioner/extension_test.go
Normal file
158
authority/provisioner/extension_test.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package provisioner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.step.sm/crypto/pemutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExtension_Marshal(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Type Type
|
||||||
|
Name string
|
||||||
|
CredentialID string
|
||||||
|
KeyValuePairs []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"ok", fields{TypeJWK, "name", "credentialID", nil}, []byte{
|
||||||
|
0x30, 0x17, 0x02, 0x01, 0x01, 0x04, 0x04, 0x6e,
|
||||||
|
0x61, 0x6d, 0x65, 0x04, 0x0c, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49,
|
||||||
|
0x44,
|
||||||
|
}, false},
|
||||||
|
{"ok with pairs", fields{TypeJWK, "name", "credentialID", []string{"foo", "bar"}}, []byte{
|
||||||
|
0x30, 0x23, 0x02, 0x01, 0x01, 0x04, 0x04, 0x6e,
|
||||||
|
0x61, 0x6d, 0x65, 0x04, 0x0c, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49,
|
||||||
|
0x44, 0x30, 0x0a, 0x13, 0x03, 0x66, 0x6f, 0x6f,
|
||||||
|
0x13, 0x03, 0x62, 0x61, 0x72,
|
||||||
|
}, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := &Extension{
|
||||||
|
Type: tt.fields.Type,
|
||||||
|
Name: tt.fields.Name,
|
||||||
|
CredentialID: tt.fields.CredentialID,
|
||||||
|
KeyValuePairs: tt.fields.KeyValuePairs,
|
||||||
|
}
|
||||||
|
got, err := e.Marshal()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Extension.Marshal() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Extension.Marshal() = %x, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtension_ToExtension(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Type Type
|
||||||
|
Name string
|
||||||
|
CredentialID string
|
||||||
|
KeyValuePairs []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want pkix.Extension
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"ok", fields{TypeJWK, "name", "credentialID", nil}, pkix.Extension{
|
||||||
|
Id: StepOIDProvisioner,
|
||||||
|
Value: []byte{
|
||||||
|
0x30, 0x17, 0x02, 0x01, 0x01, 0x04, 0x04, 0x6e,
|
||||||
|
0x61, 0x6d, 0x65, 0x04, 0x0c, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49,
|
||||||
|
0x44,
|
||||||
|
},
|
||||||
|
}, false},
|
||||||
|
{"ok empty pairs", fields{TypeJWK, "name", "credentialID", []string{}}, pkix.Extension{
|
||||||
|
Id: StepOIDProvisioner,
|
||||||
|
Value: []byte{
|
||||||
|
0x30, 0x17, 0x02, 0x01, 0x01, 0x04, 0x04, 0x6e,
|
||||||
|
0x61, 0x6d, 0x65, 0x04, 0x0c, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49,
|
||||||
|
0x44,
|
||||||
|
},
|
||||||
|
}, false},
|
||||||
|
{"ok with pairs", fields{TypeJWK, "name", "credentialID", []string{"foo", "bar"}}, pkix.Extension{
|
||||||
|
Id: StepOIDProvisioner,
|
||||||
|
Value: []byte{
|
||||||
|
0x30, 0x23, 0x02, 0x01, 0x01, 0x04, 0x04, 0x6e,
|
||||||
|
0x61, 0x6d, 0x65, 0x04, 0x0c, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49,
|
||||||
|
0x44, 0x30, 0x0a, 0x13, 0x03, 0x66, 0x6f, 0x6f,
|
||||||
|
0x13, 0x03, 0x62, 0x61, 0x72,
|
||||||
|
},
|
||||||
|
}, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := &Extension{
|
||||||
|
Type: tt.fields.Type,
|
||||||
|
Name: tt.fields.Name,
|
||||||
|
CredentialID: tt.fields.CredentialID,
|
||||||
|
KeyValuePairs: tt.fields.KeyValuePairs,
|
||||||
|
}
|
||||||
|
got, err := e.ToExtension()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Extension.ToExtension() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Extension.ToExtension() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetProvisionerExtension(t *testing.T) {
|
||||||
|
mustCertificate := func(fn string) *x509.Certificate {
|
||||||
|
cert, err := pemutil.ReadCertificate(fn)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return cert
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
cert *x509.Certificate
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want *Extension
|
||||||
|
want1 bool
|
||||||
|
}{
|
||||||
|
{"ok", args{mustCertificate("testdata/certs/good-extension.crt")}, &Extension{
|
||||||
|
Type: TypeJWK,
|
||||||
|
Name: "mariano@smallstep.com",
|
||||||
|
CredentialID: "nvgnR8wSzpUlrt_tC3mvrhwhBx9Y7T1WL_JjcFVWYBQ",
|
||||||
|
}, true},
|
||||||
|
{"fail unmarshal", args{mustCertificate("testdata/certs/bad-extension.crt")}, nil, false},
|
||||||
|
{"missing extension", args{mustCertificate("testdata/certs/aws.crt")}, nil, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, got1 := GetProvisionerExtension(tt.args.cert)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("GetProvisionerExtension() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if got1 != tt.want1 {
|
||||||
|
t.Errorf("GetProvisionerExtension() got1 = %v, want %v", got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -549,7 +549,7 @@ func TestGCP_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeGCP))
|
assert.Equals(t, v.Type, TypeGCP)
|
||||||
assert.Equals(t, v.Name, tt.gcp.GetName())
|
assert.Equals(t, v.Name, tt.gcp.GetName())
|
||||||
assert.Equals(t, v.CredentialID, tt.gcp.ServiceAccounts[0])
|
assert.Equals(t, v.CredentialID, tt.gcp.ServiceAccounts[0])
|
||||||
assert.Len(t, 4, v.KeyValuePairs)
|
assert.Len(t, 4, v.KeyValuePairs)
|
||||||
|
@ -300,7 +300,7 @@ func TestJWK_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeJWK))
|
assert.Equals(t, v.Type, TypeJWK)
|
||||||
assert.Equals(t, v.Name, tt.prov.GetName())
|
assert.Equals(t, v.Name, tt.prov.GetName())
|
||||||
assert.Equals(t, v.CredentialID, tt.prov.Key.KeyID)
|
assert.Equals(t, v.CredentialID, tt.prov.Key.KeyID)
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
@ -283,7 +283,7 @@ func TestK8sSA_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeK8sSA))
|
assert.Equals(t, v.Type, TypeK8sSA)
|
||||||
assert.Equals(t, v.Name, tc.p.GetName())
|
assert.Equals(t, v.Name, tc.p.GetName())
|
||||||
assert.Equals(t, v.CredentialID, "")
|
assert.Equals(t, v.CredentialID, "")
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
@ -327,7 +327,7 @@ func TestOIDC_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeOIDC))
|
assert.Equals(t, v.Type, TypeOIDC)
|
||||||
assert.Equals(t, v.Name, tt.prov.GetName())
|
assert.Equals(t, v.Name, tt.prov.GetName())
|
||||||
assert.Equals(t, v.CredentialID, tt.prov.ClientID)
|
assert.Equals(t, v.CredentialID, tt.prov.ClientID)
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -14,7 +13,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/smallstep/certificates/errs"
|
"github.com/smallstep/certificates/errs"
|
||||||
"go.step.sm/crypto/keyutil"
|
"go.step.sm/crypto/keyutil"
|
||||||
"go.step.sm/crypto/x509util"
|
"go.step.sm/crypto/x509util"
|
||||||
@ -404,17 +402,12 @@ func (v *validityValidator) Valid(cert *x509.Certificate, o SignOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
// type stepProvisionerASN1 struct {
|
||||||
stepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64}
|
// Type int
|
||||||
stepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(stepOIDRoot, 1)...)
|
// Name []byte
|
||||||
)
|
// CredentialID []byte
|
||||||
|
// KeyValuePairs []string `asn1:"optional,omitempty"`
|
||||||
type stepProvisionerASN1 struct {
|
// }
|
||||||
Type int
|
|
||||||
Name []byte
|
|
||||||
CredentialID []byte
|
|
||||||
KeyValuePairs []string `asn1:"optional,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type forceCNOption struct {
|
type forceCNOption struct {
|
||||||
ForceCN bool
|
ForceCN bool
|
||||||
@ -441,23 +434,22 @@ func (o *forceCNOption) Modify(cert *x509.Certificate, _ SignOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type provisionerExtensionOption struct {
|
type provisionerExtensionOption struct {
|
||||||
Type int
|
Extension
|
||||||
Name string
|
|
||||||
CredentialID string
|
|
||||||
KeyValuePairs []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValuePairs ...string) *provisionerExtensionOption {
|
func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValuePairs ...string) *provisionerExtensionOption {
|
||||||
return &provisionerExtensionOption{
|
return &provisionerExtensionOption{
|
||||||
Type: int(typ),
|
Extension: Extension{
|
||||||
Name: name,
|
Type: typ,
|
||||||
CredentialID: credentialID,
|
Name: name,
|
||||||
KeyValuePairs: keyValuePairs,
|
CredentialID: credentialID,
|
||||||
|
KeyValuePairs: keyValuePairs,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOptions) error {
|
func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOptions) error {
|
||||||
ext, err := createProvisionerExtension(o.Type, o.Name, o.CredentialID, o.KeyValuePairs...)
|
ext, err := o.ToExtension()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errs.NewError(http.StatusInternalServerError, err, "error creating certificate")
|
return errs.NewError(http.StatusInternalServerError, err, "error creating certificate")
|
||||||
}
|
}
|
||||||
@ -471,20 +463,3 @@ func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOption
|
|||||||
cert.ExtraExtensions = append([]pkix.Extension{ext}, cert.ExtraExtensions...)
|
cert.ExtraExtensions = append([]pkix.Extension{ext}, cert.ExtraExtensions...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createProvisionerExtension(typ int, name, credentialID string, keyValuePairs ...string) (pkix.Extension, error) {
|
|
||||||
b, err := asn1.Marshal(stepProvisionerASN1{
|
|
||||||
Type: typ,
|
|
||||||
Name: []byte(name),
|
|
||||||
CredentialID: []byte(credentialID),
|
|
||||||
KeyValuePairs: keyValuePairs,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return pkix.Extension{}, errors.Wrap(err, "error marshaling provisioner extension")
|
|
||||||
}
|
|
||||||
return pkix.Extension{
|
|
||||||
Id: stepOIDProvisioner,
|
|
||||||
Critical: false,
|
|
||||||
Value: b,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
@ -636,18 +636,18 @@ func Test_newProvisionerExtension_Option(t *testing.T) {
|
|||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
if assert.Len(t, 1, cert.ExtraExtensions) {
|
if assert.Len(t, 1, cert.ExtraExtensions) {
|
||||||
ext := cert.ExtraExtensions[0]
|
ext := cert.ExtraExtensions[0]
|
||||||
assert.Equals(t, ext.Id, stepOIDProvisioner)
|
assert.Equals(t, ext.Id, StepOIDProvisioner)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ok/prepend": func() test {
|
"ok/prepend": func() test {
|
||||||
return test{
|
return test{
|
||||||
cert: &x509.Certificate{ExtraExtensions: []pkix.Extension{{Id: stepOIDProvisioner, Critical: true}, {Id: []int{1, 2, 3}}}},
|
cert: &x509.Certificate{ExtraExtensions: []pkix.Extension{{Id: StepOIDProvisioner, Critical: true}, {Id: []int{1, 2, 3}}}},
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
if assert.Len(t, 3, cert.ExtraExtensions) {
|
if assert.Len(t, 3, cert.ExtraExtensions) {
|
||||||
ext := cert.ExtraExtensions[0]
|
ext := cert.ExtraExtensions[0]
|
||||||
assert.Equals(t, ext.Id, stepOIDProvisioner)
|
assert.Equals(t, ext.Id, StepOIDProvisioner)
|
||||||
assert.False(t, ext.Critical)
|
assert.False(t, ext.Critical)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
21
authority/provisioner/testdata/certs/bad-extension.crt
vendored
Normal file
21
authority/provisioner/testdata/certs/bad-extension.crt
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDeTCCAx+gAwIBAgIRAOTItW2pYuSU+PkmLW090iUwCgYIKoZIzj0EAwIwJDEi
|
||||||
|
MCAGA1UEAxMZU21hbGxzdGVwIEludGVybWVkaWF0ZSBDQTAeFw0yMjAzMTEyMjUy
|
||||||
|
MjBaFw0yMjAzMTIyMjUzMjBaMIGcMQswCQYDVQQGEwJDSDETMBEGA1UECBMKQ2Fs
|
||||||
|
aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEYMBYGA1UECRMPMSBUaGUg
|
||||||
|
U3RyZWV0IFN0MRMwEQYDVQQKDAo8bm8gdmFsdWU+MRYwFAYDVQQLEw1TbWFsbHN0
|
||||||
|
ZXAgRW5nMRkwFwYDVQQDDBB0ZXN0QGV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI
|
||||||
|
KoZIzj0DAQcDQgAE/9vvOZ1Zzysnf3VeGyotMJEMZdAborB36Ah5QL/3yQNMRWIc
|
||||||
|
pv9Dwx19pHw7SquVE8jIaPPJSjaeWnfMPDYDxaOCAbcwggGzMA4GA1UdDwEB/wQE
|
||||||
|
AwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIw
|
||||||
|
ADAdBgNVHQ4EFgQUkJUg6AsqWlqTZt6BHidRMwh1vKYwHwYDVR0jBBgwFoAUDpTg
|
||||||
|
d3VFCn6e71wXcwbDCURBomUwgZoGCCsGAQUFBwEBBIGNMIGKMBcGCCsGAQUFBzAB
|
||||||
|
hgtodHRwczovL2ZvbzBvBggrBgEFBQcwAoZjaHR0cHM6Ly9jYS5zbWFsbHN0ZXAu
|
||||||
|
Y29tOjkwMDAvcm9vdC9hNzhhODUwMDI1YzBjMjM0Mzg1ZWRhMjNkNzE5Mjk2NGNh
|
||||||
|
NTZhYTlkNzI3ZjUzNTY1M2IwYWZiODFjMWUwNTU5MBsGA1UdEQQUMBKBEHRlc3RA
|
||||||
|
ZXhhbXBsZS5jb20wIAYDVR0gBBkwFzALBglghkgBhv1sAQEwCAYGZ4EMAQICMD8G
|
||||||
|
A1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWV2
|
||||||
|
LXNlcnZlci1nMy5jcmwwFwYMKwYBBAGCpGTGKEABBAdmb29vYmFyMAoGCCqGSM49
|
||||||
|
BAMCA0gAMEUCIQCWYqOuk4bLkVVeHvo3P8TlJJ3fw6ijDDLstvdrQqAl5wIgEjSY
|
||||||
|
wVcR649Oc8PJGh/43Kpx0+4OTYPQrD/JqphVF7g=
|
||||||
|
-----END CERTIFICATE-----
|
22
authority/provisioner/testdata/certs/good-extension.crt
vendored
Normal file
22
authority/provisioner/testdata/certs/good-extension.crt
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDujCCA2GgAwIBAgIRAM5celDKTTqAGycljO7FZdEwCgYIKoZIzj0EAwIwJDEi
|
||||||
|
MCAGA1UEAxMZU21hbGxzdGVwIEludGVybWVkaWF0ZSBDQTAeFw0yMjAzMTEyMjQx
|
||||||
|
MDRaFw0yMjAzMTIyMjQyMDRaMIGcMQswCQYDVQQGEwJDSDETMBEGA1UECBMKQ2Fs
|
||||||
|
aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEYMBYGA1UECRMPMSBUaGUg
|
||||||
|
U3RyZWV0IFN0MRMwEQYDVQQKDAo8bm8gdmFsdWU+MRYwFAYDVQQLEw1TbWFsbHN0
|
||||||
|
ZXAgRW5nMRkwFwYDVQQDDBB0ZXN0QGV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI
|
||||||
|
KoZIzj0DAQcDQgAEkXffZYlSJRMxJrZHmUpEMC4jQYCkF86mLJY0iLZ8k00N/xF0
|
||||||
|
4rAGwzTU/l9tfRpNl+z/XfMMWPXS0Q8NU/o4S6OCAfkwggH1MA4GA1UdDwEB/wQE
|
||||||
|
AwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIw
|
||||||
|
ADAdBgNVHQ4EFgQUL3sSlYW8Tf2l2P+gFTdn5wsUjfgwHwYDVR0jBBgwFoAUDpTg
|
||||||
|
d3VFCn6e71wXcwbDCURBomUwgZoGCCsGAQUFBwEBBIGNMIGKMBcGCCsGAQUFBzAB
|
||||||
|
hgtodHRwczovL2ZvbzBvBggrBgEFBQcwAoZjaHR0cHM6Ly9jYS5zbWFsbHN0ZXAu
|
||||||
|
Y29tOjkwMDAvcm9vdC9hNzhhODUwMDI1YzBjMjM0Mzg1ZWRhMjNkNzE5Mjk2NGNh
|
||||||
|
NTZhYTlkNzI3ZjUzNTY1M2IwYWZiODFjMWUwNTU5MBsGA1UdEQQUMBKBEHRlc3RA
|
||||||
|
ZXhhbXBsZS5jb20wIAYDVR0gBBkwFzALBglghkgBhv1sAQEwCAYGZ4EMAQICMD8G
|
||||||
|
A1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWV2
|
||||||
|
LXNlcnZlci1nMy5jcmwwWQYMKwYBBAGCpGTGKEABBEkwRwIBAQQVbWFyaWFub0Bz
|
||||||
|
bWFsbHN0ZXAuY29tBCtudmduUjh3U3pwVWxydF90QzNtdnJod2hCeDlZN1QxV0xf
|
||||||
|
SmpjRlZXWUJRMAoGCCqGSM49BAMCA0cAMEQCIE6umrhSbeQWWVK5cWBvXj5c0cGB
|
||||||
|
bUF0rNw/dsaCaWcwAiAKSkmjhsC63DVPXPCNUki90YgVovO69foO1ZaB43lx5w==
|
||||||
|
-----END CERTIFICATE-----
|
@ -469,7 +469,7 @@ func TestX5C_AuthorizeSign(t *testing.T) {
|
|||||||
switch v := o.(type) {
|
switch v := o.(type) {
|
||||||
case certificateOptionsFunc:
|
case certificateOptionsFunc:
|
||||||
case *provisionerExtensionOption:
|
case *provisionerExtensionOption:
|
||||||
assert.Equals(t, v.Type, int(TypeX5C))
|
assert.Equals(t, v.Type, TypeX5C)
|
||||||
assert.Equals(t, v.Name, tc.p.GetName())
|
assert.Equals(t, v.Name, tc.p.GetName())
|
||||||
assert.Equals(t, v.CredentialID, "")
|
assert.Equals(t, v.CredentialID, "")
|
||||||
assert.Len(t, 0, v.KeyValuePairs)
|
assert.Len(t, 0, v.KeyValuePairs)
|
||||||
|
Loading…
Reference in New Issue
Block a user