Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impersonation support for the dashboard #4082

Merged
merged 7 commits into from
Jul 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/user/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,21 @@
* [Integrations](integrations.md)
* [Labels](labels.md)

## User Impersonation

Impersonation uses a reverse proxy to inject a user's identifying information (username, groups and extra scopes) as headers in each request to the API server. The Dashboard can pass these headers to the API server if your reverse proxy will inject them in the requests.

![Impersonation Architecture](images/dashboard-impersonation.png "Impersonation Architecture")

Impersonation is useful in situations where using a user's token isn't available, such as cloud-hosted Kubernetes services. To use impersonation a reverse proxy must:

1. Have a Kubernetes service account that [has RBAC permissions to impersonate other users](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation)
2. Generate the `Impersonate-User` header with a unique name identifying the user
3. *Optional* Generate the `Impersonate-Group` header(s) with the impersonated user's group data
4. *Optional* Generate the `Impersonate-Extra` header(s) with additional authorization data

Impersonation will only work when the reverse proxy provides the `Authorization` header with a valid service account. It will not work with any other method of authenticating to the dashboard.


----
_Copyright 2019 [The Kubernetes Dashboard Authors](https://github.com/kubernetes/dashboard/graphs/contributors)_
Binary file added docs/user/images/dashboard-impersonation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions i18n/messages.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2597,7 +2597,7 @@
<target>Compte de service par défaut</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">26</context>
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="f798949a4cdc74591fbf665c178513e4219c0898" datatype="html">
Expand All @@ -2606,7 +2606,7 @@
<target>Connexion</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">34</context>
<context context-type="linenumber">36</context>
</context-group>
</trans-unit>
<trans-unit id="6426cc90184df1cdb238f45fce5220df8438ed62" datatype="html">
Expand All @@ -2615,7 +2615,7 @@
<target>Déconnexion</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="bef0c68b6a7d96b56a8879ecfb9de80a83c151a2" datatype="html">
Expand Down
6 changes: 3 additions & 3 deletions i18n/messages.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2423,7 +2423,7 @@
<target>デフォルトのサービスアカウント</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">26</context>
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="f798949a4cdc74591fbf665c178513e4219c0898" datatype="html">
Expand All @@ -2432,7 +2432,7 @@
<target>サインイン</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">34</context>
<context context-type="linenumber">36</context>
</context-group>
</trans-unit>
<trans-unit id="6426cc90184df1cdb238f45fce5220df8438ed62" datatype="html">
Expand All @@ -2441,7 +2441,7 @@
<target>サインアウト</target>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
Expand Down
6 changes: 3 additions & 3 deletions i18n/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2224,23 +2224,23 @@
<source>Default service account</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">26</context>
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="f798949a4cdc74591fbf665c178513e4219c0898" datatype="html">
<source>Sign in
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">34</context>
<context context-type="linenumber">36</context>
</context-group>
</trans-unit>
<trans-unit id="6426cc90184df1cdb238f45fce5220df8438ed62" datatype="html">
<source>Sign out
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/userpanel/template.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
Expand Down
29 changes: 28 additions & 1 deletion src/app/backend/client/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ const (
JWETokenHeader = "jweToken"
// Default http header for user-agent
DefaultUserAgent = "dashboard"
//Impersonation Extra header
ImpersonateUserExtraHeader = "Impersonate-Extra-"
)

// VERSION of this binary
Expand Down Expand Up @@ -311,12 +313,37 @@ func (self *clientManager) buildCmdConfig(authInfo *api.AuthInfo, cfg *rest.Conf
// Extracts authorization information from the request header
func (self *clientManager) extractAuthInfo(req *restful.Request) (*api.AuthInfo, error) {
authHeader := req.HeaderParameter("Authorization")
impersonationHeader := req.HeaderParameter("Impersonate-User")
jweToken := req.HeaderParameter(JWETokenHeader)

// Authorization header will be more important than our token
token := self.extractTokenFromHeader(authHeader)
if len(token) > 0 {
return &api.AuthInfo{Token: token}, nil

authInfo := &api.AuthInfo{Token: token}

if len(impersonationHeader) > 0 {
//there's an impersonation header, lets make sure to add it
authInfo.Impersonate = impersonationHeader

//Check for impersonated groups
if groupsImpersonationHeader := req.Request.Header["Impersonate-Group"]; len(groupsImpersonationHeader) > 0 {
authInfo.ImpersonateGroups = groupsImpersonationHeader
}

//check for extra fields
for headerName, headerValues := range req.Request.Header {
if strings.HasPrefix(headerName, ImpersonateUserExtraHeader) {
extraName := headerName[len(ImpersonateUserExtraHeader):]
if authInfo.ImpersonateUserExtra == nil {
authInfo.ImpersonateUserExtra = make(map[string][]string)
}
authInfo.ImpersonateUserExtra[extraName] = headerValues
}
}
}

return authInfo, nil
}

if self.tokenManager != nil && len(jweToken) > 0 {
Expand Down
Loading