Skip to content

Commit

Permalink
Enforce Kubernetes license when creating Kube resources
Browse files Browse the repository at this point in the history
This PR prevents the registration of Kubernetes clusters in Teleport
Auth server when the auth isn't licensed for Kubernetes access.

This is required because with the new credentials forwarding mechanism,
services won't call Auth server `ProcessKubeCSR` endpoint and thus we
cannot enforce the license.

This change prevents any agent to register its `KubeServers` in Auth
server if the server isn't properly licensed to Kube. It only affects
enterprise users because the open source version of Auth is licensed
for Kubernetes access.

Part of #22533
  • Loading branch information
tigrato committed Mar 30, 2023
1 parent 9a338c5 commit fc5d2bb
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
23 changes: 23 additions & 0 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3816,9 +3816,26 @@ func (a *Server) UpsertNode(ctx context.Context, server types.Server) (*types.Ke
return lease, nil
}

// enforceLicense checks if the license allows the given resource type to be
// created.
func enforceLicense(t string) error {
switch t {
case types.KindKubeServer, types.KindKubernetesCluster:
if !modules.GetModules().Features().Kubernetes {
return trace.AccessDenied(
"this Teleport cluster is not licensed for Kubernetes, please contact the cluster administrator")
}
}
return nil
}

// UpsertKubernetesServer implements [services.Presence] by delegating to
// [Server.Services] and then potentially emitting a [usagereporter] event.
func (a *Server) UpsertKubernetesServer(ctx context.Context, server types.KubeServer) (*types.KeepAlive, error) {
if err := enforceLicense(types.KindKubeServer); err != nil {
return nil, trace.Wrap(err)
}

k, err := a.Services.UpsertKubernetesServer(ctx, server)
if err != nil {
return nil, trace.Wrap(err)
Expand Down Expand Up @@ -4241,6 +4258,9 @@ func (a *Server) ListResources(ctx context.Context, req proto.ListResourcesReque

// CreateKubernetesCluster creates a new kubernetes cluster resource.
func (a *Server) CreateKubernetesCluster(ctx context.Context, kubeCluster types.KubeCluster) error {
if err := enforceLicense(types.KindKubernetesCluster); err != nil {
return trace.Wrap(err)
}
if err := a.Services.CreateKubernetesCluster(ctx, kubeCluster); err != nil {
return trace.Wrap(err)
}
Expand All @@ -4265,6 +4285,9 @@ func (a *Server) CreateKubernetesCluster(ctx context.Context, kubeCluster types.

// UpdateKubernetesCluster updates an existing kubernetes cluster resource.
func (a *Server) UpdateKubernetesCluster(ctx context.Context, kubeCluster types.KubeCluster) error {
if err := enforceLicense(types.KindKubernetesCluster); err != nil {
return trace.Wrap(err)
}
if err := a.Kubernetes.UpdateKubernetesCluster(ctx, kubeCluster); err != nil {
return trace.Wrap(err)
}
Expand Down
11 changes: 11 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,17 @@ func (a *ServerWithRoles) ListResources(ctx context.Context, req proto.ListResou
if req.ResourceType == kubeService {
return &types.ListResourcesResponse{}, nil
}

// Check if auth server has a license for this resource type but only return an
// error if the user is not a builtin proxy or kube role.
// Builtin proxy and kube roles are allowed to list resources to avoid crashes
// even if the license is missing.
// Users with other roles will get an error if the license is missing so they
// can request a license with the correct features.
if err := enforceLicense(req.ResourceType); err != nil && !a.hasBuiltinRole(types.RoleProxy, types.RoleKube) {
return nil, trace.Wrap(err)
}

if req.UseSearchAsRoles || req.UsePreviewAsRoles {
var extraRoles []string
if req.UseSearchAsRoles {
Expand Down
6 changes: 2 additions & 4 deletions lib/auth/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/gravitational/teleport"
apidefaults "github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/tlsca"
)
Expand Down Expand Up @@ -64,9 +63,8 @@ type KubeCSRResponse struct {
// signed certificate if successful.
func (s *Server) ProcessKubeCSR(req KubeCSR) (*KubeCSRResponse, error) {
ctx := context.TODO()
if !modules.GetModules().Features().Kubernetes {
return nil, trace.AccessDenied(
"this Teleport cluster is not licensed for Kubernetes, please contact the cluster administrator")
if err := enforceLicense(types.KindKubernetesCluster); err != nil {
return nil, trace.Wrap(err)
}
if err := req.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
Expand Down

0 comments on commit fc5d2bb

Please sign in to comment.