Skip to content
Merged
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
78 changes: 77 additions & 1 deletion service/integration/attribute_values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package integration

import (
"context"
"fmt"
"log/slog"
"strings"
"testing"

"github.com/opentdf/platform/protocol/go/common"
"github.com/opentdf/platform/protocol/go/policy"
"github.com/opentdf/platform/protocol/go/policy/attributes"
"github.com/opentdf/platform/protocol/go/policy/kasregistry"
"github.com/opentdf/platform/protocol/go/policy/namespaces"
"github.com/opentdf/platform/protocol/go/policy/unsafe"
"github.com/opentdf/platform/service/internal/fixtures"
Expand Down Expand Up @@ -981,6 +983,80 @@ func (s *AttributeValuesSuite) Test_AssignPublicKeyToAttributeValue_Returns_Erro
s.Require().ErrorIs(err, db.ErrForeignKeyViolation)
}

func (s *AttributeValuesSuite) Test_AssignPublicKeyToAttributeValue_NotActiveKey_Fail() {
var kasID string
keyIDs := make([]string, 0)
defer func() {
for _, keyID := range keyIDs {
// delete the kas key
_, err := s.db.PolicyClient.DeleteKey(s.ctx, keyID)
s.Require().NoError(err)
}

if kasID != "" {
// delete the kas
_, err := s.db.PolicyClient.DeleteKeyAccessServer(s.ctx, kasID)
s.Require().NoError(err)
}
}()

// create a KAS
kas := &kasregistry.CreateKeyAccessServerRequest{
Uri: "https://example.com/kas-av-not-active",
PublicKey: &policy.PublicKey{
PublicKey: &policy.PublicKey_Remote{
Remote: "https://example.com/kas-av-not-active/key/1",
},
},
Name: "def_kas_name_av_not_active",
}
createdKAS, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, kas)
s.Require().NoError(err)
s.NotNil(createdKAS)
kasID = createdKAS.GetId()

// create a key
kasKey := &kasregistry.CreateKeyRequest{
KasId: kasID,
KeyId: "kas_key_1_av_not_active",
KeyAlgorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx, // Assuming keyCtx is defined in the test suite or fixtures
},
}
toBeRotatedKey, err := s.db.PolicyClient.CreateKey(s.ctx, kasKey)
s.Require().NoError(err)
s.NotNil(toBeRotatedKey)
keyIDs = append(keyIDs, toBeRotatedKey.GetKasKey().GetKey().GetId())

// rotate the key
newKey := &kasregistry.RotateKeyRequest_NewKey{
KeyId: "kas_key_1_av_not_active_rotated",
Algorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx, // Assuming keyCtx is defined
},
}
rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, toBeRotatedKey.GetKasKey(), newKey)
s.Require().NoError(err)
s.NotNil(rotatedInKey)
keyIDs = append(keyIDs, rotatedInKey.GetKasKey().GetKey().GetId())

// Get an attribute value
attrValue := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1")

// Attempt to assign the original (now inactive) key to the attribute value
resp, err := s.db.PolicyClient.AssignPublicKeyToValue(s.ctx, &attributes.ValueKey{
ValueId: attrValue.ID,
KeyId: toBeRotatedKey.GetKasKey().GetKey().GetId(),
})
s.Require().Error(err)
s.Nil(resp)
s.Require().Contains(err.Error(), fmt.Sprintf("key with id %s is not active", toBeRotatedKey.GetKasKey().GetKey().GetId()))
}

func (s *AttributeValuesSuite) Test_AssignPublicKeyToAttributeValue_Returns_Error_When_Key_Not_Found() {
f := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1")
resp, err := s.db.PolicyClient.AssignPublicKeyToValue(s.ctx, &attributes.ValueKey{
Expand All @@ -990,7 +1066,7 @@ func (s *AttributeValuesSuite) Test_AssignPublicKeyToAttributeValue_Returns_Erro

s.Require().Error(err)
s.Nil(resp)
s.Require().ErrorIs(err, db.ErrForeignKeyViolation)
s.Require().ErrorIs(err, db.ErrNotFound)
}

func (s *AttributeValuesSuite) Test_AssignPublicKeyToAttributeValue_Succeeds() {
Expand Down
72 changes: 71 additions & 1 deletion service/integration/attributes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1335,7 +1335,77 @@ func (s *AttributesSuite) Test_AssociatePublicKeyToAttribute_Returns_Error_When_

s.Require().Error(err)
s.Nil(resp)
s.Require().ErrorIs(err, db.ErrForeignKeyViolation)
s.Require().ErrorIs(err, db.ErrNotFound)
}

func (s *AttributesSuite) Test_AssociatePublicKeyToAttribute_NotActiveKey_Fail() {
var kasID string
keyIDs := make([]string, 0)
defer func() {
for _, keyID := range keyIDs {
// delete the kas key
_, err := s.db.PolicyClient.DeleteKey(s.ctx, keyID)
s.Require().NoError(err)
}

if kasID != "" {
// delete the kas
_, err := s.db.PolicyClient.DeleteKeyAccessServer(s.ctx, kasID)
s.Require().NoError(err)
}
}()

// create a KAS
kas := &kasregistry.CreateKeyAccessServerRequest{
Uri: "https://example.com/kas",
PublicKey: &policy.PublicKey{
PublicKey: &policy.PublicKey_Remote{
Remote: "https://example.com/kas/key/1",
},
},
Name: "def_kas-name",
}
createdKAS, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, kas)
s.Require().NoError(err)
s.NotNil(createdKAS)
kasID = createdKAS.GetId()

// create a key
kasKey := &kasregistry.CreateKeyRequest{
KasId: kasID,
KeyId: "kas_key_1",
KeyAlgorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx,
},
}
toBeRotatedKey, err := s.db.PolicyClient.CreateKey(s.ctx, kasKey)
s.Require().NoError(err)
s.NotNil(toBeRotatedKey)
keyIDs = append(keyIDs, toBeRotatedKey.GetKasKey().GetKey().GetId())

// rotate the key
newKey := &kasregistry.RotateKeyRequest_NewKey{
KeyId: "kas_key_1_rotated",
Algorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx,
},
}
rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, toBeRotatedKey.GetKasKey(), newKey)
s.Require().NoError(err)
s.NotNil(rotatedInKey)
keyIDs = append(keyIDs, rotatedInKey.GetKasKey().GetKey().GetId())

