@@ -11,11 +11,13 @@ import (
1111 "net/http"
1212 "net/http/httputil"
1313 "net/textproto"
14+ "os"
1415 "regexp"
1516 "strings"
1617 "time"
1718
1819 "github.com/go-logr/logr"
20+ "github.com/golang-jwt/jwt/v5"
1921 "github.com/gorilla/handlers"
2022 "github.com/gorilla/mux"
2123 "github.com/pkg/errors"
@@ -80,7 +82,9 @@ func NewKubeFilter(opts options.ListenerOpts, srv options.ServerOptions, gates f
8082 impersonationGroupsRegexp : opts .ImpersonationGroupsRegexp (),
8183 skipImpersonationReview : opts .SkipImpersonationReview (),
8284 reverseProxy : reverseProxy ,
85+ bearerTokenFile : opts .BearerTokenFile (),
8386 bearerToken : opts .BearerToken (),
87+ bearerTokenExpirationTime : bearerExpirationTime (opts .BearerToken ()),
8488 usernameClaimField : opts .PreferredUsernameClaim (),
8589 serverOptions : srv ,
8690 log : ctrl .Log .WithName ("proxy" ),
@@ -97,6 +101,8 @@ type kubeFilter struct {
97101 skipImpersonationReview bool
98102 reverseProxy * httputil.ReverseProxy
99103 bearerToken string
104+ bearerTokenFile string
105+ bearerTokenExpirationTime int64
100106 usernameClaimField string
101107 serverOptions options.ServerOptions
102108 log logr.Logger
@@ -180,9 +186,9 @@ func (n *kubeFilter) handleRequest(request *http.Request, selector labels.Select
180186 n .log .V (4 ).Info ("updating RawQuery" , "query" , q .Encode ())
181187 request .URL .RawQuery = q .Encode ()
182188
183- if len (n .bearerToken ) > 0 {
184- n .log .V (4 ).Info ("Updating the token" , "token" , n .bearerToken )
185- request .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , n .bearerToken ))
189+ if len (n .BearerToken () ) > 0 {
190+ n .log .V (4 ).Info ("Updating the token" , "token" , n .BearerToken () )
191+ request .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , n .BearerToken () ))
186192 }
187193}
188194
@@ -203,8 +209,8 @@ func (n *kubeFilter) impersonateHandler(writer http.ResponseWriter, request *htt
203209
204210 n .log .V (4 ).Info ("impersonating for the current request" , "username" , username , "groups" , groups , "uri" , request .URL .Path )
205211
206- if len (n .bearerToken ) > 0 {
207- request .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , n .bearerToken ))
212+ if len (n .BearerToken () ) > 0 {
213+ request .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , n .BearerToken () ))
208214 }
209215 // Dropping malicious header connection
210216 // https://github.com/projectcapsule/capsule-proxy/issues/188
@@ -502,3 +508,30 @@ func (n *kubeFilter) removingHopByHopHeaders(request *http.Request) {
502508
503509 request .Header .Del (connectionHeaderName )
504510}
511+
512+ func (n * kubeFilter ) BearerToken () string {
513+ tm := time .Unix (n .bearerTokenExpirationTime , 0 )
514+ if ! tm .After (time .Now ()) {
515+ n .log .V (5 ).Info ("Token expired. Reading new token from file" , "token" , n .bearerToken , "token file" , n .bearerTokenFile )
516+ token , _ := os .ReadFile (n .bearerTokenFile )
517+ n .bearerToken = string (token )
518+ n .bearerTokenExpirationTime = bearerExpirationTime (string (token ))
519+ }
520+
521+ return n .bearerToken
522+ }
523+
524+ func bearerExpirationTime (tokenString string ) int64 {
525+ token , _ , _ := new (jwt.Parser ).ParseUnverified (tokenString , jwt.MapClaims {})
526+ claims , _ := token .Claims .(jwt.MapClaims )
527+
528+ var mil int64
529+ switch iat := claims ["exp" ].(type ) {
530+ case float64 :
531+ mil = int64 (iat )
532+ case json.Number :
533+ mil , _ = iat .Int64 ()
534+ }
535+
536+ return mil
537+ }
0 commit comments