github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/metrics/auth.go (about) 1 // Copyright 2014 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "crypto/x509" 19 "fmt" 20 "io/ioutil" 21 "net/http" 22 "strings" 23 24 "k8s.io/apiserver/pkg/authentication/authenticator" 25 x509request "k8s.io/apiserver/pkg/authentication/request/x509" 26 "k8s.io/apiserver/pkg/authentication/user" 27 "k8s.io/heapster/metrics/options" 28 ) 29 30 func newAuthHandler(opt *options.HeapsterRunOptions, handler http.Handler) (http.Handler, error) { 31 // Authn/Authz setup 32 authn, err := newAuthenticatorFromClientCAFile(opt.TLSClientCAFile) 33 if err != nil { 34 return nil, err 35 } 36 37 authz, err := newAuthorizerFromUserList(strings.Split(opt.AllowedUsers, ",")...) 38 if err != nil { 39 return nil, err 40 } 41 42 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 43 // Check authn 44 user, ok, err := authn.AuthenticateRequest(req) 45 if err != nil { 46 http.Error(w, err.Error(), http.StatusInternalServerError) 47 return 48 } 49 if !ok { 50 http.Error(w, "Unauthorized", http.StatusUnauthorized) 51 return 52 } 53 54 // Check authz 55 allowed, err := authz.AuthorizeRequest(req, user) 56 if err != nil { 57 http.Error(w, err.Error(), http.StatusInternalServerError) 58 return 59 } 60 if !allowed { 61 http.Error(w, "Forbidden", http.StatusForbidden) 62 return 63 } 64 65 handler.ServeHTTP(w, req) 66 }), nil 67 } 68 69 // newAuthenticatorFromClientCAFile returns an authenticator.Request or an error 70 func newAuthenticatorFromClientCAFile(clientCAFile string) (authenticator.Request, error) { 71 opts := x509request.DefaultVerifyOptions() 72 73 // If at custom CA bundle is provided, load it (otherwise just use system roots) 74 if len(clientCAFile) > 0 { 75 if caData, err := ioutil.ReadFile(clientCAFile); err != nil { 76 return nil, err 77 } else if len(caData) > 0 { 78 roots := x509.NewCertPool() 79 if !roots.AppendCertsFromPEM(caData) { 80 return nil, fmt.Errorf("no valid certs found in %s", clientCAFile) 81 } 82 opts.Roots = roots 83 } 84 } 85 86 return x509request.New(opts, x509request.CommonNameUserConversion), nil 87 } 88 89 type Authorizer interface { 90 AuthorizeRequest(req *http.Request, user user.Info) (bool, error) 91 } 92 93 func newAuthorizerFromUserList(allowedUsers ...string) (Authorizer, error) { 94 if len(allowedUsers) == 1 && len(allowedUsers[0]) == 0 { 95 return &allowAnyAuthorizer{}, nil 96 } 97 u := map[string]bool{} 98 for _, allowedUser := range allowedUsers { 99 u[allowedUser] = true 100 } 101 return &userAuthorizer{u}, nil 102 } 103 104 type allowAnyAuthorizer struct{} 105 106 func (a *allowAnyAuthorizer) AuthorizeRequest(req *http.Request, user user.Info) (bool, error) { 107 return true, nil 108 } 109 110 type userAuthorizer struct { 111 allowedUsers map[string]bool 112 } 113 114 func (a *userAuthorizer) AuthorizeRequest(req *http.Request, user user.Info) (bool, error) { 115 return a.allowedUsers[user.GetName()], nil 116 }