Rename provisioner options structs:

* provisioner.ProvisionerOptions => provisioner.Options
* provisioner.Options => provisioner.SignOptions
* provisioner.SSHOptions => provisioner.SingSSHOptions
pull/312/head
Mariano Cano 4 years ago
parent e0dd1bd132
commit 6c64fb3ed2

@ -18,7 +18,7 @@ type Provisioner interface {
AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error)
GetName() string
DefaultTLSCertDuration() time.Duration
GetOptions() *provisioner.ProvisionerOptions
GetOptions() *provisioner.Options
}
// MockProvisioner for testing
@ -28,7 +28,7 @@ type MockProvisioner struct {
MgetName func() string
MauthorizeSign func(ctx context.Context, ott string) ([]provisioner.SignOption, error)
MdefaultTLSCertDuration func() time.Duration
MgetOptions func() *provisioner.ProvisionerOptions
MgetOptions func() *provisioner.Options
}
// GetName mock
@ -55,11 +55,11 @@ func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration {
return m.Mret1.(time.Duration)
}
func (m *MockProvisioner) GetOptions() *provisioner.ProvisionerOptions {
func (m *MockProvisioner) GetOptions() *provisioner.Options {
if m.MgetOptions != nil {
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
@ -134,7 +134,7 @@ func ProvisionerFromContext(ctx context.Context) (Provisioner, error) {
// SignAuthority is the interface implemented by a CA authority.
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)
}

@ -338,7 +338,7 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut
signOps = append(signOps, templateOptions)
// 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),
NotAfter: provisioner.NewTimeDuration(o.NotAfter),
}, signOps...)

@ -895,13 +895,13 @@ func TestOrderUpdateStatus(t *testing.T) {
}
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)
ret1, ret2 interface{}
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 {
return m.sign(csr, signOpts, extraOpts...)
} else if m.err != nil {
@ -1262,7 +1262,7 @@ func TestOrderFinalize(t *testing.T) {
res: clone,
csr: csr,
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)
return []*x509.Certificate{crt, inter}, nil
},
@ -1311,7 +1311,7 @@ func TestOrderFinalize(t *testing.T) {
res: &clone,
csr: csr,
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)
return []*x509.Certificate{crt, inter}, nil
},
@ -1358,7 +1358,7 @@ func TestOrderFinalize(t *testing.T) {
res: &clone,
csr: csr,
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)
return []*x509.Certificate{crt, inter}, nil
},

@ -34,7 +34,7 @@ type Authority interface {
AuthorizeSign(ott string) ([]provisioner.SignOption, error)
GetTLSOptions() *tlsutil.TLSOptions
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)
Rekey(peer *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error)

