Skip to content

Commit

Permalink
introduce func. opts. pattern and convert GetCertificate tracing to it
Browse files Browse the repository at this point in the history
  • Loading branch information
aybabtme committed Aug 4, 2020
1 parent 2415008 commit 2ab5b9c
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 99 deletions.
141 changes: 121 additions & 20 deletions v2/spiffetls/tlsconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,63 +27,135 @@ func HookTLSClientConfig(config *tls.Config, bundle x509bundle.Source, authorize
config.VerifyPeerCertificate = WrapVerifyPeerCertificate(config.VerifyPeerCertificate, bundle, authorizer)
}

type mtlsClientConfigOption struct {
getCertificateOptions []GetCertificateOption
}

// A MTLSClientConfigOption changes the defaults used to by mTLS ClientConfig functions.
type MTLSClientConfigOption func(*mtlsClientConfigOption)

// WithMTLSClientGetCertificateOption makes the ClientConfig use the given GetCertificateOption
// to obtain certificates.
func WithMTLSClientGetCertificateOption(opts ...GetCertificateOption) MTLSClientConfigOption {
return func(cco *mtlsClientConfigOption) {
cco.getCertificateOptions = opts
}
}

// MTLSClientConfig returns a TLS configuration which presents an X509-SVID
// to the server and verifies and authorizes the server X509-SVID.
func MTLSClientConfig(svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, trace Trace) *tls.Config {
func MTLSClientConfig(svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, opts ...MTLSClientConfigOption) *tls.Config {
config := new(tls.Config)
HookMTLSClientConfig(config, svid, bundle, authorizer, trace)
HookMTLSClientConfig(config, svid, bundle, authorizer, opts...)
return config
}

// HookMTLSClientConfig sets up the TLS configuration to present an X509-SVID
// to the server and verify and authorize the server X509-SVID. If there is an
// existing callback set for VerifyPeerCertificate it will be wrapped by by
// this package and invoked after SPIFFE authentication has completed.
func HookMTLSClientConfig(config *tls.Config, svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, trace Trace) {
func HookMTLSClientConfig(config *tls.Config, svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, opts ...MTLSClientConfigOption) {
dftlOpt := &mtlsClientConfigOption{}
for _, opt := range opts {
opt(dftlOpt)
}
resetAuthFields(config)
config.GetClientCertificate = GetClientCertificate(svid, trace)
config.GetClientCertificate = GetClientCertificate(svid, dftlOpt.getCertificateOptions...)
config.InsecureSkipVerify = true
config.VerifyPeerCertificate = WrapVerifyPeerCertificate(config.VerifyPeerCertificate, bundle, authorizer)
}

type mtlsWebClientConfigOption struct {
getCertificateOptions []GetCertificateOption
}

// A MTLSWebClientConfigOption changes the defaults used to by mTLS ClientConfig functions.
type MTLSWebClientConfigOption func(*mtlsWebClientConfigOption)

// WithMTLSWebClientGetCertificateOption makes the ClientConfig use the given GetCertificateOption
// to obtain certificates.
func WithMTLSWebClientGetCertificateOption(opts ...GetCertificateOption) MTLSWebClientConfigOption {
return func(cco *mtlsWebClientConfigOption) {
cco.getCertificateOptions = opts
}
}

// MTLSWebClientConfig returns a TLS configuration which presents an X509-SVID
// to the server and verifies the server certificate using provided roots (or
// the system roots if nil).
func MTLSWebClientConfig(svid x509svid.Source, roots *x509.CertPool, trace Trace) *tls.Config {
func MTLSWebClientConfig(svid x509svid.Source, roots *x509.CertPool, opts ...MTLSWebClientConfigOption) *tls.Config {
config := new(tls.Config)
HookMTLSWebClientConfig(config, svid, roots, trace)
HookMTLSWebClientConfig(config, svid, roots, opts...)
return config
}

// HookMTLSWebClientConfig sets up the TLS configuration to present an
// X509-SVID to the server and verifies the server certificate using the
// provided roots (or the system roots if nil).
func HookMTLSWebClientConfig(config *tls.Config, svid x509svid.Source, roots *x509.CertPool, trace Trace) {
func HookMTLSWebClientConfig(config *tls.Config, svid x509svid.Source, roots *x509.CertPool, opts ...MTLSWebClientConfigOption) {
dftlOpt := &mtlsWebClientConfigOption{}
for _, opt := range opts {
opt(dftlOpt)
}
resetAuthFields(config)
config.GetClientCertificate = GetClientCertificate(svid, trace)
config.GetClientCertificate = GetClientCertificate(svid, dftlOpt.getCertificateOptions...)
config.RootCAs = roots
}

type tlsServerConfigOption struct {
getCertificateOptions []GetCertificateOption
}

// A TLSServerConfigOption changes the defaults used to by mTLS ClientConfig functions.
type TLSServerConfigOption func(*tlsServerConfigOption)

// WithTLSServerGetCertificateOption makes the ServerConfig use the given GetCertificateOption
// to obtain certificates.
func WithTLSServerGetCertificateOption(opts ...GetCertificateOption) TLSServerConfigOption {
return func(cco *tlsServerConfigOption) {
cco.getCertificateOptions = opts
}
}

// TLSServerConfig returns a TLS configuration which presents an X509-SVID
// to the client and does not require or verify client certificates.
func TLSServerConfig(svid x509svid.Source, trace Trace) *tls.Config {
func TLSServerConfig(svid x509svid.Source, opts ...TLSServerConfigOption) *tls.Config {
config := new(tls.Config)
HookTLSServerConfig(config, svid, trace)
HookTLSServerConfig(config, svid, opts...)
return config
}

// HookTLSServerConfig sets up the TLS configuration to present an X509-SVID
// to the client and to not require or verify client certificates.
func HookTLSServerConfig(config *tls.Config, svid x509svid.Source, trace Trace) {
func HookTLSServerConfig(config *tls.Config, svid x509svid.Source, opts ...TLSServerConfigOption) {
dftlOpt := &tlsServerConfigOption{}
for _, opt := range opts {
opt(dftlOpt)
}
resetAuthFields(config)
config.GetCertificate = GetCertificate(svid, trace)
config.GetCertificate = GetCertificate(svid, dftlOpt.getCertificateOptions...)
}

type mtlsServerConfigOption struct {
getCertificateOptions []GetCertificateOption
}

// A MTLSServerConfigOption changes the defaults used to by mTLS ClientConfig functions.
type MTLSServerConfigOption func(*mtlsServerConfigOption)

// WithMTLSServerGetCertificateOption makes the ServerConfig use the given GetCertificateOption
// to obtain certificates.
func WithMTLSServerGetCertificateOption(opts ...GetCertificateOption) MTLSServerConfigOption {
return func(cco *mtlsServerConfigOption) {
cco.getCertificateOptions = opts
}
}

// MTLSServerConfig returns a TLS configuration which presents an X509-SVID
// to the client and requires, verifies, and authorizes client X509-SVIDs.
func MTLSServerConfig(svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, trace Trace) *tls.Config {
func MTLSServerConfig(svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, opts ...MTLSServerConfigOption) *tls.Config {
config := new(tls.Config)
HookMTLSServerConfig(config, svid, bundle, authorizer, trace)
HookMTLSServerConfig(config, svid, bundle, authorizer, opts...)
return config
}

Expand All @@ -92,10 +164,14 @@ func MTLSServerConfig(svid x509svid.Source, bundle x509bundle.Source, authorizer
// there is an existing callback set for VerifyPeerCertificate it will be
// wrapped by by this package and invoked after SPIFFE authentication has
// completed.
func HookMTLSServerConfig(config *tls.Config, svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, trace Trace) {
func HookMTLSServerConfig(config *tls.Config, svid x509svid.Source, bundle x509bundle.Source, authorizer Authorizer, opts ...MTLSServerConfigOption) {
dftlOpt := &mtlsServerConfigOption{}
for _, opt := range opts {
opt(dftlOpt)
}
resetAuthFields(config)
config.ClientAuth = tls.RequireAnyClientCert
config.GetCertificate = GetCertificate(svid, trace)
config.GetCertificate = GetCertificate(svid, dftlOpt.getCertificateOptions...)
config.VerifyPeerCertificate = WrapVerifyPeerCertificate(config.VerifyPeerCertificate, bundle, authorizer)
}

Expand All @@ -120,20 +196,45 @@ func HookMTLSWebServerConfig(config *tls.Config, cert *tls.Certificate, bundle x
config.VerifyPeerCertificate = WrapVerifyPeerCertificate(config.VerifyPeerCertificate, bundle, authorizer)
}

type getCertificateOption struct {
trace Trace
}

func newGetCertificateOption(opts []GetCertificateOption) *getCertificateOption {
out := &getCertificateOption{}
for _, opt := range opts {
opt(out)
}
return out
}

// GetCertificateOption modifies the default used by the GetCertificate function.
type GetCertificateOption func(*getCertificateOption)

// WithGetCertificateTrace will use the provided tracing callbacks
// when `GetCertificate` gets invoked.
func WithGetCertificateTrace(trace Trace) GetCertificateOption {
return func(gco *getCertificateOption) {
gco.trace = trace
}
}

// GetCertificate returns a GetCertificate callback for tls.Config. It uses the
// given X509-SVID getter to obtain a server X509-SVID for the TLS handshake.
func GetCertificate(svid x509svid.Source, trace Trace) func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
func GetCertificate(svid x509svid.Source, opts ...GetCertificateOption) func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
opt := newGetCertificateOption(opts)
return func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
return getTLSCertificate(svid, trace)
return getTLSCertificate(svid, opt.trace)
}
}

// GetClientCertificate returns a GetClientCertificate callback for tls.Config.
// It uses the given X509-SVID getter to obtain a client X509-SVID for the TLS
// handshake.
func GetClientCertificate(svid x509svid.Source, trace Trace) func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
func GetClientCertificate(svid x509svid.Source, opts ...GetCertificateOption) func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
opt := newGetCertificateOption(opts)
return func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
return getTLSCertificate(svid, trace)
return getTLSCertificate(svid, opt.trace)
}
}

Expand Down
Loading

0 comments on commit 2ab5b9c

Please sign in to comment.