Skip to content

Commit 66048de

Browse files
johnstcnkylecarbs
andcommitted
plumb through dbcrypt in enterprise/coderd:
- Adds a command dbcrypt-rotate to re-enncrypt encrypted data - Plumbs through dbcrypt in enterprise/coderd (including unit tests) - Enables database encryption in develop.sh by default Co-authored-by: Kyle Carberry <kyle@coder.com>
1 parent 8d5701a commit 66048de

28 files changed

+485
-30
lines changed

cli/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
685685
options.Database = dbfake.New()
686686
options.Pubsub = pubsub.NewInMemory()
687687
} else {
688-
sqlDB, err := connectToPostgres(ctx, logger, sqlDriver, vals.PostgresURL.String())
688+
sqlDB, err := ConnectToPostgres(ctx, logger, sqlDriver, vals.PostgresURL.String())
689689
if err != nil {
690690
return xerrors.Errorf("connect to postgres: %w", err)
691691
}
@@ -1950,7 +1950,7 @@ func BuildLogger(inv *clibase.Invocation, cfg *codersdk.DeploymentValues) (slog.
19501950
}, nil
19511951
}
19521952

1953-
func connectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string) (*sql.DB, error) {
1953+
func ConnectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string) (*sql.DB, error) {
19541954
logger.Debug(ctx, "connecting to postgresql")
19551955

19561956
// Try to connect for 30 seconds.

cli/server_createadminuser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (r *RootCmd) newCreateAdminUserCommand() *clibase.Cmd {
6262
newUserDBURL = url
6363
}
6464

65-
sqlDB, err := connectToPostgres(ctx, logger, "postgres", newUserDBURL)
65+
sqlDB, err := ConnectToPostgres(ctx, logger, "postgres", newUserDBURL)
6666
if err != nil {
6767
return xerrors.Errorf("connect to postgres: %w", err)
6868
}

cli/testdata/coder_server_--help.golden

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,14 @@ These options are only available in the Enterprise Edition.
458458
An HTTP URL that is accessible by other replicas to relay DERP
459459
traffic. Required for high availability.
460460

461+
--external-token-encryption-keys string-array, $CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS
462+
Encrypt OIDC and Git authentication tokens with AES-256-GCM in the
463+
database. The value must be a comma-separated list of base64-encoded
464+
keys. A maximum of two keys may be provided. Each key, when
465+
base64-decoded, must be exactly 32 bytes in length. The first key will
466+
be used to encrypt new values. Subsequent keys will be used as a
467+
fallback when decrypting.
468+
461469
--scim-auth-header string, $CODER_SCIM_AUTH_HEADER
462470
Enables SCIM and sets the authentication header for the built-in SCIM
463471
server. New users are automatically created with OIDC authentication.

coderd/apidoc/docs.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/deployment_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func TestDeploymentValues(t *testing.T) {
2626
cfg.OIDC.EmailField.Set("some_random_field_you_never_expected")
2727
cfg.PostgresURL.Set(hi)
2828
cfg.SCIMAPIKey.Set(hi)
29+
cfg.ExternalTokenEncryptionKeys.Set("the_random_key_we_never_expected,an_other_key_we_never_unexpected")
2930

3031
client := coderdtest.New(t, &coderdtest.Options{
3132
DeploymentValues: cfg,
@@ -44,6 +45,7 @@ func TestDeploymentValues(t *testing.T) {
4445
require.Empty(t, scrubbed.Values.OIDC.ClientSecret.Value())
4546
require.Empty(t, scrubbed.Values.PostgresURL.Value())
4647
require.Empty(t, scrubbed.Values.SCIMAPIKey.Value())
48+
require.Empty(t, scrubbed.Values.ExternalTokenEncryptionKeys.Value())
4749
}
4850

4951
func TestDeploymentStats(t *testing.T) {

coderd/httpmw/apikey.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyCon
247247
UserID: key.UserID,
248248
LoginType: key.LoginType,
249249
})
250+
if errors.Is(err, sql.ErrNoRows) {
251+
return optionalWrite(http.StatusUnauthorized, codersdk.Response{
252+
Message: SignedOutErrorMessage,
253+
Detail: "You must re-authenticate with the login provider.",
254+
})
255+
}
250256
if err != nil {
251257
return write(http.StatusInternalServerError, codersdk.Response{
252258
Message: "A database error occurred",

codersdk/deployment.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ const (
4646
FeatureExternalProvisionerDaemons FeatureName = "external_provisioner_daemons"
4747
FeatureAppearance FeatureName = "appearance"
4848
FeatureAdvancedTemplateScheduling FeatureName = "advanced_template_scheduling"
49-
FeatureTemplateAutostopRequirement FeatureName = "template_autostop_requirement"
5049
FeatureWorkspaceProxy FeatureName = "workspace_proxy"
50+
FeatureExternalTokenEncryption FeatureName = "external_token_encryption"
51+
FeatureTemplateAutostopRequirement FeatureName = "template_autostop_requirement"
5152
)
5253

5354
// FeatureNames must be kept in-sync with the Feature enum above.
@@ -64,6 +65,8 @@ var FeatureNames = []FeatureName{
6465
FeatureAdvancedTemplateScheduling,
6566
FeatureWorkspaceProxy,
6667
FeatureUserRoleManagement,
68+
FeatureExternalTokenEncryption,
69+
FeatureTemplateAutostopRequirement,
6770
}
6871

6972
// Humanize returns the feature name in a human-readable format.
@@ -152,6 +155,7 @@ type DeploymentValues struct {
152155
AgentFallbackTroubleshootingURL clibase.URL `json:"agent_fallback_troubleshooting_url,omitempty" typescript:",notnull"`
153156
BrowserOnly clibase.Bool `json:"browser_only,omitempty" typescript:",notnull"`
154157
SCIMAPIKey clibase.String `json:"scim_api_key,omitempty" typescript:",notnull"`
158+
ExternalTokenEncryptionKeys clibase.StringArray `json:"external_token_encryption_keys,omitempty" typescript:",notnull"`
155159
Provisioner ProvisionerConfig `json:"provisioner,omitempty" typescript:",notnull"`
156160
RateLimit RateLimitConfig `json:"rate_limit,omitempty" typescript:",notnull"`
157161
Experiments clibase.StringArray `json:"experiments,omitempty" typescript:",notnull"`
@@ -1603,7 +1607,14 @@ when required by your organization's security policy.`,
16031607
Annotations: clibase.Annotations{}.Mark(annotationEnterpriseKey, "true").Mark(annotationSecretKey, "true"),
16041608
Value: &c.SCIMAPIKey,
16051609
},
1606-
1610+
{
1611+
Name: "External Token Encryption Keys",
1612+
Description: "Encrypt OIDC and Git authentication tokens with AES-256-GCM in the database. The value must be a comma-separated list of base64-encoded keys. A maximum of two keys may be provided. Each key, when base64-decoded, must be exactly 32 bytes in length. The first key will be used to encrypt new values. Subsequent keys will be used as a fallback when decrypting.",
1613+
Flag: "external-token-encryption-keys",
1614+
Env: "CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS",
1615+
Annotations: clibase.Annotations{}.Mark(annotationEnterpriseKey, "true").Mark(annotationSecretKey, "true"),
1616+
Value: &c.ExternalTokenEncryptionKeys,
1617+
},
16071618
{
16081619
Name: "Disable Path Apps",
16091620
Description: "Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.",
@@ -1781,7 +1792,7 @@ func (c *DeploymentValues) WithoutSecrets() (*DeploymentValues, error) {
17811792

17821793
// This only works with string values for now.
17831794
switch v := opt.Value.(type) {
1784-
case *clibase.String:
1795+
case *clibase.String, *clibase.StringArray:
17851796
err := v.Set("")
17861797
if err != nil {
17871798
panic(err)

codersdk/deployment_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ func TestDeploymentValues_HighlyConfigurable(t *testing.T) {
5757
"SCIM API Key": {
5858
yaml: true,
5959
},
60+
"External Token Encryption Keys": {
61+
yaml: true,
62+
},
6063
// These complex objects should be configured through YAML.
6164
"Support Links": {
6265
flag: true,

docs/api/general.md

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)