mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: plumb user secrets through provisioner chain to terraform (#24542)
This change passes user secrets from coderd to the Terraform process at workspace build time so the `data.coder_secret` data source in terraform-provider-coder can resolve values at plan time. Secrets traverse two proto hops: `provisionerdserver` fetches them via`ListUserSecretsWithValues`, attaches them to `AcquiredJob.WorkspaceBuild.user_secrets` on `provisionerd.proto`; `runner.go` forwards into `PlanRequest.user_secrets` on `provisioner.proto`; the Terraform provisioner encodes each as `CODER_SECRET_ENV_<name>` or `CODER_SECRET_FILE_<hex(path)>` before invoking `terraform plan`. Only plan requests carry secrets; apply runs with `nil` because values are baked into plan state. Fetch is gated on a workspace transitioning to start. stop and delete transitions never carry secrets, so revoking or deleting a stored secret cannot make a workspace unstoppable. DB errors on the fetch fail the job outright rather than silently continuing with an empty secret set. Note that user secrets will be stored in the workspace_builds table in provisioner_state with other Terraform state (including other sensitive data).
This commit is contained in:
@@ -245,6 +245,7 @@ var (
|
||||
rbac.ResourceWorkspaceAgentDevcontainers.Type: {policy.ActionCreate},
|
||||
// Provisionerd creates usage events
|
||||
rbac.ResourceUsageEvent.Type: {policy.ActionCreate},
|
||||
rbac.ResourceUserSecret.Type: {policy.ActionRead},
|
||||
}),
|
||||
User: []rbac.Permission{},
|
||||
ByOrgID: map[string]rbac.OrgPermissions{},
|
||||
@@ -5821,7 +5822,7 @@ func (q *querier) ListUserSecretsWithValues(ctx context.Context, userID uuid.UUI
|
||||
// This query returns decrypted secret values and must only be called
|
||||
// from system contexts (provisioner, agent manifest). REST API
|
||||
// handlers should use ListUserSecrets (metadata only).
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUserSecret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.ListUserSecretsWithValues(ctx, userID)
|
||||
|
||||
@@ -5667,7 +5667,7 @@ func (s *MethodTestSuite) TestUserSecrets() {
|
||||
secret := testutil.Fake(s.T(), faker, database.UserSecret{UserID: user.ID})
|
||||
dbm.EXPECT().ListUserSecretsWithValues(gomock.Any(), user.ID).Return([]database.UserSecret{secret}, nil).AnyTimes()
|
||||
check.Args(user.ID).
|
||||
Asserts(rbac.ResourceSystem, policy.ActionRead).
|
||||
Asserts(rbac.ResourceUserSecret, policy.ActionRead).
|
||||
Returns([]database.UserSecret{secret})
|
||||
}))
|
||||
s.Run("CreateUserSecret", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
|
||||
@@ -1590,8 +1590,8 @@ func PresetParameter(t testing.TB, db database.Store, seed database.InsertPreset
|
||||
return parameters
|
||||
}
|
||||
|
||||
func UserSecret(t testing.TB, db database.Store, seed database.UserSecret) database.UserSecret {
|
||||
userSecret, err := db.CreateUserSecret(genCtx, database.CreateUserSecretParams{
|
||||
func UserSecret(t testing.TB, db database.Store, seed database.UserSecret, mutators ...func(params *database.CreateUserSecretParams)) database.UserSecret {
|
||||
params := database.CreateUserSecretParams{
|
||||
ID: takeFirst(seed.ID, uuid.New()),
|
||||
UserID: takeFirst(seed.UserID, uuid.New()),
|
||||
Name: takeFirst(seed.Name, "secret-name"),
|
||||
@@ -1600,7 +1600,11 @@ func UserSecret(t testing.TB, db database.Store, seed database.UserSecret) datab
|
||||
ValueKeyID: seed.ValueKeyID,
|
||||
EnvName: takeFirst(seed.EnvName, "SECRET_ENV_NAME"),
|
||||
FilePath: takeFirst(seed.FilePath, "~/secret/file/path"),
|
||||
})
|
||||
}
|
||||
for _, mut := range mutators {
|
||||
mut(¶ms)
|
||||
}
|
||||
userSecret, err := db.CreateUserSecret(genCtx, params)
|
||||
require.NoError(t, err, "failed to insert user secret")
|
||||
return userSecret
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user