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

Allow specifying haproxy SSL Cipher list #14505

Merged
merged 2 commits into from
Jun 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions contrib/completions/bash/oadm
Original file line number Diff line number Diff line change
Expand Up @@ -4739,6 +4739,8 @@ _oadm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/bash/oc
Original file line number Diff line number Diff line change
Expand Up @@ -4742,6 +4742,8 @@ _oc_adm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down
6 changes: 6 additions & 0 deletions contrib/completions/bash/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -4739,6 +4739,8 @@ _openshift_admin_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down Expand Up @@ -9870,6 +9872,8 @@ _openshift_cli_adm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down Expand Up @@ -23201,6 +23205,8 @@ _openshift_infra_router()
flags_with_completion+=("--certificate-authority")
flags_completion+=("_filedir")
local_nonpersistent_flags+=("--certificate-authority=")
flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--client-certificate=")
flags_with_completion+=("--client-certificate")
flags_completion+=("_filedir")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/zsh/oadm
Original file line number Diff line number Diff line change
Expand Up @@ -4888,6 +4888,8 @@ _oadm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/zsh/oc
Original file line number Diff line number Diff line change
Expand Up @@ -4891,6 +4891,8 @@ _oc_adm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down
6 changes: 6 additions & 0 deletions contrib/completions/zsh/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -4888,6 +4888,8 @@ _openshift_admin_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down Expand Up @@ -10019,6 +10021,8 @@ _openshift_cli_adm_router()
flags_with_completion=()
flags_completion=()

flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--create")
local_nonpersistent_flags+=("--create")
flags+=("--default-cert=")
Expand Down Expand Up @@ -23350,6 +23354,8 @@ _openshift_infra_router()
flags_with_completion+=("--certificate-authority")
flags_completion+=("_filedir")
local_nonpersistent_flags+=("--certificate-authority=")
flags+=("--ciphers=")
local_nonpersistent_flags+=("--ciphers=")
flags+=("--client-certificate=")
flags_with_completion+=("--client-certificate")
flags_completion+=("_filedir")
Expand Down
28 changes: 23 additions & 5 deletions images/router/haproxy/conf/haproxy-config.template
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,35 @@ global
# TODO: use when 1.5.14 is available
# ssl-default-bind-options no-sslv3

# The default cipher suite can be selected from the three sets recommended by https://wiki.mozilla.org/Security/Server_Side_TLS,
# or the user can provide one using the ROUTER_CIPHERS environment variable.
# By default when a cipher set is not provided, intermediate is used.
{{- if eq (env "ROUTER_CIPHERS" "intermediate") "modern" }}
# Modern cipher suite (no legacy browser support) from https://wiki.mozilla.org/Security/Server_Side_TLS
# tune.ssl.default-dh-param 2048
# ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
{{ else }}

{{- if eq (env "ROUTER_CIPHERS" "intermediate") "intermediate" }}
# Intermediate cipher suite (default) from https://wiki.mozilla.org/Security/Server_Side_TLS
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
ssl-default-bind-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
{{ else }}

{{- if eq (env "ROUTER_CIPHERS" "intermediate") "old" }}

# Old cipher suite (maximum compatibility but insecure) from https://wiki.mozilla.org/Security/Server_Side_TLS
# tune.ssl.default-dh-param 1024
# ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
tune.ssl.default-dh-param 1024
ssl-default-bind-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP

{{- else }}
# user provided list of ciphers (Colon separated list as seen above)
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth noting in the comment that the env here can never use the default since if they had not passed one, then the default of "intermediate" would have been used already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

# the env default is not used here since we can't get here with empty ROUTER_CIPHERS
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers {{env "ROUTER_CIPHERS" "ECDHE-ECDSA-CHACHA20-POLY1305"}}
{{- end }}
{{- end }}
{{- end }}

defaults
maxconn {{env "ROUTER_MAX_CONNECTIONS" "20000"}}
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/admin/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ type RouterConfig struct {
// MetricsImage is the image to run a sidecar container with in the router
// pod.
MetricsImage string

// Ciphers is the set of ciphers to use with bind
// modern | intermediate | old | set of cihers
Ciphers string
}

