@@ -10,6 +10,7 @@ import (
1010 "strings"
1111 "time"
1212
13+ utilnet "k8s.io/apimachinery/pkg/util/net"
1314 "k8s.io/apiserver/pkg/authentication/request/bearertoken"
1415 authuser "k8s.io/apiserver/pkg/authentication/user"
1516 "k8s.io/apiserver/pkg/server"
@@ -31,35 +32,46 @@ var (
3132 impersonateExtraHeader = strings .ToLower (transport .ImpersonateUserExtraHeaderPrefix )
3233)
3334
35+ type Options struct {
36+ DisableImpersonation bool
37+ TokenReview bool
38+ }
39+
3440type Proxy struct {
3541 oidcAuther * bearertoken.Authenticator
36- tokenAuther * tokenreview.TokenReview
42+ tokenReviewer * tokenreview.TokenReview
3743 secureServingInfo * server.SecureServingInfo
3844
3945 restConfig * rest.Config
4046 clientTransport http.RoundTripper
4147 noAuthClientTransport http.RoundTripper
48+
49+ options * Options
4250}
4351
4452func New (restConfig * rest.Config , oidcAuther * bearertoken.Authenticator ,
45- tokenAuther * tokenreview.TokenReview , ssinfo * server.SecureServingInfo ) * Proxy {
53+ tokenReviewer * tokenreview.TokenReview , ssinfo * server.SecureServingInfo , options * Options ) * Proxy {
4654 return & Proxy {
4755 restConfig : restConfig ,
4856 oidcAuther : oidcAuther ,
49- tokenAuther : tokenAuther ,
57+ tokenReviewer : tokenReviewer ,
5058 secureServingInfo : ssinfo ,
59+ options : options ,
5160 }
5261}
5362
5463func (p * Proxy ) Run (stopCh <- chan struct {}) (<- chan struct {}, error ) {
64+ klog .Infof ("waiting for oidc provider to become ready..." )
65+
66+ // standard round tripper for proxy to API Server
5567 clientRT , err := p .roundTripperForRestConfig (p .restConfig )
5668 if err != nil {
5769 return nil , err
5870 }
5971 p .clientTransport = clientRT
6072
6173 // No auth round tripper for no impersonation
62- if p .tokenAuther != nil {
74+ if p .options . DisableImpersonation || p . options . TokenReview {
6375 noAuthClientRT , err := p .roundTripperForRestConfig (& rest.Config {
6476 APIPath : p .restConfig .APIPath ,
6577 Host : p .restConfig .Host ,
@@ -112,42 +124,38 @@ func (p *Proxy) serve(proxyHandler *httputil.ReverseProxy, stopCh <-chan struct{
112124}
113125
114126func (p * Proxy ) RoundTrip (req * http.Request ) (* http.Response , error ) {
115- // auth request and handle unauthed
116- info , ok , err := p .oidcAuther .AuthenticateRequest (req )
127+ // Clone the request here since successfully authenticating the request
128+ // deletes those auth headers
129+ reqCpy := utilnet .CloneRequest (req )
117130
131+ // auth request and handle unauthed
132+ info , ok , err := p .oidcAuther .AuthenticateRequest (reqCpy )
118133 if err != nil {
119134
120135 // attempt to passthrough request if valid token
121- if p .tokenAuther != nil {
122- klog .V (4 ).Infof ("attempting to validate a token in request using TokenReview endpoint(%s)" ,
123- req .RemoteAddr )
124-
125- ok , tkErr := p .tokenAuther .Review (req )
126- // no error so passthrough the request
127- if tkErr == nil && ok {
128- klog .V (4 ).Infof ("passing request with valid token through (%s)" ,
129- req .RemoteAddr )
130- // Don't set impersonation headers and pass through without proxy auth
131- // and headers still set
132- return p .noAuthClientTransport .RoundTrip (req )
133- }
134-
135- if tkErr != nil {
136- err = fmt .Errorf ("%s, %s" , err , tkErr )
137- }
136+ if p .options .TokenReview {
137+ return p .tokenReview (reqCpy )
138138 }
139139
140- klog .Errorf ("unable to authenticate the request due to an error (%s): %s" ,
141- req .RemoteAddr , err )
142140 return nil , errUnauthorized
143141 }
144142
143+ // failed authorization
145144 if ! ok {
146145 return nil , errUnauthorized
147146 }
148147
148+ klog .V (4 ).Infof ("authenticated request: %s" , reqCpy .RemoteAddr )
149+
150+ // if we have disabled impersonation we can forward the request right away
151+ if p .options .DisableImpersonation {
152+ klog .V (2 ).Infof ("passing on request with no impersonation: %s" , reqCpy .RemoteAddr )
153+ // Send original copy here with auth header intact
154+ return p .noAuthClientTransport .RoundTrip (req )
155+ }
156+
149157 // check for incoming impersonation headers and reject if any exists
150- if p .hasImpersonation (req .Header ) {
158+ if p .hasImpersonation (reqCpy .Header ) {
151159 return nil , errImpersonateHeader
152160 }
153161
@@ -182,7 +190,29 @@ func (p *Proxy) RoundTrip(req *http.Request) (*http.Response, error) {
182190 rt := transport .NewImpersonatingRoundTripper (conf , p .clientTransport )
183191
184192 // push request through round trippers to the API server
185- return rt .RoundTrip (req )
193+ return rt .RoundTrip (reqCpy )
194+ }
195+
196+ func (p * Proxy ) tokenReview (req * http.Request ) (* http.Response , error ) {
197+ klog .V (4 ).Infof ("attempting to validate a token in request using TokenReview endpoint(%s)" ,
198+ req .RemoteAddr )
199+
200+ ok , err := p .tokenReviewer .Review (req )
201+ // no error so passthrough the request
202+ if err == nil && ok {
203+ klog .V (4 ).Infof ("passing request with valid token through (%s)" ,
204+ req .RemoteAddr )
205+ // Don't set impersonation headers and pass through without proxy auth
206+ // and headers still set
207+ return p .noAuthClientTransport .RoundTrip (req )
208+ }
209+
210+ if err != nil {
211+ klog .Errorf ("unable to authenticate the request via TokenReview due to an error (%s): %s" ,
212+ req .RemoteAddr , err )
213+ }
214+
215+ return nil , errUnauthorized
186216}
187217
188218func (p * Proxy ) hasImpersonation (header http.Header ) bool {
0 commit comments