@@ -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 time.Time
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,29 @@ func (n *kubeFilter) removingHopByHopHeaders(request *http.Request) {
502508
503509 request .Header .Del (connectionHeaderName )
504510}
511+
512+ func (n * kubeFilter ) BearerToken () string {
513+ if time .Now ().After (n .bearerTokenExpirationTime ) {
514+ n .log .V (5 ).Info ("Token expired. Reading new token from file" , "token" , n .bearerToken , "token file" , n .bearerTokenFile )
515+ token , _ := os .ReadFile (n .bearerTokenFile )
516+ n .bearerToken = string (token )
517+ n .bearerTokenExpirationTime = bearerExpirationTime (string (token ))
518+ }
519+
520+ return n .bearerToken
521+ }
522+
523+ func bearerExpirationTime (tokenString string ) time.Time {
524+ token , _ , _ := new (jwt.Parser ).ParseUnverified (tokenString , jwt.MapClaims {})
525+ claims , _ := token .Claims .(jwt.MapClaims )
526+
527+ var mil int64
528+ switch iat := claims ["exp" ].(type ) {
529+ case float64 :
530+ mil = int64 (iat )
531+ case json.Number :
532+ mil , _ = iat .Int64 ()
533+ }
534+
535+ return time .Unix (mil , 0 )
536+ }
0 commit comments