Merge pull request #96502 from 249043822/br-hsts
Fix HSTS Missing From HTTPS Server(Nessus Scanner) Kubernetes-commit: 33518271f3f97733a52369713769746f78cc4f1a
This commit is contained in:
commit
f297286279
|
|
@ -696,7 +696,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery",
|
||||
"Rev": "6c16abd71758"
|
||||
"Rev": "1d8c923392f0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go",
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -42,7 +42,7 @@ require (
|
|||
gopkg.in/square/go-jose.v2 v2.2.2
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
k8s.io/api v0.0.0-20210111205846-1198ffc40d00
|
||||
k8s.io/apimachinery v0.0.0-20210106165743-6c16abd71758
|
||||
k8s.io/apimachinery v0.0.0-20210112230657-1d8c923392f0
|
||||
k8s.io/client-go v0.0.0-20210112050101-623741e9c1d5
|
||||
k8s.io/component-base v0.0.0-20201217090229-e05af43f81e2
|
||||
k8s.io/klog/v2 v2.4.0
|
||||
|
|
@ -55,7 +55,7 @@ require (
|
|||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20210111205846-1198ffc40d00
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210106165743-6c16abd71758
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210112230657-1d8c923392f0
|
||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20210112050101-623741e9c1d5
|
||||
k8s.io/component-base => k8s.io/component-base v0.0.0-20201217090229-e05af43f81e2
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -600,7 +600,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.0.0-20210111205846-1198ffc40d00/go.mod h1:3Xl3BjPKHhLlv0+0TYKMZ8NNiKsby57AFDZIBy5Rv0o=
|
||||
k8s.io/apimachinery v0.0.0-20210106165743-6c16abd71758/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apimachinery v0.0.0-20210112230657-1d8c923392f0/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/client-go v0.0.0-20210112050101-623741e9c1d5/go.mod h1:A+8YeKeA6UyKSBUSUFFZ9Mzc+Kb7ETfGvFHLZ31zNhM=
|
||||
k8s.io/component-base v0.0.0-20201217090229-e05af43f81e2/go.mod h1:gIi+MRY/IzqtOlI456xyiW/eLgJnlivhxgZIlG3ueCQ=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ type Config struct {
|
|||
// to set values and determine whether its allowed
|
||||
AdmissionControl admission.Interface
|
||||
CorsAllowedOriginList []string
|
||||
|
||||
HSTSDirectives []string
|
||||
// FlowControl, if not nil, gives priority and fairness to request handling
|
||||
FlowControl utilflowcontrol.Interface
|
||||
|
||||
|
|
@ -755,6 +755,7 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
|||
handler = genericapifilters.WithAuditAnnotations(handler, c.AuditBackend, c.AuditPolicyChecker)
|
||||
handler = genericapifilters.WithWarningRecorder(handler)
|
||||
handler = genericapifilters.WithCacheControl(handler)
|
||||
handler = genericfilters.WithHSTS(handler, c.HSTSDirectives)
|
||||
handler = genericapifilters.WithRequestReceivedTimestamp(handler)
|
||||
handler = genericfilters.WithPanicRecovery(handler, c.RequestInfoResolver)
|
||||
return handler
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package filters
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WithHSTS is a simple HSTS implementation that wraps an http Handler.
|
||||
// If hstsDirectives is empty or nil, no HSTS support is installed.
|
||||
func WithHSTS(handler http.Handler, hstsDirectives []string) http.Handler {
|
||||
if len(hstsDirectives) == 0 {
|
||||
return handler
|
||||
}
|
||||
allDirectives := strings.Join(hstsDirectives, "; ")
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
// Chrome and Mozilla Firefox maintain an HSTS preload list
|
||||
// issue : golang.org/issue/26162
|
||||
// Set the Strict-Transport-Security header if it is not already set
|
||||
if _, ok := w.Header()["Strict-Transport-Security"]; !ok {
|
||||
w.Header().Set("Strict-Transport-Security", allDirectives)
|
||||
}
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
}
|
||||
|
|
@ -19,10 +19,12 @@ package options
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
|
||||
|
|
@ -34,6 +36,7 @@ type ServerRunOptions struct {
|
|||
AdvertiseAddress net.IP
|
||||
|
||||
CorsAllowedOriginList []string
|
||||
HSTSDirectives []string
|
||||
ExternalHost string
|
||||
MaxRequestsInFlight int
|
||||
MaxMutatingRequestsInFlight int
|
||||
|
|
@ -71,6 +74,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||
// ApplyTo applies the run options to the method receiver and returns self
|
||||
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
||||
c.CorsAllowedOriginList = s.CorsAllowedOriginList
|
||||
c.HSTSDirectives = s.HSTSDirectives
|
||||
c.ExternalAddress = s.ExternalHost
|
||||
c.MaxRequestsInFlight = s.MaxRequestsInFlight
|
||||
c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
|
||||
|
|
@ -143,9 +147,31 @@ func (s *ServerRunOptions) Validate() []error {
|
|||
errors = append(errors, fmt.Errorf("--max-resource-write-bytes can not be negative value"))
|
||||
}
|
||||
|
||||
if err := validateHSTSDirectives(s.HSTSDirectives); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
func validateHSTSDirectives(hstsDirectives []string) error {
|
||||
// HSTS Headers format: Strict-Transport-Security:max-age=expireTime [;includeSubDomains] [;preload]
|
||||
// See https://tools.ietf.org/html/rfc6797#section-6.1 for more information
|
||||
allErrors := []error{}
|
||||
for _, hstsDirective := range hstsDirectives {
|
||||
if len(strings.TrimSpace(hstsDirective)) == 0 {
|
||||
allErrors = append(allErrors, fmt.Errorf("empty value in strict-transport-security-directives"))
|
||||
continue
|
||||
}
|
||||
if hstsDirective != "includeSubDomains" && hstsDirective != "preload" {
|
||||
maxAgeDirective := strings.Split(hstsDirective, "=")
|
||||
if len(maxAgeDirective) != 2 || maxAgeDirective[0] != "max-age" {
|
||||
allErrors = append(allErrors, fmt.Errorf("--strict-transport-security-directives invalid, allowed values: max-age=expireTime, includeSubDomains, preload. see https://tools.ietf.org/html/rfc6797#section-6.1 for more information"))
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.NewAggregate(allErrors)
|
||||
}
|
||||
|
||||
// AddUniversalFlags adds flags for a specific APIServer to the specified FlagSet
|
||||
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
||||
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
|
||||
|
|
@ -161,6 +187,10 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||
"List of allowed origins for CORS, comma separated. An allowed origin can be a regular "+
|
||||
"expression to support subdomain matching. If this list is empty CORS will not be enabled.")
|
||||
|
||||
fs.StringSliceVar(&s.HSTSDirectives, "strict-transport-security-directives", s.HSTSDirectives, ""+
|
||||
"List of directives for HSTS, comma separated. If this list is empty, then HSTS directives will not "+
|
||||
"be added. Example: 'max-age=31536000,includeSubDomains,preload'")
|
||||
|
||||
deprecatedTargetRAMMB := 0
|
||||
fs.IntVar(&deprecatedTargetRAMMB, "target-ram-mb", deprecatedTargetRAMMB,
|
||||
"DEPRECATED: Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
|
||||
|
|
|
|||
|
|
@ -145,11 +145,27 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
|||
},
|
||||
expectErr: "--shutdown-delay-duration can not be negative value",
|
||||
},
|
||||
{
|
||||
name: "Test when HSTSHeaders is valid",
|
||||
testOptions: &ServerRunOptions{
|
||||
AdvertiseAddress: net.ParseIP("192.168.10.10"),
|
||||
CorsAllowedOriginList: []string{"10.10.10.100", "10.10.10.200"},
|
||||
HSTSDirectives: []string{"fakevalue", "includeSubDomains", "preload"},
|
||||
MaxRequestsInFlight: 400,
|
||||
MaxMutatingRequestsInFlight: 200,
|
||||
RequestTimeout: time.Duration(2) * time.Minute,
|
||||
MinRequestTimeout: 1800,
|
||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||
},
|
||||
expectErr: "--strict-transport-security-directives invalid, allowed values: max-age=expireTime, includeSubDomains, preload. see https://tools.ietf.org/html/rfc6797#section-6.1 for more information",
|
||||
},
|
||||
{
|
||||
name: "Test when ServerRunOptions is valid",
|
||||
testOptions: &ServerRunOptions{
|
||||
AdvertiseAddress: net.ParseIP("192.168.10.10"),
|
||||
CorsAllowedOriginList: []string{"10.10.10.100", "10.10.10.200"},
|
||||
HSTSDirectives: []string{"max-age=31536000", "includeSubDomains", "preload"},
|
||||
MaxRequestsInFlight: 400,
|
||||
MaxMutatingRequestsInFlight: 200,
|
||||
RequestTimeout: time.Duration(2) * time.Minute,
|
||||
|
|
|
|||
Loading…
Reference in New Issue