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

feat(kuma-cp) prefix system users and groups with mesh-system #3013

Merged
merged 2 commits into from
Oct 27, 2021
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
4 changes: 2 additions & 2 deletions pkg/api-server/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ var _ = Describe("Auth test", func() {
body, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
Expect(resp.Body.Close()).To(Succeed())
Expect(string(body)).To(MatchJSON(`{"title": "Access Denied", "details": "user did not authenticate"}`))
Expect(string(body)).To(MatchJSON(`{"title": "Access Denied", "details": "user \"mesh-system:anonymous/mesh-system:unauthenticated\" cannot access the resource of type \"Secret\""}`))
})

It("should be block an access to admin endpoints from other machine using HTTPS without proper client certs", func() {
Expand All @@ -126,7 +126,7 @@ var _ = Describe("Auth test", func() {
body, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
Expect(resp.Body.Close()).To(Succeed())
Expect(string(body)).To(MatchJSON(`{"title": "Access Denied", "details": "user did not authenticate"}`))
Expect(string(body)).To(MatchJSON(`{"title": "Access Denied", "details": "user \"mesh-system:anonymous/mesh-system:unauthenticated\" cannot access the resource of type \"Secret\""}`))
})
})

Expand Down
2 changes: 1 addition & 1 deletion pkg/api-server/authn/localhost.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func LocalhostAuthenticator(request *restful.Request, response *restful.Response
}
if host == "127.0.0.1" || host == "::1" {
log.V(1).Info("authenticated as admin because requests originates from the same machine")
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), user.Admin))
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), user.Admin.Authenticated()))
}
chain.ProcessFilter(request, response)
}
12 changes: 6 additions & 6 deletions pkg/api-server/config_ws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,16 @@ var _ = Describe("Config WS", func() {
"type": "static",
"static": {
"adminResources": {
"users": ["admin"],
"groups": ["admin"]
"users": ["mesh-system:admin"],
"groups": ["mesh-system:admin"]
},
"generateDpToken": {
"users": ["admin"],
"groups": ["admin"]
"users": ["mesh-system:admin"],
"groups": ["mesh-system:admin"]
},
"generateUserToken": {
"users": ["admin"],
"groups": ["admin"]
"users": ["mesh-system:admin"],
"groups": ["mesh-system:admin"]
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/config/app/kuma-cp/kuma-cp.defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -400,18 +400,18 @@ rbac:
# AdminResources defines an access to admin resources (Secret/GlobalSecret)
adminResources:
# List of users that are allowed to access admin resources
users: ["admin"] # ENV: KUMA_RBAC_STATIC_ADMIN_RESOURCES_USERS
users: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_ADMIN_RESOURCES_USERS
# List of groups that are allowed to access admin resources
groups: ["admin"] # ENV: KUMA_RBAC_STATIC_ADMIN_RESOURCES_GROUPS
groups: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_ADMIN_RESOURCES_GROUPS
# GenerateDPToken defines an access to generating dataplane token
generateDpToken:
# List of users that are allowed to generate dataplane token
users: ["admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_DP_TOKEN_USERS
users: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_DP_TOKEN_USERS
# List of groups that are allowed to generate dataplane token
groups: ["admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_DP_TOKEN_GROUPS
groups: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_DP_TOKEN_GROUPS
# GenerateDPToken defines an access to generating user token
generateUserToken:
# List of users that are allowed to generate user token
users: ["admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_USER_TOKEN_USERS
users: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_USER_TOKEN_USERS
# List of groups that are allowed to generate user token
groups: ["admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_USER_TOKEN_GROUPS
groups: ["mesh-system:admin"] # ENV: KUMA_RBAC_STATIC_GENERATE_USER_TOKEN_GROUPS
12 changes: 6 additions & 6 deletions pkg/config/rbac/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ func DefaultRBACConfig() RBACConfig {
Type: StaticType,
Static: RBACStaticConfig{
AdminResources: AdminResourcesRBACStaticConfig{
Users: []string{"admin"},
Groups: []string{"admin"},
Users: []string{"mesh-system:admin"},
Groups: []string{"mesh-system:admin"},
},
GenerateDPToken: GenerateDPTokenRBACStaticConfig{
Users: []string{"admin"},
Groups: []string{"admin"},
Users: []string{"mesh-system:admin"},
Groups: []string{"mesh-system:admin"},
},
GenerateUserToken: GenerateUserTokenRBACStaticConfig{
Users: []string{"admin"},
Groups: []string{"admin"},
Users: []string{"mesh-system:admin"},
Groups: []string{"mesh-system:admin"},
},
},
}
Expand Down
17 changes: 6 additions & 11 deletions pkg/core/resources/rbac/admin_resource_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,30 @@ func NewAdminResourceAccess(cfg config_rbac.AdminResourcesRBACStaticConfig) Reso

var _ ResourceAccess = &adminResourceAccess{}

func (a *adminResourceAccess) ValidateCreate(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user *user.User) error {
func (a *adminResourceAccess) ValidateCreate(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user user.User) error {
return a.validateAdminAccess(user, descriptor)
}

func (a *adminResourceAccess) ValidateUpdate(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user *user.User) error {
func (a *adminResourceAccess) ValidateUpdate(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user user.User) error {
return a.validateAdminAccess(user, descriptor)
}

func (a *adminResourceAccess) ValidateDelete(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user *user.User) error {
func (a *adminResourceAccess) ValidateDelete(key model.ResourceKey, spec model.ResourceSpec, descriptor model.ResourceTypeDescriptor, user user.User) error {
return a.validateAdminAccess(user, descriptor)
}

func (a *adminResourceAccess) ValidateList(descriptor model.ResourceTypeDescriptor, user *user.User) error {
func (a *adminResourceAccess) ValidateList(descriptor model.ResourceTypeDescriptor, user user.User) error {
return a.validateAdminAccess(user, descriptor)
}

func (a *adminResourceAccess) ValidateGet(key model.ResourceKey, descriptor model.ResourceTypeDescriptor, user *user.User) error {
func (a *adminResourceAccess) ValidateGet(key model.ResourceKey, descriptor model.ResourceTypeDescriptor, user user.User) error {
return a.validateAdminAccess(user, descriptor)
}

func (r *adminResourceAccess) validateAdminAccess(u *user.User, descriptor model.ResourceTypeDescriptor) error {
func (r *adminResourceAccess) validateAdminAccess(u user.User, descriptor model.ResourceTypeDescriptor) error {
if !descriptor.AdminOnly {
return nil
}
if u == nil {
return &rbac.AccessDeniedError{
Reason: "user did not authenticate",
}
}
allowed := r.usernames[u.Name]
for _, group := range u.Groups {
if r.groups[group] {
Expand Down
24 changes: 12 additions & 12 deletions pkg/core/resources/rbac/admin_resource_access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import (

var _ = Describe("Admin Resource Access", func() {
resourceAccess := resources_rbac.NewAdminResourceAccess(config_rbac.AdminResourcesRBACStaticConfig{
Users: []string{"admin"},
Users: []string{user.Admin.Name},
})

It("should allow regular user to access non admin resource", func() {
err := resourceAccess.ValidateCreate(
model.ResourceKey{Name: "xyz", Mesh: "demo"},
&mesh_proto.CircuitBreaker{},
mesh.NewCircuitBreakerResource().Descriptor(),
nil,
user.Anonymous,
)

// then
Expand All @@ -37,7 +37,7 @@ var _ = Describe("Admin Resource Access", func() {
model.ResourceKey{Name: "xyz"},
&system_proto.Secret{},
system.NewSecretResource().Descriptor(),
&user.Admin,
user.Admin,
)

// then
Expand All @@ -50,7 +50,7 @@ var _ = Describe("Admin Resource Access", func() {
model.ResourceKey{Name: "xyz"},
&system_proto.Secret{},
system.NewSecretResource().Descriptor(),
&user.User{Name: "john doe", Groups: []string{"users"}},
user.User{Name: "john doe", Groups: []string{"users"}},
)

// then
Expand All @@ -63,11 +63,11 @@ var _ = Describe("Admin Resource Access", func() {
model.ResourceKey{Name: "xyz"},
&system_proto.Secret{},
system.NewSecretResource().Descriptor(),
nil,
user.Anonymous,
)

// then
Expect(err).To(MatchError(`access denied: user did not authenticate`))
Expect(err).To(MatchError(`access denied: user "mesh-system:anonymous/mesh-system:unauthenticated" cannot access the resource of type "Secret"`))
})

It("should allow admin to access Update", func() {
Expand All @@ -76,7 +76,7 @@ var _ = Describe("Admin Resource Access", func() {
model.ResourceKey{Name: "xyz"},
&system_proto.Secret{},
system.NewSecretResource().Descriptor(),
&user.Admin,
user.Admin,
)

// then
Expand All @@ -89,7 +89,7 @@ var _ = Describe("Admin Resource Access", func() {
model.ResourceKey{Name: "xyz"},
&system_proto.Secret{},
system.NewSecretResource().Descriptor(),
&user.User{Name: "john doe", Groups: []string{"users"}},
user.User{Name: "john doe", Groups: []string{"users"}},
)

// then
Expand All @@ -101,7 +101,7 @@ var _ = Describe("Admin Resource Access", func() {
err := resourceAccess.ValidateGet(
model.ResourceKey{Name: "xyz"},
system.NewSecretResource().Descriptor(),
&user.Admin,
user.Admin,
)

// then
Expand All @@ -113,7 +113,7 @@ var _ = Describe("Admin Resource Access", func() {
err := resourceAccess.ValidateGet(
model.ResourceKey{Name: "xyz"},
system.NewSecretResource().Descriptor(),
&user.User{Name: "john doe", Groups: []string{"users"}},
user.User{Name: "john doe", Groups: []string{"users"}},
)

// then
Expand All @@ -124,7 +124,7 @@ var _ = Describe("Admin Resource Access", func() {
// when
err := resourceAccess.ValidateList(
system.NewSecretResource().Descriptor(),
&user.Admin,
user.Admin,
)

// then
Expand All @@ -135,7 +135,7 @@ var _ = Describe("Admin Resource Access", func() {
// when
err := resourceAccess.ValidateList(
system.NewSecretResource().Descriptor(),
&user.User{Name: "john doe", Groups: []string{"users"}},
user.User{Name: "john doe", Groups: []string{"users"}},
)

// then
Expand Down
10 changes: 5 additions & 5 deletions pkg/core/resources/rbac/resource_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
)

type ResourceAccess interface {
ValidateCreate(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user *user.User) error
ValidateUpdate(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user *user.User) error
ValidateDelete(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user *user.User) error
ValidateList(desc model.ResourceTypeDescriptor, user *user.User) error
ValidateGet(key model.ResourceKey, desc model.ResourceTypeDescriptor, user *user.User) error
ValidateCreate(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user user.User) error
ValidateUpdate(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user user.User) error
ValidateDelete(key model.ResourceKey, spec model.ResourceSpec, desc model.ResourceTypeDescriptor, user user.User) error
ValidateList(desc model.ResourceTypeDescriptor, user user.User) error
ValidateGet(key model.ResourceKey, desc model.ResourceTypeDescriptor, user user.User) error
}
8 changes: 4 additions & 4 deletions pkg/core/user/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import "context"
type userCtx struct{}

func Ctx(ctx context.Context, user User) context.Context {
return context.WithValue(ctx, userCtx{}, &user)
return context.WithValue(ctx, userCtx{}, user)
}

func FromCtx(ctx context.Context) *User {
if value, ok := ctx.Value(userCtx{}).(*User); ok {
func FromCtx(ctx context.Context) User {
if value, ok := ctx.Value(userCtx{}).(User); ok {
return value
}
return nil
return Anonymous
}
16 changes: 14 additions & 2 deletions pkg/core/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package user

import "strings"

const AuthenticatedGroup = "mesh-system:authenticated"

type User struct {
Name string
Groups []string
Expand All @@ -11,9 +13,19 @@ func (u User) String() string {
return u.Name + "/" + strings.Join(u.Groups, ",")
}

func (u User) Authenticated() User {
u.Groups = append(u.Groups, AuthenticatedGroup)
return u
}

// Admin is a static user that can be used when authn mechanism does not authenticate to specific user,
// but authenticate to admin without giving credential (ex. authenticate as localhost, authenticate via legacy client certs).
var Admin = User{
Name: "admin",
Groups: []string{"admin"},
Name: "mesh-system:admin",
Groups: []string{"mesh-system:admin"},
}

var Anonymous = User{
Name: "mesh-system:anonymous",
Groups: []string{"mesh-system:unauthenticated"},
}
4 changes: 2 additions & 2 deletions pkg/plugins/authn/api-server/certs/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (

// backwards compatibility with Kuma 1.3.x
func ClientCertAuthenticator(request *restful.Request, response *restful.Response, chain *restful.FilterChain) {
if user.FromCtx(request.Request.Context()) == nil && // do not overwrite existing user
if user.FromCtx(request.Request.Context()).Name == user.Anonymous.Name && // do not overwrite existing user
request.Request.TLS != nil &&
request.Request.TLS.HandshakeComplete &&
len(request.Request.TLS.PeerCertificates) > 0 {
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), user.Admin))
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), user.Admin.Authenticated()))
}
chain.ProcessFilter(request, response)
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ var _ = Describe("Admin Token Bootstrap", func() {
g.Expect(err).ToNot(HaveOccurred())
user, err := tokenIssuer.Validate(string(globalSecret.Spec.Data.Value))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(user.Name).To(Equal("admin"))
g.Expect(user.Groups).To(Equal([]string{"admin"}))
g.Expect(user.Name).To(Equal("mesh-system:admin"))
g.Expect(user.Groups).To(Equal([]string{"mesh-system:admin"}))
}).Should(Succeed())
})
})
4 changes: 2 additions & 2 deletions pkg/plugins/authn/api-server/tokens/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const bearerPrefix = "Bearer "
func UserTokenAuthenticator(issuer issuer.UserTokenIssuer) authn.Authenticator {
return func(request *restful.Request, response *restful.Response, chain *restful.FilterChain) {
authnHeader := request.Request.Header.Get("authorization")
if user.FromCtx(request.Request.Context()) == nil && // do not overwrite existing user
if user.FromCtx(request.Request.Context()).Name == user.Anonymous.Name && // do not overwrite existing user
authnHeader != "" &&
strings.HasPrefix(authnHeader, bearerPrefix) {
token := strings.TrimPrefix(authnHeader, bearerPrefix)
Expand All @@ -25,7 +25,7 @@ func UserTokenAuthenticator(issuer issuer.UserTokenIssuer) authn.Authenticator {
rest_errors.HandleError(response, &rest_errors.Unauthenticated{}, "invalid authentication data: "+err.Error())
return
}
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), u))
request.Request = request.Request.WithContext(user.Ctx(request.Request.Context(), u.Authenticated()))
}
chain.ProcessFilter(request, response)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/plugins/authn/api-server/tokens/rbac/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package rbac
import "github.com/kumahq/kuma/pkg/core/user"

type GenerateUserTokenAccess interface {
ValidateGenerate(user *user.User) error
ValidateGenerate(user user.User) error
}
5 changes: 1 addition & 4 deletions pkg/plugins/authn/api-server/tokens/rbac/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ func NewStaticGenerateUserTokenAccess(cfg config_rbac.GenerateUserTokenRBACStati
return s
}

func (s *staticGenerateUserTokenAccess) ValidateGenerate(user *user.User) error {
if user == nil {
return &rbac.AccessDeniedError{Reason: "authentication required"}
}
func (s *staticGenerateUserTokenAccess) ValidateGenerate(user user.User) error {
allowed := s.usernames[user.Name]
for _, group := range user.Groups {
if s.groups[group] {
Expand Down
2 changes: 1 addition & 1 deletion pkg/plugins/authn/api-server/tokens/ws/ws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
type noopGenerateUserTokenAccess struct {
}

func (n *noopGenerateUserTokenAccess) ValidateGenerate(*user.User) error {
func (n *noopGenerateUserTokenAccess) ValidateGenerate(user.User) error {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/tokens/builtin/rbac/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import (
)

type GenerateDataplaneTokenAccess interface {
ValidateGenerate(name string, mesh string, tags map[string][]string, tokenType string, user *user.User) error
ValidateGenerate(name string, mesh string, tags map[string][]string, tokenType string, user user.User) error
}
2 changes: 1 addition & 1 deletion pkg/tokens/builtin/rbac/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ type NoopGenerateDpTokenAccess struct {

var _ GenerateDataplaneTokenAccess = NoopGenerateDpTokenAccess{}

func (n NoopGenerateDpTokenAccess) ValidateGenerate(name string, mesh string, tags map[string][]string, tokenType string, user *user.User) error {
func (n NoopGenerateDpTokenAccess) ValidateGenerate(name string, mesh string, tags map[string][]string, tokenType string, user user.User) error {
return nil
}
Loading