@@ -9,11 +9,14 @@ import (
9
9
"time"
10
10
11
11
authv1 "k8s.io/api/authentication/v1"
12
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
12
13
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13
14
"k8s.io/client-go/kubernetes"
14
15
clientauthv1 "k8s.io/client-go/kubernetes/typed/authentication/v1"
15
16
"k8s.io/client-go/rest"
16
17
18
+ "github.com/jetstack/kube-oidc-proxy/pkg/metrics"
19
+ proxycontext "github.com/jetstack/kube-oidc-proxy/pkg/proxy/context"
17
20
"github.com/jetstack/kube-oidc-proxy/pkg/util"
18
21
)
19
22
@@ -23,43 +26,73 @@ var (
23
26
24
27
type TokenReview struct {
25
28
reviewRequester clientauthv1.TokenReviewInterface
29
+ metrics * metrics.Metrics
26
30
audiences []string
27
31
}
28
32
29
- func New (restConfig * rest.Config , audiences []string ) (* TokenReview , error ) {
33
+ func New (restConfig * rest.Config , metrics * metrics. Metrics , audiences []string ) (* TokenReview , error ) {
30
34
kubeclient , err := kubernetes .NewForConfig (restConfig )
31
35
if err != nil {
32
36
return nil , err
33
37
}
34
38
35
39
return & TokenReview {
36
40
reviewRequester : kubeclient .AuthenticationV1 ().TokenReviews (),
41
+ metrics : metrics ,
37
42
audiences : audiences ,
38
43
}, nil
39
44
}
40
45
41
46
func (t * TokenReview ) Review (req * http.Request ) (bool , error ) {
47
+ var (
48
+ code int
49
+ user string
50
+ authenticated bool
51
+ err error
52
+ )
53
+
54
+ // Start clock on metrics
55
+ tokenReviewDuration := time .Now ()
56
+ req , remoteAddr := proxycontext .RemoteAddr (req )
57
+
42
58
token , ok := util .ParseTokenFromRequest (req )
43
59
if ! ok {
44
60
return false , errors .New ("bearer token not found in request" )
45
61
}
46
-
47
62
review := t .buildReview (token )
48
63
64
+ // Setup metrics observation on defer
65
+ defer func () {
66
+ if err != nil {
67
+ if status := apierrors .APIStatus (nil ); errors .As (err , & status ) {
68
+ code = int (status .Status ().Code )
69
+ }
70
+ }
71
+
72
+ t .metrics .ObserveTokenReivewLookup (authenticated , code , remoteAddr , user , time .Since (tokenReviewDuration ))
73
+ }()
74
+
49
75
ctx , cancel := context .WithTimeout (req .Context (), timeout )
50
76
defer cancel ()
51
77
52
- resp , err := t .reviewRequester .Create (ctx , review , metav1.CreateOptions {})
78
+ var resp * authv1.TokenReview
79
+ resp , err = t .reviewRequester .Create (ctx , review , metav1.CreateOptions {})
53
80
if err != nil {
54
81
return false , err
55
82
}
56
83
84
+ // Since no error to the API server for token review, we have 200 response
85
+ // code.
86
+ code = 200
87
+ user = resp .Status .User .Username
88
+ authenticated = resp .Status .Authenticated
89
+
57
90
if len (resp .Status .Error ) > 0 {
58
91
return false , fmt .Errorf ("error authenticating using token review: %s" ,
59
92
resp .Status .Error )
60
93
}
61
94
62
- return resp . Status . Authenticated , nil
95
+ return authenticated , nil
63
96
}
64
97
65
98
func (t * TokenReview ) buildReview (token string ) * authv1.TokenReview {
0 commit comments