feat(KV): support TLS.
This commit is contained in:
parent
5639decf82
commit
92ce6d8d03
129
cmd/kv.go
129
cmd/kv.go
@ -1,6 +1,11 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/abronan/valkeyrie/store"
|
"github.com/abronan/valkeyrie/store"
|
||||||
@ -24,10 +29,12 @@ func init() {
|
|||||||
kvCmd.PersistentFlags().String("password", "", "Password for connection.")
|
kvCmd.PersistentFlags().String("password", "", "Password for connection.")
|
||||||
kvCmd.PersistentFlags().String("username", "", "Username for connection.")
|
kvCmd.PersistentFlags().String("username", "", "Username for connection.")
|
||||||
|
|
||||||
// FIXME review TLS parts
|
kvCmd.PersistentFlags().Bool("tls", false, "Enable TLS encryption.")
|
||||||
// kvCmd.PersistentFlags().Bool("tls.enable", false, "Enable TLS encryption.")
|
kvCmd.PersistentFlags().String("tls.ca", "", "Root CA for certificate verification if TLS is enabled")
|
||||||
// kvCmd.PersistentFlags().Bool("tls.insecureskipverify", false, "Trust unverified certificates if TLS is enabled.")
|
kvCmd.PersistentFlags().Bool("tls.ca.optional", false, "")
|
||||||
// kvCmd.PersistentFlags().String("tls.ca-cert-file", "", "Root CA file for certificate verification if TLS is enabled.")
|
kvCmd.PersistentFlags().String("tls.cert", "", "TLS cert")
|
||||||
|
kvCmd.PersistentFlags().String("tls.key", "", "TLS key")
|
||||||
|
kvCmd.PersistentFlags().Bool("tls.insecureskipverify", false, "Trust unverified certificates if TLS is enabled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKvConfig(cmd *cobra.Command) (*kv.Config, error) {
|
func getKvConfig(cmd *cobra.Command) (*kv.Config, error) {
|
||||||
@ -41,6 +48,11 @@ func getKvConfig(cmd *cobra.Command) (*kv.Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlsConfig, err := createTLSConfig(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &kv.Config{
|
return &kv.Config{
|
||||||
Endpoints: endpoints,
|
Endpoints: endpoints,
|
||||||
Prefix: cmd.Flag("prefix").Value.String(),
|
Prefix: cmd.Flag("prefix").Value.String(),
|
||||||
@ -48,6 +60,115 @@ func getKvConfig(cmd *cobra.Command) (*kv.Config, error) {
|
|||||||
ConnectionTimeout: time.Duration(connectionTimeout) * time.Second,
|
ConnectionTimeout: time.Duration(connectionTimeout) * time.Second,
|
||||||
Username: cmd.Flag("password").Value.String(),
|
Username: cmd.Flag("password").Value.String(),
|
||||||
Password: cmd.Flag("username").Value.String(),
|
Password: cmd.Flag("username").Value.String(),
|
||||||
|
TLS: tlsConfig,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTLSConfig(cmd *cobra.Command) (*tls.Config, error) {
|
||||||
|
enable, _ := cmd.Flags().GetBool("tls")
|
||||||
|
if !enable {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ca := cmd.Flag("tls.ca").Value.String()
|
||||||
|
caPool, err := getCertPool(ca)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
caOptional, _ := cmd.Flags().GetBool("tls.ca.optional")
|
||||||
|
clientAuth := getClientAuth(ca, caOptional)
|
||||||
|
|
||||||
|
insecureSkipVerify, _ := cmd.Flags().GetBool("tls.insecureskipverify")
|
||||||
|
privateKey := cmd.Flag("tls.key").Value.String()
|
||||||
|
certContent := cmd.Flag("tls.cert").Value.String()
|
||||||
|
|
||||||
|
if !insecureSkipVerify && (len(certContent) == 0 || len(privateKey) == 0) {
|
||||||
|
return nil, fmt.Errorf("TLS Certificate or Key file must be set when TLS configuration is created")
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := getCertificate(privateKey, certContent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load TLS keypair: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: caPool,
|
||||||
|
InsecureSkipVerify: insecureSkipVerify,
|
||||||
|
ClientAuth: clientAuth,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertPool(ca string) (*x509.CertPool, error) {
|
||||||
|
caPool := x509.NewCertPool()
|
||||||
|
|
||||||
|
if ca != "" {
|
||||||
|
caContent, err := getCAContent(ca)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read CA. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !caPool.AppendCertsFromPEM(caContent) {
|
||||||
|
return nil, fmt.Errorf("failed to parse CA")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return caPool, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCAContent(ca string) ([]byte, error) {
|
||||||
|
if _, errCA := os.Stat(ca); errCA != nil {
|
||||||
|
return []byte(ca), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
caContent, err := ioutil.ReadFile(ca)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return caContent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClientAuth(ca string, caOptional bool) tls.ClientAuthType {
|
||||||
|
if ca == "" {
|
||||||
|
return tls.NoClientCert
|
||||||
|
}
|
||||||
|
|
||||||
|
if caOptional {
|
||||||
|
return tls.VerifyClientCertIfGiven
|
||||||
|
}
|
||||||
|
return tls.RequireAndVerifyClientCert
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertificate(privateKey, certContent string) (tls.Certificate, error) {
|
||||||
|
if certContent == "" || privateKey == "" {
|
||||||
|
return tls.Certificate{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, errKeyIsFile := os.Stat(privateKey)
|
||||||
|
_, errCertIsFile := os.Stat(certContent)
|
||||||
|
|
||||||
|
if errCertIsFile == nil && os.IsNotExist(errKeyIsFile) {
|
||||||
|
return tls.Certificate{}, fmt.Errorf("tls cert is a file, but tls key is not")
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.IsNotExist(errCertIsFile) && errKeyIsFile == nil {
|
||||||
|
return tls.Certificate{}, fmt.Errorf("TLS key is a file, but tls cert is not")
|
||||||
|
}
|
||||||
|
|
||||||
|
// string
|
||||||
|
if os.IsNotExist(errCertIsFile) && os.IsNotExist(errKeyIsFile) {
|
||||||
|
return tls.X509KeyPair([]byte(certContent), []byte(privateKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
// files
|
||||||
|
if errCertIsFile == nil && errKeyIsFile == nil {
|
||||||
|
return tls.LoadX509KeyPair(certContent, privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errCertIsFile != nil {
|
||||||
|
return tls.Certificate{}, errCertIsFile
|
||||||
|
}
|
||||||
|
return tls.Certificate{}, errKeyIsFile
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,12 @@ Dump the content of a KV store.
|
|||||||
-h, --help help for kv
|
-h, --help help for kv
|
||||||
--password string Password for connection.
|
--password string Password for connection.
|
||||||
--prefix string Prefix used for KV store. (default "traefik")
|
--prefix string Prefix used for KV store. (default "traefik")
|
||||||
|
--tls Enable TLS encryption.
|
||||||
|
--tls.ca string Root CA for certificate verification if TLS is enabled
|
||||||
|
--tls.ca.optional
|
||||||
|
--tls.cert string TLS cert
|
||||||
|
--tls.insecureskipverify Trust unverified certificates if TLS is enabled.
|
||||||
|
--tls.key string TLS key
|
||||||
--username string Username for connection.
|
--username string Username for connection.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,12 @@ traefik-certs-dumper kv boltdb [flags]
|
|||||||
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
||||||
--password string Password for connection.
|
--password string Password for connection.
|
||||||
--prefix string Prefix used for KV store. (default "traefik")
|
--prefix string Prefix used for KV store. (default "traefik")
|
||||||
|
--tls Enable TLS encryption.
|
||||||
|
--tls.ca string Root CA for certificate verification if TLS is enabled
|
||||||
|
--tls.ca.optional
|
||||||
|
--tls.cert string TLS cert
|
||||||
|
--tls.insecureskipverify Trust unverified certificates if TLS is enabled.
|
||||||
|
--tls.key string TLS key
|
||||||
--username string Username for connection.
|
--username string Username for connection.
|
||||||
--watch Enable watching changes.
|
--watch Enable watching changes.
|
||||||
```
|
```
|
||||||
|
|||||||
@ -32,6 +32,12 @@ traefik-certs-dumper kv consul [flags]
|
|||||||
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
||||||
--password string Password for connection.
|
--password string Password for connection.
|
||||||
--prefix string Prefix used for KV store. (default "traefik")
|
--prefix string Prefix used for KV store. (default "traefik")
|
||||||
|
--tls Enable TLS encryption.
|
||||||
|
--tls.ca string Root CA for certificate verification if TLS is enabled
|
||||||
|
--tls.ca.optional
|
||||||
|
--tls.cert string TLS cert
|
||||||
|
--tls.insecureskipverify Trust unverified certificates if TLS is enabled.
|
||||||
|
--tls.key string TLS key
|
||||||
--username string Username for connection.
|
--username string Username for connection.
|
||||||
--watch Enable watching changes.
|
--watch Enable watching changes.
|
||||||
```
|
```
|
||||||
|
|||||||
@ -32,6 +32,12 @@ traefik-certs-dumper kv etcd [flags]
|
|||||||
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
||||||
--password string Password for connection.
|
--password string Password for connection.
|
||||||
--prefix string Prefix used for KV store. (default "traefik")
|
--prefix string Prefix used for KV store. (default "traefik")
|
||||||
|
--tls Enable TLS encryption.
|
||||||
|
--tls.ca string Root CA for certificate verification if TLS is enabled
|
||||||
|
--tls.ca.optional
|
||||||
|
--tls.cert string TLS cert
|
||||||
|
--tls.insecureskipverify Trust unverified certificates if TLS is enabled.
|
||||||
|
--tls.key string TLS key
|
||||||
--username string Username for connection.
|
--username string Username for connection.
|
||||||
--watch Enable watching changes.
|
--watch Enable watching changes.
|
||||||
```
|
```
|
||||||
|
|||||||
@ -31,6 +31,12 @@ traefik-certs-dumper kv zookeeper [flags]
|
|||||||
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
|
||||||
--password string Password for connection.
|
--password string Password for connection.
|
||||||
--prefix string Prefix used for KV store. (default "traefik")
|
--prefix string Prefix used for KV store. (default "traefik")
|
||||||
|
--tls Enable TLS encryption.
|
||||||
|
--tls.ca string Root CA for certificate verification if TLS is enabled
|
||||||
|
--tls.ca.optional
|
||||||
|
--tls.cert string TLS cert
|
||||||
|
--tls.insecureskipverify Trust unverified certificates if TLS is enabled.
|
||||||
|
--tls.key string TLS key
|
||||||
--username string Username for connection.
|
--username string Username for connection.
|
||||||
--watch Enable watching changes.
|
--watch Enable watching changes.
|
||||||
```
|
```
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user