Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Commit eb75eef

Browse files
committed
Set the remote client IP as what is present in x-forwarded header
Signed-off-by: JoshVanL <[email protected]>
1 parent 6af47f8 commit eb75eef

File tree

5 files changed

+63
-32
lines changed

5 files changed

+63
-32
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40
88
github.com/onsi/ginkgo v1.10.1
99
github.com/onsi/gomega v1.7.0
10+
github.com/sebest/xff v0.0.0-20160910043805-6c115e0ffa35
1011
github.com/sirupsen/logrus v1.4.2
1112
github.com/spf13/cobra v0.0.5
1213
github.com/spf13/pflag v1.0.5

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNG
259259
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
260260
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
261261
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
262+
github.com/sebest/xff v0.0.0-20160910043805-6c115e0ffa35 h1:eajwn6K3weW5cd1ZXLu2sJ4pvwlBiCWY4uDejOr73gM=
263+
github.com/sebest/xff v0.0.0-20160910043805-6c115e0ffa35/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0=
262264
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
263265
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
264266
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=

pkg/proxy/context/context.go

+35-17
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
package context
33

44
import (
5-
"context"
65
"net/http"
76

7+
"github.com/sebest/xff"
88
"k8s.io/apiserver/pkg/endpoints/request"
99
"k8s.io/client-go/transport"
1010
)
@@ -20,37 +20,55 @@ const (
2020

2121
// bearerTokenKey is the context key for the bearer token.
2222
bearerTokenKey
23+
24+
// bearerTokenKey is the context key for the client address.
25+
clientAddressKey
2326
)
2427

