2021-05-03 19:48:20 +00:00
|
|
|
package config
|
2018-10-05 21:48:36 +00:00
|
|
|
|
|
|
|
import (
|
2019-12-20 21:30:05 +00:00
|
|
|
"fmt"
|
2022-04-08 01:14:43 +00:00
|
|
|
"reflect"
|
2018-10-05 21:48:36 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/smallstep/assert"
|
2019-03-08 03:30:17 +00:00
|
|
|
"github.com/smallstep/certificates/authority/provisioner"
|
2021-05-03 19:48:20 +00:00
|
|
|
_ "github.com/smallstep/certificates/cas"
|
2022-01-19 16:14:45 +00:00
|
|
|
"go.step.sm/crypto/jose"
|
2018-10-05 21:48:36 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestConfigValidate(t *testing.T) {
|
2021-05-03 19:48:20 +00:00
|
|
|
maxjwk, err := jose.ReadKey("../testdata/secrets/max_pub.jwk")
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.FatalError(t, err)
|
2021-05-03 19:48:20 +00:00
|
|
|
clijwk, err := jose.ReadKey("../testdata/secrets/step_cli_key_pub.jwk")
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.FatalError(t, err)
|
|
|
|
ac := &AuthConfig{
|
2019-03-08 03:30:17 +00:00
|
|
|
Provisioners: provisioner.List{
|
|
|
|
&provisioner.JWK{
|
2018-10-30 01:00:30 +00:00
|
|
|
Name: "Max",
|
|
|
|
Type: "JWK",
|
|
|
|
Key: maxjwk,
|
2018-10-05 21:48:36 +00:00
|
|
|
},
|
2019-03-08 03:30:17 +00:00
|
|
|
&provisioner.JWK{
|
2018-10-30 01:00:30 +00:00
|
|
|
Name: "step-cli",
|
|
|
|
Type: "JWK",
|
|
|
|
Key: clijwk,
|
2018-10-05 21:48:36 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
type ConfigValidateTest struct {
|
|
|
|
config *Config
|
|
|
|
err error
|
2020-08-10 22:29:18 +00:00
|
|
|
tls TLSOptions
|
2018-10-05 21:48:36 +00:00
|
|
|
}
|
|
|
|
tests := map[string]func(*testing.T) ConfigValidateTest{
|
|
|
|
"empty-address": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("address cannot be empty"),
|
|
|
|
}
|
|
|
|
},
|
2018-12-21 23:27:22 +00:00
|
|
|
"invalid-address": func(t *testing.T) ConfigValidateTest {
|
2018-10-05 21:48:36 +00:00
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
|
|
|
Address: "127.0.0.1",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-12-21 23:27:22 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("invalid address 127.0.0.1"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-root": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("root cannot be empty"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-intermediate-cert": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("crt cannot be empty"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-intermediate-key": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("key cannot be empty"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-dnsNames": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
err: errors.New("dnsNames cannot be empty"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-TLS": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
|
|
|
},
|
|
|
|
tls: DefaultTLSOptions,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"empty-TLS-values": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
2020-08-10 22:29:18 +00:00
|
|
|
TLS: &TLSOptions{},
|
2018-10-05 21:48:36 +00:00
|
|
|
},
|
|
|
|
tls: DefaultTLSOptions,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"custom-tls-values": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
2020-08-10 22:29:18 +00:00
|
|
|
TLS: &TLSOptions{
|
|
|
|
CipherSuites: CipherSuites{
|
2018-10-05 21:48:36 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
|
|
},
|
|
|
|
MinVersion: 1.0,
|
|
|
|
MaxVersion: 1.1,
|
|
|
|
Renegotiation: true,
|
|
|
|
},
|
|
|
|
},
|
2020-08-10 22:29:18 +00:00
|
|
|
tls: TLSOptions{
|
|
|
|
CipherSuites: CipherSuites{
|
2018-10-05 21:48:36 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
|
|
},
|
|
|
|
MinVersion: 1.0,
|
|
|
|
MaxVersion: 1.1,
|
|
|
|
Renegotiation: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"tls-min>max": func(t *testing.T) ConfigValidateTest {
|
|
|
|
return ConfigValidateTest{
|
|
|
|
config: &Config{
|
2018-12-21 23:27:22 +00:00
|
|
|
Address: "127.0.0.1:443",
|
2021-05-03 19:48:20 +00:00
|
|
|
Root: []string{"../testdata/secrets/root_ca.crt"},
|
|
|
|
IntermediateCert: "../testdata/secrets/intermediate_ca.crt",
|
|
|
|
IntermediateKey: "../testdata/secrets/intermediate_ca_key",
|
2018-10-05 21:48:36 +00:00
|
|
|
DNSNames: []string{"test.smallstep.com"},
|
|
|
|
Password: "pass",
|
|
|
|
AuthorityConfig: ac,
|
2020-08-10 22:29:18 +00:00
|
|
|
TLS: &TLSOptions{
|
|
|
|
CipherSuites: CipherSuites{
|
2018-10-05 21:48:36 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
|
|
},
|
|
|
|
MinVersion: 1.2,
|
|
|
|
MaxVersion: 1.1,
|
|
|
|
Renegotiation: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("tls minVersion cannot exceed tls maxVersion"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, get := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
tc := get(t)
|
|
|
|
err := tc.config.Validate()
|
|
|
|
if err != nil {
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.Equals(t, tc.err.Error(), err.Error())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if assert.Nil(t, tc.err) {
|
2021-05-03 19:48:20 +00:00
|
|
|
fmt.Printf("tc.tls = %+v\n", tc.tls)
|
|
|
|
fmt.Printf("*tc.config.TLS = %+v\n", *tc.config.TLS)
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.Equals(t, *tc.config.TLS, tc.tls)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthConfigValidate(t *testing.T) {
|
2020-08-10 22:29:18 +00:00
|
|
|
asn1dn := ASN1DN{
|
2018-10-05 21:48:36 +00:00
|
|
|
Country: "Tazmania",
|
|
|
|
Organization: "Acme Co",
|
|
|
|
Locality: "Landscapes",
|
|
|
|
Province: "Sudden Cliffs",
|
|
|
|
StreetAddress: "TNT",
|
|
|
|
CommonName: "test",
|
|
|
|
}
|
|
|
|
|
2021-05-03 19:48:20 +00:00
|
|
|
maxjwk, err := jose.ReadKey("../testdata/secrets/max_pub.jwk")
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.FatalError(t, err)
|
2021-05-03 19:48:20 +00:00
|
|
|
clijwk, err := jose.ReadKey("../testdata/secrets/step_cli_key_pub.jwk")
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.FatalError(t, err)
|
2019-03-08 03:30:17 +00:00
|
|
|
p := provisioner.List{
|
|
|
|
&provisioner.JWK{
|
2018-10-30 01:00:30 +00:00
|
|
|
Name: "Max",
|
|
|
|
Type: "JWK",
|
|
|
|
Key: maxjwk,
|
2018-10-05 21:48:36 +00:00
|
|
|
},
|
2019-03-08 03:30:17 +00:00
|
|
|
&provisioner.JWK{
|
2018-10-30 01:00:30 +00:00
|
|
|
Name: "step-cli",
|
|
|
|
Type: "JWK",
|
|
|
|
Key: clijwk,
|
2018-10-05 21:48:36 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
type AuthConfigValidateTest struct {
|
|
|
|
ac *AuthConfig
|
2020-08-10 22:29:18 +00:00
|
|
|
asn1dn ASN1DN
|
2018-10-05 21:48:36 +00:00
|
|
|
err error
|
|
|
|
}
|
|
|
|
tests := map[string]func(*testing.T) AuthConfigValidateTest{
|
2018-10-09 06:25:18 +00:00
|
|
|
"fail-nil-authconfig": func(t *testing.T) AuthConfigValidateTest {
|
2018-10-05 21:48:36 +00:00
|
|
|
return AuthConfigValidateTest{
|
|
|
|
ac: nil,
|
|
|
|
err: errors.New("authority cannot be undefined"),
|
|
|
|
}
|
|
|
|
},
|
2019-12-16 19:22:24 +00:00
|
|
|
"ok-empty-provisioners": func(t *testing.T) AuthConfigValidateTest {
|
|
|
|
return AuthConfigValidateTest{
|
|
|
|
ac: &AuthConfig{},
|
2020-08-10 22:29:18 +00:00
|
|
|
asn1dn: ASN1DN{},
|
2019-12-16 19:22:24 +00:00
|
|
|
}
|
|
|
|
},
|
2018-10-09 06:25:18 +00:00
|
|
|
"ok-empty-asn1dn-template": func(t *testing.T) AuthConfigValidateTest {
|
2018-10-05 21:48:36 +00:00
|
|
|
return AuthConfigValidateTest{
|
|
|
|
ac: &AuthConfig{
|
|
|
|
Provisioners: p,
|
|
|
|
},
|
2020-08-10 22:29:18 +00:00
|
|
|
asn1dn: ASN1DN{},
|
2018-10-05 21:48:36 +00:00
|
|
|
}
|
|
|
|
},
|
2018-10-09 06:25:18 +00:00
|
|
|
"ok-custom-asn1dn": func(t *testing.T) AuthConfigValidateTest {
|
2018-10-05 21:48:36 +00:00
|
|
|
return AuthConfigValidateTest{
|
|
|
|
ac: &AuthConfig{
|
|
|
|
Provisioners: p,
|
|
|
|
Template: &asn1dn,
|
|
|
|
},
|
|
|
|
asn1dn: asn1dn,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, get := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
tc := get(t)
|
2019-03-05 08:07:13 +00:00
|
|
|
err := tc.ac.Validate(provisioner.Audiences{})
|
2018-10-05 21:48:36 +00:00
|
|
|
if err != nil {
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.Equals(t, tc.err.Error(), err.Error())
|
|
|
|
}
|
|
|
|
} else {
|
2019-12-20 21:30:05 +00:00
|
|
|
if assert.Nil(t, tc.err, fmt.Sprintf("expected error: %s, but got <nil>", tc.err)) {
|
2018-10-05 21:48:36 +00:00
|
|
|
assert.Equals(t, *tc.ac.Template, tc.asn1dn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-01-19 16:14:45 +00:00
|
|
|
|
|
|
|
func Test_toHostname(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
want string
|
|
|
|
}{
|
|
|
|
{name: "localhost", want: "localhost"},
|
|
|
|
{name: "ca.smallstep.com", want: "ca.smallstep.com"},
|
|
|
|
{name: "127.0.0.1", want: "127.0.0.1"},
|
|
|
|
{name: "::1", want: "[::1]"},
|
|
|
|
{name: "[::1]", want: "[::1]"},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if got := toHostname(tt.name); got != tt.want {
|
|
|
|
t.Errorf("toHostname() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-04-08 01:14:43 +00:00
|
|
|
|
|
|
|
func TestConfig_Audience(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
DNSNames []string
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
want []string
|
|
|
|
}{
|
|
|
|
{"ok", fields{[]string{
|
|
|
|
"ca", "ca.example.com", "127.0.0.1", "::1",
|
|
|
|
}}, args{"/path"}, []string{
|
|
|
|
"https://ca/path",
|
|
|
|
"https://ca.example.com/path",
|
|
|
|
"https://127.0.0.1/path",
|
|
|
|
"https://[::1]/path",
|
|
|
|
"/path",
|
|
|
|
}},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Config{
|
|
|
|
DNSNames: tt.fields.DNSNames,
|
|
|
|
}
|
|
|
|
if got := c.Audience(tt.args.path); !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("Config.Audience() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|