Skip to content

Commit 23d319a

Browse files
committed
Use the Upstream header for scope impersonation
Note: the upstream function does not forcibliy remove potential existing impersonation headers, and it also uses the existing ones ignoring any new headers we may be setting. This i ok, because we do not depend nor probably want to allow multiple levels of impersonation. Signed-off-by: Simo Sorce <[email protected]>
1 parent 3dcad95 commit 23d319a

File tree

4 files changed

+22
-39
lines changed

4 files changed

+22
-39
lines changed

hack/import-restrictions.json

-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,6 @@
367367
"allowedImportPackages": [
368368
"vendor/github.com/golang/glog",
369369
"vendor/k8s.io/kubernetes/pkg/api/legacyscheme",
370-
"github.com/openshift/origin/pkg/authorization/apis/authorization",
371370
"github.com/openshift/origin/pkg/cmd/server/api",
372371
"github.com/openshift/origin/pkg/util/http/links",
373372
"github.com/openshift/origin/pkg/authorization/authorizer/scope",

pkg/cmd/server/origin/handlers.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424

2525
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
2626
configapi "github.com/openshift/origin/pkg/cmd/server/api"
27-
authenticationapi "github.com/openshift/origin/pkg/oauthserver/api"
2827
)
2928

3029
// cacheExcludedPaths is small and simple until the handlers include the cache headers they need
@@ -155,10 +154,15 @@ func (c *MasterConfig) versionSkewFilter(handler http.Handler, contextMapper api
155154
})
156155
}
157156

