Move TLSOption, TLSVersion, CipherSuites and ASN1DN to certificates.

This commit is contained in:
Mariano Cano 2020-08-10 15:29:18 -07:00
parent 77624c6b1c
commit 4943ae58d8
12 changed files with 384 additions and 55 deletions

View file

@ -23,7 +23,6 @@ import (
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
"github.com/smallstep/certificates/logging"
"github.com/smallstep/cli/crypto/tlsutil"
)
// Authority is the interface implemented by a CA authority.
@ -32,7 +31,7 @@ type Authority interface {
// context specifies the Authorize[Sign|Revoke|etc.] method.
Authorize(ctx context.Context, ott string) ([]provisioner.SignOption, error)
AuthorizeSign(ott string) ([]provisioner.SignOption, error)
GetTLSOptions() *tlsutil.TLSOptions
GetTLSOptions() *authority.TLSOptions
Root(shasum string) (*x509.Certificate, error)
Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
Renew(peer *x509.Certificate) ([]*x509.Certificate, error)

View file

@ -32,7 +32,6 @@ import (
"github.com/smallstep/certificates/errs"
"github.com/smallstep/certificates/logging"
"github.com/smallstep/certificates/templates"
"github.com/smallstep/cli/crypto/tlsutil"
"github.com/smallstep/cli/jose"
"golang.org/x/crypto/ssh"
)
@ -547,7 +546,7 @@ type mockAuthority struct {
ret1, ret2 interface{}
err error
authorizeSign func(ott string) ([]provisioner.SignOption, error)
getTLSOptions func() *tlsutil.TLSOptions
getTLSOptions func() *authority.TLSOptions
root func(shasum string) (*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)
@ -584,11 +583,11 @@ func (m *mockAuthority) AuthorizeSign(ott string) ([]provisioner.SignOption, err
return m.ret1.([]provisioner.SignOption), m.err
}
func (m *mockAuthority) GetTLSOptions() *tlsutil.TLSOptions {
func (m *mockAuthority) GetTLSOptions() *authority.TLSOptions {
if m.getTLSOptions != nil {
return m.getTLSOptions()
}
return m.ret1.(*tlsutil.TLSOptions)
return m.ret1.(*authority.TLSOptions)
}
func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) {
@ -881,7 +880,7 @@ func Test_caHandler_Sign(t *testing.T) {
authorizeSign: func(ott string) ([]provisioner.SignOption, error) {
return tt.certAttrOpts, tt.autherr
},
getTLSOptions: func() *tlsutil.TLSOptions {
getTLSOptions: func() *authority.TLSOptions {
return nil
},
}).(*caHandler)
@ -932,7 +931,7 @@ func Test_caHandler_Renew(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
h := New(&mockAuthority{
ret1: tt.cert, ret2: tt.root, err: tt.err,
getTLSOptions: func() *tlsutil.TLSOptions {
getTLSOptions: func() *authority.TLSOptions {
return nil
},
}).(*caHandler)
@ -993,7 +992,7 @@ func Test_caHandler_Rekey(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
h := New(&mockAuthority{
ret1: tt.cert, ret2: tt.root, err: tt.err,
getTLSOptions: func() *tlsutil.TLSOptions {
getTLSOptions: func() *authority.TLSOptions {
return nil
},
}).(*caHandler)

View file

@ -5,9 +5,9 @@ import (
"encoding/json"
"net/http"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
"github.com/smallstep/cli/crypto/tlsutil"
)
// SignRequest is the request body for a certificate signature request.
@ -37,11 +37,11 @@ func (s *SignRequest) Validate() error {
// SignResponse is the response object of the certificate signature request.
type SignResponse struct {
ServerPEM Certificate `json:"crt"`
CaPEM Certificate `json:"ca"`
CertChainPEM []Certificate `json:"certChain"`
TLSOptions *tlsutil.TLSOptions `json:"tlsOptions,omitempty"`
TLS *tls.ConnectionState `json:"-"`
ServerPEM Certificate `json:"crt"`
CaPEM Certificate `json:"ca"`
CertChainPEM []Certificate `json:"certChain"`
TLSOptions *authority.TLSOptions `json:"tlsOptions,omitempty"`
TLS *tls.ConnectionState `json:"-"`
}
// Sign is an HTTP handler that reads a certificate request and an

View file

@ -12,15 +12,13 @@ import (
"github.com/smallstep/certificates/db"
kms "github.com/smallstep/certificates/kms/apiv1"
"github.com/smallstep/certificates/templates"
"github.com/smallstep/cli/crypto/tlsutil"
"github.com/smallstep/cli/crypto/x509util"
)
var (
// DefaultTLSOptions represents the default TLS version as well as the cipher
// suites used in the TLS certificates.
DefaultTLSOptions = tlsutil.TLSOptions{
CipherSuites: x509util.CipherSuites{
DefaultTLSOptions = TLSOptions{
CipherSuites: CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
@ -61,15 +59,27 @@ type Config struct {
DB *db.Config `json:"db,omitempty"`
Monitoring json.RawMessage `json:"monitoring,omitempty"`
AuthorityConfig *AuthConfig `json:"authority,omitempty"`
TLS *tlsutil.TLSOptions `json:"tls,omitempty"`
TLS *TLSOptions `json:"tls,omitempty"`
Password string `json:"password,omitempty"`
Templates *templates.Templates `json:"templates,omitempty"`
}
// ASN1DN contains ASN1.DN attributes that are used in Subject and Issuer
// x509 Certificate blocks.
type ASN1DN struct {
Country string `json:"country,omitempty" step:"country"`
Organization string `json:"organization,omitempty" step:"organization"`
OrganizationalUnit string `json:"organizationalUnit,omitempty" step:"organizationalUnit"`
Locality string `json:"locality,omitempty" step:"locality"`
Province string `json:"province,omitempty" step:"province"`
StreetAddress string `json:"streetAddress,omitempty" step:"streetAddress"`
CommonName string `json:"commonName,omitempty" step:"commonName"`
}
// AuthConfig represents the configuration options for the authority.
type AuthConfig struct {
Provisioners provisioner.List `json:"provisioners"`
Template *x509util.ASN1DN `json:"template,omitempty"`
Template *ASN1DN `json:"template,omitempty"`
Claims *provisioner.Claims `json:"claims,omitempty"`
DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"`
Backdate *provisioner.Duration `json:"backdate,omitempty"`
@ -82,7 +92,7 @@ func (c *AuthConfig) init() {
c.Provisioners = provisioner.List{}
}
if c.Template == nil {
c.Template = &x509util.ASN1DN{}
c.Template = &ASN1DN{}
}
if c.Backdate == nil {
c.Backdate = &provisioner.Duration{

View file

@ -7,8 +7,6 @@ import (
"github.com/pkg/errors"
"github.com/smallstep/assert"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/cli/crypto/tlsutil"
"github.com/smallstep/cli/crypto/x509util"
stepJOSE "github.com/smallstep/cli/jose"
)
@ -35,7 +33,7 @@ func TestConfigValidate(t *testing.T) {
type ConfigValidateTest struct {
config *Config
err error
tls tlsutil.TLSOptions
tls TLSOptions
}
tests := map[string]func(*testing.T) ConfigValidateTest{
"empty-address": func(t *testing.T) ConfigValidateTest {
@ -141,7 +139,7 @@ func TestConfigValidate(t *testing.T) {
DNSNames: []string{"test.smallstep.com"},
Password: "pass",
AuthorityConfig: ac,
TLS: &tlsutil.TLSOptions{},
TLS: &TLSOptions{},
},
tls: DefaultTLSOptions,
}
@ -156,8 +154,8 @@ func TestConfigValidate(t *testing.T) {
DNSNames: []string{"test.smallstep.com"},
Password: "pass",
AuthorityConfig: ac,
TLS: &tlsutil.TLSOptions{
CipherSuites: x509util.CipherSuites{
TLS: &TLSOptions{
CipherSuites: CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
},
MinVersion: 1.0,
@ -165,8 +163,8 @@ func TestConfigValidate(t *testing.T) {
Renegotiation: true,
},
},
tls: tlsutil.TLSOptions{
CipherSuites: x509util.CipherSuites{
tls: TLSOptions{
CipherSuites: CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
},
MinVersion: 1.0,
@ -185,8 +183,8 @@ func TestConfigValidate(t *testing.T) {
DNSNames: []string{"test.smallstep.com"},
Password: "pass",
AuthorityConfig: ac,
TLS: &tlsutil.TLSOptions{
CipherSuites: x509util.CipherSuites{
TLS: &TLSOptions{
CipherSuites: CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
},
MinVersion: 1.2,
@ -217,7 +215,7 @@ func TestConfigValidate(t *testing.T) {
}
func TestAuthConfigValidate(t *testing.T) {
asn1dn := x509util.ASN1DN{
asn1dn := ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",
@ -245,7 +243,7 @@ func TestAuthConfigValidate(t *testing.T) {
type AuthConfigValidateTest struct {
ac *AuthConfig
asn1dn x509util.ASN1DN
asn1dn ASN1DN
err error
}
tests := map[string]func(*testing.T) AuthConfigValidateTest{
@ -258,7 +256,7 @@ func TestAuthConfigValidate(t *testing.T) {
"ok-empty-provisioners": func(t *testing.T) AuthConfigValidateTest {
return AuthConfigValidateTest{
ac: &AuthConfig{},
asn1dn: x509util.ASN1DN{},
asn1dn: ASN1DN{},
}
},
"ok-empty-asn1dn-template": func(t *testing.T) AuthConfigValidateTest {
@ -266,7 +264,7 @@ func TestAuthConfigValidate(t *testing.T) {
ac: &AuthConfig{
Provisioners: p,
},
asn1dn: x509util.ASN1DN{},
asn1dn: ASN1DN{},
}
},
"ok-custom-asn1dn": func(t *testing.T) AuthConfigValidateTest {

View file

@ -17,21 +17,20 @@ import (
"github.com/smallstep/certificates/db"
"github.com/smallstep/certificates/errs"
"github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/tlsutil"
x509legacy "github.com/smallstep/cli/crypto/x509util"
"github.com/smallstep/cli/jose"
"go.step.sm/crypto/x509util"
)
// GetTLSOptions returns the tls options configured.
func (a *Authority) GetTLSOptions() *tlsutil.TLSOptions {
func (a *Authority) GetTLSOptions() *TLSOptions {
return a.config.TLS
}
var oidAuthorityKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 35}
var oidSubjectKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 14}
func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFunc {
func withDefaultASN1DN(def *ASN1DN) provisioner.CertificateModifierFunc {
return func(crt *x509.Certificate, opts provisioner.SignOptions) error {
if def == nil {
return errors.New("default ASN1DN template cannot be nil")

157
authority/tls_options.go Normal file
View file

@ -0,0 +1,157 @@
package authority
import (
"crypto/tls"
"fmt"
"github.com/pkg/errors"
)
var (
// DefaultTLSMinVersion default minimum version of TLS.
DefaultTLSMinVersion = TLSVersion(1.2)
// DefaultTLSMaxVersion default maximum version of TLS.
DefaultTLSMaxVersion = TLSVersion(1.3)
// DefaultTLSRenegotiation default TLS connection renegotiation policy.
DefaultTLSRenegotiation = false // Never regnegotiate.
// DefaultTLSCipherSuites specifies default step ciphersuite(s).
DefaultTLSCipherSuites = CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
}
// ApprovedTLSCipherSuites smallstep approved ciphersuites.
ApprovedTLSCipherSuites = CipherSuites{
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
}
)
// TLSVersion represents a TLS version number.
type TLSVersion float64
// Validate implements models.Validator and checks that a cipher suite is
// valid.
func (v TLSVersion) Validate() error {
if _, ok := tlsVersions[v]; ok {
return nil
}
return errors.Errorf("%f is not a valid tls version", v)
}
// Value returns the Go constant for the TLSVersion.
func (v TLSVersion) Value() uint16 {
return tlsVersions[v]
}
// String returns the Go constant for the TLSVersion.
func (v TLSVersion) String() string {
k := v.Value()
switch k {
case tls.VersionTLS10:
return "1.0"
case tls.VersionTLS11:
return "1.1"
case tls.VersionTLS12:
return "1.2"
case tls.VersionTLS13:
return "1.3"
default:
return fmt.Sprintf("unexpected value: %f", v)
}
}
// tlsVersions has the list of supported tls version.
var tlsVersions = map[TLSVersion]uint16{
// Defaults to TLS 1.3
0: tls.VersionTLS13,
// Options
1.0: tls.VersionTLS10,
1.1: tls.VersionTLS11,
1.2: tls.VersionTLS12,
1.3: tls.VersionTLS13,
}
// CipherSuites represents an array of string codes representing the cipher
// suites.
type CipherSuites []string
// Validate implements models.Validator and checks that a cipher suite is
// valid.
func (c CipherSuites) Validate() error {
for _, s := range c {
if _, ok := cipherSuites[s]; !ok {
return errors.Errorf("%s is not a valid cipher suite", s)
}
}
return nil
}
// Value returns an []uint16 for the cipher suites.
func (c CipherSuites) Value() []uint16 {
values := make([]uint16, len(c))
for i, s := range c {
values[i] = cipherSuites[s]
}
return values
}
// cipherSuites has the list of supported cipher suites.
var cipherSuites = map[string]uint16{
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
}
// TLSOptions represents the TLS options that can be specified on *tls.Config
// types to configure HTTPS servers and clients.
type TLSOptions struct {
CipherSuites CipherSuites `json:"cipherSuites"`
MinVersion TLSVersion `json:"minVersion"`
MaxVersion TLSVersion `json:"maxVersion"`
Renegotiation bool `json:"renegotiation"`
}
// TLSConfig returns the tls.Config equivalent of the TLSOptions.
func (t *TLSOptions) TLSConfig() *tls.Config {
var rs tls.RenegotiationSupport
if t.Renegotiation {
rs = tls.RenegotiateFreelyAsClient
} else {
rs = tls.RenegotiateNever
}
return &tls.Config{
CipherSuites: t.CipherSuites.Value(),
MinVersion: t.MinVersion.Value(),
MaxVersion: t.MaxVersion.Value(),
Renegotiation: rs,
}
}

View file

@ -0,0 +1,169 @@
package authority
import (
"crypto/tls"
"reflect"
"testing"
)
func TestTLSVersion_Validate(t *testing.T) {
tests := []struct {
name string
v TLSVersion
wantErr bool
}{
{"default", TLSVersion(0), false},
{"1.0", TLSVersion(1.0), false},
{"1.1", TLSVersion(1.1), false},
{"1.2", TLSVersion(1.2), false},
{"1.3", TLSVersion(1.3), false},
{"0.99", TLSVersion(0.99), true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.v.Validate(); (err != nil) != tt.wantErr {
t.Errorf("TLSVersion.Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestTLSVersion_String(t *testing.T) {
tests := []struct {
name string
v TLSVersion
want string
}{
{"default", TLSVersion(0), "1.3"},
{"1.0", TLSVersion(1.0), "1.0"},
{"1.1", TLSVersion(1.1), "1.1"},
{"1.2", TLSVersion(1.2), "1.2"},
{"1.3", TLSVersion(1.3), "1.3"},
{"0.99", TLSVersion(0.99), "unexpected value: 0.990000"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.v.String(); got != tt.want {
t.Errorf("TLSVersion.String() = %v, want %v", got, tt.want)
}
})
}
}
func TestCipherSuites_Validate(t *testing.T) {
tests := []struct {
name string
c CipherSuites
wantErr bool
}{
{"TLS_RSA_WITH_RC4_128_SHA", CipherSuites{"TLS_RSA_WITH_RC4_128_SHA"}, false},
{"TLS_RSA_WITH_3DES_EDE_CBC_SHA", CipherSuites{"TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, false},
{"TLS_RSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_RSA_WITH_AES_128_CBC_SHA"}, false},
{"TLS_RSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_RSA_WITH_AES_256_CBC_SHA"}, false},
{"TLS_RSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_RSA_WITH_AES_128_CBC_SHA256"}, false},
{"TLS_RSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_RSA_WITH_AES_128_GCM_SHA256"}, false},
{"TLS_RSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_RSA_WITH_AES_256_GCM_SHA384"}, false},
{"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"}, false},
{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"}, false},
{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}, false},
{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, false},
{"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"}, false},
{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"}, false},
{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"}, false},
{"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"}, false},
{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}, false},
{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}, false},
{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}, false},
{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"}, false},
{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"}, false},
{"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", CipherSuites{"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"}, false},
{"multiple", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, false},
{"fail", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_BAD_CIPHERSUITE"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.c.Validate(); (err != nil) != tt.wantErr {
t.Errorf("CipherSuites.Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestCipherSuites_Value(t *testing.T) {
tests := []struct {
name string
c CipherSuites
want []uint16
}{
{"TLS_RSA_WITH_RC4_128_SHA", CipherSuites{"TLS_RSA_WITH_RC4_128_SHA"}, []uint16{tls.TLS_RSA_WITH_RC4_128_SHA}},
{"TLS_RSA_WITH_3DES_EDE_CBC_SHA", CipherSuites{"TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}},
{"TLS_RSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_RSA_WITH_AES_128_CBC_SHA"}, []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA}},
{"TLS_RSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_RSA_WITH_AES_256_CBC_SHA"}, []uint16{tls.TLS_RSA_WITH_AES_256_CBC_SHA}},
{"TLS_RSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_RSA_WITH_AES_128_CBC_SHA256"}, []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA256}},
{"TLS_RSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_RSA_WITH_AES_128_GCM_SHA256"}, []uint16{tls.TLS_RSA_WITH_AES_128_GCM_SHA256}},
{"TLS_RSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_RSA_WITH_AES_256_GCM_SHA384"}, []uint16{tls.TLS_RSA_WITH_AES_256_GCM_SHA384}},
{"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}},
{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}},
{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}},
{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}},
{"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}},
{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}},
{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}},
{"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"}, []uint16{tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}},
{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}},
{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}},
{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}},
{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"}, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}},
{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", CipherSuites{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"}, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}},
{"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", CipherSuites{"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"}, []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}},
{"multiple", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}},
{"fail", CipherSuites{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_BAD_CIPHERSUITE"}, []uint16{tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 0}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.c.Value(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("CipherSuites.Value() = %v, want %v", got, tt.want)
}
})
}
}
func TestTLSOptions_TLSConfig(t *testing.T) {
type fields struct {
CipherSuites CipherSuites
MinVersion TLSVersion
MaxVersion TLSVersion
Renegotiation bool
}
tests := []struct {
name string
fields fields
want *tls.Config
}{
{"default", fields{DefaultTLSCipherSuites, DefaultTLSMinVersion, DefaultTLSMaxVersion, DefaultTLSRenegotiation}, &tls.Config{
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
Renegotiation: tls.RenegotiateNever,
}},
{"renegotation", fields{DefaultTLSCipherSuites, DefaultTLSMinVersion, DefaultTLSMaxVersion, true}, &tls.Config{
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
Renegotiation: tls.RenegotiateFreelyAsClient,
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &TLSOptions{
CipherSuites: tt.fields.CipherSuites,
MinVersion: tt.fields.MinVersion,
MaxVersion: tt.fields.MaxVersion,
Renegotiation: tt.fields.Renegotiation,
}
if got := o.TLSConfig(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("TLSOptions.TLSConfig() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -22,7 +22,6 @@ import (
"github.com/smallstep/certificates/errs"
"github.com/smallstep/cli/crypto/keys"
"github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/tlsutil"
"github.com/smallstep/cli/crypto/x509util"
"github.com/smallstep/cli/jose"
"gopkg.in/square/go-jose.v2/jwt"
@ -122,7 +121,7 @@ func TestAuthority_Sign(t *testing.T) {
a := testAuthority(t)
assert.FatalError(t, err)
a.config.AuthorityConfig.Template = &x509util.ASN1DN{
a.config.AuthorityConfig.Template = &ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",
@ -478,7 +477,7 @@ func TestAuthority_Renew(t *testing.T) {
assert.FatalError(t, err)
a := testAuthority(t)
a.config.AuthorityConfig.Template = &x509util.ASN1DN{
a.config.AuthorityConfig.Template = &ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",
@ -705,7 +704,7 @@ func TestAuthority_Rekey(t *testing.T) {
assert.FatalError(t, err)
a := testAuthority(t)
a.config.AuthorityConfig.Template = &x509util.ASN1DN{
a.config.AuthorityConfig.Template = &ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",
@ -946,7 +945,7 @@ func TestAuthority_Rekey(t *testing.T) {
func TestAuthority_GetTLSOptions(t *testing.T) {
type renewTest struct {
auth *Authority
opts *tlsutil.TLSOptions
opts *TLSOptions
}
tests := map[string]func() (*renewTest, error){
"default": func() (*renewTest, error) {
@ -955,8 +954,8 @@ func TestAuthority_GetTLSOptions(t *testing.T) {
},
"non-default": func() (*renewTest, error) {
a := testAuthority(t)
a.config.TLS = &tlsutil.TLSOptions{
CipherSuites: x509util.CipherSuites{
a.config.TLS = &TLSOptions{
CipherSuites: CipherSuites{
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
},

View file

@ -79,7 +79,7 @@ func TestCASign(t *testing.T) {
pub, priv, err := keys.GenerateDefaultKeyPair()
assert.FatalError(t, err)
asn1dn := &x509util.ASN1DN{
asn1dn := &authority.ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",
@ -558,7 +558,7 @@ func TestCARenew(t *testing.T) {
pub, _, err := keys.GenerateDefaultKeyPair()
assert.FatalError(t, err)
asn1dn := &x509util.ASN1DN{
asn1dn := &authority.ASN1DN{
Country: "Tazmania",
Organization: "Acme Co",
Locality: "Landscapes",

2
go.mod
View file

@ -1,6 +1,6 @@
module github.com/smallstep/certificates
go 1.13
go 1.14
require (
cloud.google.com/go v0.51.0

View file

@ -23,7 +23,6 @@ import (
"github.com/smallstep/cli/config"
"github.com/smallstep/cli/crypto/keys"
"github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/tlsutil"
"github.com/smallstep/cli/crypto/x509util"
"github.com/smallstep/cli/errs"
"github.com/smallstep/cli/jose"
@ -432,11 +431,11 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authority.Config, error) {
DisableIssuedAtCheck: false,
Provisioners: provisioner.List{prov},
},
TLS: &tlsutil.TLSOptions{
MinVersion: x509util.DefaultTLSMinVersion,
MaxVersion: x509util.DefaultTLSMaxVersion,
Renegotiation: x509util.DefaultTLSRenegotiation,
CipherSuites: x509util.DefaultTLSCipherSuites,
TLS: &authority.TLSOptions{
MinVersion: authority.DefaultTLSMinVersion,
MaxVersion: authority.DefaultTLSMaxVersion,
Renegotiation: authority.DefaultTLSRenegotiation,
CipherSuites: authority.DefaultTLSCipherSuites,
},
Templates: p.getTemplates(),
}