mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +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
|
// to set values and determine whether its allowed
|
||||||
AdmissionControl admission.Interface
|
AdmissionControl admission.Interface
|
||||||
CorsAllowedOriginList []string
|
CorsAllowedOriginList []string
|
||||||
|
HSTSDirectives []string
|
||||||
// FlowControl, if not nil, gives priority and fairness to request handling
|
// FlowControl, if not nil, gives priority and fairness to request handling
|
||||||
FlowControl utilflowcontrol.Interface
|
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.WithAuditAnnotations(handler, c.AuditBackend, c.AuditPolicyChecker)
|
||||||
handler = genericapifilters.WithWarningRecorder(handler)
|
handler = genericapifilters.WithWarningRecorder(handler)
|
||||||
handler = genericapifilters.WithCacheControl(handler)
|
handler = genericapifilters.WithCacheControl(handler)
|
||||||
|
handler = genericfilters.WithHSTS(handler, c.HSTSDirectives)
|
||||||
handler = genericapifilters.WithRequestReceivedTimestamp(handler)
|
handler = genericapifilters.WithRequestReceivedTimestamp(handler)
|
||||||
handler = genericfilters.WithPanicRecovery(handler, c.RequestInfoResolver)
|
handler = genericfilters.WithPanicRecovery(handler, c.RequestInfoResolver)
|
||||||
return handler
|
return handler
|
||||||
|
@ -54,6 +54,7 @@ go_library(
|
|||||||
"cors.go",
|
"cors.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"goaway.go",
|
"goaway.go",
|
||||||
|
"hsts.go",
|
||||||
"longrunning.go",
|
"longrunning.go",
|
||||||
"maxinflight.go",
|
"maxinflight.go",
|
||||||
"priority-and-fairness.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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apiserver/pkg/server"
|
"k8s.io/apiserver/pkg/server"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
|
||||||
@ -34,6 +36,7 @@ type ServerRunOptions struct {
|
|||||||
AdvertiseAddress net.IP
|
AdvertiseAddress net.IP
|
||||||
|
|
||||||
CorsAllowedOriginList []string
|
CorsAllowedOriginList []string
|
||||||
|
HSTSDirectives []string
|
||||||
ExternalHost string
|
ExternalHost string
|
||||||
MaxRequestsInFlight int
|
MaxRequestsInFlight int
|
||||||
MaxMutatingRequestsInFlight int
|
MaxMutatingRequestsInFlight int
|
||||||
@ -71,6 +74,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||||||
// ApplyTo applies the run options to the method receiver and returns self
|
// ApplyTo applies the run options to the method receiver and returns self
|
||||||
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
||||||
c.CorsAllowedOriginList = s.CorsAllowedOriginList
|
c.CorsAllowedOriginList = s.CorsAllowedOriginList
|
||||||
|
c.HSTSDirectives = s.HSTSDirectives
|
||||||
c.ExternalAddress = s.ExternalHost
|
c.ExternalAddress = s.ExternalHost
|
||||||
c.MaxRequestsInFlight = s.MaxRequestsInFlight
|
c.MaxRequestsInFlight = s.MaxRequestsInFlight
|
||||||
c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
|
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"))
|
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
|
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
|
// AddUniversalFlags adds flags for a specific APIServer to the specified FlagSet
|
||||||
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
||||||
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
|
// 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 "+
|
"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.")
|
"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
|
deprecatedTargetRAMMB := 0
|
||||||
fs.IntVar(&deprecatedTargetRAMMB, "target-ram-mb", deprecatedTargetRAMMB,
|
fs.IntVar(&deprecatedTargetRAMMB, "target-ram-mb", deprecatedTargetRAMMB,
|
||||||
"DEPRECATED: Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
|
"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",
|
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",
|
name: "Test when ServerRunOptions is valid",
|
||||||
testOptions: &ServerRunOptions{
|
testOptions: &ServerRunOptions{
|
||||||
AdvertiseAddress: net.ParseIP("192.168.10.10"),
|
AdvertiseAddress: net.ParseIP("192.168.10.10"),
|
||||||
CorsAllowedOriginList: []string{"10.10.10.100", "10.10.10.200"},
|
CorsAllowedOriginList: []string{"10.10.10.100", "10.10.10.200"},
|
||||||
|
HSTSDirectives: []string{"max-age=31536000", "includeSubDomains", "preload"},
|
||||||
MaxRequestsInFlight: 400,
|
MaxRequestsInFlight: 400,
|
||||||
MaxMutatingRequestsInFlight: 200,
|
MaxMutatingRequestsInFlight: 200,
|
||||||
RequestTimeout: time.Duration(2) * time.Minute,
|
RequestTimeout: time.Duration(2) * time.Minute,
|
||||||
|
Loading…
Reference in New Issue
Block a user