157+
// legacyImpersonateUserScopeHeader is the header name older servers were using
158+
// just for scopes, so we need to translate it from clients that may still be
159+
// using it.
160+
const legacyImpersonateUserScopeHeader = "Impersonate-User-Scope"
161+
158162
// translateLegacyScopeImpersonation is a filter that will translates user scope impersonation for openshift into the equivalent kube headers.
159163
func translateLegacyScopeImpersonation(handler http.Handler) http.Handler {
160164
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
161-
for _, scope := range req.Header[authenticationapi.ImpersonateUserScopeHeader] {
165+
for _, scope := range req.Header[legacyImpersonateUserScopeHeader] {
162166
req.Header[authenticationv1.ImpersonateUserExtraHeaderPrefix+authorizationapi.ScopesKey] =
163167
append(req.Header[authenticationv1.ImpersonateUserExtraHeaderPrefix+authorizationapi.ScopesKey], scope)
164168
}

pkg/oauthserver/client/impersonate.go

+12-34
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,23 @@ import (
55

66
"k8s.io/apimachinery/pkg/runtime/schema"
77
"k8s.io/apimachinery/pkg/types"
8-
utilnet "k8s.io/apimachinery/pkg/util/net"
98
"k8s.io/apiserver/pkg/authentication/user"
109
restclient "k8s.io/client-go/rest"
10+
"k8s.io/client-go/transport"
1111
"k8s.io/client-go/util/flowcontrol"
1212
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
13-
14-
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
15-
authenticationapi "github.com/openshift/origin/pkg/oauthserver/api"
1613
)
1714

18-
type impersonatingRoundTripper struct {
19-
user user.Info
20-
delegate http.RoundTripper
21-
}
22-
23-
// newImpersonatingRoundTripper will add headers to impersonate a user, including user, groups, and scopes
24-
func newImpersonatingRoundTripper(user user.Info, delegate http.RoundTripper) http.RoundTripper {
25-
return &impersonatingRoundTripper{user: user, delegate: delegate}
26-
}
27-
28-
func (rt *impersonatingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
29-
req = utilnet.CloneRequest(req)
30-
req.Header.Del(authenticationapi.ImpersonateUserHeader)
31-
req.Header.Del(authenticationapi.ImpersonateGroupHeader)
32-
req.Header.Del(authenticationapi.ImpersonateUserScopeHeader)
33-
34-
req.Header.Set(authenticationapi.ImpersonateUserHeader, rt.user.GetName())
35-
for _, group := range rt.user.GetGroups() {
36-
req.Header.Add(authenticationapi.ImpersonateGroupHeader, group)
37-
}
38-
for _, scope := range rt.user.GetExtra()[authorizationapi.ScopesKey] {
39-
req.Header.Add(authenticationapi.ImpersonateUserScopeHeader, scope)
40-
}
41-
return rt.delegate.RoundTrip(req)
42-
}
43-
4415
// NewImpersonatingConfig wraps the config's transport to impersonate a user, including user, groups, and scopes
4516
func NewImpersonatingConfig(user user.Info, config restclient.Config) restclient.Config {
4617
oldWrapTransport := config.WrapTransport
4718
config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
48-
return newImpersonatingRoundTripper(user, oldWrapTransport(rt))
19+
newConfig := transport.ImpersonationConfig{
20+
UserName: user.GetName(),
21+
Groups: user.GetGroups(),
22+
Extra: user.GetExtra(),
23+
}
24+
return transport.NewImpersonatingRoundTripper(newConfig, oldWrapTransport(rt))
4925
}
5026
return config
5127
}
@@ -68,9 +44,11 @@ func NewImpersonatingRESTClient(user user.Info, client restclient.Interface) res
6844

6945
// Verb does the impersonation per request by setting the proper headers
7046
func (c impersonatingRESTClient) impersonate(req *restclient.Request) *restclient.Request {
71-
req.SetHeader(authenticationapi.ImpersonateUserHeader, c.user.GetName())
72-
req.SetHeader(authenticationapi.ImpersonateGroupHeader, c.user.GetGroups()...)
73-
req.SetHeader(authenticationapi.ImpersonateUserScopeHeader, c.user.GetExtra()[authorizationapi.ScopesKey]...)
47+
req.SetHeader(transport.ImpersonateUserHeader, c.user.GetName())
48+
req.SetHeader(transport.ImpersonateGroupHeader, c.user.GetGroups()...)
49+
for k, vv := range c.user.GetExtra() {
50+
req.SetHeader(transport.ImpersonateUserExtraHeaderPrefix+k, vv...)
51+
}
7452
return req
7553
}
7654

test/integration/scopes_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package integration
33
import (
44
"testing"
55

6+
authenticationv1 "k8s.io/api/authentication/v1"
67
kapierrors "k8s.io/apimachinery/pkg/api/errors"
78
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
89
apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
910
"k8s.io/client-go/rest"
1011
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
1112

13+
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
1214
"github.com/openshift/origin/pkg/authorization/authorizer/scope"
1315
buildapi "github.com/openshift/origin/pkg/build/apis/build"
1416
buildclient "github.com/openshift/origin/pkg/build/generated/internalclientset"
@@ -106,7 +108,7 @@ func TestScopedImpersonation(t *testing.T) {
106108

107109
err = clusterAdminBuildClient.Build().RESTClient().Get().
108110
SetHeader(authenticationapi.ImpersonateUserHeader, "harold").
109-
SetHeader(authenticationapi.ImpersonateUserScopeHeader, "user:info").
111+
SetHeader(authenticationv1.ImpersonateUserExtraHeaderPrefix+authorizationapi.ScopesKey, "user:info").
110112
Namespace(projectName).Resource("builds").Name("name").Do().Into(&buildapi.Build{})
111113
if !kapierrors.IsForbidden(err) {
112114
t.Fatalf("unexpected error: %v", err)
@@ -115,7 +117,7 @@ func TestScopedImpersonation(t *testing.T) {
115117
user := &userapi.User{}
116118
err = userclient.NewForConfigOrDie(clusterAdminClientConfig).RESTClient().Get().
117119
SetHeader(authenticationapi.ImpersonateUserHeader, "harold").
118-
SetHeader(authenticationapi.ImpersonateUserScopeHeader, "user:info").
120+
SetHeader(authenticationv1.ImpersonateUserExtraHeaderPrefix+authorizationapi.ScopesKey, "user:info").
119121
Resource("users").Name("~").Do().Into(user)
120122
if err != nil {
121123
t.Fatalf("unexpected error: %v", err)

0 commit comments

Comments
 (0)