mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 05:57:25 +00:00
add front proxy authenticator
This commit is contained in:
parent
f34bb50ce7
commit
557e653785
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 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 headerrequest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/auth/authenticator"
|
||||||
|
"k8s.io/kubernetes/pkg/auth/user"
|
||||||
|
utilcert "k8s.io/kubernetes/pkg/util/cert"
|
||||||
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
|
x509request "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509"
|
||||||
|
)
|
||||||
|
|
||||||
|
type requestHeaderAuthRequestHandler struct {
|
||||||
|
nameHeaders []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(nameHeaders []string) (authenticator.Request, error) {
|
||||||
|
headers := []string{}
|
||||||
|
for _, headerName := range nameHeaders {
|
||||||
|
trimmedHeader := strings.TrimSpace(headerName)
|
||||||
|
if len(trimmedHeader) == 0 {
|
||||||
|
return nil, fmt.Errorf("empty header %q", headerName)
|
||||||
|
}
|
||||||
|
headers = append(headers, trimmedHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &requestHeaderAuthRequestHandler{nameHeaders: headers}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSecure(clientCA string, proxyClientNames []string, nameHeaders []string) (authenticator.Request, error) {
|
||||||
|
headerAuthenticator, err := New(nameHeaders)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(clientCA) == 0 {
|
||||||
|
return nil, fmt.Errorf("missing clientCA file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap with an x509 verifier
|
||||||
|
caData, err := ioutil.ReadFile(clientCA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading %s: %v", clientCA, err)
|
||||||
|
}
|
||||||
|
opts := x509request.DefaultVerifyOptions()
|
||||||
|
opts.Roots = x509.NewCertPool()
|
||||||
|
certs, err := utilcert.ParseCertsPEM(caData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error loading certs from %s: %v", clientCA, err)
|
||||||
|
}
|
||||||
|
for _, cert := range certs {
|
||||||
|
opts.Roots.AddCert(cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
return x509request.NewVerifier(opts, headerAuthenticator, sets.NewString(proxyClientNames...)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
|
||||||
|
name := headerValue(req.Header, a.nameHeaders)
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &user.DefaultInfo{Name: name}, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerValue(h http.Header, headerNames []string) string {
|
||||||
|
for _, headerName := range headerNames {
|
||||||
|
headerValue := h.Get(headerName)
|
||||||
|
if len(headerValue) > 0 {
|
||||||
|
return headerValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 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 headerrequest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/auth/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestHeader(t *testing.T) {
|
||||||
|
testcases := map[string]struct {
|
||||||
|
nameHeaders []string
|
||||||
|
requestHeaders http.Header
|
||||||
|
|
||||||
|
expectedUser user.Info
|
||||||
|
expectedOk bool
|
||||||
|
}{
|
||||||
|
"empty": {},
|
||||||
|
"no match": {
|
||||||
|
nameHeaders: []string{"X-Remote-User"},
|
||||||
|
},
|
||||||
|
"match": {
|
||||||
|
nameHeaders: []string{"X-Remote-User"},
|
||||||
|
requestHeaders: http.Header{"X-Remote-User": {"Bob"}},
|
||||||
|
expectedUser: &user.DefaultInfo{Name: "Bob"},
|
||||||
|
expectedOk: true,
|
||||||
|
},
|
||||||
|
"exact match": {
|
||||||
|
nameHeaders: []string{"X-Remote-User"},
|
||||||
|
requestHeaders: http.Header{
|
||||||
|
"Prefixed-X-Remote-User-With-Suffix": {"Bob"},
|
||||||
|
"X-Remote-User-With-Suffix": {"Bob"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"first match": {
|
||||||
|
nameHeaders: []string{
|
||||||
|
"X-Remote-User",
|
||||||
|
"A-Second-X-Remote-User",
|
||||||
|
"Another-X-Remote-User",
|
||||||
|
},
|
||||||
|
requestHeaders: http.Header{
|
||||||
|
"X-Remote-User": {"", "First header, second value"},
|
||||||
|
"A-Second-X-Remote-User": {"Second header, first value", "Second header, second value"},
|
||||||
|
"Another-X-Remote-User": {"Third header, first value"}},
|
||||||
|
expectedUser: &user.DefaultInfo{Name: "Second header, first value"},
|
||||||
|
expectedOk: true,
|
||||||
|
},
|
||||||
|
"case-insensitive": {
|
||||||
|
nameHeaders: []string{"x-REMOTE-user"}, // configured headers can be case-insensitive
|
||||||
|
requestHeaders: http.Header{"X-Remote-User": {"Bob"}}, // the parsed headers are normalized by the http package
|
||||||
|
expectedUser: &user.DefaultInfo{Name: "Bob"},
|
||||||
|
expectedOk: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, testcase := range testcases {
|
||||||
|
auth, err := New(testcase.nameHeaders)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
req := &http.Request{Header: testcase.requestHeaders}
|
||||||
|
|
||||||
|
user, ok, _ := auth.AuthenticateRequest(req)
|
||||||
|
if testcase.expectedOk != ok {
|
||||||
|
t.Errorf("%v: expected %v, got %v", k, testcase.expectedOk, ok)
|
||||||
|
}
|
||||||
|
if e, a := testcase.expectedUser, user; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("%v: expected %#v, got %#v", k, e, a)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -839,6 +839,7 @@ k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/allow,liggitt,0
|
|||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/passwordfile,liggitt,0
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/passwordfile,liggitt,0
|
||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous,ixdy,1
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous,ixdy,1
|
||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/basicauth,liggitt,0
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/basicauth,liggitt,0
|
||||||
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/headerrequest,deads2k,0
|
||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union,liggitt,0
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union,liggitt,0
|
||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509,liggitt,0
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509,liggitt,0
|
||||||
k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/anytoken,timstclair,1
|
k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/anytoken,timstclair,1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user