resp, err := s.db.PolicyClient.AssignPublicKeyToAttribute(s.ctx, &attributes.AttributeKey{
AttributeId: s.f.GetAttributeKey("example.com/attr/attr1").ID,
KeyId: toBeRotatedKey.GetKasKey().GetKey().GetId(),
})
s.Require().Error(err)
s.Nil(resp)
s.Require().Contains(err.Error(), fmt.Sprintf("key with id %s is not active", toBeRotatedKey.GetKasKey().GetKey().GetId()))
}

func (s *AttributesSuite) Test_AssociatePublicKeyToAttribute_Succeeds() {
Expand Down
97 changes: 89 additions & 8 deletions service/integration/namespaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,88 @@ func (s *NamespacesSuite) Test_AssociatePublicKeyToNamespace_Returns_Error_When_

s.Require().Error(err)
s.Nil(resp)
s.Require().ErrorIs(err, db.ErrForeignKeyViolation)
s.Require().ErrorIs(err, db.ErrNotFound)
}

func (s *NamespacesSuite) Test_AssignPublicKeyToNamespace_NotActiveKey_Fail() {
var kasID string
var namespaceID string
keyIDs := make([]string, 0)
defer func() {
for _, keyID := range keyIDs {
// delete the kas key
_, err := s.db.PolicyClient.DeleteKey(s.ctx, keyID)
s.Require().NoError(err)
}

if kasID != "" {
// delete the kas
_, err := s.db.PolicyClient.DeleteKeyAccessServer(s.ctx, kasID)
s.Require().NoError(err)
}

if namespaceID != "" {
_, err := s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, &policy.Namespace{Id: namespaceID}, "")
s.Require().NoError(err)
}
}()

// create a KAS
kasReq := &kasregistry.CreateKeyAccessServerRequest{
Uri: "https://example.com/kas-ns-inactive-key-test", // Unique URI for this test
PublicKey: &policy.PublicKey{
PublicKey: &policy.PublicKey_Remote{
Remote: "https://example.com/kas-ns-inactive-key-test/key/1",
},
},
Name: "kas_ns_inactive_key_test", // Unique name for this test
}
createdKAS, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, kasReq)
s.Require().NoError(err)
s.NotNil(createdKAS)
kasID = createdKAS.GetId()

kasKeyReq := &kasregistry.CreateKeyRequest{
KasId: kasID,
KeyId: "kas_key_ns_inactive_test", // Unique key ID for this test
KeyAlgorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx,
},
}
toBeRotatedKey, err := s.db.PolicyClient.CreateKey(s.ctx, kasKeyReq)
s.Require().NoError(err)
s.NotNil(toBeRotatedKey)
originalKeyID := toBeRotatedKey.GetKasKey().GetKey().GetId()
keyIDs = append(keyIDs, originalKeyID)

// rotate the key
rotateNewKeyReq := &kasregistry.RotateKeyRequest_NewKey{
KeyId: "kas_key_ns_inactive_test_rotated", // Unique rotated key ID
Algorithm: policy.Algorithm_ALGORITHM_EC_P256,
KeyMode: policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY,
PublicKeyCtx: &policy.PublicKeyCtx{
Pem: keyCtx, // Using the same key material for simplicity, real scenario might use new material
},
}
rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, toBeRotatedKey.GetKasKey(), rotateNewKeyReq)
s.Require().NoError(err)
s.NotNil(rotatedInKey)
keyIDs = append(keyIDs, rotatedInKey.GetKasKey().GetKey().GetId())

createdNamespace, err := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{Name: "test-kas-ns.com"})
s.Require().NoError(err)
s.NotNil(createdNamespace)
namespaceID = createdNamespace.GetId()

