mirror of
https://github.com/outbackdingo/matchbox.git
synced 2026-01-27 10:19:35 +00:00
bootcfg/*: Require TLS client auth for gRPC API
* gRPC API server requires a CA certificate to verify and authenticate clients (passed via -ca-file) * gRPC clients must authenticate with a client certificate and key (passed via -cert-file and -key-file)
This commit is contained in:
@@ -12,6 +12,7 @@ Configuration arguments can be provided as flags or as environment variables.
|
||||
| -rpc-address | BOOTCFG_RPC_ADDRESS | (gRPC API disabled) | 127.0.0.1:8081 |
|
||||
| -cert-file | BOOTCFG_CERT_FILE | /etc/bootcfg/server.crt | ./examples/etc/bootcfg/server.crt |
|
||||
| -key-file | BOOTCFG_KEY_FILE | /etc/bootcfg/server.key | ./examples/etc/bootcfg/server.key
|
||||
| -ca-file | BOOTCFG_CA_FILE | /etc/bootcfg/ca.crt | ./examples/etc/bootcfg/ca.crt |
|
||||
| -key-ring-path | BOOTCFG_KEY_RING_PATH | (no key ring) | ~/.secrets/vault/bootcfg/secring.gpg |
|
||||
| (no flag) | BOOTCFG_PASSPHRASE | (no passphrase) | "secret passphrase" |
|
||||
|
||||
@@ -27,7 +28,9 @@ Configuration arguments can be provided as flags or as environment variables.
|
||||
|:---------|:--------------------------------------------------|
|
||||
| CA certificate | /etc/bootcfg/ca.crt |
|
||||
| Server certificate | /etc/bootcfg/server.crt |
|
||||
| Server Private Key | /etc/bootcfg/server.key |
|
||||
| Server private key | /etc/bootcfg/server.key |
|
||||
| Client certificate | /etc/bootcfg/client.crt |
|
||||
| Client private key | /etc/bootcfg/client.key |
|
||||
|
||||
## Version
|
||||
|
||||
@@ -63,7 +66,7 @@ Run the Docker image. Mounts are used to add the provided examples.
|
||||
|
||||
### gRPC API
|
||||
|
||||
The gRPC API can be enabled with the `-rpc-address` flag and by providing a TLS server certificate and key with `-cert-file` and `-key-file`. gRPC clients (such as `bootcmd`) must verify the server's certificate with a CA bundle.
|
||||
The gRPC API can be enabled with the `-rpc-address` flag and by providing a TLS server certificate and key with `-cert-file` and `-key-file` and a CA certificate for authenticating clients with `-ca-file`. gRPC clients (such as `bootcmd`) must verify the server's certificate with a CA bundle passed via `-ca-file` and present a client certificate and key via `-cert-file` and `-key-file`.
|
||||
|
||||
Run the ACI with rkt and TLS credentials from `examples/etc/bootcfg`.
|
||||
|
||||
@@ -71,7 +74,7 @@ Run the ACI with rkt and TLS credentials from `examples/etc/bootcfg`.
|
||||
|
||||
A `bootcmd` client can call the gRPC API running at the IP used in the rkt example.
|
||||
|
||||
./bin/bootcmd profile list --endpoints 172.15.0.2:8081 --ca-file examples/etc/bootcfg/ca.crt
|
||||
./bin/bootcmd profile list --endpoints 172.15.0.2:8081 --ca-file examples/etc/bootcfg/ca.crt --cert-file examples/etc/bootcfg/client.crt --key-file examples/etc/bootcfg/client.key
|
||||
|
||||
Run the Docker image with TLS credentials from `examples/etc/bootcfg`.
|
||||
|
||||
@@ -79,7 +82,7 @@ Run the Docker image with TLS credentials from `examples/etc/bootcfg`.
|
||||
|
||||
A `bootcmd` client can call the gRPC API running at the IP used in the Docker example.
|
||||
|
||||
./bin/bootcmd profile list --endpoints 127.0.0.1:8081 --ca-file examples/etc/bootcfg/root.crt
|
||||
./bin/bootcmd profile list --endpoints 127.0.0.1:8081 --ca-file examples/etc/bootcfg/ca.crt --cert-file examples/etc/bootcfg/client.crt --key-file examples/etc/bootcfg/client.key
|
||||
|
||||
#### With [OpenPGP Signing](openpgp.md)
|
||||
|
||||
|
||||
@@ -22,15 +22,20 @@ To get help about a resource or command, run "bootcmd help resource"`,
|
||||
|
||||
// globalFlags can be set for any subcommand.
|
||||
globalFlags = struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
endpoints []string
|
||||
caFile string
|
||||
certFile string
|
||||
keyFile string
|
||||
}{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.PersistentFlags().StringSliceVar(&globalFlags.Endpoints, "endpoints", []string{"127.0.0.1:8081"}, "gRPC Endpoints")
|
||||
// gRPC Client TLS
|
||||
RootCmd.PersistentFlags().StringVar(&globalFlags.CAFile, "ca-file", "/etc/bootcfg/ca.crt", "Path to the CA bundle to verify certificates of TLS servers")
|
||||
RootCmd.PersistentFlags().StringSliceVar(&globalFlags.endpoints, "endpoints", []string{"127.0.0.1:8081"}, "gRPC Endpoints")
|
||||
// gRPC TLS Server Verification
|
||||
RootCmd.PersistentFlags().StringVar(&globalFlags.caFile, "ca-file", "/etc/bootcfg/ca.crt", "Path to the CA bundle to verify certificates of TLS servers")
|
||||
// gRPC TLS Client Authentication
|
||||
RootCmd.PersistentFlags().StringVar(&globalFlags.certFile, "cert-file", "/etc/bootcfg/client.crt", "Path to the client TLS certificate file")
|
||||
RootCmd.PersistentFlags().StringVar(&globalFlags.keyFile, "key-file", "/etc/bootcfg/client.key", "Path to the client TLS key file")
|
||||
cobra.EnablePrefixMatching = true
|
||||
}
|
||||
|
||||
@@ -81,5 +86,18 @@ func tlsInfoFromCmd(cmd *cobra.Command) *tlsutil.TLSInfo {
|
||||
if err != nil {
|
||||
exitWithError(ExitBadArgs, err)
|
||||
}
|
||||
return &tlsutil.TLSInfo{CAFile: caFile}
|
||||
certFile, err := cmd.Flags().GetString("cert-file")
|
||||
if err != nil {
|
||||
exitWithError(ExitBadArgs, err)
|
||||
}
|
||||
keyFile, err := cmd.Flags().GetString("key-file")
|
||||
if err != nil {
|
||||
exitWithError(ExitBadArgs, err)
|
||||
}
|
||||
|
||||
return &tlsutil.TLSInfo{
|
||||
CAFile: caFile,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
// TLSInfo prepares tls.Config's from TLS file inputs.
|
||||
// TLSInfo prepares tls.Config's from TLS filename inputs.
|
||||
type TLSInfo struct {
|
||||
CAFile string
|
||||
CertFile string
|
||||
@@ -13,29 +13,49 @@ type TLSInfo struct {
|
||||
|
||||
// ClientConfig returns a tls.Config for client use.
|
||||
func (info *TLSInfo) ClientConfig() (*tls.Config, error) {
|
||||
// CA for verifying the server
|
||||
pool, err := NewCertPool([]string{info.CAFile})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// client certificate (for authentication)
|
||||
cert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: false,
|
||||
// CA bundle the client should trust when verifying a server
|
||||
RootCAs: pool,
|
||||
// Client certificates to authenticate to the server
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ServerConfig returns a tls.Config for server use.
|
||||
func (info *TLSInfo) ServerConfig() (*tls.Config, error) {
|
||||
// server certificate to present to clients
|
||||
cert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// CA for authenticating clients
|
||||
pool, err := NewCertPool([]string{info.CAFile})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
// Certificates the server should present to clients
|
||||
Certificates: []tls.Certificate{cert},
|
||||
// Client Authentication (required)
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
// CA for verifying and authorizing client certificates
|
||||
ClientCAs: pool,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ func main() {
|
||||
logLevel string
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
keyRingPath string
|
||||
version bool
|
||||
help bool
|
||||
@@ -49,6 +50,8 @@ func main() {
|
||||
// gRPC Server TLS
|
||||
flag.StringVar(&flags.certFile, "cert-file", "/etc/bootcfg/server.crt", "Path to the server TLS certificate file")
|
||||
flag.StringVar(&flags.keyFile, "key-file", "/etc/bootcfg/server.key", "Path to the server TLS key file")
|
||||
// TLS Client Authentication
|
||||
flag.StringVar(&flags.caFile, "ca-file", "/etc/bootcfg/ca.crt", "Path to the CA verify and authenticate client certificates")
|
||||
|
||||
// Signing
|
||||
flag.StringVar(&flags.keyRingPath, "key-ring-path", "", "Path to a private keyring file")
|
||||
@@ -133,6 +136,7 @@ func main() {
|
||||
tlsinfo := tlsutil.TLSInfo{
|
||||
CertFile: flags.certFile,
|
||||
KeyFile: flags.keyFile,
|
||||
CAFile: flags.caFile,
|
||||
}
|
||||
tlscfg, err := tlsinfo.ServerConfig()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user