25-
// WithNoImpersonation returns a copy of parent in which the noImpersonation value is set.
26-
func WithNoImpersonation(parent context.Context) context.Context {
27-
return request.WithValue(parent, noImpersonationKey, true)
28+
// WithNoImpersonation returns a copy of the request in which the noImpersonation context value is set.
29+
func WithNoImpersonation(req *http.Request) *http.Request {
30+
return req.WithContext(request.WithValue(req.Context(), noImpersonationKey, true))
2831
}
2932

30-
// NoImpersonation returns whether the noImpersonation key has been set
31-
func NoImpersonation(ctx context.Context) bool {
32-
noImp, _ := ctx.Value(noImpersonationKey).(bool)
33+
// NoImpersonation returns whether the noImpersonation context key has been set
34+
func NoImpersonation(req *http.Request) bool {
35+
noImp, _ := req.Context().Value(noImpersonationKey).(bool)
3336
return noImp
3437
}
3538

3639
// WithImpersonationConfig returns a copy of parent in which contains the impersonation configuration.
37-
func WithImpersonationConfig(parent context.Context, conf *transport.ImpersonationConfig) context.Context {
38-
return request.WithValue(parent, impersonationConfigKey, conf)
40+
func WithImpersonationConfig(req *http.Request, conf *transport.ImpersonationConfig) *http.Request {
41+
return req.WithContext(request.WithValue(req.Context(), impersonationConfigKey, conf))
3942
}
4043

4144
// ImpersonationConfig returns the impersonation configuration held in the context if existing.
42-
func ImpersonationConfig(ctx context.Context) *transport.ImpersonationConfig {
43-
conf, _ := ctx.Value(impersonationConfigKey).(*transport.ImpersonationConfig)
45+
func ImpersonationConfig(req *http.Request) *transport.ImpersonationConfig {
46+
conf, _ := req.Context().Value(impersonationConfigKey).(*transport.ImpersonationConfig)
4447
return conf
4548
}
4649

47-
// WithBearerToken will add the bearer token from an http.Header to the context.
48-
func WithBearerToken(parent context.Context, header http.Header) context.Context {
49-
return request.WithValue(parent, bearerTokenKey, header.Get("Authorization"))
50+
// WithBearerToken will add the bearer token to the request context from an http.Header to the request context.
51+
func WithBearerToken(req *http.Request, header http.Header) *http.Request {
52+
return req.WithContext(request.WithValue(req.Context(), bearerTokenKey, header.Get("Authorization")))
5053
}
5154

52-
// BearerToken will return the bearer token stored in the context.
53-
func BearerToken(ctx context.Context) string {
54-
token, _ := ctx.Value(bearerTokenKey).(string)
55+
// BearerToken will return the bearer token stored in the request context.
56+
func BearerToken(req *http.Request) string {
57+
token, _ := req.Context().Value(bearerTokenKey).(string)
5558
return token
5659
}
60+
61+
// RemoteAddress will attempt to return the source client address if available
62+
// in the request context. If it is not, it will be gathered from the request
63+
// and entered into the context.
64+
func RemoteAddr(req *http.Request) (*http.Request, string) {
65+
ctx := req.Context()
66+
67+
clientAddress, ok := ctx.Value(clientAddressKey).(string)
68+
if !ok {
69+
clientAddress = xff.GetRemoteAddr(req)
70+
req = req.WithContext(request.WithValue(ctx, clientAddressKey, clientAddress))
71+
}
72+
73+
return req, clientAddress
74+
}

pkg/proxy/handlers.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ func (p *Proxy) withAuthenticateRequest(handler http.Handler) http.Handler {
3939
return
4040
}
4141

42-
klog.V(4).Infof("authenticated request: %s", req.RemoteAddr)
42+
var remoteAddr string
43+
req, remoteAddr = context.RemoteAddr(req)
44+
45+
klog.V(4).Infof("authenticated request: %s", remoteAddr)
4346

4447
// Add the user info to the request context
4548
req = req.WithContext(genericapirequest.WithUser(req.Context(), info.User))
@@ -65,7 +68,7 @@ func (p *Proxy) withTokenReview(handler http.Handler) http.Handler {
6568
}
6669

6770
// Set no impersonation headers and re-add removed headers.
68-
req = req.WithContext(context.WithNoImpersonation(req.Context()))
71+
req = context.WithNoImpersonation(req)
6972

7073
handler.ServeHTTP(rw, req)
7174
})
@@ -75,16 +78,19 @@ func (p *Proxy) withTokenReview(handler http.Handler) http.Handler {
7578
func (p *Proxy) withImpersonateRequest(handler http.Handler) http.Handler {
7679
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
7780
// If no impersonation has already been set, return early
78-
if context.NoImpersonation(req.Context()) {
81+
if context.NoImpersonation(req) {
7982
handler.ServeHTTP(rw, req)
8083
return
8184
}
8285

86+
var remoteAddr string
87+
req, remoteAddr = context.RemoteAddr(req)
88+
8389
// If we have disabled impersonation we can forward the request right away
8490
if p.config.DisableImpersonation {
85-
klog.V(2).Infof("passing on request with no impersonation: %s", req.RemoteAddr)
91+
klog.V(2).Infof("passing on request with no impersonation: %s", remoteAddr)
8692
// Indicate we need to not use impersonation.
87-
req = req.WithContext(context.WithNoImpersonation(req.Context()))
93+
req = context.WithNoImpersonation(req)
8894
handler.ServeHTTP(rw, req)
8995
return
9096
}
@@ -124,16 +130,16 @@ func (p *Proxy) withImpersonateRequest(handler http.Handler) http.Handler {
124130
// address.
125131
if p.config.ExtraUserHeadersClientIPEnabled {
126132
klog.V(6).Infof("adding impersonate extra user header %s: %s (%s)",
127-
UserHeaderClientIPKey, req.RemoteAddr, req.RemoteAddr)
133+
UserHeaderClientIPKey, remoteAddr, remoteAddr)
128134

129-
extra[UserHeaderClientIPKey] = append(extra[UserHeaderClientIPKey], req.RemoteAddr)
135+
extra[UserHeaderClientIPKey] = append(extra[UserHeaderClientIPKey], remoteAddr)
130136
}
131137

132138
// Add custom extra user headers to impersonation request.
133139
for k, vs := range p.config.ExtraUserHeaders {
134140
for _, v := range vs {
135141
klog.V(6).Infof("adding impersonate extra user header %s: %s (%s)",
136-
k, v, req.RemoteAddr)
142+
k, v, remoteAddr)
137143

138144
extra[k] = append(extra[k], v)
139145
}
@@ -146,7 +152,7 @@ func (p *Proxy) withImpersonateRequest(handler http.Handler) http.Handler {
146152
}
147153

148154
// Add the impersonation configuration to the context.
149-
req = req.WithContext(context.WithImpersonationConfig(req.Context(), conf))
155+
req = context.WithImpersonationConfig(req, conf)
150156
handler.ServeHTTP(rw, req)
151157
})
152158
}

pkg/proxy/proxy.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,14 @@ func (p *Proxy) RoundTrip(req *http.Request) (*http.Response, error) {
165165

166166
// If no impersonation then we return here without setting impersonation
167167
// header but re-introduce the token we removed.
168-
if context.NoImpersonation(req.Context()) {
169-
token := context.BearerToken(req.Context())
168+
if context.NoImpersonation(req) {
169+
token := context.BearerToken(req)
170170
req.Header.Add("Authorization", token)
171171
return p.noAuthClientTransport.RoundTrip(req)
172172
}
173173

174174
// Get the impersonation headers from the context.
175-
conf := context.ImpersonationConfig(req.Context())
175+
conf := context.ImpersonationConfig(req)
176176
if conf == nil {
177177
return nil, errNoImpersonationConfig
178178
}
@@ -183,20 +183,24 @@ func (p *Proxy) RoundTrip(req *http.Request) (*http.Response, error) {
183183
// Push request through round trippers to the API server.
184184
return rt.RoundTrip(req)
185185
}
186+
186187
func (p *Proxy) reviewToken(rw http.ResponseWriter, req *http.Request) bool {
188+
var remoteAddr string
189+
req, remoteAddr = context.RemoteAddr(req)
190+
187191
klog.V(4).Infof("attempting to validate a token in request using TokenReview endpoint(%s)",
188-
req.RemoteAddr)
192+
remoteAddr)
189193

190194
ok, err := p.tokenReviewer.Review(req)
191195
if err != nil {
192196
klog.Errorf("unable to authenticate the request via TokenReview due to an error (%s): %s",
193-
req.RemoteAddr, err)
197+
remoteAddr, err)
194198
return false
195199
}
196200

197201
if !ok {
198202
klog.V(4).Infof("passing request with valid token through (%s)",
199-
req.RemoteAddr)
203+
remoteAddr)
200204

201205
return false
202206
}

0 commit comments

Comments
 (0)