mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Merge pull request #96502 from 249043822/br-hsts
Fix HSTS Missing From HTTPS Server(Nessus Scanner)
This commit is contained in:
commit
33518271f3
@ -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
|
||||
|
@ -54,6 +54,7 @@ go_library(
|
||||
"cors.go",
|
||||
"doc.go",
|
||||
"goaway.go",
|
||||
"hsts.go",
|
||||
"longrunning.go",
|
||||
"maxinflight.go",
|
||||
"priority-and-fairness.go",
|
||||
|
40
staging/src/k8s.io/apiserver/pkg/server/filters/hsts.go
Normal file
40
staging/src/k8s.io/apiserver/pkg/server/filters/hsts.go
Normal file
@ -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
Block a user