Skip to content

Commit e8638ae

Browse files
committed
Donot serve certificate content for Non-SSL routes
By default, when a host does not resolve to a route in a HTTPS or tls sni request, the default cert is returned to the caller as part of the 503 response. This exposes the default cert and may pose security concerns. Haproxy strict-sni option to bind suppresses use of the default cert. This adds a new environment variable to the router deployment controller, ROUTER_STRICT_SNI, to control bind processing. When set to "true" or "TRUE", "strict-sni" is added to the bind. Default is "false". oc adm router --strict-sni sets ROUTER_STRICT_SNI="true" bug 1369865 https://bugzilla.redhat.com/show_bug.cgi?id=1369865
1 parent 653b218 commit e8638ae

File tree

11 files changed

+37
-1
lines changed

11 files changed

+37
-1
lines changed

contrib/completions/bash/oadm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4856,6 +4856,8 @@ _oadm_router()
48564856
local_nonpersistent_flags+=("--stats-port=")
48574857
flags+=("--stats-user=")
48584858
local_nonpersistent_flags+=("--stats-user=")
4859+
flags+=("--strict-sni")
4860+
local_nonpersistent_flags+=("--strict-sni")
48594861
flags+=("--subdomain=")
48604862
local_nonpersistent_flags+=("--subdomain=")
48614863
flags+=("--type=")

contrib/completions/bash/oc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4857,6 +4857,8 @@ _oc_adm_router()
48574857
local_nonpersistent_flags+=("--stats-port=")
48584858
flags+=("--stats-user=")
48594859
local_nonpersistent_flags+=("--stats-user=")
4860+
flags+=("--strict-sni")
4861+
local_nonpersistent_flags+=("--strict-sni")
48604862
flags+=("--subdomain=")
48614863
local_nonpersistent_flags+=("--subdomain=")
48624864
flags+=("--type=")

contrib/completions/bash/openshift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4856,6 +4856,8 @@ _openshift_admin_router()
48564856
local_nonpersistent_flags+=("--stats-port=")
48574857
flags+=("--stats-user=")
48584858
local_nonpersistent_flags+=("--stats-user=")
4859+
flags+=("--strict-sni")
4860+
local_nonpersistent_flags+=("--strict-sni")
48594861
flags+=("--subdomain=")
48604862
local_nonpersistent_flags+=("--subdomain=")
48614863
flags+=("--type=")
@@ -10035,6 +10037,8 @@ _openshift_cli_adm_router()
1003510037
local_nonpersistent_flags+=("--stats-port=")
1003610038
flags+=("--stats-user=")
1003710039
local_nonpersistent_flags+=("--stats-user=")
10040+
flags+=("--strict-sni")
10041+
local_nonpersistent_flags+=("--strict-sni")
1003810042
flags+=("--subdomain=")
1003910043
local_nonpersistent_flags+=("--subdomain=")
1004010044
flags+=("--type=")
@@ -23380,6 +23384,8 @@ _openshift_infra_router()
2338023384
local_nonpersistent_flags+=("--stats-port=")
2338123385
flags+=("--stats-user=")
2338223386
local_nonpersistent_flags+=("--stats-user=")
23387+
flags+=("--strict-sni")
23388+
local_nonpersistent_flags+=("--strict-sni")
2338323389
flags+=("--template=")
2338423390
local_nonpersistent_flags+=("--template=")
2338523391
flags+=("--token=")

contrib/completions/zsh/oadm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,6 +5005,8 @@ _oadm_router()
50055005
local_nonpersistent_flags+=("--stats-port=")
50065006
flags+=("--stats-user=")
50075007
local_nonpersistent_flags+=("--stats-user=")
5008+
flags+=("--strict-sni")
5009+
local_nonpersistent_flags+=("--strict-sni")
50085010
flags+=("--subdomain=")
50095011
local_nonpersistent_flags+=("--subdomain=")
50105012
flags+=("--type=")

contrib/completions/zsh/oc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5006,6 +5006,8 @@ _oc_adm_router()
50065006
local_nonpersistent_flags+=("--stats-port=")
50075007
flags+=("--stats-user=")
50085008
local_nonpersistent_flags+=("--stats-user=")
5009+
flags+=("--strict-sni")
5010+
local_nonpersistent_flags+=("--strict-sni")
50095011
flags+=("--subdomain=")
50105012
local_nonpersistent_flags+=("--subdomain=")
50115013
flags+=("--type=")

contrib/completions/zsh/openshift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,6 +5005,8 @@ _openshift_admin_router()
50055005
local_nonpersistent_flags+=("--stats-port=")
50065006
flags+=("--stats-user=")
50075007
local_nonpersistent_flags+=("--stats-user=")
5008+
flags+=("--strict-sni")
5009+
local_nonpersistent_flags+=("--strict-sni")
50085010
flags+=("--subdomain=")
50095011
local_nonpersistent_flags+=("--subdomain=")
50105012
flags+=("--type=")
@@ -10184,6 +10186,8 @@ _openshift_cli_adm_router()
1018410186
local_nonpersistent_flags+=("--stats-port=")
1018510187
flags+=("--stats-user=")
1018610188
local_nonpersistent_flags+=("--stats-user=")
10189+
flags+=("--strict-sni")
10190+
local_nonpersistent_flags+=("--strict-sni")
1018710191
flags+=("--subdomain=")
1018810192
local_nonpersistent_flags+=("--subdomain=")
1018910193
flags+=("--type=")
@@ -23529,6 +23533,8 @@ _openshift_infra_router()
2352923533
local_nonpersistent_flags+=("--stats-port=")
2353023534
flags+=("--stats-user=")
2353123535
local_nonpersistent_flags+=("--stats-user=")
23536+
flags+=("--strict-sni")
23537+
local_nonpersistent_flags+=("--strict-sni")
2353223538
flags+=("--template=")
2353323539
local_nonpersistent_flags+=("--template=")
2353423540
flags+=("--token=")

