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

HV-1702 create postgres rotating secret #192

Merged
merged 11 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
3 changes: 3 additions & 0 deletions .changelog/192.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
hvs: support postgres rotating secret CRUDL
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.22.0
github.com/hashicorp/hcp-sdk-go v0.117.0
github.com/hashicorp/hcp-sdk-go v0.121.0
github.com/lithammer/dedent v1.1.0
github.com/manifoldco/promptui v0.9.0
github.com/mitchellh/cli v1.1.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M=
github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
github.com/hashicorp/hcp-sdk-go v0.117.0 h1:7lJpkinpWdsXtejC+X7MdaE/3zhFMweB9Ym3uJ7qFJw=
github.com/hashicorp/hcp-sdk-go v0.117.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/hcp-sdk-go v0.121.0 h1:fDCB0sexSNontS7LLuhF1RJd7eYx1hmFVBFmY4kXU78=
github.com/hashicorp/hcp-sdk-go v0.121.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
MongoDBAtlas IntegrationType = "mongodb-atlas"
AWS IntegrationType = "aws"
GCP IntegrationType = "gcp"
Postgres IntegrationType = "postgres"
)

func NewCmdIntegrations(ctx *cmd.Context) *cmd.Command {
Expand Down
34 changes: 34 additions & 0 deletions internal/commands/vaultsecrets/secrets/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ var (
},
}

postgresRotatingSecretTemplate = map[string]any{
"integration_name": "",
"rotation_policy_name": "",
"postgres_params": map[string]any{
"usernames": []string{},
},
}

awsDynamicSecretTemplate = map[string]any{
"integration_name": "",
"default_ttl": "",
Expand Down Expand Up @@ -365,6 +373,31 @@ func createRun(opts *CreateOpts) error {
return fmt.Errorf("failed to create secret with name %q: %w", opts.SecretName, err)
}

case integrations.Postgres:
req := preview_secret_service.NewCreatePostgresRotatingSecretParamsWithContext(opts.Ctx)
req.OrganizationID = opts.Profile.OrganizationID
req.ProjectID = opts.Profile.ProjectID
keeefer marked this conversation as resolved.
Show resolved Hide resolved
req.AppName = opts.AppName

var postgresBody preview_models.SecretServiceCreatePostgresRotatingSecretBody
detailBytes, err := json.Marshal(internalConfig.Details)
if err != nil {
return fmt.Errorf("error marshaling details config: %w", err)
}

err = postgresBody.UnmarshalBinary(detailBytes)
if err != nil {
return fmt.Errorf("error marshaling details config: %w", err)
}

postgresBody.Name = opts.SecretName
req.Body = &postgresBody

_, err = opts.PreviewClient.CreatePostgresRotatingSecret(req, nil)
if err != nil {
return fmt.Errorf("failed to create secret with name %q: %w", opts.SecretName, err)
}

default:
return fmt.Errorf("unsupported rotating secret provider type")
}
Expand Down Expand Up @@ -538,6 +571,7 @@ var availableRotatingSecretProviders = map[string]map[string]any{
string(integrations.MongoDBAtlas): mongoDBAtlasRotatingSecretTemplate,
string(integrations.AWS): awsRotatingSecretTemplate,
string(integrations.GCP): gcpRotatingSecretTemplate,
string(integrations.Postgres): postgresRotatingSecretTemplate,
}

