Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tls: add cipher flag #9216

Closed
wants to merge 5 commits into from
Closed

Conversation

ThatsMrTalbot
Copy link

WIP implementation of TLS Cyphers flags (#8320)

This adds a new flag to the client and server specifying what tls cypher suites to enable, if not set then the full set will be available

It currently only seems to work when the TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 cipher suite is provided. If it isn't in the list then I get an error in the etcd logs (see below) and openssl s_client -connect 127.0.0.1:2379 -tls1_2 refuses to connect

Error from etcd logs when TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 is not provided:

Failed to dial 0.0.0.0:2379: connection error: desc = "transport: authentication handshake failed: remote error: tls: handshake failure"; please retry.

Any insight would be appreciated

@gyuho
Copy link
Contributor

gyuho commented Jan 24, 2018

@dvonthenen Could you help review this? Thanks!

@dvonthenen
Copy link

@gyuho sure thing!

@@ -167,16 +170,24 @@ func getTransport(c *cli.Context) (*http.Transport, error) {
if keyfile == "" {
keyfile = os.Getenv("ETCDCTL_KEY_FILE")
}
if insecureSkipVerify == false {
insecureSkipVerify = os.Getenv("ETCDCTL_INSECURE_SKIP_TLS_VERIFY") != ""

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be something to the effect of insecureSkipVerify = strings.EqualFold(os.Getenv("ETCDCTL_INSECURE_SKIP_TLS_VERIFY"), "TRUE"). Anything that doesn't match "true" from the ENV VAR is considered implicitly false.

@dvonthenen
Copy link

dvonthenen commented Jan 30, 2018

@ThatsMrTalbot In reference to only working with TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, I guess that would depend on the version of OpenSSL you are using and the supported cipher suites that are mutually shared between the server and client.

I did test setting a single arbitrary shared cipher between etcd and etcdctl (in my test case TLS_RSA_WITH_AES_256_GCM_SHA384) and it seemed to work just fine.

Just a quick look at OpenSSL latest using the -tls1_2 option, the only mutual ones are (the one with the [ ] is the one you noted works) again this depends on the version you are using:

  • TLS_RSA_WITH_AES_128_CBC_SHA256 AES128-SHA256
  • TLS_RSA_WITH_AES_128_GCM_SHA256 AES128-GCM-SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384 AES256-GCM-SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ECDHE-RSA-AES128-SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ECDHE-RSA-AES128-GCM-SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ECDHE-RSA-AES256-GCM-SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ECDHE-ECDSA-AES128-SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ECDHE-ECDSA-AES128-GCM-SHA256
  • [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ECDHE-ECDSA-AES256-GCM-SHA384]

cli.GenericFlag{Name: "cipher-suites",
Value: flags.NewStringSliceFlag(tlsutil.AvailableCipherSuites()...),
Usage: "Comma-separated list of cipher suites for the server. " +
"Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). " +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest enumerating the values in AvailableCipherSuites() rather than referencing godoc

@@ -54,6 +56,12 @@ func Start(apiv string) {
cli.StringFlag{Name: "cert-file", Value: "", Usage: "identify HTTPS client using this SSL certificate file"},
cli.StringFlag{Name: "key-file", Value: "", Usage: "identify HTTPS client using this SSL key file"},
cli.StringFlag{Name: "ca-file", Value: "", Usage: "verify certificates of HTTPS-enabled servers using this CA bundle"},
cli.BoolFlag{Name: "insecure-skip-tls-verify", Usage: "skip server certificate verification"},
cli.GenericFlag{Name: "cipher-suites",
Value: flags.NewStringSliceFlag(tlsutil.AvailableCipherSuites()...),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean AvailableCipherSuites() is the default value? I didn't think all available ciphers were included in the default set in go

Copy link
Author

@ThatsMrTalbot ThatsMrTalbot Feb 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used to validate the provided list, but the default value is still a nil slice (which is what is currently used)

@@ -155,6 +156,8 @@ func getTransport(c *cli.Context) (*http.Transport, error) {
cafile := c.GlobalString("ca-file")
certfile := c.GlobalString("cert-file")
keyfile := c.GlobalString("key-file")
insecureSkipVerify := c.GlobalBool("insecure-skip-tls-verify")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this in this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, would like this removed

@@ -55,6 +58,12 @@ func Start(apiv string) {
cli.StringFlag{Name: "cert-file", Value: "", Usage: "identify HTTPS client using this SSL certificate file"},
cli.StringFlag{Name: "key-file", Value: "", Usage: "identify HTTPS client using this SSL key file"},
cli.StringFlag{Name: "ca-file", Value: "", Usage: "verify certificates of HTTPS-enabled servers using this CA bundle"},
cli.BoolFlag{Name: "insecure-skip-tls-verify", Usage: "skip server certificate verification"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this in this PR? or it can be separated to another one?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to make local testing easier, can break it out if you want

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea. please break it out.

@@ -63,6 +65,9 @@ func init() {
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
rootCmd.PersistentFlags().StringSliceVar(&globalFlags.TLS.CipherSuites, "cipher-suites", nil, "comma-separated list of cipher suites for the server. "+
"Available cipher suites include "+strings.Join(tlsutil.AvailableCipherSuites(), ",")+". "+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: join with ", " so text can wrap

@@ -158,6 +160,8 @@ security flags:
peer TLS using self-generated certificates if --peer-key-file and --peer-cert-file are not provided.
--peer-crl-file ''
path to the peer certificate revocation list file.
--cipher-suites ''
comma-separated list of cipher suites for the server. Available cipher suites include ` + strings.Join(tlsutil.AvailableCipherSuites(), ",") + `. If omitted, the default Go cipher suites will be used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

", "


// StringSliceFlag implements the flag.Value and pflag.Value interfaces.
type StringSliceFlag struct {
Values []string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a confusing name, maybe ValidValues instead?


// NewStringSliceFlag creates a new string slice flag for which any one of the given
// strings is a valid value, and any other value is an error.
func NewStringSliceFlag(valids ...string) *StringSliceFlag {
Copy link
Contributor

@liggitt liggitt Apr 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest giving separate control over valid values and default value(s), instead of assuming []string{}

return c
}

func TLSCipherSuites(cipherNames []string) ([]uint16, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest a test like https://github.com/kubernetes/kubernetes/pull/48859/files#diff-4deda4b18dd1fb07896598924e440970R77 to make sure this doesn't drift or lag golang supported ciphers

@gyuho
Copy link
Contributor

gyuho commented Jun 4, 2018

Default should be empty, and let Go populate the list with prioritized ordering.
Closing in favor of #9801.

@gyuho gyuho closed this Jun 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

6 participants