Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 6 additions & 2 deletions pkg/grpc/actions/secrets/create_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"errors"
"fmt"

"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"github.com/superplanehq/superplane/pkg/authentication"
"github.com/superplanehq/superplane/pkg/crypto"
Expand Down Expand Up @@ -45,7 +44,12 @@ func CreateSecret(ctx context.Context, encryptor crypto.Encryptor, domainType st
return nil, status.Error(codes.InvalidArgument, err.Error())
}

secret, err := models.CreateSecret(spec.Metadata.Name, provider, userID, domainType, uuid.MustParse(domainID), data)
id, err := parseDomainID(domainID)
if err != nil {
return nil, err
}

secret, err := models.CreateSecret(spec.Metadata.Name, provider, userID, domainType, id, data)
if err != nil {
if errors.Is(err, models.ErrNameAlreadyUsed) {
return nil, status.Error(codes.InvalidArgument, err.Error())
Expand Down
14 changes: 2 additions & 12 deletions pkg/grpc/actions/secrets/delete_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,15 @@ package secrets
import (
"context"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func DeleteSecret(ctx context.Context, domainType, domainID, idOrName string) (*pb.DeleteSecretResponse, error) {
err := actions.ValidateUUIDs(idOrName)
var secret *models.Secret
secret, err := findSecretInDomain(domainType, domainID, idOrName)
if err != nil {
secret, err = models.FindSecretByName(domainType, uuid.MustParse(domainID), idOrName)
} else {
secret, err = models.FindSecretByID(domainType, uuid.MustParse(domainID), idOrName)
}

if err != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
return nil, err
}

err = secret.Delete()
Expand Down
13 changes: 2 additions & 11 deletions pkg/grpc/actions/secrets/delete_secret_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package secrets
import (
"context"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand All @@ -17,15 +14,9 @@ func DeleteSecretKey(ctx context.Context, encryptor crypto.Encryptor, domainType
return nil, status.Error(codes.InvalidArgument, "key name is required")
}

err := actions.ValidateUUIDs(idOrName)
var secret *models.Secret
secret, err := findSecretInDomain(domainType, domainID, idOrName)
if err != nil {
secret, err = models.FindSecretByName(domainType, uuid.MustParse(domainID), idOrName)
} else {
secret, err = models.FindSecretByID(domainType, uuid.MustParse(domainID), idOrName)
}
if err != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
return nil, err
}

data, err := decryptSecretData(ctx, encryptor, *secret)
Expand Down
14 changes: 2 additions & 12 deletions pkg/grpc/actions/secrets/describe_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,17 @@ import (
"context"
"encoding/json"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)

func DescribeSecret(ctx context.Context, encryptor crypto.Encryptor, domainType, domainId, idOrName string) (*pb.DescribeSecretResponse, error) {
err := actions.ValidateUUIDs(idOrName)
var secret *models.Secret
secret, err := findSecretInDomain(domainType, domainId, idOrName)
if err != nil {
secret, err = models.FindSecretByName(domainType, uuid.MustParse(domainId), idOrName)
} else {
secret, err = models.FindSecretByID(domainType, uuid.MustParse(domainId), idOrName)
}

if err != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
return nil, err
}

s, err := serializeSecret(ctx, encryptor, *secret)
Expand Down
41 changes: 41 additions & 0 deletions pkg/grpc/actions/secrets/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package secrets

import (
"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func parseDomainID(domainID string) (uuid.UUID, error) {
id, err := uuid.Parse(domainID)
if err != nil {
return uuid.Nil, status.Error(codes.InvalidArgument, "invalid domain id")
}

return id, nil
}

func findSecretInDomain(domainType, domainID, idOrName string) (*models.Secret, error) {
id, err := parseDomainID(domainID)
if err != nil {
return nil, err
}

var (
secret *models.Secret
lookupErr error
)
if err := actions.ValidateUUIDs(idOrName); err != nil {
secret, lookupErr = models.FindSecretByName(domainType, id, idOrName)
} else {
secret, lookupErr = models.FindSecretByID(domainType, id, idOrName)
}

if lookupErr != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
}

return secret, nil
}
103 changes: 103 additions & 0 deletions pkg/grpc/actions/secrets/invalid_domain_id_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package secrets

import (
"context"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/superplanehq/superplane/pkg/authentication"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/models"
secretpb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func Test__SecretsRejectInvalidDomainID(t *testing.T) {
encryptor := &crypto.NoOpEncryptor{}
ctx := authentication.SetUserIdInMetadata(context.Background(), uuid.NewString())
secret := &secretpb.Secret{
Metadata: &secretpb.Secret_Metadata{
Name: "test",
},
Spec: &secretpb.Secret_Spec{
Provider: secretpb.Secret_PROVIDER_LOCAL,
Local: &secretpb.Secret_Local{
Data: map[string]string{"token": "value"},
},
},
}

tests := []struct {
name string
run func() error
}{
{
name: "list",
run: func() error {
_, err := ListSecrets(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization")
return err
},
},
{
name: "describe",
run: func() error {
_, err := DescribeSecret(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", "test")
return err
},
},
{
name: "create",
run: func() error {
_, err := CreateSecret(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", secret)
return err
},
},
{
name: "update",
run: func() error {
_, err := UpdateSecret(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", "test", secret)
return err
},
},
{
name: "delete",
run: func() error {
_, err := DeleteSecret(ctx, models.DomainTypeOrganization, "renamed-organization", "test")
return err
},
},
{
name: "set key",
run: func() error {
_, err := SetSecretKey(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", "test", "token", "value")
return err
},
},
{
name: "delete key",
run: func() error {
_, err := DeleteSecretKey(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", "test", "token")
return err
},
},
{
name: "update name",
run: func() error {
_, err := UpdateSecretName(ctx, encryptor, models.DomainTypeOrganization, "renamed-organization", "test", "new-name")
return err
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
err := test.run()
s, ok := status.FromError(err)
assert.True(t, ok)
assert.Equal(t, codes.InvalidArgument, s.Code())
assert.Equal(t, "invalid domain id", s.Message())
})
}
}
8 changes: 6 additions & 2 deletions pkg/grpc/actions/secrets/list_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ package secrets
import (
"context"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
)

func ListSecrets(ctx context.Context, encryptor crypto.Encryptor, domainType, domainId string) (*pb.ListSecretsResponse, error) {
secrets, err := models.ListSecrets(domainType, uuid.MustParse(domainId))
id, err := parseDomainID(domainId)
if err != nil {
return nil, err
}

secrets, err := models.ListSecrets(domainType, id)
if err != nil {
return nil, err
}
Expand Down
51 changes: 51 additions & 0 deletions pkg/grpc/actions/secrets/organization_rename_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package secrets

import (
"context"
"encoding/json"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/grpc/actions/organizations"
"github.com/superplanehq/superplane/pkg/models"
organizationpb "github.com/superplanehq/superplane/pkg/protos/organizations"
secretpb "github.com/superplanehq/superplane/pkg/protos/secrets"
"github.com/superplanehq/superplane/pkg/secrets"
"github.com/superplanehq/superplane/test/support"
)

func Test__SecretsAfterOrganizationRename(t *testing.T) {
r := support.SetupWithOptions(t, support.SetupOptions{})
encryptor := &crypto.NoOpEncryptor{}
secretName := support.RandomName("secret")
data, err := json.Marshal(map[string]string{"token": "value"})
require.NoError(t, err)

_, err = models.CreateSecret(secretName, secrets.ProviderLocal, uuid.NewString(), models.DomainTypeOrganization, r.Organization.ID, data)
require.NoError(t, err)

_, err = organizations.UpdateOrganization(context.Background(), r.Organization.ID.String(), &organizationpb.Organization{
Metadata: &organizationpb.Organization_Metadata{
Name: support.RandomName("renamed-org"),
},
})
require.NoError(t, err)

listResponse, err := ListSecrets(context.Background(), encryptor, models.DomainTypeOrganization, r.Organization.ID.String())
require.NoError(t, err)
require.Len(t, listResponse.Secrets, 1)
assert.Equal(t, secretName, listResponse.Secrets[0].Metadata.Name)
assert.Equal(t, secretpb.Secret_PROVIDER_LOCAL, listResponse.Secrets[0].Spec.Provider)
require.NotNil(t, listResponse.Secrets[0].Spec.Local)
assert.Equal(t, map[string]string{"token": "***"}, listResponse.Secrets[0].Spec.Local.Data)

describeResponse, err := DescribeSecret(context.Background(), encryptor, models.DomainTypeOrganization, r.Organization.ID.String(), secretName)
require.NoError(t, err)
require.NotNil(t, describeResponse.Secret)
assert.Equal(t, secretName, describeResponse.Secret.Metadata.Name)
require.NotNil(t, describeResponse.Secret.Spec.Local)
assert.Equal(t, map[string]string{"token": "***"}, describeResponse.Secret.Spec.Local.Data)
}
13 changes: 2 additions & 11 deletions pkg/grpc/actions/secrets/set_secret_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package secrets
import (
"context"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand All @@ -17,15 +14,9 @@ func SetSecretKey(ctx context.Context, encryptor crypto.Encryptor, domainType, d
return nil, status.Error(codes.InvalidArgument, "key name is required")
}

err := actions.ValidateUUIDs(idOrName)
var secret *models.Secret
secret, err := findSecretInDomain(domainType, domainID, idOrName)
if err != nil {
secret, err = models.FindSecretByName(domainType, uuid.MustParse(domainID), idOrName)
} else {
secret, err = models.FindSecretByID(domainType, uuid.MustParse(domainID), idOrName)
}
if err != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
return nil, err
}

data, err := decryptSecretData(ctx, encryptor, *secret)
Expand Down
14 changes: 2 additions & 12 deletions pkg/grpc/actions/secrets/update_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,16 @@ package secrets
import (
"context"

"github.com/google/uuid"
"github.com/superplanehq/superplane/pkg/crypto"
"github.com/superplanehq/superplane/pkg/grpc/actions"
"github.com/superplanehq/superplane/pkg/models"
pb "github.com/superplanehq/superplane/pkg/protos/secrets"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func UpdateSecret(ctx context.Context, encryptor crypto.Encryptor, domainType, domainID, idOrName string, spec *pb.Secret) (*pb.UpdateSecretResponse, error) {
err := actions.ValidateUUIDs(idOrName)
var secret *models.Secret
secret, err := findSecretInDomain(domainType, domainID, idOrName)
if err != nil {
secret, err = models.FindSecretByName(domainType, uuid.MustParse(domainID), idOrName)
} else {
secret, err = models.FindSecretByID(domainType, uuid.MustParse(domainID), idOrName)
}

if err != nil {
return nil, status.Error(codes.InvalidArgument, "secret not found")
return nil, err
}

if spec == nil {
Expand Down
Loading