55package kubernetes
66
77import (
8- "bytes"
98 "context"
10- "encoding/json"
119 "fmt"
12- "io/ioutil"
1310 "net/http"
14- "strings"
1511 "time"
1612
1713 kubeauth "k8s.io/api/authentication/v1"
1814 kubemeta "k8s.io/apimachinery/pkg/apis/meta/v1"
1915
2016 "github.com/shaj13/go-guardian/v2/auth"
17+ "github.com/shaj13/go-guardian/v2/auth/internal"
2118 "github.com/shaj13/go-guardian/v2/auth/strategies/token"
2219)
2320
2421type kubeReview struct {
25- addr string
26- // service account token
27- token string
28- apiVersion string
29- audiences []string
30- client * http.Client
22+ requester * internal.Requester
23+ audiences []string
3124}
3225
3326func (k * kubeReview ) authenticate (ctx context.Context , r * http.Request , token string ) (auth.Info , time.Time , error ) {
34- var t time.Time
35-
36- tr := & kubeauth.TokenReview {
27+ t := time.Time {}
28+ status := & kubemeta.Status {}
29+ review := & kubeauth.TokenReview {}
30+ data := & kubeauth.TokenReview {
3731 Spec : kubeauth.TokenReviewSpec {
3832 Token : token ,
3933 Audiences : k .audiences ,
4034 },
4135 }
4236
43- body , err := json .Marshal (tr )
44- if err != nil {
45- return nil , t , fmt .Errorf (
46- "strategies/kubernetes: Failed to Marshal TokenReview Err: %s" ,
47- err ,
48- )
49- }
50-
51- url := k .addr + "/apis/" + k .apiVersion + "/tokenreviews"
52-
53- req , err := http .NewRequest (http .MethodPost , url , bytes .NewBuffer (body ))
54- if err != nil {
55- return nil , t , err
56- }
57-
58- req .Header .Set ("Authorization" , "Bearer " + k .token )
59- req .Header .Set ("Content-Type" , "application/json" )
60- req .Header .Set ("Accept" , "application/json" )
61-
62- resp , err := k .client .Do (req )
63- if err != nil {
64- return nil , t , err
65- }
66-
67- body , err = ioutil .ReadAll (resp .Body )
68- if err != nil {
69- return nil , t , err
70- }
71-
72- defer resp .Body .Close ()
37+ err := k .requester .Do (ctx , data , review , status )
7338
74- // verify the response is not an kubernetes status error.
75- status := & kubemeta. Status {}
76- err = json . Unmarshal ( body , status )
77- if err == nil && status .Status != kubemeta .StatusSuccess {
39+ switch {
40+ case err != nil :
41+ return nil , t , fmt . Errorf ( "strategies/kubernetes: %w" , err )
42+ case len ( status . Status ) > 0 && status .Status != kubemeta .StatusSuccess :
7843 return nil , t , fmt .Errorf ("strategies/kubernetes: %s" , status .Message )
79- }
80-
81- tr = & kubeauth.TokenReview {}
82- err = json .Unmarshal (body , tr )
83- if err != nil {
84- return nil , t , fmt .Errorf (
85- "strategies/kubernetes: Failed to Unmarshal Response body to TokenReview Err: %s" ,
86- err ,
87- )
88- }
89-
90- if len (tr .Status .Error ) > 0 {
91- return nil , t , fmt .Errorf ("strategies/kubernetes: %s" , tr .Status .Error )
92- }
93-
94- if ! tr .Status .Authenticated {
44+ case len (review .Status .Error ) > 0 :
45+ return nil , t , fmt .Errorf ("strategies/kubernetes: Failed to authenticate token" )
46+ case ! review .Status .Authenticated :
9547 return nil , t , fmt .Errorf ("strategies/kubernetes: Token Unauthorized" )
48+ default :
49+ user := review .Status .User
50+ extensions := make (map [string ][]string )
51+ for k , v := range user .Extra {
52+ extensions [k ] = v
53+ }
54+ return auth .NewUserInfo (user .Username , user .UID , user .Groups , extensions ), t , nil
9655 }
97-
98- user := tr .Status .User
99- extensions := make (map [string ][]string )
100- for k , v := range user .Extra {
101- extensions [k ] = v
102- }
103-
104- return auth .NewUserInfo (user .Username , user .UID , user .Groups , extensions ), t , nil
10556}
10657
10758// GetAuthenticateFunc return function to authenticate request using kubernetes token review.
@@ -118,19 +69,21 @@ func New(c auth.Cache, opts ...auth.Option) auth.Strategy {
11869}
11970
12071func newKubeReview (opts ... auth.Option ) * kubeReview {
72+
12173 kr := & kubeReview {
122- addr : "http://127.0.0.1:6443" ,
123- apiVersion : "authentication.k8s.io/v1" ,
124- client : & http.Client {
125- Transport : & http.Transport {},
74+ requester : & internal.Requester {
75+ Addr : "http://127.0.0.1:6443" ,
76+ Endpoint : "/apis/authentication.k8s.io/v1/tokenreviews" ,
77+ Client : & http.Client {
78+ Transport : & http.Transport {},
79+ },
12680 },
12781 }
12882
12983 for _ , opt := range opts {
13084 opt .Apply (kr )
85+ opt .Apply (kr .requester )
13186 }
13287
133- kr .addr = strings .TrimSuffix (kr .addr , "/" )
134- kr .apiVersion = strings .TrimPrefix (strings .TrimSuffix (kr .apiVersion , "/" ), "/" )
13588 return kr
13689}
0 commit comments