Skip to content

Commit

Permalink
tls: add mutual tls support
Browse files Browse the repository at this point in the history
  • Loading branch information
andydunstall committed Nov 30, 2024
1 parent 38789c4 commit 4e08bc0
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 2 deletions.
34 changes: 34 additions & 0 deletions agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ func (c *ListenerConfig) Validate() error {
}

type TLSConfig struct {
// Cert contains a path to the PEM encoded certificate to present to
// the server (optional).
Cert string `json:"cert" yaml:"cert"`

// Key contains a path to the PEM encoded private key (optional).
Key string `json:"key" yaml:"key"`

// RootCAs contains a path to root certificate authorities to validate
// the TLS connection to the Piko server.
//
Expand All @@ -142,12 +149,31 @@ type TLSConfig struct {
}

func (c *TLSConfig) Validate() error {
if c.Cert != "" && c.Key == "" {
return fmt.Errorf("missing key")
}

_, err := c.Load()
return err
}

func (c *TLSConfig) RegisterFlags(fs *pflag.FlagSet, prefix string) {
prefix = prefix + ".tls."
fs.StringVar(
&c.Cert,
prefix+"cert",
c.Cert,
`
Path to the PEM encoded certificate file to present to the server.`,
)
fs.StringVar(
&c.Key,
prefix+"key",
c.Key,
`
Path to the PEM encoded key file.`,
)

fs.StringVar(
&c.RootCAs,
prefix+"root-cas",
Expand All @@ -172,6 +198,14 @@ host name in that certificate.`,
func (c *TLSConfig) Load() (*tls.Config, error) {
tlsConfig := &tls.Config{}

if c.Cert != "" {
cert, err := tls.LoadX509KeyPair(c.Cert, c.Key)
if err != nil {
return nil, fmt.Errorf("load key pair: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
}

if c.RootCAs != "" {
caCert, err := os.ReadFile(c.RootCAs)
if err != nil {
Expand Down
34 changes: 34 additions & 0 deletions forward/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ func (c *PortConfig) Validate() error {
}

type TLSConfig struct {
// Cert contains a path to the PEM encoded certificate to present to
// the server (optional).
Cert string `json:"cert" yaml:"cert"`

// Key contains a path to the PEM encoded private key (optional).
Key string `json:"key" yaml:"key"`

// RootCAs contains a path to root certificate authorities to validate
// the TLS connection to the Piko server.
//
Expand All @@ -71,12 +78,31 @@ type TLSConfig struct {
}

func (c *TLSConfig) Validate() error {
if c.Cert != "" && c.Key == "" {
return fmt.Errorf("missing key")
}

_, err := c.Load()
return err
}

func (c *TLSConfig) RegisterFlags(fs *pflag.FlagSet, prefix string) {
prefix = prefix + ".tls."
fs.StringVar(
&c.Cert,
prefix+"cert",
c.Cert,
`
Path to the PEM encoded certificate file to present to the server.`,
)
fs.StringVar(
&c.Key,
prefix+"key",
c.Key,
`
Path to the PEM encoded key file.`,
)

fs.StringVar(
&c.RootCAs,
prefix+"root-cas",
Expand All @@ -101,6 +127,14 @@ host name in that certificate.`,
func (c *TLSConfig) Load() (*tls.Config, error) {
tlsConfig := &tls.Config{}

if c.Cert != "" {
cert, err := tls.LoadX509KeyPair(c.Cert, c.Key)
if err != nil {
return nil, fmt.Errorf("load key pair: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
}

if c.RootCAs != "" {
caCert, err := os.ReadFile(c.RootCAs)
if err != nil {
Expand Down
31 changes: 29 additions & 2 deletions server/config/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package config

import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"

"github.com/spf13/pflag"
)

type TLSConfig struct {
Cert string `json:"cert" yaml:"cert"`
Key string `json:"key" yaml:"key"`
Cert string `json:"cert" yaml:"cert"`
Key string `json:"key" yaml:"key"`
ClientCAs string `json:"client_cas" yaml:"client_cas"`
}

func (c *TLSConfig) Validate() error {
Expand Down Expand Up @@ -45,6 +48,16 @@ If given the server will listen on TLS`,
`
Path to the PEM encoded key file.`,
)
fs.StringVar(
&c.ClientCAs,
prefix+"client-cas",
c.ClientCAs,
`
A path to a certificate PEM file containing client certificiate authorities to
verify the client certificates.
When set the client must set a valid certificate during the TLS handshake.`,
)
}

func (c *TLSConfig) Load() (*tls.Config, error) {
Expand All @@ -59,6 +72,20 @@ func (c *TLSConfig) Load() (*tls.Config, error) {
}
tlsConfig.Certificates = []tls.Certificate{cert}

if c.ClientCAs != "" {
caCert, err := os.ReadFile(c.ClientCAs)
if err != nil {
return nil, fmt.Errorf("open client cas: %s: %w", c.ClientCAs, err)
}
caCertPool := x509.NewCertPool()
ok := caCertPool.AppendCertsFromPEM(caCert)
if !ok {
return nil, fmt.Errorf("parse client cas: %s: %w", c.ClientCAs, err)
}
tlsConfig.ClientCAs = caCertPool
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}

return tlsConfig, nil
}

Expand Down

0 comments on commit 4e08bc0

Please sign in to comment.