Skip to content

Commit

Permalink
fix: support for service account bound tokens expiration
Browse files Browse the repository at this point in the history
Signed-off-by: Pedro Parra Ortega <[email protected]>

chore: added missing file

Signed-off-by: Pedro Parra Ortega <[email protected]>

chore: lint

Signed-off-by: Pedro Parra Ortega <[email protected]>

chore: lint file

Signed-off-by: Pedro Parra Ortega <[email protected]>
  • Loading branch information
ppodevlabs committed Nov 11, 2024
1 parent 1920efd commit a0b22b7
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 5 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.21

require (
github.com/go-logr/logr v1.4.1
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
github.com/pkg/errors v0.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
Expand Down
4 changes: 4 additions & 0 deletions internal/options/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ func (k kubeOpts) BearerToken() string {
return k.config.BearerToken
}

func (k kubeOpts) BearerTokenFile() string {
return k.config.BearerTokenFile
}

func (k kubeOpts) KubernetesControlPlaneURL() *url.URL {
return &k.url
}
Expand Down
1 change: 1 addition & 0 deletions internal/options/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type ListenerOpts interface {
ImpersonationGroupsRegexp() *regexp.Regexp
PreferredUsernameClaim() string
ReverseProxyTransport() (*http.Transport, error)
BearerTokenFile() string
BearerToken() string
SkipImpersonationReview() bool
}
43 changes: 38 additions & 5 deletions internal/webserver/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import (
"net/http"
"net/http/httputil"
"net/textproto"
"os"
"regexp"
"strings"
"time"

"github.com/go-logr/logr"
"github.com/golang-jwt/jwt/v5"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/pkg/errors"
Expand Down Expand Up @@ -80,7 +82,9 @@ func NewKubeFilter(opts options.ListenerOpts, srv options.ServerOptions, gates f
impersonationGroupsRegexp: opts.ImpersonationGroupsRegexp(),
skipImpersonationReview: opts.SkipImpersonationReview(),
reverseProxy: reverseProxy,
bearerTokenFile: opts.BearerTokenFile(),
bearerToken: opts.BearerToken(),
bearerTokenExpirationTime: bearerExpirationTime(opts.BearerToken()),
usernameClaimField: opts.PreferredUsernameClaim(),
serverOptions: srv,
log: ctrl.Log.WithName("proxy"),
Expand All @@ -97,6 +101,8 @@ type kubeFilter struct {
skipImpersonationReview bool
reverseProxy *httputil.ReverseProxy
bearerToken string
bearerTokenFile string
bearerTokenExpirationTime int64
usernameClaimField string
serverOptions options.ServerOptions
log logr.Logger
Expand Down Expand Up @@ -180,9 +186,9 @@ func (n *kubeFilter) handleRequest(request *http.Request, selector labels.Select
n.log.V(4).Info("updating RawQuery", "query", q.Encode())
request.URL.RawQuery = q.Encode()

if len(n.bearerToken) > 0 {
n.log.V(4).Info("Updating the token", "token", n.bearerToken)
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", n.bearerToken))
if len(n.BearerToken()) > 0 {
n.log.V(4).Info("Updating the token", "token", n.BearerToken())
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", n.BearerToken()))
}
}

Expand All @@ -203,8 +209,8 @@ func (n *kubeFilter) impersonateHandler(writer http.ResponseWriter, request *htt

n.log.V(4).Info("impersonating for the current request", "username", username, "groups", groups, "uri", request.URL.Path)

if len(n.bearerToken) > 0 {
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", n.bearerToken))
if len(n.BearerToken()) > 0 {
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", n.BearerToken()))
}
// Dropping malicious header connection
// https://github.com/projectcapsule/capsule-proxy/issues/188
Expand Down Expand Up @@ -502,3 +508,30 @@ func (n *kubeFilter) removingHopByHopHeaders(request *http.Request) {

request.Header.Del(connectionHeaderName)
}

func (n *kubeFilter) BearerToken() string {
tm := time.Unix(n.bearerTokenExpirationTime, 0)
if !tm.After(time.Now()) {
n.log.V(5).Info("Token expired. Reading new token from file", "token", n.bearerToken, "token file", n.bearerTokenFile)
token, _ := os.ReadFile(n.bearerTokenFile)
n.bearerToken = string(token)
n.bearerTokenExpirationTime = bearerExpirationTime(string(token))
}

return n.bearerToken
}

func bearerExpirationTime(tokenString string) int64 {
token, _, _ := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
claims, _ := token.Claims.(jwt.MapClaims)

var mil int64
switch iat := claims["exp"].(type) {
case float64:
mil = int64(iat)
case json.Number:
mil, _ = iat.Int64()
}

return mil
}

0 comments on commit a0b22b7

Please sign in to comment.