From 6413d3486d007c5ba8794747525a2e2668639a85 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 7 May 2025 13:02:56 -0500 Subject: [PATCH 1/8] feat(policy): Add platform key indexer. remove comments. linting. linting. fix test. --- service/trust/platform_key_indexer.go | 255 +++++++++++++++++++++ service/trust/platform_key_indexer_test.go | 79 +++++++ 2 files changed, 334 insertions(+) create mode 100644 service/trust/platform_key_indexer.go create mode 100644 service/trust/platform_key_indexer_test.go diff --git a/service/trust/platform_key_indexer.go b/service/trust/platform_key_indexer.go new file mode 100644 index 0000000000..1676724f2a --- /dev/null +++ b/service/trust/platform_key_indexer.go @@ -0,0 +1,255 @@ +package trust + +import ( + "context" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + + "github.com/lestrrat-go/jwx/v2/jwk" + "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/policy/kasregistry" + "github.com/opentdf/platform/sdk" + "github.com/opentdf/platform/service/logger" +) + +var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified algorithm") + +// Used for reaching out to platform to get keys +type PlatformKeyIndexer struct { + // KeyIndex is the key index used to manage keys + KeyIndex + // SDK is the SDK instance used to interact with the platform + sdk *sdk.SDK + // KasURI + kasURI string + // Logger is the logger instance used for logging + log *logger.Logger +} + +// platformKeyAdapter is an adapter for KeyDetails, where keys come from the platform +type KasKeyAdapter struct { + key *policy.KasKey + log *logger.Logger +} + +func NewPlatformKeyIndexer(sdk *sdk.SDK, kasURI string, l *logger.Logger) *PlatformKeyIndexer { + return &PlatformKeyIndexer{ + sdk: sdk, + kasURI: kasURI, + log: l, + } +} + +func convertAlgToEnum(alg string) (policy.Algorithm, error) { + switch alg { + case "rsa:2048": + return policy.Algorithm_ALGORITHM_RSA_2048, nil + case "rsa:4096": + return policy.Algorithm_ALGORITHM_RSA_4096, nil + case "ec:secp256r1": + return policy.Algorithm_ALGORITHM_EC_P256, nil + case "ec:secp384r1": + return policy.Algorithm_ALGORITHM_EC_P384, nil + case "ec:secp521r1": + return policy.Algorithm_ALGORITHM_EC_P521, nil + default: + return policy.Algorithm_ALGORITHM_UNSPECIFIED, errors.New("unsupported algorithm") + } +} + +func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm string, _ bool) (KeyDetails, error) { + alg, err := convertAlgToEnum(algorithm) + if err != nil { + return nil, err + } + + req := &kasregistry.ListKeysRequest{ + KeyAlgorithm: alg, + KasFilter: &kasregistry.ListKeysRequest_KasUri{ + KasUri: p.kasURI, + }, + } + resp, err := p.sdk.KeyAccessServerRegistry.ListKeys(ctx, req) + if err != nil { + return nil, err + } + + // Find active key. + var activeKey *policy.KasKey + for _, key := range resp.GetKasKeys() { + if key.GetKey().GetKeyStatus() == policy.KeyStatus_KEY_STATUS_ACTIVE { + activeKey = key + break + } + } + if activeKey == nil { + return nil, ErrNoActiveKeyForAlgorithm + } + + return &KasKeyAdapter{ + key: activeKey, + log: p.log, + }, nil +} + +func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id KeyIdentifier) (KeyDetails, error) { + req := &kasregistry.GetKeyRequest{ + Identifier: &kasregistry.GetKeyRequest_Key{ + Key: &kasregistry.KasKeyIdentifier{ + Identifier: &kasregistry.KasKeyIdentifier_Uri{ + Uri: p.kasURI, + }, + Kid: string(id), + }, + }, + } + + resp, err := p.sdk.KeyAccessServerRegistry.GetKey(ctx, req) + if err != nil { + return nil, err + } + + return &KasKeyAdapter{ + key: resp.GetKasKey(), + log: p.log, + }, nil +} + +func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]KeyDetails, error) { + req := &kasregistry.ListKeysRequest{ + KasFilter: &kasregistry.ListKeysRequest_KasUri{ + KasUri: p.kasURI, + }, + } + resp, err := p.sdk.KeyAccessServerRegistry.ListKeys(ctx, req) + if err != nil { + return nil, err + } + + keys := make([]KeyDetails, len(resp.GetKasKeys())) + for i, key := range resp.GetKasKeys() { + keys[i] = &KasKeyAdapter{ + key: key, + log: p.log, + } + } + + return keys, nil +} + +func (p *KasKeyAdapter) ID() KeyIdentifier { + return KeyIdentifier(p.key.GetKey().GetKeyId()) +} + +// Might need to convert this to a standard format +func (p *KasKeyAdapter) Algorithm() string { + return p.key.GetKey().GetKeyAlgorithm().String() +} + +func (p *KasKeyAdapter) IsLegacy() bool { + return false +} + +// This will point to the correct "manager" +func (p *KasKeyAdapter) System() string { + var mode string + if p.key.GetKey().GetProviderConfig() != nil { + mode = p.key.GetKey().GetProviderConfig().GetName() + } + return mode +} + +func pemToPublicKey(publicPEM string) (*rsa.PublicKey, error) { + // Decode the PEM data + block, _ := pem.Decode([]byte(publicPEM)) + if block == nil || block.Type != "PUBLIC KEY" { + return nil, fmt.Errorf("failed to decode PEM block or incorrect PEM type") + } + + // Parse the public key + pub, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("failed to parse public key: %w", err) + } + + // Assert type and return + rsaPub, ok := pub.(*rsa.PublicKey) + if !ok { + return nil, fmt.Errorf("not an RSA public key") + } + + return rsaPub, nil +} + +// Repurpose of the StandardCrypto function +func rsaPublicKeyAsJSON(_ context.Context, publicPEM string) (string, error) { + pubKey, err := pemToPublicKey(publicPEM) + if err != nil { + return "", err + } + + rsaPublicKeyJwk, err := jwk.FromRaw(pubKey) + if err != nil { + return "", fmt.Errorf("jwk.FromRaw: %w", err) + } + + // Convert the public key to JSON format + pubKeyJSON, err := json.Marshal(rsaPublicKeyJwk) + if err != nil { + return "", err + } + + return string(pubKeyJSON), nil +} + +// Repurpose of the StandardCrypto function +func convertPEMToJWK(_ string) (string, error) { + return "", errors.New("convertPEMToJWK function is not implemented") +} + +func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format KeyType) (string, error) { + publicKeyCtx := p.key.GetKey().GetPublicKeyCtx() + var pubKeyCtxMap map[string]any + if err := json.Unmarshal(publicKeyCtx, &pubKeyCtxMap); err != nil { + return "", err + } + + pubKey, ok := pubKeyCtxMap["pubKey"].(string) + if !ok { + return "", errors.New("public key is not a string") + } + // Decode the base64-encoded public key + decodedPubKey, err := base64.StdEncoding.DecodeString(pubKey) + if err != nil { + return "", err + } + + switch format { + case KeyTypeJWK: + // For JWK format (currently only supported for RSA) + if p.key.GetKey().GetKeyAlgorithm() == policy.Algorithm_ALGORITHM_RSA_2048 || + p.key.GetKey().GetKeyAlgorithm() == policy.Algorithm_ALGORITHM_RSA_4096 { + return rsaPublicKeyAsJSON(ctx, string(decodedPubKey)) + } + // For EC keys, we return the public key in PEM format + jwkKey, err := convertPEMToJWK(string(decodedPubKey)) + if err != nil { + return "", err + } + + return jwkKey, nil + case KeyTypePKCS8: + return string(decodedPubKey), nil + default: + return "", errors.New("unsupported key type") + } +} + +func (p *KasKeyAdapter) ExportCertificate(_ context.Context) (string, error) { + return "", errors.New("not implemented") +} diff --git a/service/trust/platform_key_indexer_test.go b/service/trust/platform_key_indexer_test.go new file mode 100644 index 0000000000..c9293358fd --- /dev/null +++ b/service/trust/platform_key_indexer_test.go @@ -0,0 +1,79 @@ +package trust + +import ( + "context" + "encoding/json" + "testing" + + "github.com/lestrrat-go/jwx/v2/jwk" + "github.com/opentdf/platform/lib/ocrypto" + "github.com/opentdf/platform/protocol/go/policy" + "github.com/stretchr/testify/suite" +) + +type PlatformKeyIndexTestSuite struct { + suite.Suite + rsaKey KeyDetails +} + +func (s *PlatformKeyIndexTestSuite) SetupTest() { + s.rsaKey = &KasKeyAdapter{ + key: &policy.KasKey{ + KasId: "test-kas-id", + Key: &policy.AsymmetricKey{ + Id: "test-id", + KeyId: "test-key-id", + KeyAlgorithm: policy.Algorithm_ALGORITHM_RSA_2048, + KeyStatus: policy.KeyStatus_KEY_STATUS_ACTIVE, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: []byte(`{"pubKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3SEw0TkVrOFpDa0JzNjZXQVpWagpIS3NseDRseWdmaXN3aW42RUx5OU9OczZLVDRYa1crRGxsdExtck14bHZkbzVRaDg1UmFZS01mWUdDTWtPM0dGCkFsK0JOeWFOM1kwa0N1QjNPU2ErTzdyMURhNVZteVVuaEJNbFBrYnVPY1Y0cjlLMUhOSGd3eDl2UFp3RjRpQW8KQStEY1VBcWFEeHlvYjV6enNGZ0hUNjJHLzdLdEtiZ2hYT1dCanRUYUl1ZHpsK2FaSjFPemY0U1RkOXhST2QrMQordVo2VG1ocmFEUm9zdDUrTTZUN0toL2lGWk40TTFUY2hwWXU1TDhKR2tVaG9YaEdZcHUrMGczSzlqYlh6RVh5CnpJU3VXN2d6SGRWYUxvcnBkQlNkRHpOWkNvTFVoL0U1T3d5TFZFQkNKaDZJVUtvdWJ5WHVucnIxQnJmK2tLbEsKeHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="}`), + ProviderConfig: &policy.KeyProviderConfig{ + Id: "test-provider-id", + Name: "openbao", + }, + }, + }, + } +} +func (s *PlatformKeyIndexTestSuite) TearDownTest() {} + +func (s *PlatformKeyIndexTestSuite) TestKeyDetails() { + s.Equal("test-key-id", string(s.rsaKey.ID())) + s.Equal("ALGORITHM_RSA_2048", s.rsaKey.Algorithm()) + s.False(s.rsaKey.IsLegacy()) + s.Equal("openbao", s.rsaKey.System()) +} + +func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { + // Export JWK format + jwkString, err := s.rsaKey.ExportPublicKey(context.Background(), KeyTypeJWK) + s.Require().NoError(err) + s.Require().NotEmpty(jwkString) + + rsaKey, err := jwk.ParseKey([]byte(jwkString)) + s.Require().NoError(err) + s.Require().NotNil(rsaKey) +} + +func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { + // Export JWK format + pem, err := s.rsaKey.ExportPublicKey(context.Background(), KeyTypePKCS8) + s.Require().NoError(err) + s.Require().NotEmpty(pem) + + keyAdapter, ok := s.rsaKey.(*KasKeyAdapter) + s.Require().True(ok) + pubCtx := keyAdapter.key.GetKey().GetPublicKeyCtx() + s.Require().NotEmpty(pubCtx) + base64Pem := ocrypto.Base64Encode([]byte(pem)) + + var pubCtxMap map[string]interface{} + err = json.Unmarshal(pubCtx, &pubCtxMap) + s.Require().NoError(err) + + s.Equal(pubCtxMap["pubKey"], string(base64Pem)) +} + +func TestNewPlatformKeyIndexTestSuite(t *testing.T) { + suite.Run(t, new(PlatformKeyIndexTestSuite)) +} From ed2a29413852de060e9a3ceb4f1ad2a0d79b95b6 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 08:15:08 -0500 Subject: [PATCH 2/8] refactor. --- service/trust/platform_key_indexer.go | 10 +--------- service/trust/platform_key_indexer_test.go | 12 ++++-------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/service/trust/platform_key_indexer.go b/service/trust/platform_key_indexer.go index 1676724f2a..efc19b3188 100644 --- a/service/trust/platform_key_indexer.go +++ b/service/trust/platform_key_indexer.go @@ -214,17 +214,9 @@ func convertPEMToJWK(_ string) (string, error) { func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format KeyType) (string, error) { publicKeyCtx := p.key.GetKey().GetPublicKeyCtx() - var pubKeyCtxMap map[string]any - if err := json.Unmarshal(publicKeyCtx, &pubKeyCtxMap); err != nil { - return "", err - } - pubKey, ok := pubKeyCtxMap["pubKey"].(string) - if !ok { - return "", errors.New("public key is not a string") - } // Decode the base64-encoded public key - decodedPubKey, err := base64.StdEncoding.DecodeString(pubKey) + decodedPubKey, err := base64.StdEncoding.DecodeString(publicKeyCtx.GetPem()) if err != nil { return "", err } diff --git a/service/trust/platform_key_indexer_test.go b/service/trust/platform_key_indexer_test.go index c9293358fd..3e31d50bfc 100644 --- a/service/trust/platform_key_indexer_test.go +++ b/service/trust/platform_key_indexer_test.go @@ -2,7 +2,6 @@ package trust import ( "context" - "encoding/json" "testing" "github.com/lestrrat-go/jwx/v2/jwk" @@ -26,7 +25,9 @@ func (s *PlatformKeyIndexTestSuite) SetupTest() { KeyAlgorithm: policy.Algorithm_ALGORITHM_RSA_2048, KeyStatus: policy.KeyStatus_KEY_STATUS_ACTIVE, KeyMode: policy.KeyMode_KEY_MODE_LOCAL, - PublicKeyCtx: []byte(`{"pubKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3SEw0TkVrOFpDa0JzNjZXQVpWagpIS3NseDRseWdmaXN3aW42RUx5OU9OczZLVDRYa1crRGxsdExtck14bHZkbzVRaDg1UmFZS01mWUdDTWtPM0dGCkFsK0JOeWFOM1kwa0N1QjNPU2ErTzdyMURhNVZteVVuaEJNbFBrYnVPY1Y0cjlLMUhOSGd3eDl2UFp3RjRpQW8KQStEY1VBcWFEeHlvYjV6enNGZ0hUNjJHLzdLdEtiZ2hYT1dCanRUYUl1ZHpsK2FaSjFPemY0U1RkOXhST2QrMQordVo2VG1ocmFEUm9zdDUrTTZUN0toL2lGWk40TTFUY2hwWXU1TDhKR2tVaG9YaEdZcHUrMGczSzlqYlh6RVh5CnpJU3VXN2d6SGRWYUxvcnBkQlNkRHpOWkNvTFVoL0U1T3d5TFZFQkNKaDZJVUtvdWJ5WHVucnIxQnJmK2tLbEsKeHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="}`), + PublicKeyCtx: &policy.KasPublicKeyCtx{ + Pem: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3SEw0TkVrOFpDa0JzNjZXQVpWagpIS3NseDRseWdmaXN3aW42RUx5OU9OczZLVDRYa1crRGxsdExtck14bHZkbzVRaDg1UmFZS01mWUdDTWtPM0dGCkFsK0JOeWFOM1kwa0N1QjNPU2ErTzdyMURhNVZteVVuaEJNbFBrYnVPY1Y0cjlLMUhOSGd3eDl2UFp3RjRpQW8KQStEY1VBcWFEeHlvYjV6enNGZ0hUNjJHLzdLdEtiZ2hYT1dCanRUYUl1ZHpsK2FaSjFPemY0U1RkOXhST2QrMQordVo2VG1ocmFEUm9zdDUrTTZUN0toL2lGWk40TTFUY2hwWXU1TDhKR2tVaG9YaEdZcHUrMGczSzlqYlh6RVh5CnpJU3VXN2d6SGRWYUxvcnBkQlNkRHpOWkNvTFVoL0U1T3d5TFZFQkNKaDZJVUtvdWJ5WHVucnIxQnJmK2tLbEsKeHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==", + }, ProviderConfig: &policy.KeyProviderConfig{ Id: "test-provider-id", Name: "openbao", @@ -66,12 +67,7 @@ func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { pubCtx := keyAdapter.key.GetKey().GetPublicKeyCtx() s.Require().NotEmpty(pubCtx) base64Pem := ocrypto.Base64Encode([]byte(pem)) - - var pubCtxMap map[string]interface{} - err = json.Unmarshal(pubCtx, &pubCtxMap) - s.Require().NoError(err) - - s.Equal(pubCtxMap["pubKey"], string(base64Pem)) + s.Equal(pubCtx.GetPem(), string(base64Pem)) } func TestNewPlatformKeyIndexTestSuite(t *testing.T) { From f715b84c52504678742da63d119b233a8a70a23b Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 08:34:07 -0500 Subject: [PATCH 3/8] move to pkg dir and fix linting. --- .../indexer}/platform_key_indexer.go | 25 ++++++++++--------- .../indexer}/platform_key_indexer_test.go | 7 +++--- 2 files changed, 17 insertions(+), 15 deletions(-) rename service/{trust => pkg/indexer}/platform_key_indexer.go (90%) rename service/{trust => pkg/indexer}/platform_key_indexer_test.go (93%) diff --git a/service/trust/platform_key_indexer.go b/service/pkg/indexer/platform_key_indexer.go similarity index 90% rename from service/trust/platform_key_indexer.go rename to service/pkg/indexer/platform_key_indexer.go index efc19b3188..a4404dde9b 100644 --- a/service/trust/platform_key_indexer.go +++ b/service/pkg/indexer/platform_key_indexer.go @@ -15,6 +15,7 @@ import ( "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/opentdf/platform/sdk" "github.com/opentdf/platform/service/logger" + "github.com/opentdf/platform/service/trust" ) var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified algorithm") @@ -22,7 +23,7 @@ var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified a // Used for reaching out to platform to get keys type PlatformKeyIndexer struct { // KeyIndex is the key index used to manage keys - KeyIndex + trust.KeyIndex // SDK is the SDK instance used to interact with the platform sdk *sdk.SDK // KasURI @@ -62,7 +63,7 @@ func convertAlgToEnum(alg string) (policy.Algorithm, error) { } } -func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm string, _ bool) (KeyDetails, error) { +func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm string, _ bool) (trust.KeyDetails, error) { alg, err := convertAlgToEnum(algorithm) if err != nil { return nil, err @@ -97,7 +98,7 @@ func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm s }, nil } -func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id KeyIdentifier) (KeyDetails, error) { +func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id trust.KeyIdentifier) (trust.KeyDetails, error) { req := &kasregistry.GetKeyRequest{ Identifier: &kasregistry.GetKeyRequest_Key{ Key: &kasregistry.KasKeyIdentifier{ @@ -120,7 +121,7 @@ func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id KeyIdentifier) }, nil } -func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]KeyDetails, error) { +func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]trust.KeyDetails, error) { req := &kasregistry.ListKeysRequest{ KasFilter: &kasregistry.ListKeysRequest_KasUri{ KasUri: p.kasURI, @@ -131,7 +132,7 @@ func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]KeyDetails, error) return nil, err } - keys := make([]KeyDetails, len(resp.GetKasKeys())) + keys := make([]trust.KeyDetails, len(resp.GetKasKeys())) for i, key := range resp.GetKasKeys() { keys[i] = &KasKeyAdapter{ key: key, @@ -142,8 +143,8 @@ func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]KeyDetails, error) return keys, nil } -func (p *KasKeyAdapter) ID() KeyIdentifier { - return KeyIdentifier(p.key.GetKey().GetKeyId()) +func (p *KasKeyAdapter) ID() trust.KeyIdentifier { + return trust.KeyIdentifier(p.key.GetKey().GetKeyId()) } // Might need to convert this to a standard format @@ -168,7 +169,7 @@ func pemToPublicKey(publicPEM string) (*rsa.PublicKey, error) { // Decode the PEM data block, _ := pem.Decode([]byte(publicPEM)) if block == nil || block.Type != "PUBLIC KEY" { - return nil, fmt.Errorf("failed to decode PEM block or incorrect PEM type") + return nil, errors.New("failed to decode PEM block or incorrect PEM type") } // Parse the public key @@ -180,7 +181,7 @@ func pemToPublicKey(publicPEM string) (*rsa.PublicKey, error) { // Assert type and return rsaPub, ok := pub.(*rsa.PublicKey) if !ok { - return nil, fmt.Errorf("not an RSA public key") + return nil, errors.New("not an RSA public key") } return rsaPub, nil @@ -212,7 +213,7 @@ func convertPEMToJWK(_ string) (string, error) { return "", errors.New("convertPEMToJWK function is not implemented") } -func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format KeyType) (string, error) { +func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format trust.KeyType) (string, error) { publicKeyCtx := p.key.GetKey().GetPublicKeyCtx() // Decode the base64-encoded public key @@ -222,7 +223,7 @@ func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format KeyType) (st } switch format { - case KeyTypeJWK: + case trust.KeyTypeJWK: // For JWK format (currently only supported for RSA) if p.key.GetKey().GetKeyAlgorithm() == policy.Algorithm_ALGORITHM_RSA_2048 || p.key.GetKey().GetKeyAlgorithm() == policy.Algorithm_ALGORITHM_RSA_4096 { @@ -235,7 +236,7 @@ func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format KeyType) (st } return jwkKey, nil - case KeyTypePKCS8: + case trust.KeyTypePKCS8: return string(decodedPubKey), nil default: return "", errors.New("unsupported key type") diff --git a/service/trust/platform_key_indexer_test.go b/service/pkg/indexer/platform_key_indexer_test.go similarity index 93% rename from service/trust/platform_key_indexer_test.go rename to service/pkg/indexer/platform_key_indexer_test.go index 3e31d50bfc..eca72784ac 100644 --- a/service/trust/platform_key_indexer_test.go +++ b/service/pkg/indexer/platform_key_indexer_test.go @@ -7,12 +7,13 @@ import ( "github.com/lestrrat-go/jwx/v2/jwk" "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/service/trust" "github.com/stretchr/testify/suite" ) type PlatformKeyIndexTestSuite struct { suite.Suite - rsaKey KeyDetails + rsaKey trust.KeyDetails } func (s *PlatformKeyIndexTestSuite) SetupTest() { @@ -47,7 +48,7 @@ func (s *PlatformKeyIndexTestSuite) TestKeyDetails() { func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { // Export JWK format - jwkString, err := s.rsaKey.ExportPublicKey(context.Background(), KeyTypeJWK) + jwkString, err := s.rsaKey.ExportPublicKey(context.Background(), trust.KeyTypeJWK) s.Require().NoError(err) s.Require().NotEmpty(jwkString) @@ -58,7 +59,7 @@ func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { // Export JWK format - pem, err := s.rsaKey.ExportPublicKey(context.Background(), KeyTypePKCS8) + pem, err := s.rsaKey.ExportPublicKey(context.Background(), trust.KeyTypePKCS8) s.Require().NoError(err) s.Require().NotEmpty(pem) From 6fbd291a167f0f99030ff19ddd9932330f85c933 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 08:39:52 -0500 Subject: [PATCH 4/8] rename pkg. --- service/pkg/{indexer => key_indexer}/platform_key_indexer.go | 0 service/pkg/{indexer => key_indexer}/platform_key_indexer_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename service/pkg/{indexer => key_indexer}/platform_key_indexer.go (100%) rename service/pkg/{indexer => key_indexer}/platform_key_indexer_test.go (100%) diff --git a/service/pkg/indexer/platform_key_indexer.go b/service/pkg/key_indexer/platform_key_indexer.go similarity index 100% rename from service/pkg/indexer/platform_key_indexer.go rename to service/pkg/key_indexer/platform_key_indexer.go diff --git a/service/pkg/indexer/platform_key_indexer_test.go b/service/pkg/key_indexer/platform_key_indexer_test.go similarity index 100% rename from service/pkg/indexer/platform_key_indexer_test.go rename to service/pkg/key_indexer/platform_key_indexer_test.go From ca1b8e7a883535b5b44785868565343734fe28ec Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 09:23:59 -0500 Subject: [PATCH 5/8] move platform key indexer and return better errors. --- .../keymanagement}/platform_key_indexer.go | 4 ++-- .../keymanagement}/platform_key_indexer_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename service/{pkg/key_indexer => policy/keymanagement}/platform_key_indexer.go (98%) rename service/{pkg/key_indexer => policy/keymanagement}/platform_key_indexer_test.go (99%) diff --git a/service/pkg/key_indexer/platform_key_indexer.go b/service/policy/keymanagement/platform_key_indexer.go similarity index 98% rename from service/pkg/key_indexer/platform_key_indexer.go rename to service/policy/keymanagement/platform_key_indexer.go index a4404dde9b..dfecb816b7 100644 --- a/service/pkg/key_indexer/platform_key_indexer.go +++ b/service/policy/keymanagement/platform_key_indexer.go @@ -1,4 +1,4 @@ -package trust +package keymanagement import ( "context" @@ -59,7 +59,7 @@ func convertAlgToEnum(alg string) (policy.Algorithm, error) { case "ec:secp521r1": return policy.Algorithm_ALGORITHM_EC_P521, nil default: - return policy.Algorithm_ALGORITHM_UNSPECIFIED, errors.New("unsupported algorithm") + return policy.Algorithm_ALGORITHM_UNSPECIFIED, fmt.Errorf("unsupported algorithm: %s", alg) } } diff --git a/service/pkg/key_indexer/platform_key_indexer_test.go b/service/policy/keymanagement/platform_key_indexer_test.go similarity index 99% rename from service/pkg/key_indexer/platform_key_indexer_test.go rename to service/policy/keymanagement/platform_key_indexer_test.go index eca72784ac..ab10d855db 100644 --- a/service/pkg/key_indexer/platform_key_indexer_test.go +++ b/service/policy/keymanagement/platform_key_indexer_test.go @@ -1,4 +1,4 @@ -package trust +package keymanagement import ( "context" From 4fdd9badd3c12ec035f244e3996b0302d7f4de9d Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 09:24:39 -0500 Subject: [PATCH 6/8] better comment. --- service/policy/keymanagement/platform_key_indexer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/policy/keymanagement/platform_key_indexer.go b/service/policy/keymanagement/platform_key_indexer.go index dfecb816b7..370da86762 100644 --- a/service/policy/keymanagement/platform_key_indexer.go +++ b/service/policy/keymanagement/platform_key_indexer.go @@ -22,7 +22,7 @@ var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified a // Used for reaching out to platform to get keys type PlatformKeyIndexer struct { - // KeyIndex is the key index used to manage keys + // Implements the KeyIndex interface trust.KeyIndex // SDK is the SDK instance used to interact with the platform sdk *sdk.SDK From d55ad35ba2ca6f4b9ac8103d6c5c43c53885fe99 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 14:34:57 -0500 Subject: [PATCH 7/8] refactor. --- service/policy/keymanagement/platform_key_indexer.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/service/policy/keymanagement/platform_key_indexer.go b/service/policy/keymanagement/platform_key_indexer.go index 370da86762..c511e45e49 100644 --- a/service/policy/keymanagement/platform_key_indexer.go +++ b/service/policy/keymanagement/platform_key_indexer.go @@ -22,8 +22,6 @@ var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified a // Used for reaching out to platform to get keys type PlatformKeyIndexer struct { - // Implements the KeyIndex interface - trust.KeyIndex // SDK is the SDK instance used to interact with the platform sdk *sdk.SDK // KasURI From eb1d7b7d2f62c0f757e108e123581cad4d4d54d2 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 20 May 2025 14:57:45 -0500 Subject: [PATCH 8/8] refactor. --- .../key_indexer.go} | 34 +++++++++---------- .../key_indexer_test.go} | 22 ++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) rename service/{policy/keymanagement/platform_key_indexer.go => kas/key_indexer.go} (85%) rename service/{policy/keymanagement/platform_key_indexer_test.go => kas/key_indexer_test.go} (80%) diff --git a/service/policy/keymanagement/platform_key_indexer.go b/service/kas/key_indexer.go similarity index 85% rename from service/policy/keymanagement/platform_key_indexer.go rename to service/kas/key_indexer.go index c511e45e49..fbce3bbcc9 100644 --- a/service/policy/keymanagement/platform_key_indexer.go +++ b/service/kas/key_indexer.go @@ -1,4 +1,4 @@ -package keymanagement +package kas import ( "context" @@ -21,7 +21,7 @@ import ( var ErrNoActiveKeyForAlgorithm = errors.New("no active key found for specified algorithm") // Used for reaching out to platform to get keys -type PlatformKeyIndexer struct { +type KeyIndexer struct { // SDK is the SDK instance used to interact with the platform sdk *sdk.SDK // KasURI @@ -31,13 +31,13 @@ type PlatformKeyIndexer struct { } // platformKeyAdapter is an adapter for KeyDetails, where keys come from the platform -type KasKeyAdapter struct { +type KeyAdapter struct { key *policy.KasKey log *logger.Logger } -func NewPlatformKeyIndexer(sdk *sdk.SDK, kasURI string, l *logger.Logger) *PlatformKeyIndexer { - return &PlatformKeyIndexer{ +func NewPlatformKeyIndexer(sdk *sdk.SDK, kasURI string, l *logger.Logger) *KeyIndexer { + return &KeyIndexer{ sdk: sdk, kasURI: kasURI, log: l, @@ -61,7 +61,7 @@ func convertAlgToEnum(alg string) (policy.Algorithm, error) { } } -func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm string, _ bool) (trust.KeyDetails, error) { +func (p *KeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm string, _ bool) (trust.KeyDetails, error) { alg, err := convertAlgToEnum(algorithm) if err != nil { return nil, err @@ -90,13 +90,13 @@ func (p *PlatformKeyIndexer) FindKeyByAlgorithm(ctx context.Context, algorithm s return nil, ErrNoActiveKeyForAlgorithm } - return &KasKeyAdapter{ + return &KeyAdapter{ key: activeKey, log: p.log, }, nil } -func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id trust.KeyIdentifier) (trust.KeyDetails, error) { +func (p *KeyIndexer) FindKeyByID(ctx context.Context, id trust.KeyIdentifier) (trust.KeyDetails, error) { req := &kasregistry.GetKeyRequest{ Identifier: &kasregistry.GetKeyRequest_Key{ Key: &kasregistry.KasKeyIdentifier{ @@ -113,13 +113,13 @@ func (p *PlatformKeyIndexer) FindKeyByID(ctx context.Context, id trust.KeyIdenti return nil, err } - return &KasKeyAdapter{ + return &KeyAdapter{ key: resp.GetKasKey(), log: p.log, }, nil } -func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]trust.KeyDetails, error) { +func (p *KeyIndexer) ListKeys(ctx context.Context) ([]trust.KeyDetails, error) { req := &kasregistry.ListKeysRequest{ KasFilter: &kasregistry.ListKeysRequest_KasUri{ KasUri: p.kasURI, @@ -132,7 +132,7 @@ func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]trust.KeyDetails, keys := make([]trust.KeyDetails, len(resp.GetKasKeys())) for i, key := range resp.GetKasKeys() { - keys[i] = &KasKeyAdapter{ + keys[i] = &KeyAdapter{ key: key, log: p.log, } @@ -141,21 +141,21 @@ func (p *PlatformKeyIndexer) ListKeys(ctx context.Context) ([]trust.KeyDetails, return keys, nil } -func (p *KasKeyAdapter) ID() trust.KeyIdentifier { +func (p *KeyAdapter) ID() trust.KeyIdentifier { return trust.KeyIdentifier(p.key.GetKey().GetKeyId()) } // Might need to convert this to a standard format -func (p *KasKeyAdapter) Algorithm() string { +func (p *KeyAdapter) Algorithm() string { return p.key.GetKey().GetKeyAlgorithm().String() } -func (p *KasKeyAdapter) IsLegacy() bool { +func (p *KeyAdapter) IsLegacy() bool { return false } // This will point to the correct "manager" -func (p *KasKeyAdapter) System() string { +func (p *KeyAdapter) System() string { var mode string if p.key.GetKey().GetProviderConfig() != nil { mode = p.key.GetKey().GetProviderConfig().GetName() @@ -211,7 +211,7 @@ func convertPEMToJWK(_ string) (string, error) { return "", errors.New("convertPEMToJWK function is not implemented") } -func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format trust.KeyType) (string, error) { +func (p *KeyAdapter) ExportPublicKey(ctx context.Context, format trust.KeyType) (string, error) { publicKeyCtx := p.key.GetKey().GetPublicKeyCtx() // Decode the base64-encoded public key @@ -241,6 +241,6 @@ func (p *KasKeyAdapter) ExportPublicKey(ctx context.Context, format trust.KeyTyp } } -func (p *KasKeyAdapter) ExportCertificate(_ context.Context) (string, error) { +func (p *KeyAdapter) ExportCertificate(_ context.Context) (string, error) { return "", errors.New("not implemented") } diff --git a/service/policy/keymanagement/platform_key_indexer_test.go b/service/kas/key_indexer_test.go similarity index 80% rename from service/policy/keymanagement/platform_key_indexer_test.go rename to service/kas/key_indexer_test.go index ab10d855db..4fb7ed2a0a 100644 --- a/service/policy/keymanagement/platform_key_indexer_test.go +++ b/service/kas/key_indexer_test.go @@ -1,4 +1,4 @@ -package keymanagement +package kas import ( "context" @@ -11,13 +11,13 @@ import ( "github.com/stretchr/testify/suite" ) -type PlatformKeyIndexTestSuite struct { +type KeyIndexTestSuite struct { suite.Suite rsaKey trust.KeyDetails } -func (s *PlatformKeyIndexTestSuite) SetupTest() { - s.rsaKey = &KasKeyAdapter{ +func (s *KeyIndexTestSuite) SetupTest() { + s.rsaKey = &KeyAdapter{ key: &policy.KasKey{ KasId: "test-kas-id", Key: &policy.AsymmetricKey{ @@ -25,7 +25,7 @@ func (s *PlatformKeyIndexTestSuite) SetupTest() { KeyId: "test-key-id", KeyAlgorithm: policy.Algorithm_ALGORITHM_RSA_2048, KeyStatus: policy.KeyStatus_KEY_STATUS_ACTIVE, - KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + KeyMode: policy.KeyMode_KEY_MODE_CONFIG_ROOT_KEY, PublicKeyCtx: &policy.KasPublicKeyCtx{ Pem: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3SEw0TkVrOFpDa0JzNjZXQVpWagpIS3NseDRseWdmaXN3aW42RUx5OU9OczZLVDRYa1crRGxsdExtck14bHZkbzVRaDg1UmFZS01mWUdDTWtPM0dGCkFsK0JOeWFOM1kwa0N1QjNPU2ErTzdyMURhNVZteVVuaEJNbFBrYnVPY1Y0cjlLMUhOSGd3eDl2UFp3RjRpQW8KQStEY1VBcWFEeHlvYjV6enNGZ0hUNjJHLzdLdEtiZ2hYT1dCanRUYUl1ZHpsK2FaSjFPemY0U1RkOXhST2QrMQordVo2VG1ocmFEUm9zdDUrTTZUN0toL2lGWk40TTFUY2hwWXU1TDhKR2tVaG9YaEdZcHUrMGczSzlqYlh6RVh5CnpJU3VXN2d6SGRWYUxvcnBkQlNkRHpOWkNvTFVoL0U1T3d5TFZFQkNKaDZJVUtvdWJ5WHVucnIxQnJmK2tLbEsKeHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==", }, @@ -37,16 +37,16 @@ func (s *PlatformKeyIndexTestSuite) SetupTest() { }, } } -func (s *PlatformKeyIndexTestSuite) TearDownTest() {} +func (s *KeyIndexTestSuite) TearDownTest() {} -func (s *PlatformKeyIndexTestSuite) TestKeyDetails() { +func (s *KeyIndexTestSuite) TestKeyDetails() { s.Equal("test-key-id", string(s.rsaKey.ID())) s.Equal("ALGORITHM_RSA_2048", s.rsaKey.Algorithm()) s.False(s.rsaKey.IsLegacy()) s.Equal("openbao", s.rsaKey.System()) } -func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { +func (s *KeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { // Export JWK format jwkString, err := s.rsaKey.ExportPublicKey(context.Background(), trust.KeyTypeJWK) s.Require().NoError(err) @@ -57,13 +57,13 @@ func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_JWKFormat() { s.Require().NotNil(rsaKey) } -func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { +func (s *KeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { // Export JWK format pem, err := s.rsaKey.ExportPublicKey(context.Background(), trust.KeyTypePKCS8) s.Require().NoError(err) s.Require().NotEmpty(pem) - keyAdapter, ok := s.rsaKey.(*KasKeyAdapter) + keyAdapter, ok := s.rsaKey.(*KeyAdapter) s.Require().True(ok) pubCtx := keyAdapter.key.GetKey().GetPublicKeyCtx() s.Require().NotEmpty(pubCtx) @@ -72,5 +72,5 @@ func (s *PlatformKeyIndexTestSuite) TestKeyExportPublicKey_PKCSFormat() { } func TestNewPlatformKeyIndexTestSuite(t *testing.T) { - suite.Run(t, new(PlatformKeyIndexTestSuite)) + suite.Run(t, new(KeyIndexTestSuite)) }