github.com/timstclair/heapster@v0.20.0-alpha1/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/kubernetes/pkg/auth/authenticator" 25 "k8s.io/kubernetes/pkg/auth/user" 26 x509request "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509" 27 ) 28 29 func newAuthHandler(handler http.Handler) (http.Handler, error) { 30 // Authn/Authz setup 31 authn, err := newAuthenticatorFromClientCAFile(*argTLSClientCAFile) 32 if err != nil { 33 return nil, err 34 } 35 36 authz, err := newAuthorizerFromUserList(strings.Split(*argAllowedUsers, ",")...) 37 if err != nil { 38 return nil, err 39 } 40 41 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 42 // Check authn 43 user, ok, err := authn.AuthenticateRequest(req) 44 if err != nil { 45 http.Error(w, err.Error(), http.StatusInternalServerError) 46 return 47 } 48 if !ok { 49 http.Error(w, "Unauthorized", http.StatusUnauthorized) 50 return 51 } 52 53 // Check authz 54 allowed, err := authz.AuthorizeRequest(req, user) 55 if err != nil { 56 http.Error(w, err.Error(), http.StatusInternalServerError) 57 return 58 } 59 if !allowed { 60 http.Error(w, "Forbidden", http.StatusForbidden) 61 return 62 } 63 64 handler.ServeHTTP(w, req) 65 }), nil 66 } 67 68 // newAuthenticatorFromClientCAFile returns an authenticator.Request or an error 69 func newAuthenticatorFromClientCAFile(clientCAFile string) (authenticator.Request, error) { 70 opts := x509request.DefaultVerifyOptions() 71 72 // If at custom CA bundle is provided, load it (otherwise just use system roots) 73 if len(clientCAFile) > 0 { 74 if caData, err := ioutil.ReadFile(clientCAFile); err != nil { 75 return nil, err 76 } else if len(caData) > 0 { 77 roots := x509.NewCertPool() 78 if !roots.AppendCertsFromPEM(caData) { 79 return nil, fmt.Errorf("no valid certs found in %s", clientCAFile) 80 } 81 opts.Roots = roots 82 } 83 } 84 85 return x509request.New(opts, x509request.CommonNameUserConversion), nil 86 } 87 88 type Authorizer interface { 89 AuthorizeRequest(req *http.Request, user user.Info) (bool, error) 90 } 91 92 func newAuthorizerFromUserList(allowedUsers ...string) (Authorizer, error) { 93 if len(allowedUsers) == 1 && len(allowedUsers[0]) == 0 { 94 return &allowAnyAuthorizer{}, nil 95 } 96 u := map[string]bool{} 97 for _, allowedUser := range allowedUsers { 98 u[allowedUser] = true 99 } 100 return &userAuthorizer{u}, nil 101 } 102 103 type allowAnyAuthorizer struct{} 104 105 func (a *allowAnyAuthorizer) AuthorizeRequest(req *http.Request, user user.Info) (bool, error) { 106 return true, nil 107 } 108 109 type userAuthorizer struct { 110 allowedUsers map[string]bool 111 } 112 113 func (a *userAuthorizer) AuthorizeRequest(req *http.Request, user user.Info) (bool, error) { 114 return a.allowedUsers[user.GetName()], nil 115 }