git subrepo clone (merge) https://github.com/kubernetes-incubator/metrics-server.git metrics-server
subrepo:
subdir: "metrics-server"
merged: "92d8412"
upstream:
origin: "https://github.com/kubernetes-incubator/metrics-server.git"
branch: "master"
commit: "92d8412"
git-subrepo:
version: "0.4.0"
origin: "???"
commit: "???"
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticator/interfaces.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticator/interfaces.go
new file mode 100644
index 0000000..fd3d038
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticator/interfaces.go
@@ -0,0 +1,68 @@
+/*
+Copyright 2014 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 authenticator
+
+import (
+ "net/http"
+
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// Token checks a string value against a backing authentication store and returns
+// information about the current user and true if successful, false if not successful,
+// or an error if the token could not be checked.
+type Token interface {
+ AuthenticateToken(token string) (user.Info, bool, error)
+}
+
+// Request attempts to extract authentication information from a request and returns
+// information about the current user and true if successful, false if not successful,
+// or an error if the request could not be checked.
+type Request interface {
+ AuthenticateRequest(req *http.Request) (user.Info, bool, error)
+}
+
+// Password checks a username and password against a backing authentication store and
+// returns information about the user and true if successful, false if not successful,
+// or an error if the username and password could not be checked
+type Password interface {
+ AuthenticatePassword(user, password string) (user.Info, bool, error)
+}
+
+// TokenFunc is a function that implements the Token interface.
+type TokenFunc func(token string) (user.Info, bool, error)
+
+// AuthenticateToken implements authenticator.Token.
+func (f TokenFunc) AuthenticateToken(token string) (user.Info, bool, error) {
+ return f(token)
+}
+
+// RequestFunc is a function that implements the Request interface.
+type RequestFunc func(req *http.Request) (user.Info, bool, error)
+
+// AuthenticateRequest implements authenticator.Request.
+func (f RequestFunc) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ return f(req)
+}
+
+// PasswordFunc is a function that implements the Password interface.
+type PasswordFunc func(user, password string) (user.Info, bool, error)
+
+// AuthenticatePassword implements authenticator.Password.
+func (f PasswordFunc) AuthenticatePassword(user, password string) (user.Info, bool, error) {
+ return f(user, password)
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/delegating.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/delegating.go
new file mode 100644
index 0000000..61114c1
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/delegating.go
@@ -0,0 +1,115 @@
+/*
+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 authenticatorfactory
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/go-openapi/spec"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/group"
+ "k8s.io/apiserver/pkg/authentication/request/anonymous"
+ "k8s.io/apiserver/pkg/authentication/request/bearertoken"
+ "k8s.io/apiserver/pkg/authentication/request/headerrequest"
+ unionauth "k8s.io/apiserver/pkg/authentication/request/union"
+ "k8s.io/apiserver/pkg/authentication/request/websocket"
+ "k8s.io/apiserver/pkg/authentication/request/x509"
+ webhooktoken "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
+ authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
+ "k8s.io/client-go/util/cert"
+)
+
+// DelegatingAuthenticatorConfig is the minimal configuration needed to create an authenticator
+// built to delegate authentication to a kube API server
+type DelegatingAuthenticatorConfig struct {
+ Anonymous bool
+
+ TokenAccessReviewClient authenticationclient.TokenReviewInterface
+
+ // CacheTTL is the length of time that a token authentication answer will be cached.
+ CacheTTL time.Duration
+
+ // ClientCAFile is the CA bundle file used to authenticate client certificates
+ ClientCAFile string
+
+ RequestHeaderConfig *RequestHeaderConfig
+}
+
+func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
+ authenticators := []authenticator.Request{}
+ securityDefinitions := spec.SecurityDefinitions{}
+
+ // front-proxy first, then remote
+ // Add the front proxy authenticator if requested
+ if c.RequestHeaderConfig != nil {
+ requestHeaderAuthenticator, err := headerrequest.NewSecure(
+ c.RequestHeaderConfig.ClientCA,
+ c.RequestHeaderConfig.AllowedClientNames,
+ c.RequestHeaderConfig.UsernameHeaders,
+ c.RequestHeaderConfig.GroupHeaders,
+ c.RequestHeaderConfig.ExtraHeaderPrefixes,
+ )
+ if err != nil {
+ return nil, nil, err
+ }
+ authenticators = append(authenticators, requestHeaderAuthenticator)
+ }
+
+ // x509 client cert auth
+ if len(c.ClientCAFile) > 0 {
+ clientCAs, err := cert.NewPool(c.ClientCAFile)
+ if err != nil {
+ return nil, nil, fmt.Errorf("unable to load client CA file %s: %v", c.ClientCAFile, err)
+ }
+ verifyOpts := x509.DefaultVerifyOptions()
+ verifyOpts.Roots = clientCAs
+ authenticators = append(authenticators, x509.New(verifyOpts, x509.CommonNameUserConversion))
+ }
+
+ if c.TokenAccessReviewClient != nil {
+ tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.CacheTTL)
+ if err != nil {
+ return nil, nil, err
+ }
+ authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
+
+ securityDefinitions["BearerToken"] = &spec.SecurityScheme{
+ SecuritySchemeProps: spec.SecuritySchemeProps{
+ Type: "apiKey",
+ Name: "authorization",
+ In: "header",
+ Description: "Bearer Token authentication",
+ },
+ }
+ }
+
+ if len(authenticators) == 0 {
+ if c.Anonymous {
+ return anonymous.NewAuthenticator(), &securityDefinitions, nil
+ }
+ return nil, nil, errors.New("No authentication method configured")
+ }
+
+ authenticator := group.NewAuthenticatedGroupAdder(unionauth.New(authenticators...))
+ if c.Anonymous {
+ authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator())
+ }
+ return authenticator, &securityDefinitions, nil
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/loopback.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/loopback.go
new file mode 100644
index 0000000..f316565
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/loopback.go
@@ -0,0 +1,29 @@
+/*
+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 authenticatorfactory
+
+import (
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/request/bearertoken"
+ "k8s.io/apiserver/pkg/authentication/token/tokenfile"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// NewFromTokens returns an authenticator.Request or an error
+func NewFromTokens(tokens map[string]*user.DefaultInfo) authenticator.Request {
+ return bearertoken.New(tokenfile.New(tokens))
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/requestheader.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/requestheader.go
new file mode 100644
index 0000000..3eeb238
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/authenticatorfactory/requestheader.go
@@ -0,0 +1,31 @@
+/*
+Copyright 2014 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 authenticatorfactory
+
+type RequestHeaderConfig struct {
+ // UsernameHeaders are the headers to check (in order, case-insensitively) for an identity. The first header with a value wins.
+ UsernameHeaders []string
+ // GroupHeaders are the headers to check (case-insensitively) for a group names. All values will be used.
+ GroupHeaders []string
+ // ExtraHeaderPrefixes are the head prefixes to check (case-insentively) for filling in
+ // the user.Info.Extra. All values of all matching headers will be added.
+ ExtraHeaderPrefixes []string
+ // ClientCA points to CA bundle file which is used verify the identity of the front proxy
+ ClientCA string
+ // AllowedClientNames is a list of common names that may be presented by the authenticating front proxy. Empty means: accept any.
+ AllowedClientNames []string
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
new file mode 100644
index 0000000..9f0453b
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2017 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 group
+
+import (
+ "net/http"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// AuthenticatedGroupAdder adds system:authenticated group when appropriate
+type AuthenticatedGroupAdder struct {
+ // Authenticator is delegated to make the authentication decision
+ Authenticator authenticator.Request
+}
+
+// NewAuthenticatedGroupAdder wraps a request authenticator, and adds the system:authenticated group when appropriate.
+// Authentication must succeed, the user must not be system:anonymous, the groups system:authenticated or system:unauthenticated must
+// not be present
+func NewAuthenticatedGroupAdder(auth authenticator.Request) authenticator.Request {
+ return &AuthenticatedGroupAdder{auth}
+}
+
+func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ u, ok, err := g.Authenticator.AuthenticateRequest(req)
+ if err != nil || !ok {
+ return nil, ok, err
+ }
+
+ if u.GetName() == user.Anonymous {
+ return u, true, nil
+ }
+ for _, group := range u.GetGroups() {
+ if group == user.AllAuthenticated || group == user.AllUnauthenticated {
+ return u, true, nil
+ }
+ }
+
+ return &user.DefaultInfo{
+ Name: u.GetName(),
+ UID: u.GetUID(),
+ Groups: append(u.GetGroups(), user.AllAuthenticated),
+ Extra: u.GetExtra(),
+ }, true, nil
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/group_adder.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/group_adder.go
new file mode 100644
index 0000000..1f71429
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/group_adder.go
@@ -0,0 +1,50 @@
+/*
+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 group
+
+import (
+ "net/http"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// GroupAdder adds groups to an authenticated user.Info
+type GroupAdder struct {
+ // Authenticator is delegated to make the authentication decision
+ Authenticator authenticator.Request
+ // Groups are additional groups to add to the user.Info from a successful authentication
+ Groups []string
+}
+
+// NewGroupAdder wraps a request authenticator, and adds the specified groups to the returned user when authentication succeeds
+func NewGroupAdder(auth authenticator.Request, groups []string) authenticator.Request {
+ return &GroupAdder{auth, groups}
+}
+
+func (g *GroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ u, ok, err := g.Authenticator.AuthenticateRequest(req)
+ if err != nil || !ok {
+ return nil, ok, err
+ }
+ return &user.DefaultInfo{
+ Name: u.GetName(),
+ UID: u.GetUID(),
+ Groups: append(u.GetGroups(), g.Groups...),
+ Extra: u.GetExtra(),
+ }, true, nil
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go
new file mode 100644
index 0000000..4f60d52
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go
@@ -0,0 +1,48 @@
+/*
+Copyright 2017 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 group
+
+import (
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// TokenGroupAdder adds groups to an authenticated user.Info
+type TokenGroupAdder struct {
+ // Authenticator is delegated to make the authentication decision
+ Authenticator authenticator.Token
+ // Groups are additional groups to add to the user.Info from a successful authentication
+ Groups []string
+}
+
+// NewTokenGroupAdder wraps a token authenticator, and adds the specified groups to the returned user when authentication succeeds
+func NewTokenGroupAdder(auth authenticator.Token, groups []string) authenticator.Token {
+ return &TokenGroupAdder{auth, groups}
+}
+
+func (g *TokenGroupAdder) AuthenticateToken(token string) (user.Info, bool, error) {
+ u, ok, err := g.Authenticator.AuthenticateToken(token)
+ if err != nil || !ok {
+ return nil, ok, err
+ }
+ return &user.DefaultInfo{
+ Name: u.GetName(),
+ UID: u.GetUID(),
+ Groups: append(u.GetGroups(), g.Groups...),
+ Extra: u.GetExtra(),
+ }, true, nil
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go
new file mode 100644
index 0000000..a6d2294
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go
@@ -0,0 +1,36 @@
+/*
+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 anonymous
+
+import (
+ "net/http"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+const (
+ anonymousUser = user.Anonymous
+
+ unauthenticatedGroup = user.AllUnauthenticated
+)
+
+func NewAuthenticator() authenticator.Request {
+ return authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
+ return &user.DefaultInfo{Name: anonymousUser, Groups: []string{unauthenticatedGroup}}, true, nil
+ })
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go
new file mode 100644
index 0000000..5ca22f3
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go
@@ -0,0 +1,68 @@
+/*
+Copyright 2014 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 bearertoken
+
+import (
+ "errors"
+ "net/http"
+ "strings"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+type Authenticator struct {
+ auth authenticator.Token
+}
+
+func New(auth authenticator.Token) *Authenticator {
+ return &Authenticator{auth}
+}
+
+var invalidToken = errors.New("invalid bearer token")
+
+func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ auth := strings.TrimSpace(req.Header.Get("Authorization"))
+ if auth == "" {
+ return nil, false, nil
+ }
+ parts := strings.Split(auth, " ")
+ if len(parts) < 2 || strings.ToLower(parts[0]) != "bearer" {
+ return nil, false, nil
+ }
+
+ token := parts[1]
+
+ // Empty bearer tokens aren't valid
+ if len(token) == 0 {
+ return nil, false, nil
+ }
+
+ user, ok, err := a.auth.AuthenticateToken(token)
+ // if we authenticated successfully, go ahead and remove the bearer token so that no one
+ // is ever tempted to use it inside of the API server
+ if ok {
+ req.Header.Del("Authorization")
+ }
+
+ // If the token authenticator didn't error, provide a default error
+ if !ok && err == nil {
+ err = invalidToken
+ }
+
+ return user, ok, err
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go
new file mode 100644
index 0000000..948478b
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go
@@ -0,0 +1,188 @@
+/*
+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"
+ "net/url"
+ "strings"
+
+ "k8s.io/apimachinery/pkg/util/sets"
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ x509request "k8s.io/apiserver/pkg/authentication/request/x509"
+ "k8s.io/apiserver/pkg/authentication/user"
+ utilcert "k8s.io/client-go/util/cert"
+)
+
+type requestHeaderAuthRequestHandler struct {
+ // nameHeaders are the headers to check (in order, case-insensitively) for an identity. The first header with a value wins.
+ nameHeaders []string
+
+ // groupHeaders are the headers to check (case-insensitively) for group membership. All values of all headers will be added.
+ groupHeaders []string
+
+ // extraHeaderPrefixes are the head prefixes to check (case-insensitively) for filling in
+ // the user.Info.Extra. All values of all matching headers will be added.
+ extraHeaderPrefixes []string
+}
+
+func New(nameHeaders []string, groupHeaders []string, extraHeaderPrefixes []string) (authenticator.Request, error) {
+ trimmedNameHeaders, err := trimHeaders(nameHeaders...)
+ if err != nil {
+ return nil, err
+ }
+ trimmedGroupHeaders, err := trimHeaders(groupHeaders...)
+ if err != nil {
+ return nil, err
+ }
+ trimmedExtraHeaderPrefixes, err := trimHeaders(extraHeaderPrefixes...)
+ if err != nil {
+ return nil, err
+ }
+
+ return &requestHeaderAuthRequestHandler{
+ nameHeaders: trimmedNameHeaders,
+ groupHeaders: trimmedGroupHeaders,
+ extraHeaderPrefixes: trimmedExtraHeaderPrefixes,
+ }, nil
+}
+
+func trimHeaders(headerNames ...string) ([]string, error) {
+ ret := []string{}
+ for _, headerName := range headerNames {
+ trimmedHeader := strings.TrimSpace(headerName)
+ if len(trimmedHeader) == 0 {
+ return nil, fmt.Errorf("empty header %q", headerName)
+ }
+ ret = append(ret, trimmedHeader)
+ }
+
+ return ret, nil
+}
+
+func NewSecure(clientCA string, proxyClientNames []string, nameHeaders []string, groupHeaders []string, extraHeaderPrefixes []string) (authenticator.Request, error) {
+ headerAuthenticator, err := New(nameHeaders, groupHeaders, extraHeaderPrefixes)
+ 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
+ }
+ groups := allHeaderValues(req.Header, a.groupHeaders)
+ extra := newExtra(req.Header, a.extraHeaderPrefixes)
+
+ // clear headers used for authentication
+ for _, headerName := range a.nameHeaders {
+ req.Header.Del(headerName)
+ }
+ for _, headerName := range a.groupHeaders {
+ req.Header.Del(headerName)
+ }
+ for k := range extra {
+ for _, prefix := range a.extraHeaderPrefixes {
+ req.Header.Del(prefix + k)
+ }
+ }
+
+ return &user.DefaultInfo{
+ Name: name,
+ Groups: groups,
+ Extra: extra,
+ }, 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 ""
+}
+
+func allHeaderValues(h http.Header, headerNames []string) []string {
+ ret := []string{}
+ for _, headerName := range headerNames {
+ headerKey := http.CanonicalHeaderKey(headerName)
+ values, ok := h[headerKey]
+ if !ok {
+ continue
+ }
+
+ for _, headerValue := range values {
+ if len(headerValue) > 0 {
+ ret = append(ret, headerValue)
+ }
+ }
+ }
+ return ret
+}
+
+func unescapeExtraKey(encodedKey string) string {
+ key, err := url.PathUnescape(encodedKey) // Decode %-encoded bytes.
+ if err != nil {
+ return encodedKey // Always record extra strings, even if malformed/unencoded.
+ }
+ return key
+}
+
+func newExtra(h http.Header, headerPrefixes []string) map[string][]string {
+ ret := map[string][]string{}
+
+ // we have to iterate over prefixes first in order to have proper ordering inside the value slices
+ for _, prefix := range headerPrefixes {
+ for headerName, vv := range h {
+ if !strings.HasPrefix(strings.ToLower(headerName), strings.ToLower(prefix)) {
+ continue
+ }
+
+ extraKey := unescapeExtraKey(strings.ToLower(headerName[len(prefix):]))
+ ret[extraKey] = append(ret[extraKey], vv...)
+ }
+ }
+
+ return ret
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
new file mode 100644
index 0000000..1613940
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
@@ -0,0 +1,72 @@
+/*
+Copyright 2014 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 union
+
+import (
+ "net/http"
+
+ utilerrors "k8s.io/apimachinery/pkg/util/errors"
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+// unionAuthRequestHandler authenticates requests using a chain of authenticator.Requests
+type unionAuthRequestHandler struct {
+ // Handlers is a chain of request authenticators to delegate to
+ Handlers []authenticator.Request
+ // FailOnError determines whether an error returns short-circuits the chain
+ FailOnError bool
+}
+
+// New returns a request authenticator that validates credentials using a chain of authenticator.Request objects.
+// The entire chain is tried until one succeeds. If all fail, an aggregate error is returned.
+func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
+ if len(authRequestHandlers) == 1 {
+ return authRequestHandlers[0]
+ }
+ return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false}
+}
+
+// NewFailOnError returns a request authenticator that validates credentials using a chain of authenticator.Request objects.
+// The first error short-circuits the chain.
+func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator.Request {
+ if len(authRequestHandlers) == 1 {
+ return authRequestHandlers[0]
+ }
+ return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: true}
+}
+
+// AuthenticateRequest authenticates the request using a chain of authenticator.Request objects.
+func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ var errlist []error
+ for _, currAuthRequestHandler := range authHandler.Handlers {
+ info, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
+ if err != nil {
+ if authHandler.FailOnError {
+ return info, ok, err
+ }
+ errlist = append(errlist, err)
+ continue
+ }
+
+ if ok {
+ return info, ok, err
+ }
+ }
+
+ return nil, false, utilerrors.NewAggregate(errlist)
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go
new file mode 100644
index 0000000..4a30bb6
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go
@@ -0,0 +1,109 @@
+/*
+Copyright 2017 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 websocket
+
+import (
+ "encoding/base64"
+ "errors"
+ "net/http"
+ "net/textproto"
+ "strings"
+ "unicode/utf8"
+
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+ "k8s.io/apiserver/pkg/util/wsstream"
+)
+
+const bearerProtocolPrefix = "base64url.bearer.authorization.k8s.io."
+
+var protocolHeader = textproto.CanonicalMIMEHeaderKey("Sec-WebSocket-Protocol")
+
+var errInvalidToken = errors.New("invalid bearer token")
+
+// ProtocolAuthenticator allows a websocket connection to provide a bearer token as a subprotocol
+// in the format "base64url.bearer.authorization.<base64url-without-padding(bearer-token)>"
+type ProtocolAuthenticator struct {
+ // auth is the token authenticator to use to validate the token
+ auth authenticator.Token
+}
+
+func NewProtocolAuthenticator(auth authenticator.Token) *ProtocolAuthenticator {
+ return &ProtocolAuthenticator{auth}
+}
+
+func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ // Only accept websocket connections
+ if !wsstream.IsWebSocketRequest(req) {
+ return nil, false, nil
+ }
+
+ token := ""
+ sawTokenProtocol := false
+ filteredProtocols := []string{}
+ for _, protocolHeader := range req.Header[protocolHeader] {
+ for _, protocol := range strings.Split(protocolHeader, ",") {
+ protocol = strings.TrimSpace(protocol)
+
+ if !strings.HasPrefix(protocol, bearerProtocolPrefix) {
+ filteredProtocols = append(filteredProtocols, protocol)
+ continue
+ }
+
+ if sawTokenProtocol {
+ return nil, false, errors.New("multiple base64.bearer.authorization tokens specified")
+ }
+ sawTokenProtocol = true
+
+ encodedToken := strings.TrimPrefix(protocol, bearerProtocolPrefix)
+ decodedToken, err := base64.RawURLEncoding.DecodeString(encodedToken)
+ if err != nil {
+ return nil, false, errors.New("invalid base64.bearer.authorization token encoding")
+ }
+ if !utf8.Valid(decodedToken) {
+ return nil, false, errors.New("invalid base64.bearer.authorization token")
+ }
+ token = string(decodedToken)
+ }
+ }
+
+ // Must pass at least one other subprotocol so that we can remove the one containing the bearer token,
+ // and there is at least one to echo back to the client
+ if len(token) > 0 && len(filteredProtocols) == 0 {
+ return nil, false, errors.New("missing additional subprotocol")
+ }
+
+ if len(token) == 0 {
+ return nil, false, nil
+ }
+
+ user, ok, err := a.auth.AuthenticateToken(token)
+
+ // on success, remove the protocol with the token
+ if ok {
+ // https://tools.ietf.org/html/rfc6455#section-11.3.4 indicates the Sec-WebSocket-Protocol header may appear multiple times
+ // in a request, and is logically the same as a single Sec-WebSocket-Protocol header field that contains all values
+ req.Header.Set(protocolHeader, strings.Join(filteredProtocols, ","))
+ }
+
+ // If the token authenticator didn't error, provide a default error
+ if !ok && err == nil {
+ err = errInvalidToken
+ }
+
+ return user, ok, err
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/doc.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/doc.go
new file mode 100644
index 0000000..8f3d36b
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2014 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 x509 provides a request authenticator that validates and
+// extracts user information from client certificates
+package x509 // import "k8s.io/apiserver/pkg/authentication/request/x509"
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go
new file mode 100644
index 0000000..708a89e
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go
@@ -0,0 +1,215 @@
+/*
+Copyright 2014 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 x509
+
+import (
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/golang/glog"
+ "github.com/prometheus/client_golang/prometheus"
+
+ utilerrors "k8s.io/apimachinery/pkg/util/errors"
+ "k8s.io/apimachinery/pkg/util/sets"
+ "k8s.io/apiserver/pkg/authentication/authenticator"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+var clientCertificateExpirationHistogram = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "apiserver",
+ Subsystem: "client",
+ Name: "certificate_expiration_seconds",
+ Help: "Distribution of the remaining lifetime on the certificate used to authenticate a request.",
+ Buckets: []float64{
+ 0,
+ (6 * time.Hour).Seconds(),
+ (12 * time.Hour).Seconds(),
+ (24 * time.Hour).Seconds(),
+ (2 * 24 * time.Hour).Seconds(),
+ (4 * 24 * time.Hour).Seconds(),
+ (7 * 24 * time.Hour).Seconds(),
+ (30 * 24 * time.Hour).Seconds(),
+ (3 * 30 * 24 * time.Hour).Seconds(),
+ (6 * 30 * 24 * time.Hour).Seconds(),
+ (12 * 30 * 24 * time.Hour).Seconds(),
+ },
+ },
+)
+
+func init() {
+ prometheus.MustRegister(clientCertificateExpirationHistogram)
+}
+
+// UserConversion defines an interface for extracting user info from a client certificate chain
+type UserConversion interface {
+ User(chain []*x509.Certificate) (user.Info, bool, error)
+}
+
+// UserConversionFunc is a function that implements the UserConversion interface.
+type UserConversionFunc func(chain []*x509.Certificate) (user.Info, bool, error)
+
+// User implements x509.UserConversion
+func (f UserConversionFunc) User(chain []*x509.Certificate) (user.Info, bool, error) {
+ return f(chain)
+}
+
+// Authenticator implements request.Authenticator by extracting user info from verified client certificates
+type Authenticator struct {
+ opts x509.VerifyOptions
+ user UserConversion
+}
+
+// New returns a request.Authenticator that verifies client certificates using the provided
+// VerifyOptions, and converts valid certificate chains into user.Info using the provided UserConversion
+func New(opts x509.VerifyOptions, user UserConversion) *Authenticator {
+ return &Authenticator{opts, user}
+}
+
+// AuthenticateRequest authenticates the request using presented client certificates
+func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 {
+ return nil, false, nil
+ }
+
+ // Use intermediates, if provided
+ optsCopy := a.opts
+ if optsCopy.Intermediates == nil && len(req.TLS.PeerCertificates) > 1 {
+ optsCopy.Intermediates = x509.NewCertPool()
+ for _, intermediate := range req.TLS.PeerCertificates[1:] {
+ optsCopy.Intermediates.AddCert(intermediate)
+ }
+ }
+
+ remaining := req.TLS.PeerCertificates[0].NotAfter.Sub(time.Now())
+ clientCertificateExpirationHistogram.Observe(remaining.Seconds())
+ chains, err := req.TLS.PeerCertificates[0].Verify(optsCopy)
+ if err != nil {
+ return nil, false, err
+ }
+
+ var errlist []error
+ for _, chain := range chains {
+ user, ok, err := a.user.User(chain)
+ if err != nil {
+ errlist = append(errlist, err)
+ continue
+ }
+
+ if ok {
+ return user, ok, err
+ }
+ }
+ return nil, false, utilerrors.NewAggregate(errlist)
+}
+
+// Verifier implements request.Authenticator by verifying a client cert on the request, then delegating to the wrapped auth
+type Verifier struct {
+ opts x509.VerifyOptions
+ auth authenticator.Request
+
+ // allowedCommonNames contains the common names which a verified certificate is allowed to have.
+ // If empty, all verified certificates are allowed.
+ allowedCommonNames sets.String
+}
+
+// NewVerifier create a request.Authenticator by verifying a client cert on the request, then delegating to the wrapped auth
+func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request, allowedCommonNames sets.String) authenticator.Request {
+ return &Verifier{opts, auth, allowedCommonNames}
+}
+
+// AuthenticateRequest verifies the presented client certificate, then delegates to the wrapped auth
+func (a *Verifier) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
+ if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 {
+ return nil, false, nil
+ }
+
+ // Use intermediates, if provided
+ optsCopy := a.opts
+ if optsCopy.Intermediates == nil && len(req.TLS.PeerCertificates) > 1 {
+ optsCopy.Intermediates = x509.NewCertPool()
+ for _, intermediate := range req.TLS.PeerCertificates[1:] {
+ optsCopy.Intermediates.AddCert(intermediate)
+ }
+ }
+
+ if _, err := req.TLS.PeerCertificates[0].Verify(optsCopy); err != nil {
+ return nil, false, err
+ }
+ if err := a.verifySubject(req.TLS.PeerCertificates[0].Subject); err != nil {
+ return nil, false, err
+ }
+ return a.auth.AuthenticateRequest(req)
+}
+
+func (a *Verifier) verifySubject(subject pkix.Name) error {
+ // No CN restrictions
+ if len(a.allowedCommonNames) == 0 {
+ return nil
+ }
+ // Enforce CN restrictions
+ if a.allowedCommonNames.Has(subject.CommonName) {
+ return nil
+ }
+ glog.Warningf("x509: subject with cn=%s is not in the allowed list: %v", subject.CommonName, a.allowedCommonNames.List())
+ return fmt.Errorf("x509: subject with cn=%s is not allowed", subject.CommonName)
+}
+
+// DefaultVerifyOptions returns VerifyOptions that use the system root certificates, current time,
+// and requires certificates to be valid for client auth (x509.ExtKeyUsageClientAuth)
+func DefaultVerifyOptions() x509.VerifyOptions {
+ return x509.VerifyOptions{
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+ }
+}
+
+// CommonNameUserConversion builds user info from a certificate chain using the subject's CommonName
+var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
+ if len(chain[0].Subject.CommonName) == 0 {
+ return nil, false, nil
+ }
+ return &user.DefaultInfo{
+ Name: chain[0].Subject.CommonName,
+ Groups: chain[0].Subject.Organization,
+ }, true, nil
+})
+
+// DNSNameUserConversion builds user info from a certificate chain using the first DNSName on the certificate
+var DNSNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
+ if len(chain[0].DNSNames) == 0 {
+ return nil, false, nil
+ }
+ return &user.DefaultInfo{Name: chain[0].DNSNames[0]}, true, nil
+})
+
+// EmailAddressUserConversion builds user info from a certificate chain using the first EmailAddress on the certificate
+var EmailAddressUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
+ var emailAddressOID asn1.ObjectIdentifier = []int{1, 2, 840, 113549, 1, 9, 1}
+ if len(chain[0].EmailAddresses) == 0 {
+ for _, name := range chain[0].Subject.Names {
+ if name.Type.Equal(emailAddressOID) {
+ return &user.DefaultInfo{Name: name.Value.(string)}, true, nil
+ }
+ }
+ return nil, false, nil
+ }
+ return &user.DefaultInfo{Name: chain[0].EmailAddresses[0]}, true, nil
+})
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
new file mode 100644
index 0000000..1b7bbc1
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
@@ -0,0 +1,73 @@
+/*
+Copyright 2014 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 serviceaccount
+
+import (
+ "fmt"
+ "strings"
+
+ apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
+)
+
+const (
+ ServiceAccountUsernamePrefix = "system:serviceaccount:"
+ ServiceAccountUsernameSeparator = ":"
+ ServiceAccountGroupPrefix = "system:serviceaccounts:"
+ AllServiceAccountsGroup = "system:serviceaccounts"
+)
+
+// MakeUsername generates a username from the given namespace and ServiceAccount name.
+// The resulting username can be passed to SplitUsername to extract the original namespace and ServiceAccount name.
+func MakeUsername(namespace, name string) string {
+ return ServiceAccountUsernamePrefix + namespace + ServiceAccountUsernameSeparator + name
+}
+
+var invalidUsernameErr = fmt.Errorf("Username must be in the form %s", MakeUsername("namespace", "name"))
+
+// SplitUsername returns the namespace and ServiceAccount name embedded in the given username,
+// or an error if the username is not a valid name produced by MakeUsername
+func SplitUsername(username string) (string, string, error) {
+ if !strings.HasPrefix(username, ServiceAccountUsernamePrefix) {
+ return "", "", invalidUsernameErr
+ }
+ trimmed := strings.TrimPrefix(username, ServiceAccountUsernamePrefix)
+ parts := strings.Split(trimmed, ServiceAccountUsernameSeparator)
+ if len(parts) != 2 {
+ return "", "", invalidUsernameErr
+ }
+ namespace, name := parts[0], parts[1]
+ if len(apimachineryvalidation.ValidateNamespaceName(namespace, false)) != 0 {
+ return "", "", invalidUsernameErr
+ }
+ if len(apimachineryvalidation.ValidateServiceAccountName(name, false)) != 0 {
+ return "", "", invalidUsernameErr
+ }
+ return namespace, name, nil
+}
+
+// MakeGroupNames generates service account group names for the given namespace
+func MakeGroupNames(namespace string) []string {
+ return []string{
+ AllServiceAccountsGroup,
+ MakeNamespaceGroupName(namespace),
+ }
+}
+
+// MakeNamespaceGroupName returns the name of the group all service accounts in the namespace are included in
+func MakeNamespaceGroupName(namespace string) string {
+ return ServiceAccountGroupPrefix + namespace
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go
new file mode 100644
index 0000000..57bb6c5
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go
@@ -0,0 +1,97 @@
+/*
+Copyright 2014 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 tokenfile
+
+import (
+ "encoding/csv"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/golang/glog"
+ "k8s.io/apiserver/pkg/authentication/user"
+)
+
+type TokenAuthenticator struct {
+ tokens map[string]*user.DefaultInfo
+}
+
+// New returns a TokenAuthenticator for a single token
+func New(tokens map[string]*user.DefaultInfo) *TokenAuthenticator {
+ return &TokenAuthenticator{
+ tokens: tokens,
+ }
+}
+
+// NewCSV returns a TokenAuthenticator, populated from a CSV file.
+// The CSV file must contain records in the format "token,username,useruid"
+func NewCSV(path string) (*TokenAuthenticator, error) {
+ file, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ recordNum := 0
+ tokens := make(map[string]*user.DefaultInfo)
+ reader := csv.NewReader(file)
+ reader.FieldsPerRecord = -1
+ for {
+ record, err := reader.Read()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ if len(record) < 3 {
+ return nil, fmt.Errorf("token file '%s' must have at least 3 columns (token, user name, user uid), found %d", path, len(record))
+ }
+
+ recordNum++
+ if record[0] == "" {
+ glog.Warningf("empty token has been found in token file '%s', record number '%d'", path, recordNum)
+ continue
+ }
+
+ obj := &user.DefaultInfo{
+ Name: record[1],
+ UID: record[2],
+ }
+ if _, exist := tokens[record[0]]; exist {
+ glog.Warningf("duplicate token has been found in token file '%s', record number '%d'", path, recordNum)
+ }
+ tokens[record[0]] = obj
+
+ if len(record) >= 4 {
+ obj.Groups = strings.Split(record[3], ",")
+ }
+ }
+
+ return &TokenAuthenticator{
+ tokens: tokens,
+ }, nil
+}
+
+func (a *TokenAuthenticator) AuthenticateToken(value string) (user.Info, bool, error) {
+ user, ok := a.tokens[value]
+ if !ok {
+ return nil, false, nil
+ }
+ return user, true, nil
+}
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/doc.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/doc.go
new file mode 100644
index 0000000..570c51a
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2014 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 user contains utilities for dealing with simple user exchange in the auth
+// packages. The user.Info interface defines an interface for exchanging that info.
+package user
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/user.go b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/user.go
new file mode 100644
index 0000000..f02dc39
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/authentication/user/user.go
@@ -0,0 +1,83 @@
+/*
+Copyright 2014 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 user
+
+// Info describes a user that has been authenticated to the system.
+type Info interface {
+ // GetName returns the name that uniquely identifies this user among all
+ // other active users.
+ GetName() string
+ // GetUID returns a unique value for a particular user that will change
+ // if the user is removed from the system and another user is added with
+ // the same name.
+ GetUID() string
+ // GetGroups returns the names of the groups the user is a member of
+ GetGroups() []string
+
+ // GetExtra can contain any additional information that the authenticator
+ // thought was interesting. One example would be scopes on a token.
+ // Keys in this map should be namespaced to the authenticator or
+ // authenticator/authorizer pair making use of them.
+ // For instance: "example.org/foo" instead of "foo"
+ // This is a map[string][]string because it needs to be serializeable into
+ // a SubjectAccessReviewSpec.authorization.k8s.io for proper authorization
+ // delegation flows
+ // In order to faithfully round-trip through an impersonation flow, these keys
+ // MUST be lowercase.
+ GetExtra() map[string][]string
+}
+
+// DefaultInfo provides a simple user information exchange object
+// for components that implement the UserInfo interface.
+type DefaultInfo struct {
+ Name string
+ UID string
+ Groups []string
+ Extra map[string][]string
+}
+
+func (i *DefaultInfo) GetName() string {
+ return i.Name
+}
+
+func (i *DefaultInfo) GetUID() string {
+ return i.UID
+}
+
+func (i *DefaultInfo) GetGroups() []string {
+ return i.Groups
+}
+
+func (i *DefaultInfo) GetExtra() map[string][]string {
+ return i.Extra
+}
+
+// well-known user and group names
+const (
+ SystemPrivilegedGroup = "system:masters"
+ NodesGroup = "system:nodes"
+ AllUnauthenticated = "system:unauthenticated"
+ AllAuthenticated = "system:authenticated"
+
+ Anonymous = "system:anonymous"
+ APIServerUser = "system:apiserver"
+
+ // core kubernetes process identities
+ KubeProxy = "system:kube-proxy"
+ KubeControllerManager = "system:kube-controller-manager"
+ KubeScheduler = "system:kube-scheduler"
+)