@ -550,7 +550,7 @@ type mockAuthority struct {
authorizeSign func(ott string) ([]provisioner.SignOption, error)
getTLSOptions func() *tlsutil.TLSOptions
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)
rekey func(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
loadProvisionerByCertificate func(cert *x509.Certificate) (provisioner.Interface, error)
@ -560,7 +560,7 @@ type mockAuthority struct {
getEncryptedKey func(kid string) (string, error)
getRoots 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)
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)
@ -599,7 +599,7 @@ func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) {
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 {
return m.sign(cr, opts, signOpts...)
}
@ -669,7 +669,7 @@ func (m *mockAuthority) GetFederation() ([]*x509.Certificate, error) {
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 {
return m.signSSH(ctx, key, opts, signOpts...)
}

@ -60,7 +60,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
return
}
opts := provisioner.Options{
opts := provisioner.SignOptions{
NotBefore: body.NotBefore,
NotAfter: body.NotAfter,
TemplateData: body.TemplateData,

@ -19,7 +19,7 @@ import (
// SSHAuthority is the interface implemented by a SSH CA authority.
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)
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)
@ -274,7 +274,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
}
}
opts := provisioner.SSHOptions{
opts := provisioner.SignSSHOptions{
CertType: body.CertType,
KeyID: body.KeyID,
Principals: body.Principals,
@ -322,7 +322,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
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 {
WriteError(w, errs.ForbiddenErr(err))
return

@ -319,13 +319,13 @@ func Test_caHandler_SSHSign(t *testing.T) {
authorizeSign: func(ott string) ([]provisioner.SignOption, error) {
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
},
signSSHAddUser: func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) {
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
},
}).(*caHandler)

@ -283,7 +283,7 @@ func TestNewEmbedded_Sign(t *testing.T) {
csr, err := x509.ParseCertificateRequest(cr)
assert.FatalError(t, err)
cert, err := a.Sign(csr, provisioner.Options{})
cert, err := a.Sign(csr, provisioner.SignOptions{})
assert.FatalError(t, err)
assert.Equals(t, []string{"foo.bar.zar"}, cert[0].DNSNames)
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) {
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SSHOptions{
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SignSSHOptions{
CertType: "user",
Principals: []string{"name"},
}, jwk)
}
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(
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),

@ -13,11 +13,11 @@ import (
// provisioning flow.
type ACME struct {
*base
Type string `json:"type"`
Name string `json:"name"`
ForceCN bool `json:"forceCN,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
ForceCN bool `json:"forceCN,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
}
@ -47,7 +47,7 @@ func (p *ACME) GetEncryptedKey() (string, string, bool) {
}
// GetOptions returns the configured provisioner options.
func (p *ACME) GetOptions() *ProvisionerOptions {
func (p *ACME) GetOptions() *Options {
return p.Options
}

@ -126,14 +126,14 @@ type awsInstanceIdentityDocument struct {
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
type AWS struct {
*base
Type string `json:"type"`
Name string `json:"name"`
Accounts []string `json:"accounts"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
InstanceAge Duration `json:"instanceAge,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
Accounts []string `json:"accounts"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
InstanceAge Duration `json:"instanceAge,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
config *awsConfig
audiences Audiences
@ -483,7 +483,7 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
}
// Default to cert type to host
defaults := SSHOptions{
defaults := SignSSHOptions{
CertType: SSHHostCert,
Principals: principals,
}

@ -647,51 +647,51 @@ func TestAWS_AuthorizeSSHSign(t *testing.T) {
assert.FatalError(t, err)
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"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedHostOptionsIP := &SSHOptions{
expectedHostOptionsIP := &SignSSHOptions{
CertType: "host", Principals: []string{"127.0.0.1"},
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"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedCustomOptions := &SSHOptions{
expectedCustomOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"foo.local"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
token string
sshOpts SSHOptions
sshOpts SignSSHOptions
key interface{}
}
tests := []struct {
name string
aws *AWS
args args
expected *SSHOptions
expected *SignSSHOptions
code int
wantErr bool
wantSignErr bool
}{
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SSHOptions{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-principal-ip", p1, args{t1, SSHOptions{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-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-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
{"fail-type", p1, args{t1, SSHOptions{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-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-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, 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, SignSSHOptions{Principals: []string{"127.0.0.1"}}, pub}, expectedHostOptionsIP, 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, 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, SignSSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, 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, 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", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
}
for _, tt := range tests {
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
type Azure struct {
*base
Type string `json:"type"`
Name string `json:"name"`
TenantID string `json:"tenantID"`
ResourceGroups []string `json:"resourceGroups"`
Audience string `json:"audience,omitempty"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
TenantID string `json:"tenantID"`
ResourceGroups []string `json:"resourceGroups"`
Audience string `json:"audience,omitempty"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
config *azureConfig
oidcConfig openIDConfiguration
@ -350,7 +350,7 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio
}
// Default to host + known hostnames
defaults := SSHOptions{
defaults := SignSSHOptions{
CertType: SSHHostCert,
Principals: principals,
}

@ -571,41 +571,41 @@ func TestAzure_AuthorizeSSHSign(t *testing.T) {
assert.FatalError(t, err)
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
expectedHostOptions := &SSHOptions{
expectedHostOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"virtualMachine"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedCustomOptions := &SSHOptions{
expectedCustomOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"foo.bar"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
token string
sshOpts SSHOptions
sshOpts SignSSHOptions
key interface{}
}
tests := []struct {
name string
azure *Azure
args args
expected *SSHOptions
expected *SignSSHOptions
code int
wantErr bool
wantSignErr bool
}{
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-principals", p1, args{t1, SSHOptions{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-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.bar"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
{"fail-type", p1, args{t1, SSHOptions{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-extra-principal", p1, args{t1, SSHOptions{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-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, 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, SignSSHOptions{CertType: "host", Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, 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, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, 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, SignSSHOptions{Principals: []string{"virtualMachine", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true},
{"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
}
for _, tt := range tests {
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
type GCP struct {
*base
Type string `json:"type"`
Name string `json:"name"`
ServiceAccounts []string `json:"serviceAccounts"`
ProjectIDs []string `json:"projectIDs"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
InstanceAge Duration `json:"instanceAge,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
ServiceAccounts []string `json:"serviceAccounts"`
ProjectIDs []string `json:"projectIDs"`
DisableCustomSANs bool `json:"disableCustomSANs"`
DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"`
InstanceAge Duration `json:"instanceAge,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
config *gcpConfig
keyStore *keyStore
@ -394,7 +394,7 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
}
// Default to host + known hostnames
defaults := SSHOptions{
defaults := SignSSHOptions{
CertType: SSHHostCert,
Principals: principals,
}

@ -623,51 +623,51 @@ func TestGCP_AuthorizeSSHSign(t *testing.T) {
assert.FatalError(t, err)
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"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedHostOptionsPrincipal1 := &SSHOptions{
expectedHostOptionsPrincipal1 := &SignSSHOptions{
CertType: "host", Principals: []string{"instance-name.c.project-id.internal"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedHostOptionsPrincipal2 := &SSHOptions{
expectedHostOptionsPrincipal2 := &SignSSHOptions{
CertType: "host", Principals: []string{"instance-name.zone.c.project-id.internal"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
expectedCustomOptions := &SSHOptions{
expectedCustomOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"foo.bar", "bar.foo"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
token string
sshOpts SSHOptions
sshOpts SignSSHOptions
key interface{}
}
tests := []struct {
name string
gcp *GCP
args args
expected *SSHOptions
expected *SignSSHOptions
code int
wantErr bool
wantSignErr bool
}{
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SSHOptions{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-principal1", p1, args{t1, SSHOptions{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-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-custom", p2, args{t2, SSHOptions{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-type", p1, args{t1, SSHOptions{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-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-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false},
{"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, 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, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal1, 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, 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, SignSSHOptions{Principals: []string{"foo.bar", "bar.foo"}}, pub}, expectedCustomOptions, http.StatusOK, false, false},
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true},
{"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, 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, 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", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
{"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

@ -20,19 +20,19 @@ type jwtPayload 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
// signature requests.
type JWK struct {
*base
Type string `json:"type"`
Name string `json:"name"`
Key *jose.JSONWebKey `json:"key"`
EncryptedKey string `json:"encryptedKey,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
Key *jose.JSONWebKey `json:"key"`
EncryptedKey string `json:"encryptedKey,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
audiences Audiences
}

@ -404,41 +404,41 @@ func TestJWK_AuthorizeSSHSign(t *testing.T) {
userDuration := p1.claimer.DefaultUserSSHCertDuration()
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
expectedUserOptions := &SSHOptions{
expectedUserOptions := &SignSSHOptions{
CertType: "user", Principals: []string{"name"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
}
expectedHostOptions := &SSHOptions{
expectedHostOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"smallstep.com"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
token string
sshOpts SSHOptions
sshOpts SignSSHOptions
key interface{}
}
tests := []struct {
name string
prov *JWK
args args
expected *SSHOptions
expected *SignSSHOptions
code int
wantErr bool
wantSignErr bool
}{
{"user", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"user-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
{"user-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"user-principals", p1, args{t1, SSHOptions{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},
{"host", p1, args{t2, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false},
{"host-type", p1, args{t2, SSHOptions{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-options", p1, args{t2, SSHOptions{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-signature", p1, args{failSig, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
{"rail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
{"user", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"user-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
{"user-type", p1, args{t1, SignSSHOptions{CertType: "user"}, 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, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"host", p1, args{t2, SignSSHOptions{}, 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, SignSSHOptions{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", SignSSHOptions{}, pub}, expectedUserOptions, http.StatusUnauthorized, true, false},
{"fail-signature", p1, args{failSig, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
{"rail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -487,72 +487,72 @@ func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) {
userDuration := p1.claimer.DefaultUserSSHCertDuration()
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
expectedUserOptions := &SSHOptions{
expectedUserOptions := &SignSSHOptions{
CertType: "user", Principals: []string{"name"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
}
expectedHostOptions := &SSHOptions{
expectedHostOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"smallstep.com"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
sub, iss, aud string
iat time.Time
tokSSHOpts *SSHOptions
userSSHOpts *SSHOptions
tokSSHOpts *SignSSHOptions
userSSHOpts *SignSSHOptions
jwk *jose.JSONWebKey
}
tests := []struct {
name string
prov *JWK
args args
expected *SSHOptions
expected *SignSSHOptions
wantErr bool
wantSignErr bool
}{
{"ok-user", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, 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-user-opts", p1, args{sub, iss, aud, iat, &SSHOptions{}, &SSHOptions{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-user-mixed", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user"}, &SSHOptions{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-user-validAfter", p1, args{sub, iss, aud, iat, &SSHOptions{
{"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, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, &SignSSHOptions{}, jwk}, expectedHostOptions, 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, &SignSSHOptions{}, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, jwk}, expectedHostOptions, 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, &SignSSHOptions{Principals: []string{"smallstep.com"}}, &SignSSHOptions{CertType: "host"}, jwk}, expectedHostOptions, false, false},
{"ok-user-validAfter", p1, args{sub, iss, aud, iat, &SignSSHOptions{
CertType: "user", Principals: []string{"name"},
}, &SSHOptions{
}, &SignSSHOptions{
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)),
}, 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"},
}, &SSHOptions{
}, &SignSSHOptions{
ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
}, jwk}, &SSHOptions{
}, jwk}, &SignSSHOptions{
CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)),
}, 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"},
}, &SSHOptions{
}, &SignSSHOptions{
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)),
}, 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)),
}, &SSHOptions{
}, &SignSSHOptions{
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)),
}, false, false},
{"fail-certType", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{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-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-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-subject", p1, args{"", iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
{"fail-issuer", p1, args{sub, "invalid", aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
{"fail-audience", p1, args{sub, iss, "invalid", iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, 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-notBefore", p1, args{sub, iss, aud, iat.Add(5 * time.Minute), &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false},
{"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, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{Principals: []string{"root"}}, 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, &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, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, 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, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, 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), &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false},
}
for _, tt := range tests {
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 {
t.Errorf("JWK.AuthorizeSSHSign() error = %v, wantErr %v", err, tt.wantErr)
} else if !tt.wantErr && assert.NotNil(t, got) {
var opts SSHOptions
var opts SignSSHOptions
if tt.args.userSSHOpts != nil {
opts = *tt.args.userSSHOpts
}

@ -41,11 +41,11 @@ type k8sSAPayload struct {
// entity trusted to make signature requests.
type K8sSA struct {
*base
Type string `json:"type"`
Name string `json:"name"`
PubKeys []byte `json:"publicKeys,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
PubKeys []byte `json:"publicKeys,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
audiences Audiences
//kauthn kauthn.AuthenticationV1Interface

@ -53,18 +53,18 @@ type openIDPayload struct {
// ClientSecret is mandatory, but it can be an empty string.
type OIDC struct {
*base
Type string `json:"type"`
Name string `json:"name"`
ClientID string `json:"clientID"`
ClientSecret string `json:"clientSecret"`
ConfigurationEndpoint string `json:"configurationEndpoint"`
TenantID string `json:"tenantID,omitempty"`
Admins []string `json:"admins,omitempty"`
Domains []string `json:"domains,omitempty"`
Groups []string `json:"groups,omitempty"`
ListenAddress string `json:"listenAddress,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
ClientID string `json:"clientID"`
ClientSecret string `json:"clientSecret"`
ConfigurationEndpoint string `json:"configurationEndpoint"`
TenantID string `json:"tenantID,omitempty"`
Admins []string `json:"admins,omitempty"`
Domains []string `json:"domains,omitempty"`
Groups []string `json:"groups,omitempty"`
ListenAddress string `json:"listenAddress,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
configuration openIDConfiguration
keyStore *keyStore
claimer *Claimer
@ -380,7 +380,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "oidc.AuthorizeSSHSign")
}
defaults := SSHOptions{
defaults := SignSSHOptions{
CertType: SSHUserCert,
Principals: iden.Usernames,
}

@ -534,64 +534,64 @@ func TestOIDC_AuthorizeSSHSign(t *testing.T) {
userDuration := p1.claimer.DefaultUserSSHCertDuration()
hostDuration := p1.claimer.DefaultHostSSHCertDuration()
expectedUserOptions := &SSHOptions{
expectedUserOptions := &SignSSHOptions{
CertType: "user", Principals: []string{"name", "name@smallstep.com"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
}
expectedAdminOptions := &SSHOptions{
expectedAdminOptions := &SignSSHOptions{
CertType: "user", Principals: []string{"root", "root@example.com"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)),
}
expectedHostOptions := &SSHOptions{
expectedHostOptions := &SignSSHOptions{
CertType: "host", Principals: []string{"smallstep.com"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)),
}
type args struct {
token string
sshOpts SSHOptions
sshOpts SignSSHOptions
key interface{}
}
tests := []struct {
name string
prov *OIDC
args args
expected *SSHOptions
expected *SignSSHOptions
code int
wantErr bool
wantSignErr bool
}{
{"ok", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
{"ok-user", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"name"}}, pub},
&SSHOptions{CertType: "user", Principals: []string{"name"},
{"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false},
{"ok-user", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false},
{"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"name"}}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
{"ok-principals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{Principals: []string{"mariano"}}, pub},
&SSHOptions{CertType: "user", Principals: []string{"mariano"},
{"ok-principals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{Principals: []string{"mariano"}}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"mariano"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
{"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{}, pub},
&SSHOptions{CertType: "user", Principals: []string{"max", "mariano"},
{"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"max", "mariano"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
{"ok-options", p1, args{t1, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
&SSHOptions{CertType: "user", Principals: []string{"name"},
{"ok-options", p1, args{t1, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
{"admin", p3, args{okAdmin, SSHOptions{}, pub}, expectedAdminOptions, http.StatusOK, false, false},
{"admin-user", p3, args{okAdmin, SSHOptions{CertType: "user"}, pub}, expectedAdminOptions, http.StatusOK, false, false},
{"admin-principals", p3, args{okAdmin, SSHOptions{Principals: []string{"root"}}, pub},
&SSHOptions{CertType: "user", Principals: []string{"root"},
{"admin", p3, args{okAdmin, SignSSHOptions{}, 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, SignSSHOptions{Principals: []string{"root"}}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"root"},
ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false},
{"admin-options", p3, args{okAdmin, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
&SSHOptions{CertType: "user", Principals: []string{"name"},
{"admin-options", p3, args{okAdmin, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub},
&SignSSHOptions{CertType: "user", Principals: []string{"name"},
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},
{"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true},
{"fail-user-host", p1, args{t1, SSHOptions{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-email", p3, args{failEmail, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
{"fail-getIdentity", p5, args{failGetIdentityToken, SSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false},
{"fail-sshCA-disabled", p6, args{"foo", SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
{"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, 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, SignSSHOptions{Principals: []string{"root"}}, pub}, nil, http.StatusOK, false, true},
{"fail-email", p3, args{failEmail, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
{"fail-getIdentity", p5, args{failGetIdentityToken, SignSSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false},
{"fail-sshCA-disabled", p6, args{"foo", SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false},
}
for _, tt := range tests {
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
// creating a new certificate.
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)
}
// 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.
// nolint:golint
type ProvisionerOptions struct {
type Options struct {
// 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.
Template string `json:"template"`
@ -38,7 +37,7 @@ type ProvisionerOptions struct {
}
// 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 != "")
}
@ -46,7 +45,7 @@ func (o *ProvisionerOptions) HasTemplate() bool {
// defined in the ProvisionerOptions, the provisioner generated data, and the
// user data provided in the request. If no template has been provided,
// 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)
}
@ -54,7 +53,7 @@ func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (Certifi
// defined in the ProvisionerOptions, the provisioner generated data and the
// user data provided in the request. If no template has been provided in the
// 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 data == nil {
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.
if !o.HasTemplate() {
return []x509util.Option{

@ -42,7 +42,7 @@ func TestProvisionerOptions_HasTemplate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &ProvisionerOptions{
o := &Options{
Template: tt.fields.Template,
TemplateFile: tt.fields.TemplateFile,
TemplateData: tt.fields.TemplateData,
@ -65,7 +65,7 @@ func TestTemplateOptions(t *testing.T) {
},
}
type args struct {
o *ProvisionerOptions
o *Options
data x509util.TemplateData
}
tests := []struct {
@ -81,14 +81,14 @@ func TestTemplateOptions(t *testing.T) {
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, false},
{"okCustomTemplate", args{&ProvisionerOptions{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{
{"okCustomTemplate", args{&Options{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{
CertBuffer: bytes.NewBufferString(`{
"subject": {"commonName":"foo"},
"sans": [{"type":"dns","value":"foo.com"}],
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, 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 {
t.Run(tt.name, func(t *testing.T) {
@ -99,7 +99,7 @@ func TestTemplateOptions(t *testing.T) {
}
var opts x509util.Options
if cof != nil {
for _, fn := range cof.Options(Options{}) {
for _, fn := range cof.Options(SignOptions{}) {
if err := fn(csr, &opts); err != nil {
t.Errorf("x509util.Options() error = %v", err)
return
@ -125,10 +125,10 @@ func TestCustomTemplateOptions(t *testing.T) {
},
}
type args struct {
o *ProvisionerOptions
o *Options
data x509util.TemplateData
defaultTemplate string
userOptions Options
userOptions SignOptions
}
tests := []struct {
name string
@ -136,48 +136,48 @@ func TestCustomTemplateOptions(t *testing.T) {
want x509util.Options
wantErr bool
}{
{"ok", args{nil, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
{"ok", args{nil, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
CertBuffer: bytes.NewBufferString(`{
"subject": {"commonName":"foobar"},
"sans": [{"type":"dns","value":"foo.com"}],
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, false},
{"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, Options{}}, x509util.Options{
{"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, SignOptions{}}, x509util.Options{
CertBuffer: bytes.NewBufferString(`{
"subject": {"commonName":"foo"},
"sans": [{"type":"dns","value":"foo.com"}],
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, false},
{"okNoData", args{&ProvisionerOptions{}, nil, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{
{"okNoData", args{&Options{}, nil, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{
CertBuffer: bytes.NewBufferString(`{
"subject": null,
"sans": null,
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, 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(`{
"subject": {"commonName":"foobar"},
"sans": [{"type":"dns","value":"foo.com"}],
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"]
}`)}, 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},
{"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},
{"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},
{"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"}`),
}, 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>"}`),
}, false},
{"fail", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{}, true},
{"failTemplateData", 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{&Options{TemplateData: []byte(`{"badJSON}`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{}, true},
}
for _, tt := range tests {
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.
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.
type Options struct {
type SignOptions struct {
NotAfter TimeDuration `json:"notAfter"`
NotBefore TimeDuration `json:"notBefore"`
TemplateData json.RawMessage `json:"templateData"`
@ -35,7 +35,7 @@ type SignOption interface{}
// CertificateValidator is an interface used to validate a given X.509 certificate.
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.
@ -47,7 +47,7 @@ type CertificateRequestValidator interface {
// Types implementing this interface will be validated with a
// CertificateValidator.
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.
@ -59,10 +59,10 @@ type CertificateEnforcer interface {
// CertificateModifierFunc allows to create simple certificate modifiers just
// 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.
func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts Options) error {
func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts SignOptions) error {
return fn(cert, opts)
}
@ -270,7 +270,7 @@ func (eee ExtraExtsEnforcer) Enforce(cert *x509.Certificate) error {
// 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
notBefore := so.NotBefore.Time()
if notBefore.IsZero() {
@ -301,7 +301,7 @@ type profileLimitDuration struct {
// Option returns an x509util option that limits the validity period of a
// 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
notBefore := so.NotBefore.Time()
if notBefore.IsZero() {
@ -347,7 +347,7 @@ func newValidityValidator(min, max time.Duration) *validityValidator {
// Valid validates the certificate validity settings (notBefore/notAfter) and
// and total duration.
func (v *validityValidator) Valid(cert *x509.Certificate, o Options) error {
func (v *validityValidator) Valid(cert *x509.Certificate, o SignOptions) error {
var (
na = cert.NotAfter.Truncate(time.Second)
nb = cert.NotBefore.Truncate(time.Second)
@ -397,7 +397,7 @@ func newForceCNOption(forceCN bool) *forceCNOption {
return &forceCNOption{forceCN}
}
func (o *forceCNOption) Modify(cert *x509.Certificate, _ Options) error {
func (o *forceCNOption) Modify(cert *x509.Certificate, _ SignOptions) error {
if !o.ForceCN {
// Forcing CN is disabled, do nothing to certificate
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...)
if err != nil {
return err

@ -399,7 +399,7 @@ func Test_ExtraExtsEnforcer_Enforce(t *testing.T) {
func Test_validityValidator_Valid(t *testing.T) {
type test struct {
cert *x509.Certificate
opts Options
opts SignOptions
vv *validityValidator
err error
}
@ -408,7 +408,7 @@ func Test_validityValidator_Valid(t *testing.T) {
return test{
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
cert: &x509.Certificate{NotAfter: time.Now().Add(-5 * time.Minute)},
opts: Options{},
opts: SignOptions{},
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},
cert: &x509.Certificate{NotBefore: time.Now().Add(10 * time.Minute),
NotAfter: time.Now().Add(5 * time.Minute)},
opts: Options{},
opts: SignOptions{},
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},
cert: &x509.Certificate{NotBefore: n,
NotAfter: n.Add(3 * time.Minute)},
opts: Options{},
opts: SignOptions{},
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},
cert: &x509.Certificate{NotBefore: n,
NotAfter: n.Add(5 * time.Minute)},
opts: Options{},
opts: SignOptions{},
}
},
"fail/duration-too-great": func() test {
@ -464,7 +464,7 @@ func Test_validityValidator_Valid(t *testing.T) {
return test{
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
cert: cert,
opts: Options{Backdate: time.Second},
opts: SignOptions{Backdate: time.Second},
}
},
"ok/duration-exact-max-with-backdate": func() test {
@ -475,7 +475,7 @@ func Test_validityValidator_Valid(t *testing.T) {
return test{
vv: &validityValidator{5 * time.Minute, 24 * time.Hour},
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) {
type test struct {
so Options
so SignOptions
fcn forceCNOption
cert *x509.Certificate
valid func(*x509.Certificate)
@ -507,7 +507,7 @@ func Test_forceCN_Option(t *testing.T) {
"ok/CN-not-forced": func() test {
return test{
fcn: forceCNOption{false},
so: Options{},
so: SignOptions{},
cert: &x509.Certificate{
Subject: pkix.Name{},
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 {
return test{
fcn: forceCNOption{true},
so: Options{},
so: SignOptions{},
cert: &x509.Certificate{
Subject: pkix.Name{
CommonName: "Some Common Name",
@ -535,7 +535,7 @@ func Test_forceCN_Option(t *testing.T) {
"ok/CN-forced-and-not-set": func() test {
return test{
fcn: forceCNOption{true},
so: Options{},
so: SignOptions{},
cert: &x509.Certificate{
Subject: pkix.Name{},
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 {
return test{
fcn: forceCNOption{true},
so: Options{},
so: SignOptions{},
cert: &x509.Certificate{
Subject: pkix.Name{},
DNSNames: []string{},
@ -576,7 +576,7 @@ func Test_forceCN_Option(t *testing.T) {
func Test_profileDefaultDuration_Option(t *testing.T) {
type test struct {
so Options
so SignOptions
pdd profileDefaultDuration
cert *x509.Certificate
valid func(*x509.Certificate)
@ -585,7 +585,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
"ok/notBefore-notAfter-duration-empty": func() test {
return test{
pdd: profileDefaultDuration(0),
so: Options{},
so: SignOptions{},
cert: new(x509.Certificate),
valid: func(cert *x509.Certificate) {
n := now()
@ -601,7 +601,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
nb := time.Now().Add(5 * time.Minute).UTC()
return test{
pdd: profileDefaultDuration(0),
so: Options{NotBefore: NewTimeDuration(nb)},
so: SignOptions{NotBefore: NewTimeDuration(nb)},
cert: new(x509.Certificate),
valid: func(cert *x509.Certificate) {
assert.Equals(t, cert.NotBefore, nb)
@ -613,7 +613,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
d := 4 * time.Hour
return test{
pdd: profileDefaultDuration(d),
so: Options{Backdate: time.Second},
so: SignOptions{Backdate: time.Second},
cert: new(x509.Certificate),
valid: func(cert *x509.Certificate) {
n := now()
@ -629,7 +629,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
na := now().Add(10 * time.Minute).UTC()
return test{
pdd: profileDefaultDuration(0),
so: Options{NotAfter: NewTimeDuration(na)},
so: SignOptions{NotAfter: NewTimeDuration(na)},
cert: new(x509.Certificate),
valid: func(cert *x509.Certificate) {
n := now()
@ -646,7 +646,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) {
d := 4 * time.Hour
return test{
pdd: profileDefaultDuration(d),
so: Options{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)},
so: SignOptions{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)},
cert: new(x509.Certificate),
valid: func(cert *x509.Certificate) {
assert.Equals(t, cert.NotBefore, nb)
@ -698,7 +698,7 @@ func Test_newProvisionerExtension_Option(t *testing.T) {
for name, run := range tests {
t.Run(name, func(t *testing.T) {
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)
})
}
@ -710,7 +710,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
type test struct {
pld profileLimitDuration
so Options
so SignOptions
cert *x509.Certificate
valid func(*x509.Certificate)
err error
@ -721,7 +721,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
assert.FatalError(t, err)
return test{
pld: profileLimitDuration{def: 4 * time.Hour, notBefore: n.Add(8 * time.Hour)},
so: Options{NotBefore: d},
so: SignOptions{NotBefore: d},
cert: new(x509.Certificate),
err: errors.New("requested certificate notBefore ("),
}
@ -731,7 +731,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
assert.FatalError(t, err)
return test{
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),
err: errors.New("requested certificate notAfter ("),
}
@ -741,7 +741,7 @@ func Test_profileLimitDuration_Option(t *testing.T) {
assert.FatalError(t, err)
return test{
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),
valid: func(cert *x509.Certificate) {
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 {
return test{
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),
valid: func(cert *x509.Certificate) {
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 {
return test{
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),
valid: func(cert *x509.Certificate) {
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 {
return test{
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),
valid: func(cert *x509.Certificate) {
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 {
return test{
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),
valid: func(cert *x509.Certificate) {
assert.Equals(t, cert.NotBefore, n.Add(-time.Minute))

@ -30,20 +30,20 @@ type SSHCertModifier interface {
// to modify the SSH certificate.
type SSHCertOptionModifier interface {
SignOption
Option(o SSHOptions) SSHCertModifier
Option(o SignSSHOptions) SSHCertModifier
}
// SSHCertValidator is the interface used to validate an SSH certificate.
type SSHCertValidator interface {
SignOption
Valid(cert *ssh.Certificate, opts SSHOptions) error
Valid(cert *ssh.Certificate, opts SignSSHOptions) error
}
// SSHCertOptionsValidator is the interface used to validate the custom
// options used to modify the SSH certificate.
type SSHCertOptionsValidator interface {
SignOption
Valid(got SSHOptions) error
Valid(got SignSSHOptions) error
}
// 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)
}
// SSHOptions contains the options that can be passed to the SignSSH method.
type SSHOptions struct {
// SignSSHOptions contains the options that can be passed to the SignSSH method.
type SignSSHOptions struct {
CertType string `json:"certType"`
KeyID string `json:"keyID"`
Principals []string `json:"principals"`
@ -65,12 +65,12 @@ type SSHOptions struct {
}
// Type returns the uint32 representation of the CertType.
func (o SSHOptions) Type() uint32 {
func (o SignSSHOptions) Type() uint32 {
return sshCertTypeUInt32(o.CertType)
}
// 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 {
case "": // ignore
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
// 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 {
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
// modifies the certificate with the given options if they are not set.
type sshCertDefaultsModifier SSHOptions
type sshCertDefaultsModifier SignSSHOptions
// Modify implements the SSHCertModifier interface.
func (m sshCertDefaultsModifier) Modify(cert *ssh.Certificate) error {
@ -215,7 +215,7 @@ type sshDefaultDuration struct {
*Claimer
}
func (m *sshDefaultDuration) Option(o SSHOptions) SSHCertModifier {
func (m *sshDefaultDuration) Option(o SignSSHOptions) SSHCertModifier {
return sshModifierFunc(func(cert *ssh.Certificate) error {
d, err := m.DefaultSSHCertDuration(cert.CertType)
if err != nil {
@ -248,7 +248,7 @@ type sshLimitDuration struct {
NotAfter time.Time
}
func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier {
func (m *sshLimitDuration) Option(o SignSSHOptions) SSHCertModifier {
if m.NotAfter.IsZero() {
defaultDuration := &sshDefaultDuration{m.Claimer}
return defaultDuration.Option(o)
@ -297,12 +297,12 @@ func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier {
// sshCertOptionsValidator validates the user SSHOptions with the ones
// usually present in the token.
type sshCertOptionsValidator SSHOptions
type sshCertOptionsValidator SignSSHOptions
// Valid implements SSHCertOptionsValidator and returns nil if both
// SSHOptions match.
func (v sshCertOptionsValidator) Valid(got SSHOptions) error {
want := SSHOptions(v)
func (v sshCertOptionsValidator) Valid(got SignSSHOptions) error {
want := SignSSHOptions(v)
return want.match(got)
}
@ -310,7 +310,7 @@ type sshCertValidityValidator struct {
*Claimer
}
func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SSHOptions) error {
func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SignSSHOptions) error {
switch {
case cert.ValidAfter == 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{}
// 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 {
case len(cert.Nonce) == 0:
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{}
// 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 {
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
// 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 {
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 {
t.Run(tt.name, func(t *testing.T) {
o := SSHOptions{
o := SignSSHOptions{
CertType: tt.fields.CertType,
}
if got := o.Type(); got != tt.want {
@ -40,7 +40,7 @@ func TestSSHOptions_Type(t *testing.T) {
func TestSSHOptions_Modify(t *testing.T) {
type test struct {
so *SSHOptions
so *SignSSHOptions
cert *ssh.Certificate
valid func(*ssh.Certificate)
err error
@ -48,21 +48,21 @@ func TestSSHOptions_Modify(t *testing.T) {
tests := map[string](func() test){
"fail/unexpected-cert-type": func() test {
return test{
so: &SSHOptions{CertType: "foo"},
so: &SignSSHOptions{CertType: "foo"},
cert: new(ssh.Certificate),
err: errors.Errorf("ssh certificate has an unknown type - foo"),
}
},
"fail/validAfter-greater-validBefore": func() test {
return test{
so: &SSHOptions{CertType: "user"},
so: &SignSSHOptions{CertType: "user"},
cert: &ssh.Certificate{ValidAfter: uint64(15), ValidBefore: uint64(10)},
err: errors.Errorf("ssh certificate valid after cannot be greater than valid before"),
}
},
"ok/user-cert": func() test {
return test{
so: &SSHOptions{CertType: "user"},
so: &SignSSHOptions{CertType: "user"},
cert: new(ssh.Certificate),
valid: func(cert *ssh.Certificate) {
assert.Equals(t, cert.CertType, uint32(ssh.UserCert))
@ -71,7 +71,7 @@ func TestSSHOptions_Modify(t *testing.T) {
},
"ok/host-cert": func() test {
return test{
so: &SSHOptions{CertType: "host"},
so: &SignSSHOptions{CertType: "host"},
cert: new(ssh.Certificate),
valid: func(cert *ssh.Certificate) {
assert.Equals(t, cert.CertType, uint32(ssh.HostCert))
@ -81,7 +81,7 @@ func TestSSHOptions_Modify(t *testing.T) {
"ok": func() test {
va := time.Now().Add(5 * time.Minute)
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)}
return test{
so: so,
@ -114,43 +114,43 @@ func TestSSHOptions_Modify(t *testing.T) {
func TestSSHOptions_Match(t *testing.T) {
type test struct {
so SSHOptions
cmp SSHOptions
so SignSSHOptions
cmp SignSSHOptions
err error
}
tests := map[string](func() test){
"fail/cert-type": func() test {
return test{
so: SSHOptions{CertType: "foo"},
cmp: SSHOptions{CertType: "bar"},
so: SignSSHOptions{CertType: "foo"},
cmp: SignSSHOptions{CertType: "bar"},
err: errors.Errorf("ssh certificate type does not match - got bar, want foo"),
}
},
"fail/pricipals": func() test {
return test{
so: SSHOptions{Principals: []string{"foo"}},
cmp: SSHOptions{Principals: []string{"bar"}},
so: SignSSHOptions{Principals: []string{"foo"}},
cmp: SignSSHOptions{Principals: []string{"bar"}},
err: errors.Errorf("ssh certificate principals does not match - got [bar], want [foo]"),
}
},
"fail/validAfter": func() test {
return test{
so: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))},
cmp: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))},
so: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))},
cmp: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))},
err: errors.Errorf("ssh certificate valid after does not match"),
}
},
"fail/validBefore": func() test {
return test{
so: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))},
cmp: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))},
so: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))},
cmp: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))},
err: errors.Errorf("ssh certificate valid before does not match"),
}
},
"ok/original-empty": func() test {
return test{
so: SSHOptions{},
cmp: SSHOptions{
so: SignSSHOptions{},
cmp: SignSSHOptions{
CertType: "foo",
Principals: []string{"foo"},
ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)),
@ -160,8 +160,8 @@ func TestSSHOptions_Match(t *testing.T) {
},
"ok/cmp-empty": func() test {
return test{
cmp: SSHOptions{},
so: SSHOptions{
cmp: SignSSHOptions{},
so: SignSSHOptions{
CertType: "foo",
Principals: []string{"foo"},
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))
vb := NewTimeDuration(n.Add(5 * time.Minute))
return test{
cmp: SSHOptions{
cmp: SignSSHOptions{
CertType: "foo",
Principals: []string{"foo"},
ValidAfter: va,
ValidBefore: vb,
},
so: SSHOptions{
so: SignSSHOptions{
CertType: "foo",
Principals: []string{"foo"},
ValidAfter: va,
@ -330,7 +330,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) {
n := time.Now()
va := NewTimeDuration(n.Add(1 * time.Minute))
vb := NewTimeDuration(n.Add(5 * time.Minute))
so := SSHOptions{
so := SignSSHOptions{
Principals: []string{"foo", "bar"},
CertType: "host",
ValidAfter: va,
@ -349,7 +349,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) {
},
"ok/no-changes": func() test {
n := time.Now()
so := SSHOptions{
so := SignSSHOptions{
Principals: []string{"foo", "bar"},
CertType: "host",
ValidAfter: NewTimeDuration(n.Add(15 * time.Minute)),
@ -659,7 +659,7 @@ func Test_sshCertDefaultValidator_Valid(t *testing.T) {
}
for _, tt := range tests {
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) {
assert.HasPrefix(t, err.Error(), tt.err.Error())
}
@ -678,31 +678,31 @@ func Test_sshCertValidityValidator(t *testing.T) {
tests := []struct {
name string
cert *ssh.Certificate
opts SSHOptions
opts SignSSHOptions
err error
}{
{
"fail/validAfter-0",
&ssh.Certificate{CertType: ssh.UserCert},
SSHOptions{},
SignSSHOptions{},
errors.New("ssh certificate validAfter cannot be 0"),
},
{
"fail/validBefore-in-past",
&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"),
},
{
"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())},
SSHOptions{},
SignSSHOptions{},
errors.New("ssh certificate validBefore cannot be before validAfter"),
},
{
"fail/cert-type-not-set",
&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"),
},
{
@ -712,7 +712,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(now().Unix()),
ValidBefore: uint64(now().Add(10 * time.Minute).Unix()),
},
SSHOptions{},
SignSSHOptions{},
errors.New("unknown ssh certificate type 3"),
},
{
@ -722,7 +722,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(n.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"),
},
{
@ -732,7 +732,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(n.Unix()),
ValidBefore: uint64(n.Add(5 * time.Minute).Unix()),
},
SSHOptions{Backdate: time.Second},
SignSSHOptions{Backdate: time.Second},
nil,
},
{
@ -742,7 +742,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(n.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"),
},
{
@ -752,7 +752,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(n.Unix()),
ValidBefore: uint64(n.Add(24*time.Hour + time.Second).Unix()),
},
SSHOptions{Backdate: time.Second},
SignSSHOptions{Backdate: time.Second},
nil,
},
{
@ -762,7 +762,7 @@ func Test_sshCertValidityValidator(t *testing.T) {
ValidAfter: uint64(now().Unix()),
ValidBefore: uint64(now().Add(8 * time.Hour).Unix()),
},
SSHOptions{Backdate: time.Second},
SignSSHOptions{Backdate: time.Second},
nil,
},
}
@ -908,7 +908,7 @@ func Test_sshValidityModifier(t *testing.T) {
for name, run := range tests {
t.Run(name, func(t *testing.T) {
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) {
assert.HasPrefix(t, err.Error(), tt.err.Error())
}
@ -962,7 +962,7 @@ func Test_sshDefaultDuration_Option(t *testing.T) {
Claimer *Claimer
}
type args struct {
o SSHOptions
o SignSSHOptions
cert *ssh.Certificate
}
tests := []struct {
@ -972,26 +972,26 @@ func Test_sshDefaultDuration_Option(t *testing.T) {
want *ssh.Certificate
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},
{"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},
{"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},
{"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},
{"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},
{"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},
{"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},
{"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},
{"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},
{"fail zero", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true},
{"fail type", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true},
{"fail zero", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true},
{"fail type", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -1015,7 +1015,7 @@ func Test_sshLimitDuration_Option(t *testing.T) {
NotAfter time.Time
}
type args struct {
o SSHOptions
o SignSSHOptions
}
tests := []struct {
name string

@ -10,7 +10,7 @@ import (
"golang.org/x/crypto/ssh"
)
func validateSSHCertificate(cert *ssh.Certificate, opts *SSHOptions) error {
func validateSSHCertificate(cert *ssh.Certificate, opts *SignSSHOptions) error {
switch {
case cert == 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)
if err != nil {
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) {
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SSHOptions{
return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SignSSHOptions{
CertType: "user",
Principals: []string{"name"},
}, jwk)
}
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",
Principals: []string{"smallstep.com"},
}, 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(
jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key},
new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID),

@ -25,11 +25,11 @@ type x5cPayload struct {
// signature requests.
type X5C struct {
*base
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *ProvisionerOptions `json:"options,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
claimer *Claimer
audiences Audiences
rootPool *x509.CertPool

@ -696,7 +696,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
Audience: []string{testAudiences.SSHSign[0]},
},
Step: &stepPayload{SSH: &SSHOptions{
Step: &stepPayload{SSH: &SignSSHOptions{
CertType: SSHHostCert,
Principals: []string{"max", "mariano", "alan"},
ValidAfter: TimeDuration{d: 5 * time.Minute},
@ -728,7 +728,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)),
Audience: []string{testAudiences.SSHSign[0]},
},
Step: &stepPayload{SSH: &SSHOptions{}},
Step: &stepPayload{SSH: &SignSSHOptions{}},
}
tok, err := generateX5CSSHToken(x5cJWK, claims, withX5CHdr(x5cCerts))
assert.FatalError(t, err)
@ -759,7 +759,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
case sshCertOptionsValidator:
tc.claims.Step.SSH.ValidAfter.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:
assert.Equals(t, string(v), "foo")
case sshCertTypeModifier:
@ -771,7 +771,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) {
case sshCertValidBeforeModifier:
assert.Equals(t, int64(v), tc.claims.Step.SSH.ValidBefore.RelativeTime(nw).Unix())
case sshCertDefaultsModifier:
assert.Equals(t, SSHOptions(v), SSHOptions{CertType: SSHUserCert})
assert.Equals(t, SignSSHOptions(v), SignSSHOptions{CertType: SSHUserCert})
case *sshLimitDuration:
assert.Equals(t, v.Claimer, tc.p.claimer)
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.
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 validators []provisioner.SSHCertValidator
@ -453,7 +453,7 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub
// Apply validators from provisioner.
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")
}
}

@ -62,7 +62,7 @@ func (m sshTestCertModifier) Modify(cert *ssh.Certificate) error {
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 == "" {
return nil
}
@ -71,7 +71,7 @@ func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SSHOp
type sshTestOptionsValidator string
func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error {
func (v sshTestOptionsValidator) Valid(opts provisioner.SignSSHOptions) error {
if v == "" {
return nil
}
@ -80,7 +80,7 @@ func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error {
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))
}
@ -109,7 +109,7 @@ func TestAuthority_SignSSH(t *testing.T) {
}
type args struct {
key ssh.PublicKey
opts provisioner.SSHOptions
opts provisioner.SignSSHOptions
signOpts []provisioner.SignOption
}
type want struct {
@ -125,27 +125,27 @@ func TestAuthority_SignSSH(t *testing.T) {
want want
wantErr bool
}{
{"ok-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []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-opts-type-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{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-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.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-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-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-cert-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []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-opts-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []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},
{"fail-opts-type", fields{signer, signer}, args{pub, provisioner.SSHOptions{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-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []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-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []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-no-user-key", fields{nil, signer}, args{pub, provisioner.SSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{}, true},
{"fail-no-host-key", fields{signer, nil}, args{pub, provisioner.SSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{}, true},
{"fail-bad-type", fields{signer, nil}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true},
{"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.SignSSHOptions{}, []provisioner.SignOption{hostOptions}}, want{CertType: ssh.HostCert}, 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.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert}, 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.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.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.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.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("")}}, 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.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("")}}, 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.SignSSHOptions{CertType: "foo"}, []provisioner.SignOption{}}, 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.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("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.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("an error")}}, 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.SignSSHOptions{CertType: "user"}, []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.SignSSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true},
}
for _, tt := range tests {
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}
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 {
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.
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 (
certOptions []x509util.Option
certValidators []provisioner.CertificateValidator

@ -132,7 +132,7 @@ func TestAuthority_Sign(t *testing.T) {
}
nb := time.Now()
signOpts := provisioner.Options{
signOpts := provisioner.SignOptions{
NotBefore: provisioner.NewTimeDuration(nb),
NotAfter: provisioner.NewTimeDuration(nb.Add(time.Minute * 5)),
}
@ -150,7 +150,7 @@ func TestAuthority_Sign(t *testing.T) {
type signTest struct {
auth *Authority
csr *x509.CertificateRequest
signOpts provisioner.Options
signOpts provisioner.SignOptions
extraOpts []provisioner.SignOption
notBefore time.Time
notAfter time.Time
@ -210,7 +210,7 @@ func TestAuthority_Sign(t *testing.T) {
},
"fail provisioner duration claim": func(t *testing.T) *signTest {
csr := getCSR(t, priv)
_signOpts := provisioner.Options{
_signOpts := provisioner.SignOptions{
NotBefore: provisioner.NewTimeDuration(nb),
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 {
return func(p x509util.Profile) error {
crt := p.Subject()
return m.Modify(crt, provisioner.Options{})
return m.Modify(crt, provisioner.SignOptions{})
}
}
now := time.Now().UTC()
nb1 := now.Add(-time.Minute * 7)
na1 := now
so := &provisioner.Options{
so := &provisioner.SignOptions{
NotBefore: provisioner.NewTimeDuration(nb1),
NotAfter: provisioner.NewTimeDuration(na1),
}
@ -656,14 +656,14 @@ func TestAuthority_Rekey(t *testing.T) {
certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption {
return func(p x509util.Profile) error {
crt := p.Subject()
return m.Modify(crt, provisioner.Options{})
return m.Modify(crt, provisioner.SignOptions{})
}
}
now := time.Now().UTC()
nb1 := now.Add(-time.Minute * 7)
na1 := now
so := &provisioner.Options{
so := &provisioner.SignOptions{
NotBefore: provisioner.NewTimeDuration(nb1),
NotAfter: provisioner.NewTimeDuration(na1),
}

@ -133,7 +133,7 @@ func (p *Provisioner) SSHToken(certType, keyID string, principals []string) (str
token.WithIssuer(p.name),
token.WithAudience(p.sshAudience),
token.WithValidity(notBefore, notAfter),
token.WithSSH(provisioner.SSHOptions{
token.WithSSH(provisioner.SignSSHOptions{
CertType: certType,
Principals: principals,
KeyID: keyID,

Loading…
Cancel
Save