const (
Expand Down Expand Up @@ -305,6 +309,7 @@ func NewCmdRouter(f *clientcmd.Factory, parentName, name string, out, errout io.
cmd.Flags().StringVar(&cfg.ExternalHostPartitionPath, "external-host-partition-path", cfg.ExternalHostPartitionPath, "If the underlying router implementation uses partitions for control boundaries, this is the path to use for that partition.")
cmd.Flags().BoolVar(&cfg.DisableNamespaceOwnershipCheck, "disable-namespace-ownership-check", cfg.DisableNamespaceOwnershipCheck, "Disables the namespace ownership check and allows different namespaces to claim either different paths to a route host or overlapping host names in case of a wildcard route. The default behavior (false) to restrict claims to the oldest namespace that has claimed either the host or the subdomain. Please be aware that if namespace ownership checks are disabled, routes in a different namespace can use this mechanism to 'steal' sub-paths for existing domains. This is only safe if route creation privileges are restricted, or if all the users can be trusted.")
cmd.Flags().StringVar(&cfg.MaxConnections, "max-connections", cfg.MaxConnections, "Specifies the maximum number of concurrent connections. Not supported for F5.")
cmd.Flags().StringVar(&cfg.Ciphers, "ciphers", cfg.Ciphers, "Specifies the cipher suites to use. You can choose a predefined cipher set ('modern', 'intermediate', or 'old') or specify exact cipher suites by passing a : separated list. Not supported for F5.")

cfg.Action.BindForOutput(cmd.Flags())
cmd.Flags().String("output-version", "", "The preferred API versions of the output objects")
Expand Down Expand Up @@ -644,6 +649,7 @@ func RunCmdRouter(f *clientcmd.Factory, cmd *cobra.Command, out, errout io.Write
"ROUTER_EXTERNAL_HOST_PRIVKEY": privkeyPath,
"ROUTER_EXTERNAL_HOST_INTERNAL_ADDRESS": cfg.ExternalHostInternalIP,
"ROUTER_EXTERNAL_HOST_VXLAN_GW_CIDR": cfg.ExternalHostVxLANGateway,
"ROUTER_CIPHERS": cfg.Ciphers,
"STATS_PORT": strconv.Itoa(cfg.StatsPort),
"STATS_USERNAME": cfg.StatsUsername,
"STATS_PASSWORD": cfg.StatsPassword,
Expand Down
3 changes: 3 additions & 0 deletions pkg/cmd/infra/router/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type TemplateRouter struct {
RouterService *ktypes.NamespacedName
BindPortsAfterSync bool
MaxConnections string
Ciphers string
MetricsType string
}

Expand Down Expand Up @@ -100,6 +101,7 @@ func (o *TemplateRouter) Bind(flag *pflag.FlagSet) {
flag.BoolVar(&o.ExtendedValidation, "extended-validation", util.Env("EXTENDED_VALIDATION", "true") == "true", "If set, then an additional extended validation step is performed on all routes admitted in by this router. Defaults to true and enables the extended validation checks.")
flag.BoolVar(&o.BindPortsAfterSync, "bind-ports-after-sync", util.Env("ROUTER_BIND_PORTS_AFTER_SYNC", "") == "true", "Bind ports only after route state has been synchronized")
flag.StringVar(&o.MaxConnections, "max-connections", util.Env("ROUTER_MAX_CONNECTIONS", ""), "Specifies the maximum number of concurrent connections.")
flag.StringVar(&o.Ciphers, "ciphers", util.Env("ROUTER_CIPHERS", ""), "Specifies the cipher suites to use. You can choose a predefined cipher set ('modern', 'intermediate', or 'old') or specify exact cipher suites by passing a : separated list.")
flag.StringVar(&o.MetricsType, "metrics-type", util.Env("ROUTER_METRICS_TYPE", ""), "Specifies the type of metrics to gather. Supports 'haproxy'.")
}

Expand Down Expand Up @@ -299,6 +301,7 @@ func (o *TemplateRouterOptions) Run() error {
IncludeUDP: o.RouterSelection.IncludeUDP,
AllowWildcardRoutes: o.RouterSelection.AllowWildcardRoutes,
MaxConnections: o.MaxConnections,
Ciphers: o.Ciphers,
}

oc, kc, err := o.Config.Clients()
Expand Down
1 change: 1 addition & 0 deletions pkg/router/template/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type TemplatePluginConfig struct {
PeerService *ktypes.NamespacedName
BindPortsAfterSync bool
MaxConnections string
Ciphers string
}

// routerInterface controls the interaction of the plugin with the underlying router implementation
Expand Down
2 changes: 2 additions & 0 deletions test/cmd/router.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ os::cmd::expect_failure_and_text 'oadm router --dry-run --host-network=false --h
os::cmd::expect_failure_and_text 'oadm router --dry-run --host-network=false --host-ports=false --router-canonical-hostname=1.2.3.4 -o yaml' 'error: canonical hostname must not be an IP address'
# max_conn
os::cmd::expect_success_and_text 'oadm router --dry-run --host-network=false --host-ports=false --max-connections=14583 -o yaml' '14583'
# ciphers
os::cmd::expect_success_and_text 'oadm router --dry-run --host-network=false --host-ports=false --ciphers=modern -o yaml' 'modern'

# mount tls crt as secret
os::cmd::expect_success_and_not_text 'oadm router --dry-run --host-network=false --host-ports=false -o yaml' 'value: /etc/pki/tls/private/tls.crt'
Expand Down