Skip to content

Commit

Permalink
add support for auth providers
Browse files Browse the repository at this point in the history
  • Loading branch information
rajatjindal committed Nov 20, 2019
1 parent c426c12 commit a7566e9
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 4 deletions.
21 changes: 21 additions & 0 deletions pkg/authproviders/authprovider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package authproviders

import (
"fmt"

clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

//GetToken gets the token from auth provider config
func GetToken(ap *clientcmdapi.AuthProviderConfig) (string, error) {
switch ap.Name {
case "gcp":
return ap.Config["access-token"], nil
case "azure":
return ap.Config["access-token"], nil
case "oidc":
return ap.Config["id-token"], nil
}

return "", fmt.Errorf("unsupported auth provider %s", ap.Name)
}
49 changes: 46 additions & 3 deletions pkg/cmd/whoami.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package cmd
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"

"github.com/rajatjindal/kubectl-whoami/pkg/k8s"
"github.com/spf13/cobra"
Expand All @@ -23,6 +25,25 @@ type WhoAmIOptions struct {
args []string
kubeclient kubernetes.Interface
printVersion bool

tokenRetriever *tokenRetriever
}

// tokenRetriever helps to retrieve token
type tokenRetriever struct {
rountTripper http.RoundTripper
token string
}

//RoundTrip gets token
func (t *tokenRetriever) RoundTrip(req *http.Request) (*http.Response, error) {
header := req.Header.Get("authorization")
switch {
case strings.HasPrefix(header, "Bearer "):
t.token = strings.ReplaceAll(header, "Bearer ", "")
}

return t.rountTripper.RoundTrip(req)
}

// NewWhoAmIOptions provides an instance of WhoAmIOptions with default values
Expand Down Expand Up @@ -76,6 +97,12 @@ func (o *WhoAmIOptions) Complete(cmd *cobra.Command, args []string) error {
return err
}

o.tokenRetriever = &tokenRetriever{}
config.Wrap(func(rt http.RoundTripper) http.RoundTripper {
o.tokenRetriever.rountTripper = rt
return o.tokenRetriever
})

o.kubeclient, err = kubernetes.NewForConfig(config)
if err != nil {
return err
Expand Down Expand Up @@ -105,9 +132,9 @@ func (o *WhoAmIOptions) Run() error {
return err
}

var token string
// from vendor/k8s.io/client-go/transport/round_trippers.go:HTTPWrappersForConfig function, tokenauth has preference over basicauth
if c.HasTokenAuth() {
var token string
if config.BearerTokenFile != "" {
d, err := ioutil.ReadFile(config.BearerTokenFile)
if err != nil {
Expand All @@ -120,7 +147,16 @@ func (o *WhoAmIOptions) Run() error {
if config.BearerToken != "" {
token = config.BearerToken
}
}

if token == "" && config.AuthProvider != nil {
token, err = o.getToken()
if err != nil {
return err
}
}

if token != "" {
username, err := k8s.WhoAmI(o.kubeclient, token)
if err != nil {
return err
Expand All @@ -142,8 +178,15 @@ func (o *WhoAmIOptions) Run() error {
if c.HasCertAuth() {
fmt.Println("kubecfg:certauth:admin")
return nil

}

return fmt.Errorf("could not identify auth type")
return nil
}

func (o *WhoAmIOptions) getToken() (string, error) {
err := k8s.WhatCanI(o.kubeclient)
if err != nil {
return "", err
}
return o.tokenRetriever.token, nil
}
18 changes: 18 additions & 0 deletions pkg/k8s/tokenretriever.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package k8s

import (
authorizationv1 "k8s.io/api/authorization/v1"
"k8s.io/client-go/kubernetes"
)

//WhatCanI runs self subject review request
func WhatCanI(kubeclient kubernetes.Interface) error {
sar := &authorizationv1.SelfSubjectRulesReview{
Spec: authorizationv1.SelfSubjectRulesReviewSpec{
Namespace: "default",
},
}

_, err := kubeclient.AuthorizationV1().SelfSubjectRulesReviews().Create(sar)
return err
}
8 changes: 7 additions & 1 deletion pkg/k8s/tokenreview.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package k8s

import (
"fmt"
"regexp"

authenticationapi "k8s.io/api/authentication/v1"
Expand All @@ -17,17 +18,22 @@ func WhoAmI(kubeclient kubernetes.Interface, token string) (string, error) {
})

if err != nil {
fmt.Println(err.Error())
if k8serrors.IsForbidden(err) {
return getUsernameFromError(err), nil
}

return "", err
}

if result.Status.Error != "" {
return "", fmt.Errorf(result.Status.Error)
}

return result.Status.User.Username, nil
}

func getUsernameFromError(err error) string {
fmt.Println(err.Error())
re := regexp.MustCompile(`^.* User "(.*)" cannot .*$`)
return re.ReplaceAllString(err.Error(), "$1")
}

0 comments on commit a7566e9

Please sign in to comment.