resp, err := s.db.PolicyClient.AssignPublicKeyToNamespace(s.ctx, &namespaces.NamespaceKey{
NamespaceId: createdNamespace.GetId(),
KeyId: originalKeyID,
})
s.Require().Error(err)
s.Nil(resp)
s.Require().Contains(err.Error(), fmt.Sprintf("key with id %s is not active", originalKeyID))
}

func (s *NamespacesSuite) Test_AssociatePublicKeyToNamespace_Succeeds() {
Expand Down Expand Up @@ -1258,17 +1339,17 @@ func (s *NamespacesSuite) Test_RemovePublicKeyFromNamespace_Not_Found_Fails() {
s.NotNil(resp)
}

func TestNamespacesSuite(t *testing.T) {
if testing.Short() {
t.Skip("skipping namespaces integration tests")
}
suite.Run(t, new(NamespacesSuite))
}

func (s *NamespacesSuite) getActiveNamespaceFixtures() []fixtures.FixtureDataNamespace {
return []fixtures.FixtureDataNamespace{
s.f.GetNamespaceKey("example.com"),
s.f.GetNamespaceKey("example.net"),
s.f.GetNamespaceKey("example.org"),
}
}

func TestNamespacesSuite(t *testing.T) {
if testing.Short() {
t.Skip("skipping namespaces integration tests")
}
suite.Run(t, new(NamespacesSuite))
}
2 changes: 1 addition & 1 deletion service/internal/fixtures/policy_fixtures.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ kas_registry_keys:
key_algorithm: 1 # ALGORITHM_RSA_2048
key_id: kas_key_2
key_mode: 1 # KEY_MODE_LOCAL
key_status: 2 # KEY_STATUS_INACTIVE
key_status: 1 # KEY_STATUS_ACTIVE
private_key_ctx: eyJ3cmFwcGVkS2V5IjoiYTJWNUNnPT0iLCJrZXlJZCI6ImtleSJ9Cg==
public_key_ctx: eyJwZW0iOiJhMlY1Q2c9PSJ9Cg==
provider_config_id: 19098106-54a1-4d33-8846-4894b5b6db3e # provider_config_2
Expand Down
4 changes: 4 additions & 0 deletions service/policy/db/attribute_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ func (c PolicyDBClient) RemoveKeyAccessServerFromValue(ctx context.Context, k *a
}

func (c PolicyDBClient) AssignPublicKeyToValue(ctx context.Context, k *attributes.ValueKey) (*attributes.ValueKey, error) {
if err := c.verifyKeyIsActive(ctx, k.GetKeyId()); err != nil {
return nil, err
}

vk, err := c.Queries.assignPublicKeyToAttributeValue(ctx, assignPublicKeyToAttributeValueParams{
ValueID: k.GetValueId(),
KeyAccessServerKeyID: k.GetKeyId(),
Expand Down
4 changes: 4 additions & 0 deletions service/policy/db/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,10 @@ func (c PolicyDBClient) RemoveKeyAccessServerFromAttribute(ctx context.Context,
}

func (c PolicyDBClient) AssignPublicKeyToAttribute(ctx context.Context, k *attributes.AttributeKey) (*attributes.AttributeKey, error) {
if err := c.verifyKeyIsActive(ctx, k.GetKeyId()); err != nil {
return nil, err
}

ak, err := c.Queries.assignPublicKeyToAttributeDefinition(ctx, assignPublicKeyToAttributeDefinitionParams{
DefinitionID: k.GetAttributeId(),
KeyAccessServerKeyID: k.GetKeyId(),
Expand Down
15 changes: 15 additions & 0 deletions service/policy/db/key_access_server_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -916,3 +916,18 @@ func (c PolicyDBClient) rotateBaseKey(ctx context.Context, rotatedOutKeyID *poli

return nil
}

func (c PolicyDBClient) verifyKeyIsActive(ctx context.Context, id string) error {
key, err := c.GetKey(ctx, &kasregistry.GetKeyRequest_Id{
Id: id,
})
if err != nil {
return err
}

if key.GetKey().GetKeyStatus() != policy.KeyStatus_KEY_STATUS_ACTIVE {
return fmt.Errorf("key with id %s is not active", id)
}

return nil
}
4 changes: 4 additions & 0 deletions service/policy/db/namespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ func (c PolicyDBClient) RemoveKeyAccessServerFromNamespace(ctx context.Context,
}

func (c PolicyDBClient) AssignPublicKeyToNamespace(ctx context.Context, k *namespaces.NamespaceKey) (*namespaces.NamespaceKey, error) {
if err := c.verifyKeyIsActive(ctx, k.GetKeyId()); err != nil {
return nil, err
}

key, err := c.Queries.assignPublicKeyToNamespace(ctx, assignPublicKeyToNamespaceParams{
NamespaceID: k.GetNamespaceId(),
KeyAccessServerKeyID: k.GetKeyId(),
Expand Down
Loading