forked from TrueCloudLab/certificates
Rename provisioner options structs:
* provisioner.ProvisionerOptions => provisioner.Options * provisioner.Options => provisioner.SignOptions * provisioner.SSHOptions => provisioner.SingSSHOptions
This commit is contained in:
parent
e0dd1bd132
commit
6c64fb3ed2
37 changed files with 405 additions and 406 deletions
|
@ -18,7 +18,7 @@ type Provisioner interface {
|
||||||
AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error)
|
AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error)
|
||||||
GetName() string
|
GetName() string
|
||||||
DefaultTLSCertDuration() time.Duration
|
DefaultTLSCertDuration() time.Duration
|
||||||
GetOptions() *provisioner.ProvisionerOptions
|
GetOptions() *provisioner.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockProvisioner for testing
|
// MockProvisioner for testing
|
||||||
|
@ -28,7 +28,7 @@ type MockProvisioner struct {
|
||||||
MgetName func() string
|
MgetName func() string
|
||||||
MauthorizeSign func(ctx context.Context, ott string) ([]provisioner.SignOption, error)
|
MauthorizeSign func(ctx context.Context, ott string) ([]provisioner.SignOption, error)
|
||||||
MdefaultTLSCertDuration func() time.Duration
|
MdefaultTLSCertDuration func() time.Duration
|
||||||
MgetOptions func() *provisioner.ProvisionerOptions
|
MgetOptions func() *provisioner.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetName mock
|
// GetName mock
|
||||||
|
@ -55,11 +55,11 @@ func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration {
|
||||||
return m.Mret1.(time.Duration)
|
return m.Mret1.(time.Duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockProvisioner) GetOptions() *provisioner.ProvisionerOptions {
|
func (m *MockProvisioner) GetOptions() *provisioner.Options {
|
||||||
if m.MgetOptions != nil {
|
if m.MgetOptions != nil {
|
||||||
return m.MgetOptions()
|
return m.MgetOptions()
|
||||||
}
|
}
|
||||||
return m.Mret1.(*provisioner.ProvisionerOptions)
|
return m.Mret1.(*provisioner.Options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextKey is the key type for storing and searching for ACME request
|
// ContextKey is the key type for storing and searching for ACME request
|
||||||
|
@ -134,7 +134,7 @@ func ProvisionerFromContext(ctx context.Context) (Provisioner, error) {
|
||||||
|
|
||||||
// SignAuthority is the interface implemented by a CA authority.
|
// SignAuthority is the interface implemented by a CA authority.
|
||||||
type SignAuthority interface {
|
type SignAuthority interface {
|
||||||
Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
||||||
LoadProvisionerByID(string) (provisioner.Interface, error)
|
LoadProvisionerByID(string) (provisioner.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut
|
||||||
signOps = append(signOps, templateOptions)
|
signOps = append(signOps, templateOptions)
|
||||||
|
|
||||||
// Create and store a new certificate.
|
// Create and store a new certificate.
|
||||||
certChain, err := auth.Sign(csr, provisioner.Options{
|
certChain, err := auth.Sign(csr, provisioner.SignOptions{
|
||||||
NotBefore: provisioner.NewTimeDuration(o.NotBefore),
|
NotBefore: provisioner.NewTimeDuration(o.NotBefore),
|
||||||
NotAfter: provisioner.NewTimeDuration(o.NotAfter),
|
NotAfter: provisioner.NewTimeDuration(o.NotAfter),
|
||||||
}, signOps...)
|
}, signOps...)
|
||||||
|
|
|
@ -895,13 +895,13 @@ func TestOrderUpdateStatus(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockSignAuth struct {
|
type mockSignAuth struct {
|
||||||
sign func(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
sign func(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
||||||
loadProvisionerByID func(string) (provisioner.Interface, error)
|
loadProvisionerByID func(string) (provisioner.Interface, error)
|
||||||
ret1, ret2 interface{}
|
ret1, ret2 interface{}
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
if m.sign != nil {
|
if m.sign != nil {
|
||||||
return m.sign(csr, signOpts, extraOpts...)
|
return m.sign(csr, signOpts, extraOpts...)
|
||||||
} else if m.err != nil {
|
} else if m.err != nil {
|
||||||
|
@ -1262,7 +1262,7 @@ func TestOrderFinalize(t *testing.T) {
|
||||||
res: clone,
|
res: clone,
|
||||||
csr: csr,
|
csr: csr,
|
||||||
sa: &mockSignAuth{
|
sa: &mockSignAuth{
|
||||||
sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
assert.Equals(t, len(signOps), 6)
|
assert.Equals(t, len(signOps), 6)
|
||||||
return []*x509.Certificate{crt, inter}, nil
|
return []*x509.Certificate{crt, inter}, nil
|
||||||
},
|
},
|
||||||
|
@ -1311,7 +1311,7 @@ func TestOrderFinalize(t *testing.T) {
|
||||||
res: &clone,
|
res: &clone,
|
||||||
csr: csr,
|
csr: csr,
|
||||||
sa: &mockSignAuth{
|
sa: &mockSignAuth{
|
||||||
sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
assert.Equals(t, len(signOps), 6)
|
assert.Equals(t, len(signOps), 6)
|
||||||
return []*x509.Certificate{crt, inter}, nil
|
return []*x509.Certificate{crt, inter}, nil
|
||||||
},
|
},
|
||||||
|
@ -1358,7 +1358,7 @@ func TestOrderFinalize(t *testing.T) {
|
||||||
res: &clone,
|
res: &clone,
|
||||||
csr: csr,
|
csr: csr,
|
||||||
sa: &mockSignAuth{
|
sa: &mockSignAuth{
|
||||||
sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
assert.Equals(t, len(signOps), 6)
|
assert.Equals(t, len(signOps), 6)
|
||||||
return []*x509.Certificate{crt, inter}, nil
|
return []*x509.Certificate{crt, inter}, nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -34,7 +34,7 @@ type Authority interface {
|
||||||
AuthorizeSign(ott string) ([]provisioner.SignOption, error)
|
AuthorizeSign(ott string) ([]provisioner.SignOption, error)
|
||||||
GetTLSOptions() *tlsutil.TLSOptions
|
GetTLSOptions() *tlsutil.TLSOptions
|
||||||
Root(shasum string) (*x509.Certificate, error)
|
Root(shasum string) (*x509.Certificate, error)
|
||||||
Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
||||||
Renew(peer *x509.Certificate) ([]*x509.Certificate, error)
|
Renew(peer *x509.Certificate) ([]*x509.Certificate, error)
|
||||||
Rekey(peer *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
|
Rekey(peer *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
|
||||||
LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error)
|
LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error)
|
||||||
|
|
|
@ -550,7 +550,7 @@ type mockAuthority struct {
|
||||||
authorizeSign func(ott string) ([]provisioner.SignOption, error)
|
authorizeSign func(ott string) ([]provisioner.SignOption, error)
|
||||||
getTLSOptions func() *tlsutil.TLSOptions
|
getTLSOptions func() *tlsutil.TLSOptions
|
||||||
root func(shasum string) (*x509.Certificate, error)
|
root func(shasum string) (*x509.Certificate, error)
|
||||||
sign func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
sign func(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
||||||
renew func(cert *x509.Certificate) ([]*x509.Certificate, error)
|
renew func(cert *x509.Certificate) ([]*x509.Certificate, error)
|
||||||
rekey func(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
|
rekey func(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
|
||||||
loadProvisionerByCertificate func(cert *x509.Certificate) (provisioner.Interface, error)
|
loadProvisionerByCertificate func(cert *x509.Certificate) (provisioner.Interface, error)
|
||||||
|
@ -560,7 +560,7 @@ type mockAuthority struct {
|
||||||
getEncryptedKey func(kid string) (string, error)
|
getEncryptedKey func(kid string) (string, error)
|
||||||
getRoots func() ([]*x509.Certificate, error)
|
getRoots func() ([]*x509.Certificate, error)
|
||||||
getFederation func() ([]*x509.Certificate, error)
|
getFederation func() ([]*x509.Certificate, error)
|
||||||
signSSH func(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
signSSH func(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
||||||
signSSHAddUser func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error)
|
signSSHAddUser func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error)
|
||||||
renewSSH func(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error)
|
renewSSH func(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error)
|
||||||
rekeySSH func(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
rekeySSH func(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
||||||
|
@ -599,7 +599,7 @@ func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) {
|
||||||
return m.ret1.(*x509.Certificate), m.err
|
return m.ret1.(*x509.Certificate), m.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
if m.sign != nil {
|
if m.sign != nil {
|
||||||
return m.sign(cr, opts, signOpts...)
|
return m.sign(cr, opts, signOpts...)
|
||||||
}
|
}
|
||||||
|
@ -669,7 +669,7 @@ func (m *mockAuthority) GetFederation() ([]*x509.Certificate, error) {
|
||||||
return m.ret1.([]*x509.Certificate), m.err
|
return m.ret1.([]*x509.Certificate), m.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockAuthority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
func (m *mockAuthority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||||
if m.signSSH != nil {
|
if m.signSSH != nil {
|
||||||
return m.signSSH(ctx, key, opts, signOpts...)
|
return m.signSSH(ctx, key, opts, signOpts...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := provisioner.Options{
|
opts := provisioner.SignOptions{
|
||||||
NotBefore: body.NotBefore,
|
NotBefore: body.NotBefore,
|
||||||
NotAfter: body.NotAfter,
|
NotAfter: body.NotAfter,
|
||||||
TemplateData: body.TemplateData,
|
TemplateData: body.TemplateData,
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
|
|
||||||
// SSHAuthority is the interface implemented by a SSH CA authority.
|
// SSHAuthority is the interface implemented by a SSH CA authority.
|
||||||
type SSHAuthority interface {
|
type SSHAuthority interface {
|
||||||
SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
||||||
RenewSSH(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error)
|
RenewSSH(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error)
|
||||||
RekeySSH(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
RekeySSH(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
|
||||||
SignSSHAddUser(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error)
|
SignSSHAddUser(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error)
|
||||||
|
@ -274,7 +274,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := provisioner.SSHOptions{
|
opts := provisioner.SignSSHOptions{
|
||||||
CertType: body.CertType,
|
CertType: body.CertType,
|
||||||
KeyID: body.KeyID,
|
KeyID: body.KeyID,
|
||||||
Principals: body.Principals,
|
Principals: body.Principals,
|
||||||
|
@ -322,7 +322,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
|
||||||
NotAfter: time.Unix(int64(cert.ValidBefore), 0),
|
NotAfter: time.Unix(int64(cert.ValidBefore), 0),
|
||||||
})
|
})
|
||||||
|
|
||||||
certChain, err := h.Authority.Sign(cr, provisioner.Options{}, signOpts...)
|
certChain, err := h.Authority.Sign(cr, provisioner.SignOptions{}, signOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteError(w, errs.ForbiddenErr(err))
|
WriteError(w, errs.ForbiddenErr(err))
|
||||||
return
|
return
|
||||||
|
|
|
@ -319,13 +319,13 @@ func Test_caHandler_SSHSign(t *testing.T) {
|
||||||
authorizeSign: func(ott string) ([]provisioner.SignOption, error) {
|
authorizeSign: func(ott string) ([]provisioner.SignOption, error) {
|
||||||
return []provisioner.SignOption{}, tt.authErr
|
return []provisioner.SignOption{}, tt.authErr
|
||||||
},
|
},
|
||||||
signSSH: func(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
signSSH: func(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||||
return tt.signCert, tt.signErr
|
return tt.signCert, tt.signErr
|
||||||
},
|
},
|
||||||
signSSHAddUser: func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) {
|
signSSHAddUser: func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) {
|
||||||
return tt.addUserCert, tt.addUserErr
|
return tt.addUserCert, tt.addUserErr
|
||||||
},
|
},
|
||||||
sign: func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
sign: func(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
return tt.tlsSignCerts, tt.tlsSignErr
|
return tt.tlsSignCerts, tt.tlsSignErr
|
||||||
},
|
},
|
||||||
}).(*caHandler)
|
}).(*caHandler)
|
||||||
|
|
|
@ -283,7 +283,7 @@ func TestNewEmbedded_Sign(t *testing.T) {
|
||||||
csr, err := x509.ParseCertificateRequest(cr)
|
csr, err := x509.ParseCertificateRequest(cr)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
cert, err := a.Sign(csr, provisioner.Options{})
|
cert, err := a.Sign(csr, provisioner.SignOptions{})
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
assert.Equals(t, []string{"foo.bar.zar"}, cert[0].DNSNames)
|
assert.Equals(t, []string{"foo.bar.zar"}, cert[0].DNSNames)
|
||||||
assert.Equals(t, crt, cert[1])
|
assert.Equals(t, crt, cert[1])
|
||||||
|
|
|
@ -830,17 +830,17 @@ func TestAuthority_authorizeRenew(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
||||||
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SSHOptions{
|
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SignSSHOptions{
|
||||||
CertType: "user",
|
CertType: "user",
|
||||||
Principals: []string{"name"},
|
Principals: []string{"name"},
|
||||||
}, jwk)
|
}, jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
type stepPayload struct {
|
type stepPayload struct {
|
||||||
SSH *provisioner.SSHOptions `json:"ssh,omitempty"`
|
SSH *provisioner.SignSSHOptions `json:"ssh,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *provisioner.SSHOptions, jwk *jose.JSONWebKey) (string, error) {
|
func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *provisioner.SignSSHOptions, jwk *jose.JSONWebKey) (string, error) {
|
||||||
sig, err := jose.NewSigner(
|
sig, err := jose.NewSigner(
|
||||||
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
|
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
|
||||||
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),
|
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),
|
||||||
|
|
|
@ -13,11 +13,11 @@ import (
|
||||||
// provisioning flow.
|
// provisioning flow.
|
||||||
type ACME struct {
|
type ACME struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ForceCN bool `json:"forceCN,omitempty"`
|
ForceCN bool `json:"forceCN,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func (p *ACME) GetEncryptedKey() (string, string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOptions returns the configured provisioner options.
|
// GetOptions returns the configured provisioner options.
|
||||||
func (p *ACME) GetOptions() *ProvisionerOptions {
|
func (p *ACME) GetOptions() *Options {
|
||||||
return p.Options
|
return p.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,14 +126,14 @@ type awsInstanceIdentityDocument struct {
|
||||||
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
|
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
|
||||||
type AWS struct {
|
type AWS struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Accounts []string `json:"accounts"`
|
Accounts []string `json:"accounts"`
|
||||||
DisableCustomSANs bool `json:"disableCustomSANs"`
|
DisableCustomSANs bool `json:"disableCustomSANs"`
|
||||||
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
||||||
InstanceAge Duration `json:"instanceAge,omitempty"`
|
InstanceAge Duration `json:"instanceAge,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
config *awsConfig
|
config *awsConfig
|
||||||
audiences Audiences
|
audiences Audiences
|
||||||
|
@ -483,7 +483,7 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to cert type to host
|
// Default to cert type to host
|
||||||
defaults := SSHOptions{
|
defaults := SignSSHOptions{
|
||||||
CertType: SSHHostCert,
|
CertType: SSHHostCert,
|
||||||
Principals: principals,
|
Principals: principals,
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,51 +647,51 @@ func TestAWS_AuthorizeSSHSign(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"},
|
CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptionsIP := &SSHOptions{
|
expectedHostOptionsIP := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"127.0.0.1"},
|
CertType: "host", Principals: []string{"127.0.0.1"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptionsHostname := &SSHOptions{
|
expectedHostOptionsHostname := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"},
|
CertType: "host", Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedCustomOptions := &SSHOptions{
|
expectedCustomOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"foo.local"},
|
CertType: "host", Principals: []string{"foo.local"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
token string
|
token string
|
||||||
sshOpts SSHOptions
|
sshOpts SignSSHOptions
|
||||||
key interface{}
|
key interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
aws *AWS
|
aws *AWS
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
code int
|
code int
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-principal-ip", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1"}}, pub}, expectedHostOptionsIP, http.StatusOK, false, false},
|
{"ok-principal-ip", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1"}}, pub}, expectedHostOptionsIP, http.StatusOK, false, false},
|
||||||
{"ok-principal-hostname", p1, args{t1, SSHOptions{Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptionsHostname, http.StatusOK, false, false},
|
{"ok-principal-hostname", p1, args{t1, SignSSHOptions{Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptionsHostname, http.StatusOK, false, false},
|
||||||
{"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
{"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
||||||
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
||||||
{"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
{"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -83,15 +83,15 @@ type azurePayload struct {
|
||||||
// and https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service
|
// and https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service
|
||||||
type Azure struct {
|
type Azure struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
TenantID string `json:"tenantID"`
|
TenantID string `json:"tenantID"`
|
||||||
ResourceGroups []string `json:"resourceGroups"`
|
ResourceGroups []string `json:"resourceGroups"`
|
||||||
Audience string `json:"audience,omitempty"`
|
Audience string `json:"audience,omitempty"`
|
||||||
DisableCustomSANs bool `json:"disableCustomSANs"`
|
DisableCustomSANs bool `json:"disableCustomSANs"`
|
||||||
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
config *azureConfig
|
config *azureConfig
|
||||||
oidcConfig openIDConfiguration
|
oidcConfig openIDConfiguration
|
||||||
|
@ -350,7 +350,7 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to host + known hostnames
|
// Default to host + known hostnames
|
||||||
defaults := SSHOptions{
|
defaults := SignSSHOptions{
|
||||||
CertType: SSHHostCert,
|
CertType: SSHHostCert,
|
||||||
Principals: principals,
|
Principals: principals,
|
||||||
}
|
}
|
||||||
|
|
|
@ -571,41 +571,41 @@ func TestAzure_AuthorizeSSHSign(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"virtualMachine"},
|
CertType: "host", Principals: []string{"virtualMachine"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedCustomOptions := &SSHOptions{
|
expectedCustomOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"foo.bar"},
|
CertType: "host", Principals: []string{"foo.bar"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
token string
|
token string
|
||||||
sshOpts SSHOptions
|
sshOpts SignSSHOptions
|
||||||
key interface{}
|
key interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
azure *Azure
|
azure *Azure
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
code int
|
code int
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.bar"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
{"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.bar"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
||||||
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
||||||
{"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"virtualMachine", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"virtualMachine", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
{"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -77,15 +77,15 @@ func newGCPConfig() *gcpConfig {
|
||||||
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity
|
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity
|
||||||
type GCP struct {
|
type GCP struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ServiceAccounts []string `json:"serviceAccounts"`
|
ServiceAccounts []string `json:"serviceAccounts"`
|
||||||
ProjectIDs []string `json:"projectIDs"`
|
ProjectIDs []string `json:"projectIDs"`
|
||||||
DisableCustomSANs bool `json:"disableCustomSANs"`
|
DisableCustomSANs bool `json:"disableCustomSANs"`
|
||||||
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
|
||||||
InstanceAge Duration `json:"instanceAge,omitempty"`
|
InstanceAge Duration `json:"instanceAge,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
config *gcpConfig
|
config *gcpConfig
|
||||||
keyStore *keyStore
|
keyStore *keyStore
|
||||||
|
@ -394,7 +394,7 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to host + known hostnames
|
// Default to host + known hostnames
|
||||||
defaults := SSHOptions{
|
defaults := SignSSHOptions{
|
||||||
CertType: SSHHostCert,
|
CertType: SSHHostCert,
|
||||||
Principals: principals,
|
Principals: principals,
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,51 +623,51 @@ func TestGCP_AuthorizeSSHSign(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"},
|
CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptionsPrincipal1 := &SSHOptions{
|
expectedHostOptionsPrincipal1 := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"instance-name.c.project-id.internal"},
|
CertType: "host", Principals: []string{"instance-name.c.project-id.internal"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptionsPrincipal2 := &SSHOptions{
|
expectedHostOptionsPrincipal2 := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"instance-name.zone.c.project-id.internal"},
|
CertType: "host", Principals: []string{"instance-name.zone.c.project-id.internal"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
expectedCustomOptions := &SSHOptions{
|
expectedCustomOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"foo.bar", "bar.foo"},
|
CertType: "host", Principals: []string{"foo.bar", "bar.foo"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
token string
|
token string
|
||||||
sshOpts SSHOptions
|
sshOpts SignSSHOptions
|
||||||
key interface{}
|
key interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
gcp *GCP
|
gcp *GCP
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
code int
|
code int
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-principal1", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal1, http.StatusOK, false, false},
|
{"ok-principal1", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal1, http.StatusOK, false, false},
|
||||||
{"ok-principal2", p1, args{t1, SSHOptions{Principals: []string{"instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal2, http.StatusOK, false, false},
|
{"ok-principal2", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal2, http.StatusOK, false, false},
|
||||||
{"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.bar", "bar.foo"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
{"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.bar", "bar.foo"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
|
||||||
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
|
||||||
{"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
{"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -20,19 +20,19 @@ type jwtPayload struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type stepPayload struct {
|
type stepPayload struct {
|
||||||
SSH *SSHOptions `json:"ssh,omitempty"`
|
SSH *SignSSHOptions `json:"ssh,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JWK is the default provisioner, an entity that can sign tokens necessary for
|
// JWK is the default provisioner, an entity that can sign tokens necessary for
|
||||||
// signature requests.
|
// signature requests.
|
||||||
type JWK struct {
|
type JWK struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Key *jose.JSONWebKey `json:"key"`
|
Key *jose.JSONWebKey `json:"key"`
|
||||||
EncryptedKey string `json:"encryptedKey,omitempty"`
|
EncryptedKey string `json:"encryptedKey,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
audiences Audiences
|
audiences Audiences
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,41 +404,41 @@ func TestJWK_AuthorizeSSHSign(t *testing.T) {
|
||||||
|
|
||||||
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedUserOptions := &SSHOptions{
|
expectedUserOptions := &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"},
|
CertType: "user", Principals: []string{"name"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"smallstep.com"},
|
CertType: "host", Principals: []string{"smallstep.com"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
token string
|
token string
|
||||||
sshOpts SSHOptions
|
sshOpts SignSSHOptions
|
||||||
key interface{}
|
key interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
prov *JWK
|
prov *JWK
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
code int
|
code int
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"user", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"user", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"user-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
|
{"user-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"user-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"user-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"user-principals", p1, args{t1, SSHOptions{Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"user-principals", p1, args{t1, SignSSHOptions{Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"user-options", p1, args{t1, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"user-options", p1, args{t1, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"host", p1, args{t2, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"host", p1, args{t2, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"host-type", p1, args{t2, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"host-type", p1, args{t2, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"host-principals", p1, args{t2, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"host-principals", p1, args{t2, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"host-options", p1, args{t2, SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
{"host-options", p1, args{t2, SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"fail-sshCA-disabled", p2, args{"foo", SSHOptions{}, pub}, expectedUserOptions, http.StatusUnauthorized, true, false},
|
{"fail-sshCA-disabled", p2, args{"foo", SignSSHOptions{}, pub}, expectedUserOptions, http.StatusUnauthorized, true, false},
|
||||||
{"fail-signature", p1, args{failSig, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
{"fail-signature", p1, args{failSig, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
||||||
{"rail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
|
{"rail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -487,72 +487,72 @@ func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) {
|
||||||
|
|
||||||
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedUserOptions := &SSHOptions{
|
expectedUserOptions := &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"},
|
CertType: "user", Principals: []string{"name"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"smallstep.com"},
|
CertType: "host", Principals: []string{"smallstep.com"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
sub, iss, aud string
|
sub, iss, aud string
|
||||||
iat time.Time
|
iat time.Time
|
||||||
tokSSHOpts *SSHOptions
|
tokSSHOpts *SignSSHOptions
|
||||||
userSSHOpts *SSHOptions
|
userSSHOpts *SignSSHOptions
|
||||||
jwk *jose.JSONWebKey
|
jwk *jose.JSONWebKey
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
prov *JWK
|
prov *JWK
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"ok-user", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, expectedUserOptions, false, false},
|
{"ok-user", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, expectedUserOptions, false, false},
|
||||||
{"ok-host", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, &SSHOptions{}, jwk}, expectedHostOptions, false, false},
|
{"ok-host", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, &SignSSHOptions{}, jwk}, expectedHostOptions, false, false},
|
||||||
{"ok-user-opts", p1, args{sub, iss, aud, iat, &SSHOptions{}, &SSHOptions{CertType: "user", Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false},
|
{"ok-user-opts", p1, args{sub, iss, aud, iat, &SignSSHOptions{}, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false},
|
||||||
{"ok-host-opts", p1, args{sub, iss, aud, iat, &SSHOptions{}, &SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, jwk}, expectedHostOptions, false, false},
|
{"ok-host-opts", p1, args{sub, iss, aud, iat, &SignSSHOptions{}, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, jwk}, expectedHostOptions, false, false},
|
||||||
{"ok-user-mixed", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user"}, &SSHOptions{Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false},
|
{"ok-user-mixed", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user"}, &SignSSHOptions{Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false},
|
||||||
{"ok-host-mixed", p1, args{sub, iss, aud, iat, &SSHOptions{Principals: []string{"smallstep.com"}}, &SSHOptions{CertType: "host"}, jwk}, expectedHostOptions, false, false},
|
{"ok-host-mixed", p1, args{sub, iss, aud, iat, &SignSSHOptions{Principals: []string{"smallstep.com"}}, &SignSSHOptions{CertType: "host"}, jwk}, expectedHostOptions, false, false},
|
||||||
{"ok-user-validAfter", p1, args{sub, iss, aud, iat, &SSHOptions{
|
{"ok-user-validAfter", p1, args{sub, iss, aud, iat, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"},
|
CertType: "user", Principals: []string{"name"},
|
||||||
}, &SSHOptions{
|
}, &SignSSHOptions{
|
||||||
ValidAfter: NewTimeDuration(tm.Add(-time.Hour)),
|
ValidAfter: NewTimeDuration(tm.Add(-time.Hour)),
|
||||||
}, jwk}, &SSHOptions{
|
}, jwk}, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(-time.Hour)), ValidBefore: NewTimeDuration(tm.Add(userDuration - time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(-time.Hour)), ValidBefore: NewTimeDuration(tm.Add(userDuration - time.Hour)),
|
||||||
}, false, false},
|
}, false, false},
|
||||||
{"ok-user-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{
|
{"ok-user-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"},
|
CertType: "user", Principals: []string{"name"},
|
||||||
}, &SSHOptions{
|
}, &SignSSHOptions{
|
||||||
ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
||||||
}, jwk}, &SSHOptions{
|
}, jwk}, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
||||||
}, false, false},
|
}, false, false},
|
||||||
{"ok-user-validAfter-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{
|
{"ok-user-validAfter-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"},
|
CertType: "user", Principals: []string{"name"},
|
||||||
}, &SSHOptions{
|
}, &SignSSHOptions{
|
||||||
ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
||||||
}, jwk}, &SSHOptions{
|
}, jwk}, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
||||||
}, false, false},
|
}, false, false},
|
||||||
{"ok-user-match", p1, args{sub, iss, aud, iat, &SSHOptions{
|
{"ok-user-match", p1, args{sub, iss, aud, iat, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)),
|
||||||
}, &SSHOptions{
|
}, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)),
|
||||||
}, jwk}, &SSHOptions{
|
}, jwk}, &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
|
||||||
}, false, false},
|
}, false, false},
|
||||||
{"fail-certType", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{CertType: "host"}, jwk}, nil, false, true},
|
{"fail-certType", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{CertType: "host"}, jwk}, nil, false, true},
|
||||||
{"fail-principals", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{Principals: []string{"root"}}, jwk}, nil, false, true},
|
{"fail-principals", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{Principals: []string{"root"}}, jwk}, nil, false, true},
|
||||||
{"fail-validAfter", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm)}, &SSHOptions{ValidAfter: NewTimeDuration(tm.Add(time.Hour))}, jwk}, nil, false, true},
|
{"fail-validAfter", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm)}, &SignSSHOptions{ValidAfter: NewTimeDuration(tm.Add(time.Hour))}, jwk}, nil, false, true},
|
||||||
{"fail-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}, ValidBefore: NewTimeDuration(tm.Add(time.Hour))}, &SSHOptions{ValidBefore: NewTimeDuration(tm.Add(10 * time.Hour))}, jwk}, nil, false, true},
|
{"fail-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidBefore: NewTimeDuration(tm.Add(time.Hour))}, &SignSSHOptions{ValidBefore: NewTimeDuration(tm.Add(10 * time.Hour))}, jwk}, nil, false, true},
|
||||||
{"fail-subject", p1, args{"", iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
|
{"fail-subject", p1, args{"", iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
|
||||||
{"fail-issuer", p1, args{sub, "invalid", aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
|
{"fail-issuer", p1, args{sub, "invalid", aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
|
||||||
{"fail-audience", p1, args{sub, iss, "invalid", iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
|
{"fail-audience", p1, args{sub, iss, "invalid", iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
|
||||||
{"fail-expired", p1, args{sub, iss, aud, iat.Add(-6 * time.Minute), &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
|
{"fail-expired", p1, args{sub, iss, aud, iat.Add(-6 * time.Minute), &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
|
||||||
{"fail-notBefore", p1, args{sub, iss, aud, iat.Add(5 * time.Minute), &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
|
{"fail-notBefore", p1, args{sub, iss, aud, iat.Add(5 * time.Minute), &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -561,7 +561,7 @@ func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) {
|
||||||
if got, err := tt.prov.AuthorizeSSHSign(context.Background(), token); (err != nil) != tt.wantErr {
|
if got, err := tt.prov.AuthorizeSSHSign(context.Background(), token); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("JWK.AuthorizeSSHSign() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("JWK.AuthorizeSSHSign() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
} else if !tt.wantErr && assert.NotNil(t, got) {
|
} else if !tt.wantErr && assert.NotNil(t, got) {
|
||||||
var opts SSHOptions
|
var opts SignSSHOptions
|
||||||
if tt.args.userSSHOpts != nil {
|
if tt.args.userSSHOpts != nil {
|
||||||
opts = *tt.args.userSSHOpts
|
opts = *tt.args.userSSHOpts
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,11 @@ type k8sSAPayload struct {
|
||||||
// entity trusted to make signature requests.
|
// entity trusted to make signature requests.
|
||||||
type K8sSA struct {
|
type K8sSA struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PubKeys []byte `json:"publicKeys,omitempty"`
|
PubKeys []byte `json:"publicKeys,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
audiences Audiences
|
audiences Audiences
|
||||||
//kauthn kauthn.AuthenticationV1Interface
|
//kauthn kauthn.AuthenticationV1Interface
|
||||||
|
|
|
@ -53,18 +53,18 @@ type openIDPayload struct {
|
||||||
// ClientSecret is mandatory, but it can be an empty string.
|
// ClientSecret is mandatory, but it can be an empty string.
|
||||||
type OIDC struct {
|
type OIDC struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ClientID string `json:"clientID"`
|
ClientID string `json:"clientID"`
|
||||||
ClientSecret string `json:"clientSecret"`
|
ClientSecret string `json:"clientSecret"`
|
||||||
ConfigurationEndpoint string `json:"configurationEndpoint"`
|
ConfigurationEndpoint string `json:"configurationEndpoint"`
|
||||||
TenantID string `json:"tenantID,omitempty"`
|
TenantID string `json:"tenantID,omitempty"`
|
||||||
Admins []string `json:"admins,omitempty"`
|
Admins []string `json:"admins,omitempty"`
|
||||||
Domains []string `json:"domains,omitempty"`
|
Domains []string `json:"domains,omitempty"`
|
||||||
Groups []string `json:"groups,omitempty"`
|
Groups []string `json:"groups,omitempty"`
|
||||||
ListenAddress string `json:"listenAddress,omitempty"`
|
ListenAddress string `json:"listenAddress,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
configuration openIDConfiguration
|
configuration openIDConfiguration
|
||||||
keyStore *keyStore
|
keyStore *keyStore
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
|
@ -380,7 +380,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "oidc.AuthorizeSSHSign")
|
return nil, errs.Wrap(http.StatusInternalServerError, err, "oidc.AuthorizeSSHSign")
|
||||||
}
|
}
|
||||||
defaults := SSHOptions{
|
defaults := SignSSHOptions{
|
||||||
CertType: SSHUserCert,
|
CertType: SSHUserCert,
|
||||||
Principals: iden.Usernames,
|
Principals: iden.Usernames,
|
||||||
}
|
}
|
||||||
|
|
|
@ -534,64 +534,64 @@ func TestOIDC_AuthorizeSSHSign(t *testing.T) {
|
||||||
|
|
||||||
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
userDuration := p1.claimer.DefaultUserSSHCertDuration()
|
||||||
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
|
||||||
expectedUserOptions := &SSHOptions{
|
expectedUserOptions := &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"name", "name@smallstep.com"},
|
CertType: "user", Principals: []string{"name", "name@smallstep.com"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
||||||
}
|
}
|
||||||
expectedAdminOptions := &SSHOptions{
|
expectedAdminOptions := &SignSSHOptions{
|
||||||
CertType: "user", Principals: []string{"root", "root@example.com"},
|
CertType: "user", Principals: []string{"root", "root@example.com"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
|
||||||
}
|
}
|
||||||
expectedHostOptions := &SSHOptions{
|
expectedHostOptions := &SignSSHOptions{
|
||||||
CertType: "host", Principals: []string{"smallstep.com"},
|
CertType: "host", Principals: []string{"smallstep.com"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
token string
|
token string
|
||||||
sshOpts SSHOptions
|
sshOpts SignSSHOptions
|
||||||
key interface{}
|
key interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
prov *OIDC
|
prov *OIDC
|
||||||
args args
|
args args
|
||||||
expected *SSHOptions
|
expected *SignSSHOptions
|
||||||
code int
|
code int
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantSignErr bool
|
wantSignErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
|
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"ok-user", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
{"ok-user", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
|
||||||
{"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"name"}}, pub},
|
{"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"name"}}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"name"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"ok-principals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{Principals: []string{"mariano"}}, pub},
|
{"ok-principals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{Principals: []string{"mariano"}}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"mariano"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"mariano"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{}, pub},
|
{"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"max", "mariano"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"max", "mariano"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"ok-options", p1, args{t1, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
|
{"ok-options", p1, args{t1, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"name"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"admin", p3, args{okAdmin, SSHOptions{}, pub}, expectedAdminOptions, http.StatusOK, false, false},
|
{"admin", p3, args{okAdmin, SignSSHOptions{}, pub}, expectedAdminOptions, http.StatusOK, false, false},
|
||||||
{"admin-user", p3, args{okAdmin, SSHOptions{CertType: "user"}, pub}, expectedAdminOptions, http.StatusOK, false, false},
|
{"admin-user", p3, args{okAdmin, SignSSHOptions{CertType: "user"}, pub}, expectedAdminOptions, http.StatusOK, false, false},
|
||||||
{"admin-principals", p3, args{okAdmin, SSHOptions{Principals: []string{"root"}}, pub},
|
{"admin-principals", p3, args{okAdmin, SignSSHOptions{Principals: []string{"root"}}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"root"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"root"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"admin-options", p3, args{okAdmin, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
|
{"admin-options", p3, args{okAdmin, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
|
||||||
&SSHOptions{CertType: "user", Principals: []string{"name"},
|
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
|
||||||
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
|
||||||
{"admin-host", p3, args{okAdmin, SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub},
|
{"admin-host", p3, args{okAdmin, SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub},
|
||||||
expectedHostOptions, http.StatusOK, false, false},
|
expectedHostOptions, http.StatusOK, false, false},
|
||||||
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
|
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
|
||||||
{"fail-user-host", p1, args{t1, SSHOptions{CertType: "host"}, pub}, nil, http.StatusOK, false, true},
|
{"fail-user-host", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-user-principals", p1, args{t1, SSHOptions{Principals: []string{"root"}}, pub}, nil, http.StatusOK, false, true},
|
{"fail-user-principals", p1, args{t1, SignSSHOptions{Principals: []string{"root"}}, pub}, nil, http.StatusOK, false, true},
|
||||||
{"fail-email", p3, args{failEmail, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
{"fail-email", p3, args{failEmail, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
||||||
{"fail-getIdentity", p5, args{failGetIdentityToken, SSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false},
|
{"fail-getIdentity", p5, args{failGetIdentityToken, SignSSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false},
|
||||||
{"fail-sshCA-disabled", p6, args{"foo", SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
{"fail-sshCA-disabled", p6, args{"foo", SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -12,19 +12,18 @@ import (
|
||||||
// CertificateOptions is an interface that returns a list of options passed when
|
// CertificateOptions is an interface that returns a list of options passed when
|
||||||
// creating a new certificate.
|
// creating a new certificate.
|
||||||
type CertificateOptions interface {
|
type CertificateOptions interface {
|
||||||
Options(Options) []x509util.Option
|
Options(SignOptions) []x509util.Option
|
||||||
}
|
}
|
||||||
|
|
||||||
type certificateOptionsFunc func(Options) []x509util.Option
|
type certificateOptionsFunc func(SignOptions) []x509util.Option
|
||||||
|
|
||||||
func (fn certificateOptionsFunc) Options(so Options) []x509util.Option {
|
func (fn certificateOptionsFunc) Options(so SignOptions) []x509util.Option {
|
||||||
return fn(so)
|
return fn(so)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProvisionerOptions are a collection of custom options that can be added to
|
// Options are a collection of custom options that can be added to
|
||||||
// each provisioner.
|
// each provisioner.
|
||||||
// nolint:golint
|
type Options struct {
|
||||||
type ProvisionerOptions struct {
|
|
||||||
// Template contains a X.509 certificate template. It can be a JSON template
|
// Template contains a X.509 certificate template. It can be a JSON template
|
||||||
// escaped in a string or it can be also encoded in base64.
|
// escaped in a string or it can be also encoded in base64.
|
||||||
Template string `json:"template"`
|
Template string `json:"template"`
|
||||||
|
@ -38,7 +37,7 @@ type ProvisionerOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasTemplate returns true if a template is defined in the provisioner options.
|
// HasTemplate returns true if a template is defined in the provisioner options.
|
||||||
func (o *ProvisionerOptions) HasTemplate() bool {
|
func (o *Options) HasTemplate() bool {
|
||||||
return o != nil && (o.Template != "" || o.TemplateFile != "")
|
return o != nil && (o.Template != "" || o.TemplateFile != "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ func (o *ProvisionerOptions) HasTemplate() bool {
|
||||||
// defined in the ProvisionerOptions, the provisioner generated data, and the
|
// defined in the ProvisionerOptions, the provisioner generated data, and the
|
||||||
// user data provided in the request. If no template has been provided,
|
// user data provided in the request. If no template has been provided,
|
||||||
// x509util.DefaultLeafTemplate will be used.
|
// x509util.DefaultLeafTemplate will be used.
|
||||||
func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (CertificateOptions, error) {
|
func TemplateOptions(o *Options, data x509util.TemplateData) (CertificateOptions, error) {
|
||||||
return CustomTemplateOptions(o, data, x509util.DefaultLeafTemplate)
|
return CustomTemplateOptions(o, data, x509util.DefaultLeafTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (Certifi
|
||||||
// defined in the ProvisionerOptions, the provisioner generated data and the
|
// defined in the ProvisionerOptions, the provisioner generated data and the
|
||||||
// user data provided in the request. If no template has been provided in the
|
// user data provided in the request. If no template has been provided in the
|
||||||
// ProvisionerOptions, the given template will be used.
|
// ProvisionerOptions, the given template will be used.
|
||||||
func CustomTemplateOptions(o *ProvisionerOptions, data x509util.TemplateData, defaultTemplate string) (CertificateOptions, error) {
|
func CustomTemplateOptions(o *Options, data x509util.TemplateData, defaultTemplate string) (CertificateOptions, error) {
|
||||||
if o != nil {
|
if o != nil {
|
||||||
if data == nil {
|
if data == nil {
|
||||||
data = x509util.NewTemplateData()
|
data = x509util.NewTemplateData()
|
||||||
|
@ -68,7 +67,7 @@ func CustomTemplateOptions(o *ProvisionerOptions, data x509util.TemplateData, de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return certificateOptionsFunc(func(so Options) []x509util.Option {
|
return certificateOptionsFunc(func(so SignOptions) []x509util.Option {
|
||||||
// We're not provided user data without custom templates.
|
// We're not provided user data without custom templates.
|
||||||
if !o.HasTemplate() {
|
if !o.HasTemplate() {
|
||||||
return []x509util.Option{
|
return []x509util.Option{
|
||||||
|
|
|
@ -42,7 +42,7 @@ func TestProvisionerOptions_HasTemplate(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
o := &ProvisionerOptions{
|
o := &Options{
|
||||||
Template: tt.fields.Template,
|
Template: tt.fields.Template,
|
||||||
TemplateFile: tt.fields.TemplateFile,
|
TemplateFile: tt.fields.TemplateFile,
|
||||||
TemplateData: tt.fields.TemplateData,
|
TemplateData: tt.fields.TemplateData,
|
||||||
|
@ -65,7 +65,7 @@ func TestTemplateOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
o *ProvisionerOptions
|
o *Options
|
||||||
data x509util.TemplateData
|
data x509util.TemplateData
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -81,14 +81,14 @@ func TestTemplateOptions(t *testing.T) {
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"okCustomTemplate", args{&ProvisionerOptions{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{
|
{"okCustomTemplate", args{&Options{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{
|
CertBuffer: bytes.NewBufferString(`{
|
||||||
"subject": {"commonName":"foo"},
|
"subject": {"commonName":"foo"},
|
||||||
"sans": [{"type":"dns","value":"foo.com"}],
|
"sans": [{"type":"dns","value":"foo.com"}],
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"fail", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON`)}, data}, x509util.Options{}, true},
|
{"fail", args{&Options{TemplateData: []byte(`{"badJSON`)}, data}, x509util.Options{}, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -99,7 +99,7 @@ func TestTemplateOptions(t *testing.T) {
|
||||||
}
|
}
|
||||||
var opts x509util.Options
|
var opts x509util.Options
|
||||||
if cof != nil {
|
if cof != nil {
|
||||||
for _, fn := range cof.Options(Options{}) {
|
for _, fn := range cof.Options(SignOptions{}) {
|
||||||
if err := fn(csr, &opts); err != nil {
|
if err := fn(csr, &opts); err != nil {
|
||||||
t.Errorf("x509util.Options() error = %v", err)
|
t.Errorf("x509util.Options() error = %v", err)
|
||||||
return
|
return
|
||||||
|
@ -125,10 +125,10 @@ func TestCustomTemplateOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
o *ProvisionerOptions
|
o *Options
|
||||||
data x509util.TemplateData
|
data x509util.TemplateData
|
||||||
defaultTemplate string
|
defaultTemplate string
|
||||||
userOptions Options
|
userOptions SignOptions
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -136,48 +136,48 @@ func TestCustomTemplateOptions(t *testing.T) {
|
||||||
want x509util.Options
|
want x509util.Options
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", args{nil, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"ok", args{nil, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{
|
CertBuffer: bytes.NewBufferString(`{
|
||||||
"subject": {"commonName":"foobar"},
|
"subject": {"commonName":"foobar"},
|
||||||
"sans": [{"type":"dns","value":"foo.com"}],
|
"sans": [{"type":"dns","value":"foo.com"}],
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, Options{}}, x509util.Options{
|
{"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{
|
CertBuffer: bytes.NewBufferString(`{
|
||||||
"subject": {"commonName":"foo"},
|
"subject": {"commonName":"foo"},
|
||||||
"sans": [{"type":"dns","value":"foo.com"}],
|
"sans": [{"type":"dns","value":"foo.com"}],
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"okNoData", args{&ProvisionerOptions{}, nil, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"okNoData", args{&Options{}, nil, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{
|
CertBuffer: bytes.NewBufferString(`{
|
||||||
"subject": null,
|
"subject": null,
|
||||||
"sans": null,
|
"sans": null,
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"okTemplateData", args{&ProvisionerOptions{TemplateData: []byte(`{"foo":"bar"}`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"okTemplateData", args{&Options{TemplateData: []byte(`{"foo":"bar"}`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{
|
CertBuffer: bytes.NewBufferString(`{
|
||||||
"subject": {"commonName":"foobar"},
|
"subject": {"commonName":"foobar"},
|
||||||
"sans": [{"type":"dns","value":"foo.com"}],
|
"sans": [{"type":"dns","value":"foo.com"}],
|
||||||
"keyUsage": ["digitalSignature"],
|
"keyUsage": ["digitalSignature"],
|
||||||
"extKeyUsage": ["serverAuth", "clientAuth"]
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
||||||
}`)}, false},
|
}`)}, false},
|
||||||
{"okTemplate", args{&ProvisionerOptions{Template: "{{ toJson .Insecure.CR }}"}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"okTemplate", args{&Options{Template: "{{ toJson .Insecure.CR }}"}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
||||||
{"okFile", args{&ProvisionerOptions{TemplateFile: "./testdata/templates/cr.tpl"}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"okFile", args{&Options{TemplateFile: "./testdata/templates/cr.tpl"}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
||||||
{"okBase64", args{&ProvisionerOptions{Template: "e3sgdG9Kc29uIC5JbnNlY3VyZS5DUiB9fQ=="}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
|
{"okBase64", args{&Options{Template: "e3sgdG9Kc29uIC5JbnNlY3VyZS5DUiB9fQ=="}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
CertBuffer: bytes.NewBufferString(csrCertificate)}, false},
|
||||||
{"okUserOptions", args{&ProvisionerOptions{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, Options{TemplateData: []byte(`{"foo":"bar"}`)}}, x509util.Options{
|
{"okUserOptions", args{&Options{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, SignOptions{TemplateData: []byte(`{"foo":"bar"}`)}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{"foo": "bar"}`),
|
CertBuffer: bytes.NewBufferString(`{"foo": "bar"}`),
|
||||||
}, false},
|
}, false},
|
||||||
{"okBadUserOptions", args{&ProvisionerOptions{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, Options{TemplateData: []byte(`{"badJSON"}`)}}, x509util.Options{
|
{"okBadUserOptions", args{&Options{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, SignOptions{TemplateData: []byte(`{"badJSON"}`)}}, x509util.Options{
|
||||||
CertBuffer: bytes.NewBufferString(`{"foo": "<no value>"}`),
|
CertBuffer: bytes.NewBufferString(`{"foo": "<no value>"}`),
|
||||||
}, false},
|
}, false},
|
||||||
{"fail", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{}, true},
|
{"fail", args{&Options{TemplateData: []byte(`{"badJSON`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{}, true},
|
||||||
{"failTemplateData", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON}`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{}, true},
|
{"failTemplateData", args{&Options{TemplateData: []byte(`{"badJSON}`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{}, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -20,9 +20,9 @@ import (
|
||||||
// DefaultCertValidity is the default validity for a certificate if none is specified.
|
// DefaultCertValidity is the default validity for a certificate if none is specified.
|
||||||
const DefaultCertValidity = 24 * time.Hour
|
const DefaultCertValidity = 24 * time.Hour
|
||||||
|
|
||||||
// Options contains the options that can be passed to the Sign method. Backdate
|
// SignOptions contains the options that can be passed to the Sign method. Backdate
|
||||||
// is automatically filled and can only be configured in the CA.
|
// is automatically filled and can only be configured in the CA.
|
||||||
type Options struct {
|
type SignOptions struct {
|
||||||
NotAfter TimeDuration `json:"notAfter"`
|
NotAfter TimeDuration `json:"notAfter"`
|
||||||
NotBefore TimeDuration `json:"notBefore"`
|
NotBefore TimeDuration `json:"notBefore"`
|
||||||
TemplateData json.RawMessage `json:"templateData"`
|
TemplateData json.RawMessage `json:"templateData"`
|
||||||
|
@ -35,7 +35,7 @@ type SignOption interface{}
|
||||||
|
|
||||||
// CertificateValidator is an interface used to validate a given X.509 certificate.
|
// CertificateValidator is an interface used to validate a given X.509 certificate.
|
||||||
type CertificateValidator interface {
|
type CertificateValidator interface {
|
||||||
Valid(cert *x509.Certificate, opts Options) error
|
Valid(cert *x509.Certificate, opts SignOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateRequestValidator is an interface used to validate a given X.509 certificate request.
|
// CertificateRequestValidator is an interface used to validate a given X.509 certificate request.
|
||||||
|
@ -47,7 +47,7 @@ type CertificateRequestValidator interface {
|
||||||
// Types implementing this interface will be validated with a
|
// Types implementing this interface will be validated with a
|
||||||
// CertificateValidator.
|
// CertificateValidator.
|
||||||
type CertificateModifier interface {
|
type CertificateModifier interface {
|
||||||
Modify(cert *x509.Certificate, opts Options) error
|
Modify(cert *x509.Certificate, opts SignOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateEnforcer is an interface used to modify a given X.509 certificate.
|
// CertificateEnforcer is an interface used to modify a given X.509 certificate.
|
||||||
|
@ -59,10 +59,10 @@ type CertificateEnforcer interface {
|
||||||
|
|
||||||
// CertificateModifierFunc allows to create simple certificate modifiers just
|
// CertificateModifierFunc allows to create simple certificate modifiers just
|
||||||
// with a function.
|
// with a function.
|
||||||
type CertificateModifierFunc func(cert *x509.Certificate, opts Options) error
|
type CertificateModifierFunc func(cert *x509.Certificate, opts SignOptions) error
|
||||||
|
|
||||||
// Modify implements CertificateModifier and just calls the defined function.
|
// Modify implements CertificateModifier and just calls the defined function.
|
||||||
func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts Options) error {
|
func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts SignOptions) error {
|
||||||
return fn(cert, opts)
|
return fn(cert, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ func (eee ExtraExtsEnforcer) Enforce(cert *x509.Certificate) error {
|
||||||
// duration.
|
// duration.
|
||||||
type profileDefaultDuration time.Duration
|
type profileDefaultDuration time.Duration
|
||||||
|
|
||||||
func (v profileDefaultDuration) Modify(cert *x509.Certificate, so Options) error {
|
func (v profileDefaultDuration) Modify(cert *x509.Certificate, so SignOptions) error {
|
||||||
var backdate time.Duration
|
var backdate time.Duration
|
||||||
notBefore := so.NotBefore.Time()
|
notBefore := so.NotBefore.Time()
|
||||||
if notBefore.IsZero() {
|
if notBefore.IsZero() {
|
||||||
|
@ -301,7 +301,7 @@ type profileLimitDuration struct {
|
||||||
|
|
||||||
// Option returns an x509util option that limits the validity period of a
|
// Option returns an x509util option that limits the validity period of a
|
||||||
// certificate to one that is superficially imposed.
|
// certificate to one that is superficially imposed.
|
||||||
func (v profileLimitDuration) Modify(cert *x509.Certificate, so Options) error {
|
func (v profileLimitDuration) Modify(cert *x509.Certificate, so SignOptions) error {
|
||||||
var backdate time.Duration
|
var backdate time.Duration
|
||||||
notBefore := so.NotBefore.Time()
|
notBefore := so.NotBefore.Time()
|
||||||
if notBefore.IsZero() {
|
if notBefore.IsZero() {
|
||||||
|
@ -347,7 +347,7 @@ func newValidityValidator(min, max time.Duration) *validityValidator {
|
||||||
|
|
||||||
// Valid validates the certificate validity settings (notBefore/notAfter) and
|
// Valid validates the certificate validity settings (notBefore/notAfter) and
|
||||||
// and total duration.
|
// and total duration.
|
||||||
func (v *validityValidator) Valid(cert *x509.Certificate, o Options) error {
|
func (v *validityValidator) Valid(cert *x509.Certificate, o SignOptions) error {
|
||||||
var (
|
var (
|
||||||
na = cert.NotAfter.Truncate(time.Second)
|
na = cert.NotAfter.Truncate(time.Second)
|
||||||
nb = cert.NotBefore.Truncate(time.Second)
|
nb = cert.NotBefore.Truncate(time.Second)
|
||||||
|
@ -397,7 +397,7 @@ func newForceCNOption(forceCN bool) *forceCNOption {
|
||||||
return &forceCNOption{forceCN}
|
return &forceCNOption{forceCN}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *forceCNOption) Modify(cert *x509.Certificate, _ Options) error {
|
func (o *forceCNOption) Modify(cert *x509.Certificate, _ SignOptions) error {
|
||||||
if !o.ForceCN {
|
if !o.ForceCN {
|
||||||
// Forcing CN is disabled, do nothing to certificate
|
// Forcing CN is disabled, do nothing to certificate
|
||||||
return nil
|
return nil
|
||||||
|
@ -430,7 +430,7 @@ func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ Options) error {
|
func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOptions) error {
|
||||||
ext, err := createProvisionerExtension(o.Type, o.Name, o.CredentialID, o.KeyValuePairs...)
|
ext, err := createProvisionerExtension(o.Type, o.Name, o.CredentialID, o.KeyValuePairs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -399,7 +399,7 @@ func Test_ExtraExtsEnforcer_Enforce(t *testing.T) {
|
||||||
func Test_validityValidator_Valid(t *testing.T) {
|
func Test_validityValidator_Valid(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
cert *x509.Certificate
|
cert *x509.Certificate
|
||||||
opts Options
|
opts SignOptions
|
||||||
vv *validityValidator
|
vv *validityValidator
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
return test{
|
return test{
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: &x509.Certificate{NotAfter: time.Now().Add(-5 * time.Minute)},
|
cert: &x509.Certificate{NotAfter: time.Now().Add(-5 * time.Minute)},
|
||||||
opts: Options{},
|
opts: SignOptions{},
|
||||||
err: errors.New("notAfter cannot be in the past"),
|
err: errors.New("notAfter cannot be in the past"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -417,7 +417,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: &x509.Certificate{NotBefore: time.Now().Add(10 * time.Minute),
|
cert: &x509.Certificate{NotBefore: time.Now().Add(10 * time.Minute),
|
||||||
NotAfter: time.Now().Add(5 * time.Minute)},
|
NotAfter: time.Now().Add(5 * time.Minute)},
|
||||||
opts: Options{},
|
opts: SignOptions{},
|
||||||
err: errors.New("notAfter cannot be before notBefore"),
|
err: errors.New("notAfter cannot be before notBefore"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -427,7 +427,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: &x509.Certificate{NotBefore: n,
|
cert: &x509.Certificate{NotBefore: n,
|
||||||
NotAfter: n.Add(3 * time.Minute)},
|
NotAfter: n.Add(3 * time.Minute)},
|
||||||
opts: Options{},
|
opts: SignOptions{},
|
||||||
err: errors.New("is less than the authorized minimum certificate duration of "),
|
err: errors.New("is less than the authorized minimum certificate duration of "),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -437,7 +437,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: &x509.Certificate{NotBefore: n,
|
cert: &x509.Certificate{NotBefore: n,
|
||||||
NotAfter: n.Add(5 * time.Minute)},
|
NotAfter: n.Add(5 * time.Minute)},
|
||||||
opts: Options{},
|
opts: SignOptions{},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fail/duration-too-great": func() test {
|
"fail/duration-too-great": func() test {
|
||||||
|
@ -464,7 +464,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
return test{
|
return test{
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: cert,
|
cert: cert,
|
||||||
opts: Options{Backdate: time.Second},
|
opts: SignOptions{Backdate: time.Second},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ok/duration-exact-max-with-backdate": func() test {
|
"ok/duration-exact-max-with-backdate": func() test {
|
||||||
|
@ -475,7 +475,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
return test{
|
return test{
|
||||||
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
|
||||||
cert: cert,
|
cert: cert,
|
||||||
opts: Options{Backdate: backdate},
|
opts: SignOptions{Backdate: backdate},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ func Test_validityValidator_Valid(t *testing.T) {
|
||||||
|
|
||||||
func Test_forceCN_Option(t *testing.T) {
|
func Test_forceCN_Option(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
so Options
|
so SignOptions
|
||||||
fcn forceCNOption
|
fcn forceCNOption
|
||||||
cert *x509.Certificate
|
cert *x509.Certificate
|
||||||
valid func(*x509.Certificate)
|
valid func(*x509.Certificate)
|
||||||
|
@ -507,7 +507,7 @@ func Test_forceCN_Option(t *testing.T) {
|
||||||
"ok/CN-not-forced": func() test {
|
"ok/CN-not-forced": func() test {
|
||||||
return test{
|
return test{
|
||||||
fcn: forceCNOption{false},
|
fcn: forceCNOption{false},
|
||||||
so: Options{},
|
so: SignOptions{},
|
||||||
cert: &x509.Certificate{
|
cert: &x509.Certificate{
|
||||||
Subject: pkix.Name{},
|
Subject: pkix.Name{},
|
||||||
DNSNames: []string{"acme.example.com", "step.example.com"},
|
DNSNames: []string{"acme.example.com", "step.example.com"},
|
||||||
|
@ -520,7 +520,7 @@ func Test_forceCN_Option(t *testing.T) {
|
||||||
"ok/CN-forced-and-set": func() test {
|
"ok/CN-forced-and-set": func() test {
|
||||||
return test{
|
return test{
|
||||||
fcn: forceCNOption{true},
|
fcn: forceCNOption{true},
|
||||||
so: Options{},
|
so: SignOptions{},
|
||||||
cert: &x509.Certificate{
|
cert: &x509.Certificate{
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "Some Common Name",
|
CommonName: "Some Common Name",
|
||||||
|
@ -535,7 +535,7 @@ func Test_forceCN_Option(t *testing.T) {
|
||||||
"ok/CN-forced-and-not-set": func() test {
|
"ok/CN-forced-and-not-set": func() test {
|
||||||
return test{
|
return test{
|
||||||
fcn: forceCNOption{true},
|
fcn: forceCNOption{true},
|
||||||
so: Options{},
|
so: SignOptions{},
|
||||||
cert: &x509.Certificate{
|
cert: &x509.Certificate{
|
||||||
Subject: pkix.Name{},
|
Subject: pkix.Name{},
|
||||||
DNSNames: []string{"acme.example.com", "step.example.com"},
|
DNSNames: []string{"acme.example.com", "step.example.com"},
|
||||||
|
@ -548,7 +548,7 @@ func Test_forceCN_Option(t *testing.T) {
|
||||||
"fail/CN-forced-and-empty-DNSNames": func() test {
|
"fail/CN-forced-and-empty-DNSNames": func() test {
|
||||||
return test{
|
return test{
|
||||||
fcn: forceCNOption{true},
|
fcn: forceCNOption{true},
|
||||||
so: Options{},
|
so: SignOptions{},
|
||||||
cert: &x509.Certificate{
|
cert: &x509.Certificate{
|
||||||
Subject: pkix.Name{},
|
Subject: pkix.Name{},
|
||||||
DNSNames: []string{},
|
DNSNames: []string{},
|
||||||
|
@ -576,7 +576,7 @@ func Test_forceCN_Option(t *testing.T) {
|
||||||
|
|
||||||
func Test_profileDefaultDuration_Option(t *testing.T) {
|
func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
so Options
|
so SignOptions
|
||||||
pdd profileDefaultDuration
|
pdd profileDefaultDuration
|
||||||
cert *x509.Certificate
|
cert *x509.Certificate
|
||||||
valid func(*x509.Certificate)
|
valid func(*x509.Certificate)
|
||||||
|
@ -585,7 +585,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
"ok/notBefore-notAfter-duration-empty": func() test {
|
"ok/notBefore-notAfter-duration-empty": func() test {
|
||||||
return test{
|
return test{
|
||||||
pdd: profileDefaultDuration(0),
|
pdd: profileDefaultDuration(0),
|
||||||
so: Options{},
|
so: SignOptions{},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
n := now()
|
n := now()
|
||||||
|
@ -601,7 +601,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
nb := time.Now().Add(5 * time.Minute).UTC()
|
nb := time.Now().Add(5 * time.Minute).UTC()
|
||||||
return test{
|
return test{
|
||||||
pdd: profileDefaultDuration(0),
|
pdd: profileDefaultDuration(0),
|
||||||
so: Options{NotBefore: NewTimeDuration(nb)},
|
so: SignOptions{NotBefore: NewTimeDuration(nb)},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, nb)
|
assert.Equals(t, cert.NotBefore, nb)
|
||||||
|
@ -613,7 +613,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
d := 4 * time.Hour
|
d := 4 * time.Hour
|
||||||
return test{
|
return test{
|
||||||
pdd: profileDefaultDuration(d),
|
pdd: profileDefaultDuration(d),
|
||||||
so: Options{Backdate: time.Second},
|
so: SignOptions{Backdate: time.Second},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
n := now()
|
n := now()
|
||||||
|
@ -629,7 +629,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
na := now().Add(10 * time.Minute).UTC()
|
na := now().Add(10 * time.Minute).UTC()
|
||||||
return test{
|
return test{
|
||||||
pdd: profileDefaultDuration(0),
|
pdd: profileDefaultDuration(0),
|
||||||
so: Options{NotAfter: NewTimeDuration(na)},
|
so: SignOptions{NotAfter: NewTimeDuration(na)},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
n := now()
|
n := now()
|
||||||
|
@ -646,7 +646,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
|
||||||
d := 4 * time.Hour
|
d := 4 * time.Hour
|
||||||
return test{
|
return test{
|
||||||
pdd: profileDefaultDuration(d),
|
pdd: profileDefaultDuration(d),
|
||||||
so: Options{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)},
|
so: SignOptions{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, nb)
|
assert.Equals(t, cert.NotBefore, nb)
|
||||||
|
@ -698,7 +698,7 @@ func Test_newProvisionerExtension_Option(t *testing.T) {
|
||||||
for name, run := range tests {
|
for name, run := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
tt := run()
|
tt := run()
|
||||||
assert.FatalError(t, newProvisionerExtensionOption(TypeJWK, "foo", "bar", "baz", "zap").Modify(tt.cert, Options{}))
|
assert.FatalError(t, newProvisionerExtensionOption(TypeJWK, "foo", "bar", "baz", "zap").Modify(tt.cert, SignOptions{}))
|
||||||
tt.valid(tt.cert)
|
tt.valid(tt.cert)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -710,7 +710,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
|
|
||||||
type test struct {
|
type test struct {
|
||||||
pld profileLimitDuration
|
pld profileLimitDuration
|
||||||
so Options
|
so SignOptions
|
||||||
cert *x509.Certificate
|
cert *x509.Certificate
|
||||||
valid func(*x509.Certificate)
|
valid func(*x509.Certificate)
|
||||||
err error
|
err error
|
||||||
|
@ -721,7 +721,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 4 * time.Hour, notBefore: n.Add(8 * time.Hour)},
|
pld: profileLimitDuration{def: 4 * time.Hour, notBefore: n.Add(8 * time.Hour)},
|
||||||
so: Options{NotBefore: d},
|
so: SignOptions{NotBefore: d},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
err: errors.New("requested certificate notBefore ("),
|
err: errors.New("requested certificate notBefore ("),
|
||||||
}
|
}
|
||||||
|
@ -731,7 +731,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
||||||
so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d},
|
so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
err: errors.New("requested certificate notAfter ("),
|
err: errors.New("requested certificate notAfter ("),
|
||||||
}
|
}
|
||||||
|
@ -741,7 +741,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
||||||
so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d, Backdate: 1 * time.Minute},
|
so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d, Backdate: 1 * time.Minute},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
||||||
|
@ -752,7 +752,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
"ok/valid-notAfter-nil-limit-over-default": func() test {
|
"ok/valid-notAfter-nil-limit-over-default": func() test {
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 1 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
pld: profileLimitDuration{def: 1 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
||||||
so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute},
|
so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
||||||
|
@ -763,7 +763,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
"ok/valid-notAfter-nil-limit-under-default": func() test {
|
"ok/valid-notAfter-nil-limit-under-default": func() test {
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
||||||
so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute},
|
so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour))
|
||||||
|
@ -774,7 +774,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
"ok/over-limit-with-backdate": func() test {
|
"ok/over-limit-with-backdate": func() test {
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(6 * time.Hour)},
|
||||||
so: Options{Backdate: 1 * time.Minute},
|
so: SignOptions{Backdate: 1 * time.Minute},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, n.Add(-time.Minute))
|
assert.Equals(t, cert.NotBefore, n.Add(-time.Minute))
|
||||||
|
@ -785,7 +785,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
|
||||||
"ok/under-limit-with-backdate": func() test {
|
"ok/under-limit-with-backdate": func() test {
|
||||||
return test{
|
return test{
|
||||||
pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(30 * time.Hour)},
|
pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(30 * time.Hour)},
|
||||||
so: Options{Backdate: 1 * time.Minute},
|
so: SignOptions{Backdate: 1 * time.Minute},
|
||||||
cert: new(x509.Certificate),
|
cert: new(x509.Certificate),
|
||||||
valid: func(cert *x509.Certificate) {
|
valid: func(cert *x509.Certificate) {
|
||||||
assert.Equals(t, cert.NotBefore, n.Add(-time.Minute))
|
assert.Equals(t, cert.NotBefore, n.Add(-time.Minute))
|
||||||
|
|
|
@ -30,20 +30,20 @@ type SSHCertModifier interface {
|
||||||
// to modify the SSH certificate.
|
// to modify the SSH certificate.
|
||||||
type SSHCertOptionModifier interface {
|
type SSHCertOptionModifier interface {
|
||||||
SignOption
|
SignOption
|
||||||
Option(o SSHOptions) SSHCertModifier
|
Option(o SignSSHOptions) SSHCertModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHCertValidator is the interface used to validate an SSH certificate.
|
// SSHCertValidator is the interface used to validate an SSH certificate.
|
||||||
type SSHCertValidator interface {
|
type SSHCertValidator interface {
|
||||||
SignOption
|
SignOption
|
||||||
Valid(cert *ssh.Certificate, opts SSHOptions) error
|
Valid(cert *ssh.Certificate, opts SignSSHOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHCertOptionsValidator is the interface used to validate the custom
|
// SSHCertOptionsValidator is the interface used to validate the custom
|
||||||
// options used to modify the SSH certificate.
|
// options used to modify the SSH certificate.
|
||||||
type SSHCertOptionsValidator interface {
|
type SSHCertOptionsValidator interface {
|
||||||
SignOption
|
SignOption
|
||||||
Valid(got SSHOptions) error
|
Valid(got SignSSHOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// sshModifierFunc is an adapter to allow the use of ordinary functions as SSH
|
// sshModifierFunc is an adapter to allow the use of ordinary functions as SSH
|
||||||
|
@ -54,8 +54,8 @@ func (f sshModifierFunc) Modify(cert *ssh.Certificate) error {
|
||||||
return f(cert)
|
return f(cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHOptions contains the options that can be passed to the SignSSH method.
|
// SignSSHOptions contains the options that can be passed to the SignSSH method.
|
||||||
type SSHOptions struct {
|
type SignSSHOptions struct {
|
||||||
CertType string `json:"certType"`
|
CertType string `json:"certType"`
|
||||||
KeyID string `json:"keyID"`
|
KeyID string `json:"keyID"`
|
||||||
Principals []string `json:"principals"`
|
Principals []string `json:"principals"`
|
||||||
|
@ -65,12 +65,12 @@ type SSHOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the uint32 representation of the CertType.
|
// Type returns the uint32 representation of the CertType.
|
||||||
func (o SSHOptions) Type() uint32 {
|
func (o SignSSHOptions) Type() uint32 {
|
||||||
return sshCertTypeUInt32(o.CertType)
|
return sshCertTypeUInt32(o.CertType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify implements SSHCertModifier and sets the SSHOption in the ssh.Certificate.
|
// Modify implements SSHCertModifier and sets the SSHOption in the ssh.Certificate.
|
||||||
func (o SSHOptions) Modify(cert *ssh.Certificate) error {
|
func (o SignSSHOptions) Modify(cert *ssh.Certificate) error {
|
||||||
switch o.CertType {
|
switch o.CertType {
|
||||||
case "": // ignore
|
case "": // ignore
|
||||||
case SSHUserCert:
|
case SSHUserCert:
|
||||||
|
@ -100,7 +100,7 @@ func (o SSHOptions) Modify(cert *ssh.Certificate) error {
|
||||||
|
|
||||||
// match compares two SSHOptions and return an error if they don't match. It
|
// match compares two SSHOptions and return an error if they don't match. It
|
||||||
// ignores zero values.
|
// ignores zero values.
|
||||||
func (o SSHOptions) match(got SSHOptions) error {
|
func (o SignSSHOptions) match(got SignSSHOptions) error {
|
||||||
if o.CertType != "" && got.CertType != "" && o.CertType != got.CertType {
|
if o.CertType != "" && got.CertType != "" && o.CertType != got.CertType {
|
||||||
return errors.Errorf("ssh certificate type does not match - got %v, want %v", got.CertType, o.CertType)
|
return errors.Errorf("ssh certificate type does not match - got %v, want %v", got.CertType, o.CertType)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ func (m sshCertValidBeforeModifier) Modify(cert *ssh.Certificate) error {
|
||||||
|
|
||||||
// sshCertDefaultsModifier implements a SSHCertModifier that
|
// sshCertDefaultsModifier implements a SSHCertModifier that
|
||||||
// modifies the certificate with the given options if they are not set.
|
// modifies the certificate with the given options if they are not set.
|
||||||
type sshCertDefaultsModifier SSHOptions
|
type sshCertDefaultsModifier SignSSHOptions
|
||||||
|
|
||||||
// Modify implements the SSHCertModifier interface.
|
// Modify implements the SSHCertModifier interface.
|
||||||
func (m sshCertDefaultsModifier) Modify(cert *ssh.Certificate) error {
|
func (m sshCertDefaultsModifier) Modify(cert *ssh.Certificate) error {
|
||||||
|
@ -215,7 +215,7 @@ type sshDefaultDuration struct {
|
||||||
*Claimer
|
*Claimer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *sshDefaultDuration) Option(o SSHOptions) SSHCertModifier {
|
func (m *sshDefaultDuration) Option(o SignSSHOptions) SSHCertModifier {
|
||||||
return sshModifierFunc(func(cert *ssh.Certificate) error {
|
return sshModifierFunc(func(cert *ssh.Certificate) error {
|
||||||
d, err := m.DefaultSSHCertDuration(cert.CertType)
|
d, err := m.DefaultSSHCertDuration(cert.CertType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -248,7 +248,7 @@ type sshLimitDuration struct {
|
||||||
NotAfter time.Time
|
NotAfter time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier {
|
func (m *sshLimitDuration) Option(o SignSSHOptions) SSHCertModifier {
|
||||||
if m.NotAfter.IsZero() {
|
if m.NotAfter.IsZero() {
|
||||||
defaultDuration := &sshDefaultDuration{m.Claimer}
|
defaultDuration := &sshDefaultDuration{m.Claimer}
|
||||||
return defaultDuration.Option(o)
|
return defaultDuration.Option(o)
|
||||||
|
@ -297,12 +297,12 @@ func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier {
|
||||||
|
|
||||||
// sshCertOptionsValidator validates the user SSHOptions with the ones
|
// sshCertOptionsValidator validates the user SSHOptions with the ones
|
||||||
// usually present in the token.
|
// usually present in the token.
|
||||||
type sshCertOptionsValidator SSHOptions
|
type sshCertOptionsValidator SignSSHOptions
|
||||||
|
|
||||||
// Valid implements SSHCertOptionsValidator and returns nil if both
|
// Valid implements SSHCertOptionsValidator and returns nil if both
|
||||||
// SSHOptions match.
|
// SSHOptions match.
|
||||||
func (v sshCertOptionsValidator) Valid(got SSHOptions) error {
|
func (v sshCertOptionsValidator) Valid(got SignSSHOptions) error {
|
||||||
want := SSHOptions(v)
|
want := SignSSHOptions(v)
|
||||||
return want.match(got)
|
return want.match(got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ type sshCertValidityValidator struct {
|
||||||
*Claimer
|
*Claimer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SSHOptions) error {
|
func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SignSSHOptions) error {
|
||||||
switch {
|
switch {
|
||||||
case cert.ValidAfter == 0:
|
case cert.ValidAfter == 0:
|
||||||
return errors.New("ssh certificate validAfter cannot be 0")
|
return errors.New("ssh certificate validAfter cannot be 0")
|
||||||
|
@ -355,7 +355,7 @@ func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SSHOptions)
|
||||||
type sshCertDefaultValidator struct{}
|
type sshCertDefaultValidator struct{}
|
||||||
|
|
||||||
// Valid returns an error if the given certificate does not contain the necessary fields.
|
// Valid returns an error if the given certificate does not contain the necessary fields.
|
||||||
func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SSHOptions) error {
|
func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error {
|
||||||
switch {
|
switch {
|
||||||
case len(cert.Nonce) == 0:
|
case len(cert.Nonce) == 0:
|
||||||
return errors.New("ssh certificate nonce cannot be empty")
|
return errors.New("ssh certificate nonce cannot be empty")
|
||||||
|
@ -390,7 +390,7 @@ func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SSHOptions) err
|
||||||
type sshDefaultPublicKeyValidator struct{}
|
type sshDefaultPublicKeyValidator struct{}
|
||||||
|
|
||||||
// Valid checks that certificate request common name matches the one configured.
|
// Valid checks that certificate request common name matches the one configured.
|
||||||
func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SSHOptions) error {
|
func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error {
|
||||||
if cert.Key == nil {
|
if cert.Key == nil {
|
||||||
return errors.New("ssh certificate key cannot be nil")
|
return errors.New("ssh certificate key cannot be nil")
|
||||||
}
|
}
|
||||||
|
@ -420,7 +420,7 @@ func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SSHOptions)
|
||||||
type sshCertKeyIDValidator string
|
type sshCertKeyIDValidator string
|
||||||
|
|
||||||
// Valid returns an error if the given certificate does not contain the necessary fields.
|
// Valid returns an error if the given certificate does not contain the necessary fields.
|
||||||
func (v sshCertKeyIDValidator) Valid(cert *ssh.Certificate, o SSHOptions) error {
|
func (v sshCertKeyIDValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error {
|
||||||
if string(v) != cert.KeyId {
|
if string(v) != cert.KeyId {
|
||||||
return errors.Errorf("invalid ssh certificate KeyId; want %s, but got %s", string(v), cert.KeyId)
|
return errors.Errorf("invalid ssh certificate KeyId; want %s, but got %s", string(v), cert.KeyId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestSSHOptions_Type(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
o := SSHOptions{
|
o := SignSSHOptions{
|
||||||
CertType: tt.fields.CertType,
|
CertType: tt.fields.CertType,
|
||||||
}
|
}
|
||||||
if got := o.Type(); got != tt.want {
|
if got := o.Type(); got != tt.want {
|
||||||
|
@ -40,7 +40,7 @@ func TestSSHOptions_Type(t *testing.T) {
|
||||||
|
|
||||||
func TestSSHOptions_Modify(t *testing.T) {
|
func TestSSHOptions_Modify(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
so *SSHOptions
|
so *SignSSHOptions
|
||||||
cert *ssh.Certificate
|
cert *ssh.Certificate
|
||||||
valid func(*ssh.Certificate)
|
valid func(*ssh.Certificate)
|
||||||
err error
|
err error
|
||||||
|
@ -48,21 +48,21 @@ func TestSSHOptions_Modify(t *testing.T) {
|
||||||
tests := map[string](func() test){
|
tests := map[string](func() test){
|
||||||
"fail/unexpected-cert-type": func() test {
|
"fail/unexpected-cert-type": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: &SSHOptions{CertType: "foo"},
|
so: &SignSSHOptions{CertType: "foo"},
|
||||||
cert: new(ssh.Certificate),
|
cert: new(ssh.Certificate),
|
||||||
err: errors.Errorf("ssh certificate has an unknown type - foo"),
|
err: errors.Errorf("ssh certificate has an unknown type - foo"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fail/validAfter-greater-validBefore": func() test {
|
"fail/validAfter-greater-validBefore": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: &SSHOptions{CertType: "user"},
|
so: &SignSSHOptions{CertType: "user"},
|
||||||
cert: &ssh.Certificate{ValidAfter: uint64(15), ValidBefore: uint64(10)},
|
cert: &ssh.Certificate{ValidAfter: uint64(15), ValidBefore: uint64(10)},
|
||||||
err: errors.Errorf("ssh certificate valid after cannot be greater than valid before"),
|
err: errors.Errorf("ssh certificate valid after cannot be greater than valid before"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ok/user-cert": func() test {
|
"ok/user-cert": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: &SSHOptions{CertType: "user"},
|
so: &SignSSHOptions{CertType: "user"},
|
||||||
cert: new(ssh.Certificate),
|
cert: new(ssh.Certificate),
|
||||||
valid: func(cert *ssh.Certificate) {
|
valid: func(cert *ssh.Certificate) {
|
||||||
assert.Equals(t, cert.CertType, uint32(ssh.UserCert))
|
assert.Equals(t, cert.CertType, uint32(ssh.UserCert))
|
||||||
|
@ -71,7 +71,7 @@ func TestSSHOptions_Modify(t *testing.T) {
|
||||||
},
|
},
|
||||||
"ok/host-cert": func() test {
|
"ok/host-cert": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: &SSHOptions{CertType: "host"},
|
so: &SignSSHOptions{CertType: "host"},
|
||||||
cert: new(ssh.Certificate),
|
cert: new(ssh.Certificate),
|
||||||
valid: func(cert *ssh.Certificate) {
|
valid: func(cert *ssh.Certificate) {
|
||||||
assert.Equals(t, cert.CertType, uint32(ssh.HostCert))
|
assert.Equals(t, cert.CertType, uint32(ssh.HostCert))
|
||||||
|
@ -81,7 +81,7 @@ func TestSSHOptions_Modify(t *testing.T) {
|
||||||
"ok": func() test {
|
"ok": func() test {
|
||||||
va := time.Now().Add(5 * time.Minute)
|
va := time.Now().Add(5 * time.Minute)
|
||||||
vb := time.Now().Add(1 * time.Hour)
|
vb := time.Now().Add(1 * time.Hour)
|
||||||
so := &SSHOptions{CertType: "host", KeyID: "foo", Principals: []string{"foo", "bar"},
|
so := &SignSSHOptions{CertType: "host", KeyID: "foo", Principals: []string{"foo", "bar"},
|
||||||
ValidAfter: NewTimeDuration(va), ValidBefore: NewTimeDuration(vb)}
|
ValidAfter: NewTimeDuration(va), ValidBefore: NewTimeDuration(vb)}
|
||||||
return test{
|
return test{
|
||||||
so: so,
|
so: so,
|
||||||
|
@ -114,43 +114,43 @@ func TestSSHOptions_Modify(t *testing.T) {
|
||||||
|
|
||||||
func TestSSHOptions_Match(t *testing.T) {
|
func TestSSHOptions_Match(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
so SSHOptions
|
so SignSSHOptions
|
||||||
cmp SSHOptions
|
cmp SignSSHOptions
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
tests := map[string](func() test){
|
tests := map[string](func() test){
|
||||||
"fail/cert-type": func() test {
|
"fail/cert-type": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: SSHOptions{CertType: "foo"},
|
so: SignSSHOptions{CertType: "foo"},
|
||||||
cmp: SSHOptions{CertType: "bar"},
|
cmp: SignSSHOptions{CertType: "bar"},
|
||||||
err: errors.Errorf("ssh certificate type does not match - got bar, want foo"),
|
err: errors.Errorf("ssh certificate type does not match - got bar, want foo"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fail/pricipals": func() test {
|
"fail/pricipals": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: SSHOptions{Principals: []string{"foo"}},
|
so: SignSSHOptions{Principals: []string{"foo"}},
|
||||||
cmp: SSHOptions{Principals: []string{"bar"}},
|
cmp: SignSSHOptions{Principals: []string{"bar"}},
|
||||||
err: errors.Errorf("ssh certificate principals does not match - got [bar], want [foo]"),
|
err: errors.Errorf("ssh certificate principals does not match - got [bar], want [foo]"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fail/validAfter": func() test {
|
"fail/validAfter": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))},
|
so: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))},
|
||||||
cmp: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))},
|
cmp: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))},
|
||||||
err: errors.Errorf("ssh certificate valid after does not match"),
|
err: errors.Errorf("ssh certificate valid after does not match"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fail/validBefore": func() test {
|
"fail/validBefore": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))},
|
so: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))},
|
||||||
cmp: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))},
|
cmp: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))},
|
||||||
err: errors.Errorf("ssh certificate valid before does not match"),
|
err: errors.Errorf("ssh certificate valid before does not match"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ok/original-empty": func() test {
|
"ok/original-empty": func() test {
|
||||||
return test{
|
return test{
|
||||||
so: SSHOptions{},
|
so: SignSSHOptions{},
|
||||||
cmp: SSHOptions{
|
cmp: SignSSHOptions{
|
||||||
CertType: "foo",
|
CertType: "foo",
|
||||||
Principals: []string{"foo"},
|
Principals: []string{"foo"},
|
||||||
ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)),
|
ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)),
|
||||||
|
@ -160,8 +160,8 @@ func TestSSHOptions_Match(t *testing.T) {
|
||||||
},
|
},
|
||||||
"ok/cmp-empty": func() test {
|
"ok/cmp-empty": func() test {
|
||||||
return test{
|
return test{
|
||||||
cmp: SSHOptions{},
|
cmp: SignSSHOptions{},
|
||||||
so: SSHOptions{
|
so: SignSSHOptions{
|
||||||
CertType: "foo",
|
CertType: "foo",
|
||||||
Principals: []string{"foo"},
|
Principals: []string{"foo"},
|
||||||
ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)),
|
ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)),
|
||||||
|
@ -174,13 +174,13 @@ func TestSSHOptions_Match(t *testing.T) {
|
||||||
va := NewTimeDuration(n.Add(1 * time.Minute))
|
va := NewTimeDuration(n.Add(1 * time.Minute))
|
||||||
vb := NewTimeDuration(n.Add(5 * time.Minute))
|
vb := NewTimeDuration(n.Add(5 * time.Minute))
|
||||||
return test{
|
return test{
|
||||||
cmp: SSHOptions{
|
cmp: SignSSHOptions{
|
||||||
CertType: "foo",
|
CertType: "foo",
|
||||||
Principals: []string{"foo"},
|
Principals: []string{"foo"},
|
||||||
ValidAfter: va,
|
ValidAfter: va,
|
||||||
ValidBefore: vb,
|
ValidBefore: vb,
|
||||||
},
|
},
|
||||||
so: SSHOptions{
|
so: SignSSHOptions{
|
||||||
CertType: "foo",
|
CertType: "foo",
|
||||||
Principals: []string{"foo"},
|
Principals: []string{"foo"},
|
||||||
ValidAfter: va,
|
ValidAfter: va,
|
||||||
|
@ -330,7 +330,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) {
|
||||||
n := time.Now()
|
n := time.Now()
|
||||||
va := NewTimeDuration(n.Add(1 * time.Minute))
|
va := NewTimeDuration(n.Add(1 * time.Minute))
|
||||||
vb := NewTimeDuration(n.Add(5 * time.Minute))
|
vb := NewTimeDuration(n.Add(5 * time.Minute))
|
||||||
so := SSHOptions{
|
so := SignSSHOptions{
|
||||||
Principals: []string{"foo", "bar"},
|
Principals: []string{"foo", "bar"},
|
||||||
CertType: "host",
|
CertType: "host",
|
||||||
ValidAfter: va,
|
ValidAfter: va,
|
||||||
|
@ -349,7 +349,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) {
|
||||||
},
|
},
|
||||||
"ok/no-changes": func() test {
|
"ok/no-changes": func() test {
|
||||||
n := time.Now()
|
n := time.Now()
|
||||||
so := SSHOptions{
|
so := SignSSHOptions{
|
||||||
Principals: []string{"foo", "bar"},
|
Principals: []string{"foo", "bar"},
|
||||||
CertType: "host",
|
CertType: "host",
|
||||||
ValidAfter: NewTimeDuration(n.Add(15 * time.Minute)),
|
ValidAfter: NewTimeDuration(n.Add(15 * time.Minute)),
|
||||||
|
@ -659,7 +659,7 @@ func Test_sshCertDefaultValidator_Valid(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if err := v.Valid(tt.cert, SSHOptions{}); err != nil {
|
if err := v.Valid(tt.cert, SignSSHOptions{}); err != nil {
|
||||||
if assert.NotNil(t, tt.err) {
|
if assert.NotNil(t, tt.err) {
|
||||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||||
}
|
}
|
||||||
|
@ -678,31 +678,31 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
cert *ssh.Certificate
|
cert *ssh.Certificate
|
||||||
opts SSHOptions
|
opts SignSSHOptions
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"fail/validAfter-0",
|
"fail/validAfter-0",
|
||||||
&ssh.Certificate{CertType: ssh.UserCert},
|
&ssh.Certificate{CertType: ssh.UserCert},
|
||||||
SSHOptions{},
|
SignSSHOptions{},
|
||||||
errors.New("ssh certificate validAfter cannot be 0"),
|
errors.New("ssh certificate validAfter cannot be 0"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fail/validBefore-in-past",
|
"fail/validBefore-in-past",
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(-time.Minute).Unix())},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(-time.Minute).Unix())},
|
||||||
SSHOptions{},
|
SignSSHOptions{},
|
||||||
errors.New("ssh certificate validBefore cannot be in the past"),
|
errors.New("ssh certificate validBefore cannot be in the past"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fail/validBefore-before-validAfter",
|
"fail/validBefore-before-validAfter",
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Add(5 * time.Minute).Unix()), ValidBefore: uint64(now().Add(3 * time.Minute).Unix())},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Add(5 * time.Minute).Unix()), ValidBefore: uint64(now().Add(3 * time.Minute).Unix())},
|
||||||
SSHOptions{},
|
SignSSHOptions{},
|
||||||
errors.New("ssh certificate validBefore cannot be before validAfter"),
|
errors.New("ssh certificate validBefore cannot be before validAfter"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fail/cert-type-not-set",
|
"fail/cert-type-not-set",
|
||||||
&ssh.Certificate{ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(10 * time.Minute).Unix())},
|
&ssh.Certificate{ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(10 * time.Minute).Unix())},
|
||||||
SSHOptions{},
|
SignSSHOptions{},
|
||||||
errors.New("ssh certificate type has not been set"),
|
errors.New("ssh certificate type has not been set"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -712,7 +712,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(now().Unix()),
|
ValidAfter: uint64(now().Unix()),
|
||||||
ValidBefore: uint64(now().Add(10 * time.Minute).Unix()),
|
ValidBefore: uint64(now().Add(10 * time.Minute).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{},
|
SignSSHOptions{},
|
||||||
errors.New("unknown ssh certificate type 3"),
|
errors.New("unknown ssh certificate type 3"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -722,7 +722,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(n.Unix()),
|
ValidAfter: uint64(n.Unix()),
|
||||||
ValidBefore: uint64(n.Add(4 * time.Minute).Unix()),
|
ValidBefore: uint64(n.Add(4 * time.Minute).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{Backdate: time.Second},
|
SignSSHOptions{Backdate: time.Second},
|
||||||
errors.New("requested duration of 4m0s is less than minimum accepted duration for selected provisioner of 5m0s"),
|
errors.New("requested duration of 4m0s is less than minimum accepted duration for selected provisioner of 5m0s"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -732,7 +732,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(n.Unix()),
|
ValidAfter: uint64(n.Unix()),
|
||||||
ValidBefore: uint64(n.Add(5 * time.Minute).Unix()),
|
ValidBefore: uint64(n.Add(5 * time.Minute).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{Backdate: time.Second},
|
SignSSHOptions{Backdate: time.Second},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -742,7 +742,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(n.Unix()),
|
ValidAfter: uint64(n.Unix()),
|
||||||
ValidBefore: uint64(n.Add(48 * time.Hour).Unix()),
|
ValidBefore: uint64(n.Add(48 * time.Hour).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{Backdate: time.Second},
|
SignSSHOptions{Backdate: time.Second},
|
||||||
errors.New("requested duration of 48h0m0s is greater than maximum accepted duration for selected provisioner of 24h0m1s"),
|
errors.New("requested duration of 48h0m0s is greater than maximum accepted duration for selected provisioner of 24h0m1s"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -752,7 +752,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(n.Unix()),
|
ValidAfter: uint64(n.Unix()),
|
||||||
ValidBefore: uint64(n.Add(24*time.Hour + time.Second).Unix()),
|
ValidBefore: uint64(n.Add(24*time.Hour + time.Second).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{Backdate: time.Second},
|
SignSSHOptions{Backdate: time.Second},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -762,7 +762,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
|
||||||
ValidAfter: uint64(now().Unix()),
|
ValidAfter: uint64(now().Unix()),
|
||||||
ValidBefore: uint64(now().Add(8 * time.Hour).Unix()),
|
ValidBefore: uint64(now().Add(8 * time.Hour).Unix()),
|
||||||
},
|
},
|
||||||
SSHOptions{Backdate: time.Second},
|
SignSSHOptions{Backdate: time.Second},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -908,7 +908,7 @@ func Test_sshValidityModifier(t *testing.T) {
|
||||||
for name, run := range tests {
|
for name, run := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
tt := run()
|
tt := run()
|
||||||
if err := tt.svm.Option(SSHOptions{}).Modify(tt.cert); err != nil {
|
if err := tt.svm.Option(SignSSHOptions{}).Modify(tt.cert); err != nil {
|
||||||
if assert.NotNil(t, tt.err) {
|
if assert.NotNil(t, tt.err) {
|
||||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||||
}
|
}
|
||||||
|
@ -962,7 +962,7 @@ func Test_sshDefaultDuration_Option(t *testing.T) {
|
||||||
Claimer *Claimer
|
Claimer *Claimer
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
o SSHOptions
|
o SignSSHOptions
|
||||||
cert *ssh.Certificate
|
cert *ssh.Certificate
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -972,26 +972,26 @@ func Test_sshDefaultDuration_Option(t *testing.T) {
|
||||||
want *ssh.Certificate
|
want *ssh.Certificate
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"user", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}},
|
{"user", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}},
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(16 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(16 * time.Hour)}, false},
|
||||||
{"host", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}},
|
{"host", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}},
|
||||||
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(30 * 24 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(30 * 24 * time.Hour)}, false},
|
||||||
{"user claim", fields{newClaimer(&Claims{DefaultUserSSHDur: &Duration{1 * time.Hour}})}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}},
|
{"user claim", fields{newClaimer(&Claims{DefaultUserSSHDur: &Duration{1 * time.Hour}})}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}},
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false},
|
||||||
{"host claim", fields{newClaimer(&Claims{DefaultHostSSHDur: &Duration{1 * time.Hour}})}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}},
|
{"host claim", fields{newClaimer(&Claims{DefaultHostSSHDur: &Duration{1 * time.Hour}})}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}},
|
||||||
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false},
|
||||||
{"user backdate", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert}},
|
{"user backdate", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert}},
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(16 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(16 * time.Hour)}, false},
|
||||||
{"host backdate", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert}},
|
{"host backdate", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert}},
|
||||||
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(30 * 24 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(30 * 24 * time.Hour)}, false},
|
||||||
{"user validAfter", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(1 * time.Hour)}},
|
{"user validAfter", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(1 * time.Hour)}},
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(time.Hour), ValidBefore: unix(17 * time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(time.Hour), ValidBefore: unix(17 * time.Hour)}, false},
|
||||||
{"user validBefore", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidBefore: unix(1 * time.Hour)}},
|
{"user validBefore", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidBefore: unix(1 * time.Hour)}},
|
||||||
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(time.Hour)}, false},
|
&ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(time.Hour)}, false},
|
||||||
{"host validAfter validBefore", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}},
|
{"host validAfter validBefore", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}},
|
||||||
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}, false},
|
&ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}, false},
|
||||||
{"fail zero", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true},
|
{"fail zero", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true},
|
||||||
{"fail type", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true},
|
{"fail type", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -1015,7 +1015,7 @@ func Test_sshLimitDuration_Option(t *testing.T) {
|
||||||
NotAfter time.Time
|
NotAfter time.Time
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
o SSHOptions
|
o SignSSHOptions
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateSSHCertificate(cert *ssh.Certificate, opts *SSHOptions) error {
|
func validateSSHCertificate(cert *ssh.Certificate, opts *SignSSHOptions) error {
|
||||||
switch {
|
switch {
|
||||||
case cert == nil:
|
case cert == nil:
|
||||||
return fmt.Errorf("certificate is nil")
|
return fmt.Errorf("certificate is nil")
|
||||||
|
@ -39,7 +39,7 @@ func validateSSHCertificate(cert *ssh.Certificate, opts *SSHOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func signSSHCertificate(key crypto.PublicKey, opts SSHOptions, signOpts []SignOption, signKey crypto.Signer) (*ssh.Certificate, error) {
|
func signSSHCertificate(key crypto.PublicKey, opts SignSSHOptions, signOpts []SignOption, signKey crypto.Signer) (*ssh.Certificate, error) {
|
||||||
pub, err := ssh.NewPublicKey(key)
|
pub, err := ssh.NewPublicKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -713,20 +713,20 @@ func generateK8sSAToken(jwk *jose.JSONWebKey, claims *k8sSAPayload, tokOpts ...t
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
||||||
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SSHOptions{
|
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SignSSHOptions{
|
||||||
CertType: "user",
|
CertType: "user",
|
||||||
Principals: []string{"name"},
|
Principals: []string{"name"},
|
||||||
}, jwk)
|
}, jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSimpleSSHHostToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
func generateSimpleSSHHostToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) {
|
||||||
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SSHOptions{
|
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SignSSHOptions{
|
||||||
CertType: "host",
|
CertType: "host",
|
||||||
Principals: []string{"smallstep.com"},
|
Principals: []string{"smallstep.com"},
|
||||||
}, jwk)
|
}, jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *SSHOptions, jwk *jose.JSONWebKey) (string, error) {
|
func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *SignSSHOptions, jwk *jose.JSONWebKey) (string, error) {
|
||||||
sig, err := jose.NewSigner(
|
sig, err := jose.NewSigner(
|
||||||
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
|
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
|
||||||
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),
|
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),
|
||||||
|
|
|
@ -25,11 +25,11 @@ type x5cPayload struct {
|
||||||
// signature requests.
|
// signature requests.
|
||||||
type X5C struct {
|
type X5C struct {
|
||||||
*base
|
*base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Roots []byte `json:"roots"`
|
Roots []byte `json:"roots"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
Options *ProvisionerOptions `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
audiences Audiences
|
audiences Audiences
|
||||||
rootPool *x509.CertPool
|
rootPool *x509.CertPool
|
||||||
|
|
|
@ -696,7 +696,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
|
||||||
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
|
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
|
||||||
Audience: []string{testAudiences.SSHSign[0]},
|
Audience: []string{testAudiences.SSHSign[0]},
|
||||||
},
|
},
|
||||||
Step: &stepPayload{SSH: &SSHOptions{
|
Step: &stepPayload{SSH: &SignSSHOptions{
|
||||||
CertType: SSHHostCert,
|
CertType: SSHHostCert,
|
||||||
Principals: []string{"max", "mariano", "alan"},
|
Principals: []string{"max", "mariano", "alan"},
|
||||||
ValidAfter: TimeDuration{d: 5 * time.Minute},
|
ValidAfter: TimeDuration{d: 5 * time.Minute},
|
||||||
|
@ -728,7 +728,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
|
||||||
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
|
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
|
||||||
Audience: []string{testAudiences.SSHSign[0]},
|
Audience: []string{testAudiences.SSHSign[0]},
|
||||||
},
|
},
|
||||||
Step: &stepPayload{SSH: &SSHOptions{}},
|
Step: &stepPayload{SSH: &SignSSHOptions{}},
|
||||||
}
|
}
|
||||||
tok, err := generateX5CSSHToken(x5cJWK, claims, withX5CHdr(x5cCerts))
|
tok, err := generateX5CSSHToken(x5cJWK, claims, withX5CHdr(x5cCerts))
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -759,7 +759,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
|
||||||
case sshCertOptionsValidator:
|
case sshCertOptionsValidator:
|
||||||
tc.claims.Step.SSH.ValidAfter.t = time.Time{}
|
tc.claims.Step.SSH.ValidAfter.t = time.Time{}
|
||||||
tc.claims.Step.SSH.ValidBefore.t = time.Time{}
|
tc.claims.Step.SSH.ValidBefore.t = time.Time{}
|
||||||
assert.Equals(t, SSHOptions(v), *tc.claims.Step.SSH)
|
assert.Equals(t, SignSSHOptions(v), *tc.claims.Step.SSH)
|
||||||
case sshCertKeyIDModifier:
|
case sshCertKeyIDModifier:
|
||||||
assert.Equals(t, string(v), "foo")
|
assert.Equals(t, string(v), "foo")
|
||||||
case sshCertTypeModifier:
|
case sshCertTypeModifier:
|
||||||
|
@ -771,7 +771,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
|
||||||
case sshCertValidBeforeModifier:
|
case sshCertValidBeforeModifier:
|
||||||
assert.Equals(t, int64(v), tc.claims.Step.SSH.ValidBefore.RelativeTime(nw).Unix())
|
assert.Equals(t, int64(v), tc.claims.Step.SSH.ValidBefore.RelativeTime(nw).Unix())
|
||||||
case sshCertDefaultsModifier:
|
case sshCertDefaultsModifier:
|
||||||
assert.Equals(t, SSHOptions(v), SSHOptions{CertType: SSHUserCert})
|
assert.Equals(t, SignSSHOptions(v), SignSSHOptions{CertType: SSHUserCert})
|
||||||
case *sshLimitDuration:
|
case *sshLimitDuration:
|
||||||
assert.Equals(t, v.Claimer, tc.p.claimer)
|
assert.Equals(t, v.Claimer, tc.p.claimer)
|
||||||
assert.Equals(t, v.NotAfter, x5cCerts[0].NotAfter)
|
assert.Equals(t, v.NotAfter, x5cCerts[0].NotAfter)
|
||||||
|
|
|
@ -204,7 +204,7 @@ func (a *Authority) GetSSHBastion(ctx context.Context, user string, hostname str
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignSSH creates a signed SSH certificate with the given public key and options.
|
// SignSSH creates a signed SSH certificate with the given public key and options.
|
||||||
func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||||
var mods []provisioner.SSHCertModifier
|
var mods []provisioner.SSHCertModifier
|
||||||
var validators []provisioner.SSHCertValidator
|
var validators []provisioner.SSHCertValidator
|
||||||
|
|
||||||
|
@ -453,7 +453,7 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub
|
||||||
|
|
||||||
// Apply validators from provisioner.
|
// Apply validators from provisioner.
|
||||||
for _, v := range validators {
|
for _, v := range validators {
|
||||||
if err := v.Valid(cert, provisioner.SSHOptions{Backdate: backdate}); err != nil {
|
if err := v.Valid(cert, provisioner.SignSSHOptions{Backdate: backdate}); err != nil {
|
||||||
return nil, errs.Wrap(http.StatusForbidden, err, "rekeySSH")
|
return nil, errs.Wrap(http.StatusForbidden, err, "rekeySSH")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (m sshTestCertModifier) Modify(cert *ssh.Certificate) error {
|
||||||
|
|
||||||
type sshTestCertValidator string
|
type sshTestCertValidator string
|
||||||
|
|
||||||
func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SSHOptions) error {
|
func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SignSSHOptions) error {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SSHOp
|
||||||
|
|
||||||
type sshTestOptionsValidator string
|
type sshTestOptionsValidator string
|
||||||
|
|
||||||
func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error {
|
func (v sshTestOptionsValidator) Valid(opts provisioner.SignSSHOptions) error {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error {
|
||||||
|
|
||||||
type sshTestOptionsModifier string
|
type sshTestOptionsModifier string
|
||||||
|
|
||||||
func (m sshTestOptionsModifier) Option(opts provisioner.SSHOptions) provisioner.SSHCertModifier {
|
func (m sshTestOptionsModifier) Option(opts provisioner.SignSSHOptions) provisioner.SSHCertModifier {
|
||||||
return sshTestCertModifier(string(m))
|
return sshTestCertModifier(string(m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ func TestAuthority_SignSSH(t *testing.T) {
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
key ssh.PublicKey
|
key ssh.PublicKey
|
||||||
opts provisioner.SSHOptions
|
opts provisioner.SignSSHOptions
|
||||||
signOpts []provisioner.SignOption
|
signOpts []provisioner.SignOption
|
||||||
}
|
}
|
||||||
type want struct {
|
type want struct {
|
||||||
|
@ -125,27 +125,27 @@ func TestAuthority_SignSSH(t *testing.T) {
|
||||||
want want
|
want want
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions}}, want{CertType: ssh.UserCert}, false},
|
{"ok-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"ok-host", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{hostOptions}}, want{CertType: ssh.HostCert}, false},
|
{"ok-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{hostOptions}}, want{CertType: ssh.HostCert}, false},
|
||||||
{"ok-opts-type-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert}, false},
|
{"ok-opts-type-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"ok-opts-type-host", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert}, false},
|
{"ok-opts-type-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert}, false},
|
||||||
{"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user", Principals: []string{"user"}}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, Principals: []string{"user"}}, false},
|
{"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user", Principals: []string{"user"}}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, Principals: []string{"user"}}, false},
|
||||||
{"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host", Principals: []string{"foo.test.com", "bar.test.com"}}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, Principals: []string{"foo.test.com", "bar.test.com"}}, false},
|
{"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host", Principals: []string{"foo.test.com", "bar.test.com"}}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, Principals: []string{"foo.test.com", "bar.test.com"}}, false},
|
||||||
{"ok-opts-valid-after", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user", ValidAfter: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, ValidAfter: uint64(now.Unix())}, false},
|
{"ok-opts-valid-after", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user", ValidAfter: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, ValidAfter: uint64(now.Unix())}, false},
|
||||||
{"ok-opts-valid-before", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host", ValidBefore: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, ValidBefore: uint64(now.Unix())}, false},
|
{"ok-opts-valid-before", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host", ValidBefore: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, ValidBefore: uint64(now.Unix())}, false},
|
||||||
{"ok-cert-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("")}}, want{CertType: ssh.UserCert}, false},
|
{"ok-cert-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("")}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"ok-cert-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("")}}, want{CertType: ssh.UserCert}, false},
|
{"ok-cert-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("")}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"ok-opts-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("")}}, want{CertType: ssh.UserCert}, false},
|
{"ok-opts-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("")}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"ok-opts-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("")}}, want{CertType: ssh.UserCert}, false},
|
{"ok-opts-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("")}}, want{CertType: ssh.UserCert}, false},
|
||||||
{"fail-opts-type", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "foo"}, []provisioner.SignOption{}}, want{}, true},
|
{"fail-opts-type", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "foo"}, []provisioner.SignOption{}}, want{}, true},
|
||||||
{"fail-cert-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("an error")}}, want{}, true},
|
{"fail-cert-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("an error")}}, want{}, true},
|
||||||
{"fail-cert-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("an error")}}, want{}, true},
|
{"fail-cert-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("an error")}}, want{}, true},
|
||||||
{"fail-opts-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("an error")}}, want{}, true},
|
{"fail-opts-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("an error")}}, want{}, true},
|
||||||
{"fail-opts-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("an error")}}, want{}, true},
|
{"fail-opts-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("an error")}}, want{}, true},
|
||||||
{"fail-bad-sign-options", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, "wrong type"}}, want{}, true},
|
{"fail-bad-sign-options", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, "wrong type"}}, want{}, true},
|
||||||
{"fail-no-user-key", fields{nil, signer}, args{pub, provisioner.SSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{}, true},
|
{"fail-no-user-key", fields{nil, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{}, true},
|
||||||
{"fail-no-host-key", fields{signer, nil}, args{pub, provisioner.SSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{}, true},
|
{"fail-no-host-key", fields{signer, nil}, args{pub, provisioner.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{}, true},
|
||||||
{"fail-bad-type", fields{signer, nil}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true},
|
{"fail-bad-type", fields{signer, nil}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ var oidAuthorityKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 35}
|
||||||
var oidSubjectKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 14}
|
var oidSubjectKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 14}
|
||||||
|
|
||||||
func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFunc {
|
func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFunc {
|
||||||
return func(crt *x509.Certificate, opts provisioner.Options) error {
|
return func(crt *x509.Certificate, opts provisioner.SignOptions) error {
|
||||||
if def == nil {
|
if def == nil {
|
||||||
return errors.New("default ASN1DN template cannot be nil")
|
return errors.New("default ASN1DN template cannot be nil")
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign creates a signed certificate from a certificate signing request.
|
// Sign creates a signed certificate from a certificate signing request.
|
||||||
func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||||
var (
|
var (
|
||||||
certOptions []x509util.Option
|
certOptions []x509util.Option
|
||||||
certValidators []provisioner.CertificateValidator
|
certValidators []provisioner.CertificateValidator
|
||||||
|
|
|
@ -132,7 +132,7 @@ func TestAuthority_Sign(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nb := time.Now()
|
nb := time.Now()
|
||||||
signOpts := provisioner.Options{
|
signOpts := provisioner.SignOptions{
|
||||||
NotBefore: provisioner.NewTimeDuration(nb),
|
NotBefore: provisioner.NewTimeDuration(nb),
|
||||||
NotAfter: provisioner.NewTimeDuration(nb.Add(time.Minute * 5)),
|
NotAfter: provisioner.NewTimeDuration(nb.Add(time.Minute * 5)),
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ func TestAuthority_Sign(t *testing.T) {
|
||||||
type signTest struct {
|
type signTest struct {
|
||||||
auth *Authority
|
auth *Authority
|
||||||
csr *x509.CertificateRequest
|
csr *x509.CertificateRequest
|
||||||
signOpts provisioner.Options
|
signOpts provisioner.SignOptions
|
||||||
extraOpts []provisioner.SignOption
|
extraOpts []provisioner.SignOption
|
||||||
notBefore time.Time
|
notBefore time.Time
|
||||||
notAfter time.Time
|
notAfter time.Time
|
||||||
|
@ -210,7 +210,7 @@ func TestAuthority_Sign(t *testing.T) {
|
||||||
},
|
},
|
||||||
"fail provisioner duration claim": func(t *testing.T) *signTest {
|
"fail provisioner duration claim": func(t *testing.T) *signTest {
|
||||||
csr := getCSR(t, priv)
|
csr := getCSR(t, priv)
|
||||||
_signOpts := provisioner.Options{
|
_signOpts := provisioner.SignOptions{
|
||||||
NotBefore: provisioner.NewTimeDuration(nb),
|
NotBefore: provisioner.NewTimeDuration(nb),
|
||||||
NotAfter: provisioner.NewTimeDuration(nb.Add(time.Hour * 25)),
|
NotAfter: provisioner.NewTimeDuration(nb.Add(time.Hour * 25)),
|
||||||
}
|
}
|
||||||
|
@ -429,14 +429,14 @@ func TestAuthority_Renew(t *testing.T) {
|
||||||
certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption {
|
certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption {
|
||||||
return func(p x509util.Profile) error {
|
return func(p x509util.Profile) error {
|
||||||
crt := p.Subject()
|
crt := p.Subject()
|
||||||
return m.Modify(crt, provisioner.Options{})
|
return m.Modify(crt, provisioner.SignOptions{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
nb1 := now.Add(-time.Minute * 7)
|
nb1 := now.Add(-time.Minute * 7)
|
||||||
na1 := now
|
na1 := now
|
||||||
so := &provisioner.Options{
|
so := &provisioner.SignOptions{
|
||||||
NotBefore: provisioner.NewTimeDuration(nb1),
|
NotBefore: provisioner.NewTimeDuration(nb1),
|
||||||
NotAfter: provisioner.NewTimeDuration(na1),
|
NotAfter: provisioner.NewTimeDuration(na1),
|
||||||
}
|
}
|
||||||
|
@ -656,14 +656,14 @@ func TestAuthority_Rekey(t *testing.T) {
|
||||||
certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption {
|
certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption {
|
||||||
return func(p x509util.Profile) error {
|
return func(p x509util.Profile) error {
|
||||||
crt := p.Subject()
|
crt := p.Subject()
|
||||||
return m.Modify(crt, provisioner.Options{})
|
return m.Modify(crt, provisioner.SignOptions{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
nb1 := now.Add(-time.Minute * 7)
|
nb1 := now.Add(-time.Minute * 7)
|
||||||
na1 := now
|
na1 := now
|
||||||
so := &provisioner.Options{
|
so := &provisioner.SignOptions{
|
||||||
NotBefore: provisioner.NewTimeDuration(nb1),
|
NotBefore: provisioner.NewTimeDuration(nb1),
|
||||||
NotAfter: provisioner.NewTimeDuration(na1),
|
NotAfter: provisioner.NewTimeDuration(na1),
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ func (p *Provisioner) SSHToken(certType, keyID string, principals []string) (str
|
||||||
token.WithIssuer(p.name),
|
token.WithIssuer(p.name),
|
||||||
token.WithAudience(p.sshAudience),
|
token.WithAudience(p.sshAudience),
|
||||||
token.WithValidity(notBefore, notAfter),
|
token.WithValidity(notBefore, notAfter),
|
||||||
token.WithSSH(provisioner.SSHOptions{
|
token.WithSSH(provisioner.SignSSHOptions{
|
||||||
CertType: certType,
|
CertType: certType,
|
||||||
Principals: principals,
|
Principals: principals,
|
||||||
KeyID: keyID,
|
KeyID: keyID,
|
||||||
|
|
Loading…
Reference in a new issue