pulumi / pulumi-kubernetes-operator

A Kubernetes Operator that automates the deployment of Pulumi Stacks
Apache License 2.0
226 stars 54 forks source link

Implement an authorization layer for operator-to-workspace communication #712

Closed EronWright closed 1 month ago

EronWright commented 1 month ago

Overview

This PR implements an authentication and authorization layer for the agent's RPC endpoint.

Authentication is performed by authenticating a bearer token via the TokenReview API. The operator uses its built-in service account token. Authorization is performed via the SubjectAccessReview API, which checks for following RBAC permission:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
rules:
- apiGroups:
  - auto.pulumi.com
  resources:
  - workspaces/rpc
  verbs:
  - use

The workspace pod's service account must be granted the system:auth-delegator role using a ClusterRoleBinding. For. convenience, the installer creates a service account named pulumi into the default namespace, with an associated binding.

The operator itself is granted the necessary permission to access the RPC endpoint.

Proposed changes

Future Enhancement

This implementation uses the operator's default service account token, but to further improve security it should use an audience-scoped token, where the audience is the agent service address as opposed to the API server. Such tokens may be created by the operator with a call to TokenRequest, and checked with TokenReview by adding the expected audience to the context (authenticator.WithAudience).

Related issues (optional)

Closes #609

Examples

Some example requests:

random-yaml-workspace-0 pulumi 2024-10-09T21:09:43.905Z INFO    cmd.serve.grpc  finished unary call with code OK        {"grpc.start_time": "2024-10-09T21:09:43Z", "grpc.request.deadline": "2024-10-09T21:59:43Z", "system": "grpc", "span.kind": "server", "grpc.service": "agent.AutomationService", "grpc.method": "WhoAmI", "user.id": "81be050c-9ad4-4708-9a52-413064700747", "user.name": "system:serviceaccount:default:dev", "peer.address": "127.0.0.1:56394", "auth.mode": "kubernetes", "grpc.code": "OK", "grpc.time_ms": 441.086}

random-yaml-workspace-0 pulumi 2024-10-09T21:09:52.934Z INFO    cmd.serve.grpc  finished unary call with code Unauthenticated   {"grpc.start_time": "2024-10-09T21:09:52Z", "grpc.request.deadline": "2024-10-09T21:59:52Z", "system": "grpc", "span.kind": "server", "grpc.service": "agent.AutomationService", "grpc.method": "WhoAmI", "peer.address": "127.0.0.1:57380", "auth.mode": "kubernetes", "error": "rpc error: code = Unauthenticated desc = Request unauthenticated with Bearer", "grpc.code": "Unauthenticated", "grpc.time_ms": 0.095}
codecov[bot] commented 1 month ago

Codecov Report

Attention: Patch coverage is 38.57868% with 121 lines in your changes missing coverage. Please review.

Project coverage is 53.00%. Comparing base (a4c8810) to head (c6b5ca3). Report is 1 commits behind head on v2.

Files with missing lines Patch % Lines
agent/pkg/server/auth.go 45.16% 50 Missing and 1 partial :warning:
agent/cmd/serve.go 7.69% 36 Missing :warning:
agent/pkg/client/client.go 0.00% 18 Missing :warning:
operator/internal/controller/auto/utils.go 0.00% 11 Missing :warning:
agent/cmd/root.go 55.55% 4 Missing :warning:
...r/internal/controller/auto/workspace_controller.go 95.23% 1 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## v2 #712 +/- ## ========================================== - Coverage 53.68% 53.00% -0.69% ========================================== Files 27 29 +2 Lines 2902 3081 +179 ========================================== + Hits 1558 1633 +75 - Misses 1164 1267 +103 - Partials 180 181 +1 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

EronWright commented 1 month ago

Note that the chart tests are failing for unrelated reasons - the job doesn't build the docker image and uses the wrong image name.