@@ -9,11 +9,14 @@ import (
99 "time"
1010
1111 authv1 "k8s.io/api/authentication/v1"
12+ apierrors "k8s.io/apimachinery/pkg/api/errors"
1213 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1314 "k8s.io/client-go/kubernetes"
1415 clientauthv1 "k8s.io/client-go/kubernetes/typed/authentication/v1"
1516 "k8s.io/client-go/rest"
1617
18+ "github.com/jetstack/kube-oidc-proxy/pkg/metrics"
19+ proxycontext "github.com/jetstack/kube-oidc-proxy/pkg/proxy/context"
1720 "github.com/jetstack/kube-oidc-proxy/pkg/util"
1821)
1922
@@ -23,43 +26,73 @@ var (
2326
2427type TokenReview struct {
2528 reviewRequester clientauthv1.TokenReviewInterface
29+ metrics * metrics.Metrics
2630 audiences []string
2731}
2832
29- func New (restConfig * rest.Config , audiences []string ) (* TokenReview , error ) {
33+ func New (restConfig * rest.Config , metrics * metrics. Metrics , audiences []string ) (* TokenReview , error ) {
3034 kubeclient , err := kubernetes .NewForConfig (restConfig )
3135 if err != nil {
3236 return nil , err
3337 }
3438
3539 return & TokenReview {
3640 reviewRequester : kubeclient .AuthenticationV1 ().TokenReviews (),
41+ metrics : metrics ,
3742 audiences : audiences ,
3843 }, nil
3944}
4045
4146func (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+
4258 token , ok := util .ParseTokenFromRequest (req )
4359 if ! ok {
4460 return false , errors .New ("bearer token not found in request" )
4561 }
46-
4762 review := t .buildReview (token )
4863
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+
4975 ctx , cancel := context .WithTimeout (req .Context (), timeout )
5076 defer cancel ()
5177
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 {})
5380 if err != nil {
5481 return false , err
5582 }
5683
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+
5790 if len (resp .Status .Error ) > 0 {
5891 return false , fmt .Errorf ("error authenticating using token review: %s" ,
5992 resp .Status .Error )
6093 }
6194
62- return resp . Status . Authenticated , nil
95+ return authenticated , nil
6396}
6497
6598func (t * TokenReview ) buildReview (token string ) * authv1.TokenReview {
0 commit comments