var availableDynamicSecretProviders = map[string]map[string]any{
Expand Down
121 changes: 87 additions & 34 deletions internal/commands/vaultsecrets/secrets/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"path/filepath"
"testing"

"github.com/hashicorp/hcp/internal/commands/vaultsecrets/integrations"

"github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -134,6 +136,7 @@ func TestCreateRun(t *testing.T) {
ErrMsg string
MockCalled bool
AugmentOpts func(*CreateOpts)
Provider integrations.IntegrationType
Input []byte
}{
{
Expand Down Expand Up @@ -186,6 +189,7 @@ func TestCreateRun(t *testing.T) {
o.Type = secretTypeRotating
},
MockCalled: true,
Provider: integrations.MongoDBAtlas,
Input: []byte(`type = "mongodb-atlas"
details = {
integration_name = "mongo-db-integration"
Expand All @@ -203,6 +207,23 @@ details = {
"collection_name" = "cn2"
}]
}
}`),
},
{
Name: "Success: Create a Postgres rotating secret",
RespErr: false,
AugmentOpts: func(o *CreateOpts) {
o.Type = secretTypeRotating
},
MockCalled: true,
Provider: integrations.Postgres,
Input: []byte(`type = "postgres"
details = {
integration_name = "postgres-integration"
rotation_policy_name = "built-in:60-days-2-active"
postgres_params = {
usernames = ["postgres_user_1"]
}
}`),
},
{
Expand Down Expand Up @@ -310,45 +331,77 @@ details = {
}
} else if opts.Type == secretTypeRotating {
if c.MockCalled {
if c.RespErr {
pvs.EXPECT().CreateMongoDBAtlasRotatingSecret(mock.Anything, mock.Anything).Return(nil, errors.New(c.ErrMsg)).Once()
} else {
pvs.EXPECT().CreateMongoDBAtlasRotatingSecret(&preview_secret_service.CreateMongoDBAtlasRotatingSecretParams{
OrganizationID: testProfile(t).OrganizationID,
ProjectID: testProfile(t).ProjectID,
AppName: testProfile(t).VaultSecrets.AppName,
Body: &preview_models.SecretServiceCreateMongoDBAtlasRotatingSecretBody{
Name: opts.SecretName,
IntegrationName: "mongo-db-integration",
RotationPolicyName: "built-in:60-days-2-active",
SecretDetails: &preview_models.Secrets20231128MongoDBAtlasSecretDetails{
MongodbGroupID: "mbdgi",
MongodbRoles: []*preview_models.Secrets20231128MongoDBRole{
{
RoleName: "rn1",
DatabaseName: "dn1",
CollectionName: "cn1",
},
{
RoleName: "rn2",
DatabaseName: "dn2",
CollectionName: "cn2",
switch c.Provider {
case integrations.MongoDBAtlas:
if c.RespErr {
pvs.EXPECT().CreateMongoDBAtlasRotatingSecret(mock.Anything, mock.Anything).Return(nil, errors.New(c.ErrMsg)).Once()
} else {
pvs.EXPECT().CreateMongoDBAtlasRotatingSecret(&preview_secret_service.CreateMongoDBAtlasRotatingSecretParams{
OrganizationID: testProfile(t).OrganizationID,
ProjectID: testProfile(t).ProjectID,
AppName: testProfile(t).VaultSecrets.AppName,
Body: &preview_models.SecretServiceCreateMongoDBAtlasRotatingSecretBody{
Name: opts.SecretName,
IntegrationName: "mongo-db-integration",
RotationPolicyName: "built-in:60-days-2-active",
SecretDetails: &preview_models.Secrets20231128MongoDBAtlasSecretDetails{
MongodbGroupID: "mbdgi",
MongodbRoles: []*preview_models.Secrets20231128MongoDBRole{
{
RoleName: "rn1",
DatabaseName: "dn1",
CollectionName: "cn1",
},
{
RoleName: "rn2",
DatabaseName: "dn2",
CollectionName: "cn2",
},
},
},
},
},
Context: opts.Ctx,
}, mock.Anything).Return(&preview_secret_service.CreateMongoDBAtlasRotatingSecretOK{
Payload: &preview_models.Secrets20231128CreateMongoDBAtlasRotatingSecretResponse{
Config: &preview_models.Secrets20231128RotatingSecretConfig{
AppName: opts.AppName,
CreatedAt: dt,
IntegrationName: "mongo-db-integration",
RotationPolicyName: "built-in:60-days-2-active",
Context: opts.Ctx,
}, mock.Anything).Return(&preview_secret_service.CreateMongoDBAtlasRotatingSecretOK{
Payload: &preview_models.Secrets20231128CreateMongoDBAtlasRotatingSecretResponse{
Config: &preview_models.Secrets20231128RotatingSecretConfig{
AppName: opts.AppName,
CreatedAt: dt,
IntegrationName: "mongo-db-integration",
RotationPolicyName: "built-in:60-days-2-active",
Name: opts.SecretName,
},
},
}, nil).Once()
}
case integrations.Postgres:
if c.RespErr {
pvs.EXPECT().CreatePostgresRotatingSecret(mock.Anything, mock.Anything).Return(nil, errors.New(c.ErrMsg)).Once()
} else {
println(testProfile(t).ProjectID)
pvs.EXPECT().CreatePostgresRotatingSecret(&preview_secret_service.CreatePostgresRotatingSecretParams{
OrganizationID: testProfile(t).OrganizationID,
ProjectID: testProfile(t).ProjectID,
AppName: testProfile(t).VaultSecrets.AppName,
Body: &preview_models.SecretServiceCreatePostgresRotatingSecretBody{
Name: opts.SecretName,
IntegrationName: "postgres-integration",
RotationPolicyName: "built-in:60-days-2-active",
PostgresParams: &preview_models.Secrets20231128PostgresParams{Usernames: []string{"postgres_user_1"}},
},
},
}, nil).Once()
Context: opts.Ctx,
}, mock.Anything).Return(&preview_secret_service.CreatePostgresRotatingSecretOK{
Payload: &preview_models.Secrets20231128CreatePostgresRotatingSecretResponse{
Config: &preview_models.Secrets20231128PostgresRotatingSecretConfig{
AppName: opts.AppName,
CreatedAt: dt,
IntegrationName: "postgres-integration",
RotationPolicyName: "built-in:60-days-2-active",
Name: opts.SecretName,
PostgresParams: &preview_models.Secrets20231128PostgresParams{Usernames: []string{"postgres_user_1"}},
},
},
}, nil).Once()
}
}
}
} else if opts.Type == secretTypeDynamic {
Expand Down
25 changes: 25 additions & 0 deletions internal/commands/vaultsecrets/secrets/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,31 @@ func updateRun(opts *UpdateOpts) error {
if err != nil {
return fmt.Errorf("failed to update secret with name %q: %w", opts.SecretName, err)
}

case integrations.Postgres:
req := preview_secret_service.NewUpdatePostgresRotatingSecretParamsWithContext(opts.Ctx)
req.OrganizationID = opts.Profile.OrganizationID
req.ProjectID = opts.Profile.ProjectID
req.AppName = opts.AppName
req.Name = opts.SecretName

var postgresBody preview_models.SecretServiceUpdatePostgresRotatingSecretBody
detailBytes, err := json.Marshal(internalConfig.Details)
if err != nil {
return fmt.Errorf("error marshaling details config: %w", err)
}

err = postgresBody.UnmarshalBinary(detailBytes)
if err != nil {
return fmt.Errorf("error unmarshaling details config: %w", err)
}

req.Body = &postgresBody

_, err = opts.PreviewClient.UpdatePostgresRotatingSecret(req, nil)
if err != nil {
return fmt.Errorf("failed to update secret with name %q: %w", opts.SecretName, err)
}
}

case secretTypeDynamic:
Expand Down
Loading