Skip to content

Commit 1cf1de7

Browse files
committed
fix: support service account bound token expiration
Signed-off-by: Pedro Parra Ortega <parraortega.pedro@gmail.com> fix: save time instead Signed-off-by: Pedro Parra Ortega <parraortega.pedro@gmail.com> fix: Update internal/webserver/webserver.go Co-authored-by: Dario Tranchitella <dario@tranchitella.eu> Signed-off-by: Pedro Parra Ortega <parraortega.pedro@gmail.com> fix: correct typo Signed-off-by: Pedro Parra Ortega <parraortega.pedro@gmail.com>
1 parent f854815 commit 1cf1de7

File tree

5 files changed

+45
-5
lines changed

5 files changed

+45
-5
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.21
44

55
require (
66
github.com/go-logr/logr v1.4.2
7+
github.com/golang-jwt/jwt/v5 v5.2.1
78
github.com/gorilla/handlers v1.5.2
89
github.com/gorilla/mux v1.8.1
910
github.com/pkg/errors v0.9.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
6262
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
6363
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
6464
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
65+
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
66+
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
6567
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
6668
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
6769
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=

internal/options/kube.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ func (k kubeOpts) BearerToken() string {
6464
return k.config.BearerToken
6565
}
6666

67+
func (k kubeOpts) BearerTokenFile() string {
68+
return k.config.BearerTokenFile
69+
}
70+
6771
func (k kubeOpts) KubernetesControlPlaneURL() *url.URL {
6872
return &k.url
6973
}

internal/options/listener.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type ListenerOpts interface {
1919
ImpersonationGroupsRegexp() *regexp.Regexp
2020
PreferredUsernameClaim() string
2121
ReverseProxyTransport() (*http.Transport, error)
22+
BearerTokenFile() string
2223
BearerToken() string
2324
SkipImpersonationReview() bool
2425
}

internal/webserver/webserver.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)