images/router/haproxy/conf/haproxy-config.template

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,10 @@ backend be_sni
204204

205205
frontend fe_sni
206206
# terminate ssl on edge
207-
bind 127.0.0.1:{{env "ROUTER_SERVICE_SNI_PORT" "10444"}} ssl no-sslv3 {{ if gt (len .DefaultCertificate) 0 }}crt {{.DefaultCertificate}}{{ else }}crt /var/lib/haproxy/conf/default_pub_keys.pem{{ end }} crt-list /var/lib/haproxy/conf/cert_config.map accept-proxy
207+
bind 127.0.0.1:{{env "ROUTER_SERVICE_SNI_PORT" "10444"}} ssl no-sslv3
208+
{{- if matchPattern "true|TRUE" (env "ROUTER_STRICT_SNI" "") }} strict-sni {{ end }}
209+
{{- if gt (len .DefaultCertificate) 0 }} crt {{.DefaultCertificate}}{{ else }} crt /var/lib/haproxy/conf/default_pub_keys.pem{{ end }}
210+
{{- ""}} crt-list /var/lib/haproxy/conf/cert_config.map accept-proxy
208211
mode http
209212

210213
# check re-encrypt backends first - from most specific to general path.

pkg/cmd/admin/router/router.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ type RouterConfig struct {
230230
// Ciphers is the set of ciphers to use with bind
231231
// modern | intermediate | old | set of cihers
232232
Ciphers string
233+
234+
// Strict SNI (do not use default cert)
235+
StrictSNI bool
233236
}
234237

235238
const (
@@ -310,6 +313,7 @@ func NewCmdRouter(f *clientcmd.Factory, parentName, name string, out, errout io.
310313
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.")
311314
cmd.Flags().StringVar(&cfg.MaxConnections, "max-connections", cfg.MaxConnections, "Specifies the maximum number of concurrent connections. Not supported for F5.")
312315
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.")
316+
cmd.Flags().BoolVar(&cfg.StrictSNI, "strict-sni", cfg.StrictSNI, "Use strict-sni bind processing (do not use default cert). Not supported for F5.")
313317

314318
cfg.Action.BindForOutput(cmd.Flags())
315319
cmd.Flags().String("output-version", "", "The preferred API versions of the output objects")
@@ -664,6 +668,9 @@ func RunCmdRouter(f *clientcmd.Factory, cmd *cobra.Command, out, errout io.Write
664668
if cfg.DisableNamespaceOwnershipCheck {
665669
env["ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK"] = "true"
666670
}
671+
if cfg.StrictSNI {
672+
env["ROUTER_STRICT_SNI"] = "true"
673+
}
667674
if len(cfg.RouterCanonicalHostname) > 0 {
668675
if errs := validation.IsDNS1123Subdomain(cfg.RouterCanonicalHostname); len(errs) != 0 {
669676
return fmt.Errorf("invalid canonical hostname (RFC 1123): %s", cfg.RouterCanonicalHostname)

pkg/cmd/infra/router/template.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type TemplateRouter struct {
7272
BindPortsAfterSync bool
7373
MaxConnections string
7474
Ciphers string
75+
StrictSNI bool
7576
MetricsType string
7677
}
7778

@@ -102,6 +103,7 @@ func (o *TemplateRouter) Bind(flag *pflag.FlagSet) {
102103
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")
103104
flag.StringVar(&o.MaxConnections, "max-connections", util.Env("ROUTER_MAX_CONNECTIONS", ""), "Specifies the maximum number of concurrent connections.")
104105
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.")
106+
flag.BoolVar(&o.StrictSNI, "strict-sni", util.Env("ROUTER_STRICT_SNI", "") == "true", "Use strict-sni bind processing (do not use default cert).")
105107
flag.StringVar(&o.MetricsType, "metrics-type", util.Env("ROUTER_METRICS_TYPE", ""), "Specifies the type of metrics to gather. Supports 'haproxy'.")
106108
}
107109

@@ -302,6 +304,7 @@ func (o *TemplateRouterOptions) Run() error {
302304
AllowWildcardRoutes: o.RouterSelection.AllowWildcardRoutes,
303305
MaxConnections: o.MaxConnections,
304306
Ciphers: o.Ciphers,
307+
StrictSNI: o.StrictSNI,
305308
}
306309

307310
oc, kc, err := o.Config.Clients()

pkg/router/template/plugin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type TemplatePluginConfig struct {
5555
BindPortsAfterSync bool
5656
MaxConnections string
5757
Ciphers string
58+
StrictSNI bool
5859
}
5960

6061
// routerInterface controls the interaction of the plugin with the underlying router implementation

test/cmd/router.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ os::cmd::expect_failure_and_text 'oadm router --dry-run --host-network=false --h
4444
os::cmd::expect_success_and_text 'oadm router --dry-run --host-network=false --host-ports=false --max-connections=14583 -o yaml' '14583'
4545
# ciphers
4646
os::cmd::expect_success_and_text 'oadm router --dry-run --host-network=false --host-ports=false --ciphers=modern -o yaml' 'modern'
47+
# strict-sni
48+
os::cmd::expect_success_and_text 'oadm router --dry-run --host-network=false --host-ports=false --strict-sni -o yaml' 'ROUTER_STRICT_SNI'
4749

4850
# mount tls crt as secret
4951
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'

0 commit comments

Comments
 (0)