From 15e7968938eb8b68e9649c5c778ffa986f7c0219 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 10 Jun 2025 08:58:59 -0500 Subject: [PATCH 01/30] feat(sdk): Enable base key support. --- sdk/basekey.go | 92 +++++++++++++++++++++++++++++++++++++++++++++++ sdk/options.go | 1 + sdk/sdk.go | 1 + sdk/tdf.go | 40 +++++++++++++++++---- sdk/tdf_config.go | 9 +++++ 5 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 sdk/basekey.go diff --git a/sdk/basekey.go b/sdk/basekey.go new file mode 100644 index 0000000000..7d19c70eeb --- /dev/null +++ b/sdk/basekey.go @@ -0,0 +1,92 @@ +package sdk + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/wellknownconfiguration" + "google.golang.org/protobuf/encoding/protojson" +) + +// Should match: +// https://github.com/opentdf/platform/blob/main/service/wellknownconfiguration/wellknown_configuration.go#L25 +const baseKeyWellKnown = "base_key" + +// TODO: Move this function to ocrypto? +func getKasKeyAlg(alg string) policy.Algorithm { + switch alg { + case "rsa:2048": + return policy.Algorithm_ALGORITHM_RSA_2048 + case "rsa:4096": + return policy.Algorithm_ALGORITHM_RSA_4096 + case "ec:secp256r1": + return policy.Algorithm_ALGORITHM_EC_P256 + case "ec:secp384r1": + return policy.Algorithm_ALGORITHM_EC_P384 + case "ec:secp521r1": + return policy.Algorithm_ALGORITHM_EC_P521 + default: + return policy.Algorithm_ALGORITHM_UNSPECIFIED + } +} + +// TODO: Move this function to ocrypto? +func formatAlg(alg policy.Algorithm) (string, error) { + switch alg { + case policy.Algorithm_ALGORITHM_RSA_2048: + return "rsa:2048", nil + case policy.Algorithm_ALGORITHM_RSA_4096: + return "rsa:4096", nil + case policy.Algorithm_ALGORITHM_EC_P256: + return "ec:secp256r1", nil + case policy.Algorithm_ALGORITHM_EC_P384: + return "ec:secp384r1", nil + case policy.Algorithm_ALGORITHM_EC_P521: + return "ec:secp512r1", nil + case policy.Algorithm_ALGORITHM_UNSPECIFIED: + fallthrough + default: + return "", fmt.Errorf("unsupported algorithm: %s", alg) + } +} + +func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { + simpleKasKey := &policy.SimpleKasKey{} + + req := &wellknownconfiguration.GetWellKnownConfigurationRequest{} + response, err := s.wellknownConfiguration.GetWellKnownConfiguration(ctx, req) + if err != nil { + return nil, errors.Join(errors.New("unable to retrieve config information, and none was provided"), err) + } + configuration := response.GetConfiguration() + if configuration == nil { + return nil, ErrWellKnowConfigEmpty + } + configStructure, ok := configuration.AsMap()[baseKeyWellKnown] + if !ok { + return nil, errors.New("base key not found in well-known configuration") + } + configMap, ok := configStructure.(map[string]interface{}) + if !ok { + return nil, errors.New("invalid base key format") + } + if len(configMap) == 0 { + return nil, errors.New("base key is empty") + } + + configMap["algorithm"] = getKasKeyAlg(configMap["algorithm"].(string)) + configJSON, err := json.Marshal(configMap) + if err != nil { + return nil, errors.Join(errors.New("base key marshal failed"), err) + } + + err = protojson.Unmarshal(configJSON, simpleKasKey) + if err != nil { + return nil, errors.Join(errors.New("unable to unmarshal base key"), err) + } + + return simpleKasKey, nil +} diff --git a/sdk/options.go b/sdk/options.go index 7ad993388d..4c5fa29c40 100644 --- a/sdk/options.go +++ b/sdk/options.go @@ -43,6 +43,7 @@ type config struct { entityResolutionConn *ConnectRPCConnection collectionStore *collectionStore shouldValidatePlatformConnectivity bool + isBaseKeyEnabled bool } // Options specific to TDF protocol features diff --git a/sdk/sdk.go b/sdk/sdk.go index 38e5424eeb..b3c4f47e8b 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -40,6 +40,7 @@ const ( ErrPlatformTokenEndpointNotFound = Error("token_endpoint not found in well-known idp configuration") ErrPlatformEndpointNotFound = Error("platform_endpoint not found in well-known configuration") ErrAccessTokenInvalid = Error("access token is invalid") + ErrWellKnowConfigEmpty = Error("well-known configuration is empty") ) type Error string diff --git a/sdk/tdf.go b/sdk/tdf.go index f0ee48dfb8..cb85dc76a2 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -180,12 +180,40 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } - dk := s.defaultKases(tdfConfig) - tdfConfig.splitPlan, err = g.plan(dk, func() string { - return uuid.New().String() - }) - if err != nil { - return nil, err + if !tdfConfig.isBaseKeyEnabled { + dk := s.defaultKases(tdfConfig) + tdfConfig.splitPlan, err = g.plan(dk, func() string { + return uuid.New().String() + }) + if err != nil { + return nil, err + } + } else if tdfConfig.isBaseKeyEnabled && len(g.grants) == 0 { + // Handle base key case. + if len(tdfConfig.kasInfoList) > 0 { + return nil, fmt.Errorf("base key is enabled, but kasInfoList is not empty: %w", errInvalidKasInfo) + } + // Get base key from the well-known configuration + key, err := s.getBaseKey(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get base key: %w", err) + } + + algoString, err := formatAlg(key.GetPublicKey().GetAlgorithm()) + if err != nil { + return nil, fmt.Errorf("formatAlg failed: %w", err) + } + + // ? Maybe we shouldn't overwrite the key type + tdfConfig.keyType = ocrypto.KeyType(algoString) + tdfConfig.kasInfoList = []KASInfo{ + { + URL: key.GetKasUri(), + PublicKey: key.GetPublicKey().GetPem(), + KID: key.GetPublicKey().GetKid(), + Algorithm: algoString, + }, + } } } diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index 8e2fca3225..e63957bae8 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -79,6 +79,7 @@ type TDFConfig struct { keyType ocrypto.KeyType useHex bool excludeVersionFromManifest bool + isBaseKeyEnabled bool } func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { @@ -90,6 +91,7 @@ func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { integrityAlgorithm: HS256, segmentIntegrityAlgorithm: GMAC, keyType: ocrypto.RSA2048Key, // default to RSA + isBaseKeyEnabled: true, // Default to true. } for _, o := range opt { @@ -265,6 +267,13 @@ func WithTargetMode(mode string) TDFOption { } } +func WithBaseKeyEnabled(enabled bool) TDFOption { + return func(c *TDFConfig) error { + c.isBaseKeyEnabled = enabled + return nil + } +} + // Schema Validation where 0 = none (skip), 1 = lax (allowing novel entries, 'falsy' values for unkowns), 2 = strict (rejecting novel entries, strict match to manifest schema) type SchemaValidationIntensity int From 1e3acd318294527ccd71fd159b278a59d4359797 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 10 Jun 2025 09:11:56 -0500 Subject: [PATCH 02/30] changes. --- sdk/basekey.go | 7 ++++++- sdk/tdf.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 7d19c70eeb..9fd0ec69a7 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -77,7 +77,12 @@ func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { return nil, errors.New("base key is empty") } - configMap["algorithm"] = getKasKeyAlg(configMap["algorithm"].(string)) + publicKey, ok := configMap["public_key"].(map[string]interface{}) + if !ok { + return nil, errors.New("public key structure not found in base key configuration") + } + + configMap["algorithm"] = getKasKeyAlg(publicKey["algorithm"].(string)) configJSON, err := json.Marshal(configMap) if err != nil { return nil, errors.Join(errors.New("base key marshal failed"), err) diff --git a/sdk/tdf.go b/sdk/tdf.go index cb85dc76a2..1b05c2211e 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -191,7 +191,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R } else if tdfConfig.isBaseKeyEnabled && len(g.grants) == 0 { // Handle base key case. if len(tdfConfig.kasInfoList) > 0 { - return nil, fmt.Errorf("base key is enabled, but kasInfoList is not empty: %w", errInvalidKasInfo) + return nil, fmt.Errorf("base key is enabled, but kasInfoList is not empty") } // Get base key from the well-known configuration key, err := s.getBaseKey(ctx) From 3e8b84bb86fb4f1cc83b8cc137db03daef78bdcd Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 10 Jun 2025 09:16:40 -0500 Subject: [PATCH 03/30] check, --- sdk/basekey.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/basekey.go b/sdk/basekey.go index 9fd0ec69a7..7f1a844acb 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -77,6 +77,8 @@ func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { return nil, errors.New("base key is empty") } + return nil, fmt.Errorf("The base key structure returned is: %s", configMap) + publicKey, ok := configMap["public_key"].(map[string]interface{}) if !ok { return nil, errors.New("public key structure not found in base key configuration") From 914a0699f440b8618f79afa1ce7ffe8c8843ba20 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 10 Jun 2025 09:21:03 -0500 Subject: [PATCH 04/30] change public_key. --- sdk/basekey.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 7f1a844acb..bf0af09b61 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -77,14 +77,13 @@ func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { return nil, errors.New("base key is empty") } - return nil, fmt.Errorf("The base key structure returned is: %s", configMap) - publicKey, ok := configMap["public_key"].(map[string]interface{}) if !ok { return nil, errors.New("public key structure not found in base key configuration") } - configMap["algorithm"] = getKasKeyAlg(publicKey["algorithm"].(string)) + publicKey["algorithm"] = getKasKeyAlg(publicKey["algorithm"].(string)) + configMap["public_key"] = publicKey configJSON, err := json.Marshal(configMap) if err != nil { return nil, errors.Join(errors.New("base key marshal failed"), err) From 4cad58fe9cc5f1722b63ccf22a1ca7d867dec89c Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 11:59:44 -0500 Subject: [PATCH 05/30] feat(sdk): Base key support. --- sdk/basekey.go | 85 ++++++++--- sdk/basekey_test.go | 345 ++++++++++++++++++++++++++++++++++++++++++ sdk/nanotdf.go | 84 +++++++--- sdk/nanotdf_config.go | 31 ++-- sdk/nanotdf_test.go | 297 ++++++++++++++++++++++++++++++++++++ sdk/options.go | 1 - sdk/tdf.go | 67 ++++---- sdk/tdf_config.go | 6 +- sdk/tdf_test.go | 174 +++++++++++++++++---- 9 files changed, 977 insertions(+), 113 deletions(-) create mode 100644 sdk/basekey_test.go diff --git a/sdk/basekey.go b/sdk/basekey.go index bf0af09b61..ef93886bc9 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/wellknownconfiguration" "google.golang.org/protobuf/encoding/protojson" @@ -13,20 +14,34 @@ import ( // Should match: // https://github.com/opentdf/platform/blob/main/service/wellknownconfiguration/wellknown_configuration.go#L25 -const baseKeyWellKnown = "base_key" +const ( + baseKeyWellKnown = "base_key" + baseKeyAlg = "algorithm" + baseKeyPublicKey = "public_key" + wellKnownConfigKey = "configuration" +) + +var ( + errWellKnownConfigFormat = errors.New("well-known configuration has invalid format") + errBaseKeyNotFound = errors.New("base key not found in well-known configuration") + errBaseKeyInvalidFormat = errors.New("base key has invalid format") + errBaseKeyEmpty = errors.New("base key is empty or not provided") + errMarshalBaseKeyFailed = errors.New("failed to marshal base key configuration") + errUnmarshalBaseKeyFailed = errors.New("failed to unmarshal base key configuration") +) // TODO: Move this function to ocrypto? func getKasKeyAlg(alg string) policy.Algorithm { switch alg { - case "rsa:2048": + case string(ocrypto.RSA2048Key): return policy.Algorithm_ALGORITHM_RSA_2048 case "rsa:4096": return policy.Algorithm_ALGORITHM_RSA_4096 - case "ec:secp256r1": + case string(ocrypto.EC256Key): return policy.Algorithm_ALGORITHM_EC_P256 - case "ec:secp384r1": + case string(ocrypto.EC384Key): return policy.Algorithm_ALGORITHM_EC_P384 - case "ec:secp521r1": + case string(ocrypto.EC521Key): return policy.Algorithm_ALGORITHM_EC_P521 default: return policy.Algorithm_ALGORITHM_UNSPECIFIED @@ -37,15 +52,15 @@ func getKasKeyAlg(alg string) policy.Algorithm { func formatAlg(alg policy.Algorithm) (string, error) { switch alg { case policy.Algorithm_ALGORITHM_RSA_2048: - return "rsa:2048", nil + return string(ocrypto.RSA2048Key), nil case policy.Algorithm_ALGORITHM_RSA_4096: return "rsa:4096", nil case policy.Algorithm_ALGORITHM_EC_P256: - return "ec:secp256r1", nil + return string(ocrypto.EC256Key), nil case policy.Algorithm_ALGORITHM_EC_P384: - return "ec:secp384r1", nil + return string(ocrypto.EC384Key), nil case policy.Algorithm_ALGORITHM_EC_P521: - return "ec:secp512r1", nil + return string(ocrypto.EC521Key), nil case policy.Algorithm_ALGORITHM_UNSPECIFIED: fallthrough default: @@ -53,7 +68,7 @@ func formatAlg(alg policy.Algorithm) (string, error) { } } -func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { +func getBaseKey(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { simpleKasKey := &policy.SimpleKasKey{} req := &wellknownconfiguration.GetWellKnownConfigurationRequest{} @@ -65,34 +80,58 @@ func (s SDK) getBaseKey(ctx context.Context) (*policy.SimpleKasKey, error) { if configuration == nil { return nil, ErrWellKnowConfigEmpty } - configStructure, ok := configuration.AsMap()[baseKeyWellKnown] + configStructure, ok := configuration.AsMap()[wellKnownConfigKey] if !ok { - return nil, errors.New("base key not found in well-known configuration") + return nil, err } + configMap, ok := configStructure.(map[string]interface{}) if !ok { - return nil, errors.New("invalid base key format") + return nil, errWellKnownConfigFormat + } + + simpleKasKey, err = parseSimpleKasKey(configMap) + if err != nil { + return nil, err + } + + return simpleKasKey, nil +} + +func parseSimpleKasKey(configMap map[string]interface{}) (*policy.SimpleKasKey, error) { + simpleKasKey := &policy.SimpleKasKey{} + baseKey, ok := configMap[baseKeyWellKnown] + if !ok { + return nil, errBaseKeyNotFound + } + + baseKeyMap, ok := baseKey.(map[string]interface{}) + if !ok { + return nil, errBaseKeyInvalidFormat } - if len(configMap) == 0 { - return nil, errors.New("base key is empty") + if len(baseKeyMap) == 0 { + return nil, errBaseKeyEmpty } - publicKey, ok := configMap["public_key"].(map[string]interface{}) + publicKey, ok := baseKeyMap[baseKeyPublicKey].(map[string]interface{}) if !ok { - return nil, errors.New("public key structure not found in base key configuration") + return nil, errBaseKeyInvalidFormat } - publicKey["algorithm"] = getKasKeyAlg(publicKey["algorithm"].(string)) - configMap["public_key"] = publicKey - configJSON, err := json.Marshal(configMap) + alg, ok := publicKey[baseKeyAlg].(string) + if !ok { + return nil, errBaseKeyInvalidFormat + } + publicKey[baseKeyAlg] = getKasKeyAlg(alg) + baseKeyMap[baseKeyPublicKey] = publicKey + configJSON, err := json.Marshal(baseKey) if err != nil { - return nil, errors.Join(errors.New("base key marshal failed"), err) + return nil, errors.Join(errMarshalBaseKeyFailed, err) } err = protojson.Unmarshal(configJSON, simpleKasKey) if err != nil { - return nil, errors.Join(errors.New("unable to unmarshal base key"), err) + return nil, errors.Join(errUnmarshalBaseKeyFailed, err) } - return simpleKasKey, nil } diff --git a/sdk/basekey_test.go b/sdk/basekey_test.go new file mode 100644 index 0000000000..9b3aa3e027 --- /dev/null +++ b/sdk/basekey_test.go @@ -0,0 +1,345 @@ +package sdk + +import ( + "context" + "errors" + "testing" + + "github.com/opentdf/platform/lib/ocrypto" + "github.com/opentdf/platform/protocol/go/policy" + wellknownpb "github.com/opentdf/platform/protocol/go/wellknownconfiguration" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/types/known/structpb" +) + +const ( + testPem = "a-pem" + testKasURI = "https://test-kas.example.com" + testRSAAlgorithm = "rsa:2048" + testKid = "test-key-id" +) + +// Mock implementation of the WellKnownServiceClient for testing +type mockWellKnownService struct { + configMap map[string]interface{} + err error + called bool +} + +// Test suite for getBaseKey function +type BaseKeyTestSuite struct { + suite.Suite + sdk SDK +} + +func newMockWellKnownService(configMap map[string]interface{}, err error) *mockWellKnownService { + return &mockWellKnownService{ + configMap: configMap, + err: err, + called: false, + } +} + +func (m *mockWellKnownService) GetWellKnownConfiguration( + ctx context.Context, + req *wellknownpb.GetWellKnownConfigurationRequest, +) (*wellknownpb.GetWellKnownConfigurationResponse, error) { + m.called = true + + if m.err != nil { + return nil, m.err + } + + // Convert map to structpb + configStruct, err := structpb.NewStruct(m.configMap) + if err != nil { + return nil, err + } + + return &wellknownpb.GetWellKnownConfigurationResponse{ + Configuration: configStruct, + }, nil +} + +func TestGetKasKeyAlg(t *testing.T) { + tests := []struct { + name string + algStr string + expected policy.Algorithm + }{ + { + name: "rsa 2048", + algStr: string(ocrypto.RSA2048Key), + expected: policy.Algorithm_ALGORITHM_RSA_2048, + }, + { + name: "rsa 4096", + algStr: "rsa:4096", + expected: policy.Algorithm_ALGORITHM_RSA_4096, + }, + { + name: "ec secp256r1", + algStr: string(ocrypto.EC256Key), + expected: policy.Algorithm_ALGORITHM_EC_P256, + }, + { + name: "ec secp384r1", + algStr: string(ocrypto.EC384Key), + expected: policy.Algorithm_ALGORITHM_EC_P384, + }, + { + name: "ec secp521r1", + algStr: string(ocrypto.EC521Key), + expected: policy.Algorithm_ALGORITHM_EC_P521, + }, + { + name: "unsupported algorithm", + algStr: "unsupported", + expected: policy.Algorithm_ALGORITHM_UNSPECIFIED, + }, + { + name: "empty string", + algStr: "", + expected: policy.Algorithm_ALGORITHM_UNSPECIFIED, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := getKasKeyAlg(test.algStr) + assert.Equal(t, test.expected, result, "Algorithm enum mismatch") + }) + } +} + +func TestFormatAlg(t *testing.T) { + tests := []struct { + name string + alg policy.Algorithm + expected string + expectError bool + }{ + { + name: "RSA 2048", + alg: policy.Algorithm_ALGORITHM_RSA_2048, + expected: string(ocrypto.RSA2048Key), + expectError: false, + }, + { + name: "RSA 4096", + alg: policy.Algorithm_ALGORITHM_RSA_4096, + expected: "rsa:4096", + expectError: false, + }, + { + name: "EC P256", + alg: policy.Algorithm_ALGORITHM_EC_P256, + expected: string(ocrypto.EC256Key), + expectError: false, + }, + { + name: "EC P384", + alg: policy.Algorithm_ALGORITHM_EC_P384, + expected: string(ocrypto.EC384Key), + expectError: false, + }, + { + name: "EC P521", + alg: policy.Algorithm_ALGORITHM_EC_P521, + expected: string(ocrypto.EC521Key), // Note: This matches the implementation + expectError: false, + }, + { + name: "Unspecified algorithm", + alg: policy.Algorithm_ALGORITHM_UNSPECIFIED, + expected: "", + expectError: true, + }, + { + name: "Invalid algorithm", + alg: policy.Algorithm(99), + expected: "", + expectError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result, err := formatAlg(test.alg) + if test.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, result, "Algorithm string mismatch") + } + }) + } +} + +func (s *BaseKeyTestSuite) SetupTest() { + s.sdk = SDK{} +} + +func TestBaseKeySuite(t *testing.T) { + suite.Run(t, new(BaseKeyTestSuite)) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeySuccess() { + // Create a valid base key configuration + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + baseKeyPublicKey: map[string]interface{}{ + baseKeyAlg: testRSAAlgorithm, + "kid": testKid, + "pem": testPem, + }, + }, + }, + } + + // Set up mock wellknown service + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.NoError(err) + s.True(mockService.called) + s.NotNil(baseKey) + s.Equal(testKasURI, baseKey.GetKasUri()) + s.NotNil(baseKey.GetPublicKey()) + s.Equal(testKid, baseKey.GetPublicKey().GetKid()) + s.Equal(policy.Algorithm_ALGORITHM_RSA_2048, baseKey.GetPublicKey().GetAlgorithm()) + s.Equal(testPem, baseKey.GetPublicKey().GetPem()) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyServiceError() { + // Setup mock service with error + mockService := newMockWellKnownService(nil, errors.New("service unavailable")) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.Contains(err.Error(), "unable to retrieve config information") + s.Contains(err.Error(), "service unavailable") +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyMissingBaseKey() { + // Create wellknown configuration without base key + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + "some_other_config": "value", + }, + } + + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.Contains(err.Error(), errBaseKeyNotFound.Error()) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidBaseKeyFormat() { + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + baseKeyWellKnown: "invalid-base-key", + }, + } + + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyEmptyBaseKey() { + // Create empty base key map + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + baseKeyWellKnown: map[string]interface{}{}, + }, + } + + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.ErrorContains(err, errBaseKeyEmpty.Error()) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyMissingPublicKey() { + // Create base key without public_key field + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + // Missing public_key field + }, + }, + } + + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) +} + +func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidPublicKey() { + // Create base key with invalid public_key (string instead of map) + wellknownConfig := map[string]interface{}{ + wellKnownConfigKey: map[string]interface{}{ + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + baseKeyPublicKey: "invalid-public-key", // Should be a map + }, + }, + } + + mockService := newMockWellKnownService(wellknownConfig, nil) + s.sdk.wellknownConfiguration = mockService + + // Call getBaseKey + baseKey, err := getBaseKey(s.T().Context(), s.sdk) + + // Validate result + s.True(mockService.called) + s.Error(err) + s.Nil(baseKey) + s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) +} diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index 910dc3f729..e1eab23821 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -15,6 +15,7 @@ import ( "time" "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/lib/ocrypto" ) @@ -787,24 +788,9 @@ func (s SDK) CreateNanoTDF(writer io.Writer, reader io.Reader, config NanoTDFCon return 0, errors.New("exceeds max size for nano tdf") } - kasURL, err := config.kasURL.GetURL() + ki, err := getKasInfoForNanoTDF(&s, &config) if err != nil { - return 0, fmt.Errorf("config.kasURL failed:%w", err) - } - if kasURL == "https://" || kasURL == "http://" { - return 0, errors.New("config.kasUrl is empty") - } - ki, err := s.getPublicKey(context.Background(), kasURL, config.bindCfg.eccMode.String()) - if err != nil { - return 0, fmt.Errorf("getECPublicKey failed:%w", err) - } - - // update KAS URL with kid if set - if ki.KID != "" && !s.nanoFeatures.noKID { - err = config.kasURL.setURLWithIdentifier(kasURL, ki.KID) - if err != nil { - return 0, fmt.Errorf("getECPublicKey setURLWithIdentifier failed:%w", err) - } + return 0, fmt.Errorf("getKasInfoForNanoTDF failed: %w", err) } config.kasPublicKey, err = ocrypto.ECPubKeyFromPem([]byte(ki.PublicKey)) @@ -1106,3 +1092,67 @@ func createNanoTDFSymmetricKey(config NanoTDFConfig) ([]byte, error) { return symmetricKey, nil } + +func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { + if config.baseKeyEnabled { + ki, err := getNanoKasInfoFromBaseKey(s) + if err != nil { + return nil, err + } + config.kasURL.setURLWithIdentifier(ki.URL, ki.KID) + config.bindCfg.eccMode, err = ocrypto.ECKeyTypeToMode(ocrypto.KeyType(ki.Algorithm)) + if err != nil { + return nil, fmt.Errorf("ocrypto.ECKeyTypeToMode failed: %w", err) + } + return ki, nil + } + + kasURL, err := config.kasURL.GetURL() + if err != nil { + return nil, fmt.Errorf("config.kasURL failed:%w", err) + } + if kasURL == "https://" || kasURL == "http://" { + return nil, errors.New("config.kasUrl is empty") + } + ki, err := s.getPublicKey(context.Background(), kasURL, config.bindCfg.eccMode.String()) + if err != nil { + return nil, fmt.Errorf("getECPublicKey failed:%w", err) + } + + // update KAS URL with kid if set + if ki.KID != "" && !s.nanoFeatures.noKID { + err = config.kasURL.setURLWithIdentifier(kasURL, ki.KID) + if err != nil { + return nil, fmt.Errorf("getECPublicKey setURLWithIdentifier failed:%w", err) + } + } + + return ki, nil +} + +func getNanoKasInfoFromBaseKey(s *SDK) (*KASInfo, error) { + baseKey, err := getBaseKey(context.Background(), *s) + if err != nil { + return nil, err + } + + // Check if algorithm is one of the supported EC algorithms + algorithm := baseKey.GetPublicKey().GetAlgorithm() + if algorithm != policy.Algorithm_ALGORITHM_EC_P256 && + algorithm != policy.Algorithm_ALGORITHM_EC_P384 && + algorithm != policy.Algorithm_ALGORITHM_EC_P521 { + return nil, fmt.Errorf("base key algorithm is not supported for nano: %s", algorithm) + } + + alg, err := formatAlg(baseKey.GetPublicKey().GetAlgorithm()) + if err != nil { + return nil, fmt.Errorf("formatAlg failed: %w", err) + } + + return &KASInfo{ + URL: baseKey.GetKasUri(), + PublicKey: baseKey.GetPublicKey().GetPem(), + KID: baseKey.GetPublicKey().GetKid(), + Algorithm: alg, + }, nil +} diff --git a/sdk/nanotdf_config.go b/sdk/nanotdf_config.go index 5efde5663d..dc14863589 100644 --- a/sdk/nanotdf_config.go +++ b/sdk/nanotdf_config.go @@ -17,16 +17,17 @@ import ( // ============================================================================================================ type NanoTDFConfig struct { - keyPair ocrypto.ECKeyPair - kasPublicKey *ecdh.PublicKey - attributes []AttributeValueFQN - cipher CipherMode - kasURL ResourceLocator - sigCfg signatureConfig - policy policyInfo - bindCfg bindingConfig - collectionCfg *collectionConfig - policyMode PolicyType // Added field for policy mode + keyPair ocrypto.ECKeyPair + kasPublicKey *ecdh.PublicKey + attributes []AttributeValueFQN + cipher CipherMode + kasURL ResourceLocator + sigCfg signatureConfig + policy policyInfo + bindCfg bindingConfig + collectionCfg *collectionConfig + policyMode PolicyType // Added field for policy mode + baseKeyEnabled bool } type NanoTDFOption func(*NanoTDFConfig) error @@ -56,7 +57,8 @@ func (s SDK) NewNanoTDFConfig() (*NanoTDFConfig, error) { useCollection: false, header: []byte{}, }, - policyMode: NanoTDFPolicyModeDefault, + policyMode: NanoTDFPolicyModeDefault, + baseKeyEnabled: false, } return c, nil @@ -100,6 +102,13 @@ func (config *NanoTDFConfig) SetPolicyMode(mode PolicyType) error { return nil } +// * Set that the sdk should use the base key when no attributes are present. +// ! Enabling this option will cause the SDK to ignore any KAS information passed in +// ! and instead use the base key from the well-known configuration. +func (config *NanoTDFConfig) EnableBaseKey() { + config.baseKeyEnabled = true +} + // WithNanoDataAttributes appends the given data attributes to the bound policy func WithNanoDataAttributes(attributes ...string) NanoTDFOption { return func(c *NanoTDFConfig) error { diff --git a/sdk/nanotdf_test.go b/sdk/nanotdf_test.go index 2854548ec3..cc5e6178f0 100644 --- a/sdk/nanotdf_test.go +++ b/sdk/nanotdf_test.go @@ -2,18 +2,28 @@ package sdk import ( "bytes" + "context" "crypto/ecdh" "crypto/rand" "encoding/gob" + "errors" "io" "os" "testing" "github.com/opentdf/platform/lib/ocrypto" + "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/wellknownconfiguration" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/types/known/structpb" +) + +const ( + nanoFakePem = "pem" ) // nanotdfEqual compares two nanoTdf structures for equality. @@ -386,3 +396,290 @@ func TestDataSet(t *testing.T) { t.Fatal("header did not reset") } } + +type NanoSuite struct { + suite.Suite +} + +func TestNanoTDF(t *testing.T) { + suite.Run(t, new(NanoSuite)) +} + +// mockWellKnownServiceClient is a mock implementation of sdkconnect.WellKnownServiceClient +type mockWellKnownServiceClient struct { + mockResponse func() (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) +} + +func (m *mockWellKnownServiceClient) GetWellKnownConfiguration(ctx context.Context, req *wellknownconfiguration.GetWellKnownConfigurationRequest) (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) { + if m.mockResponse != nil { + return m.mockResponse() + } + return nil, errors.New("no mock response configured") +} + +func (s *NanoSuite) Test_CreateNanoTDF_BaseKey() { + // Mock KAS Info + mockKASInfo := &KASInfo{ + URL: "https://kas.example.com", + PublicKey: mockECPublicKey1, + KID: "key-p256", + Algorithm: "ec:secp256r1", + } + + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_EC_P256, mockKASInfo.KID, mockECPublicKey1, mockKASInfo.URL) + wellKnown := createWellKnown(baseKey) + mockClient := createMockWellKnownServiceClient(&s.Suite, wellKnown, nil) + + // Create SDK + sdk := &SDK{ + wellknownConfiguration: mockClient, + } + + config, err := sdk.NewNanoTDFConfig() + s.Require().NoError(err) + + config.EnableBaseKey() + config.SetKasURL("http://should-change.com") + + // Mock writer and reader + writer := new(bytes.Buffer) + reader := bytes.NewReader([]byte("test data")) + + // Call CreateNanoTDF + _, err = sdk.CreateNanoTDF(writer, reader, *config) + s.Require().NoError(err) + + // Check that writer is not empty + s.Require().NotEmpty(writer.Bytes()) +} + +func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { + tests := []struct { + name string + baseKeyEnabled bool + algorithm policy.Algorithm + kasURI string + publicKeyPem string + kid string + wellKnownError error + expectedInfo *KASInfo + expectedError string + }{ + { + name: "Base Key Enabled - EC P256 - Success", + baseKeyEnabled: true, + algorithm: policy.Algorithm_ALGORITHM_EC_P256, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p256", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p256", + Algorithm: "ec:secp256r1", + }, + }, + { + name: "Base Key Enabled - EC P384 - Success", + baseKeyEnabled: true, + algorithm: policy.Algorithm_ALGORITHM_EC_P384, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p384", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p384", + Algorithm: "ec:secp384r1", + }, + }, + { + name: "Base Key Enabled - EC P521 - Success", + baseKeyEnabled: true, + algorithm: policy.Algorithm_ALGORITHM_EC_P521, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p521", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p521", + Algorithm: "ec:secp521r1", + }, + }, + { + name: "Base Key Enabled - Unsupported algorithm RSA 2048", + baseKeyEnabled: true, + algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-rsa", + expectedError: "base key algorithm is not supported for nano", + }, + } + + for _, tt := range tests { + s.Run(tt.name, func() { + // Create a mock wellknown configuration response + baseKey := createTestBaseKeyMap(&s.Suite, tt.algorithm, tt.kid, tt.publicKeyPem, tt.kasURI) + wellKnown := createWellKnown(baseKey) + mockClient := createMockWellKnownServiceClient(&s.Suite, wellKnown, tt.wellKnownError) + + // Create SDK with mocked wellknown client + sdk := &SDK{ + wellknownConfiguration: mockClient, + } + + // Create a NanoTDFConfig + config := NanoTDFConfig{ + baseKeyEnabled: tt.baseKeyEnabled, + } + config.SetKasURL("http://should-change.com") + + // Call the getKasInfoForNanoTDF function + info, err := getKasInfoForNanoTDF(sdk, &config) + + // Check for expected errors + if tt.expectedError != "" { + s.Require().Error(err) + s.Require().Contains(err.Error(), tt.expectedError) + s.Require().Nil(info) + return + } + + // Check success case + s.Require().NoError(err) + s.Require().NotNil(info) + s.Require().Equal(tt.expectedInfo.URL, info.URL) + s.Require().Equal(tt.expectedInfo.PublicKey, info.PublicKey) + s.Require().Equal(tt.expectedInfo.KID, info.KID) + s.Require().Equal(tt.expectedInfo.Algorithm, info.Algorithm) + // Ensure the config was updated. + actualURL, err := config.kasURL.GetURL() + s.Require().NoError(err) + s.Require().Equal(tt.kasURI, actualURL) + expectedEcMode, err := ocrypto.ECKeyTypeToMode(ocrypto.KeyType(tt.expectedInfo.Algorithm)) + s.Require().NoError(err) + s.Require().Equal(expectedEcMode, config.bindCfg.eccMode) + }) + } +} + +func (s *NanoSuite) Test_PopulateNanoBaseKeyWithMockWellKnown() { + // Define test cases + tests := []struct { + name string + algorithm policy.Algorithm + kasURI string + publicKeyPem string + kid string + wellKnownError error + expectedInfo *KASInfo + expectedError string + }{ + { + name: "EC P256 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P256, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p256", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p256", + Algorithm: "ec:secp256r1", + }, + }, + { + name: "EC P384 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P384, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p384", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p384", + Algorithm: "ec:secp384r1", + }, + }, + { + name: "EC P521 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P521, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p521", + expectedInfo: &KASInfo{ + URL: "https://kas.example.com", + PublicKey: nanoFakePem, + KID: "key-p521", + Algorithm: "ec:secp521r1", + }, + }, + { + name: "Error from WellKnown Config", + algorithm: policy.Algorithm_ALGORITHM_EC_P256, + kasURI: "https://kas.example.com", + wellKnownError: errors.New("failed to get configuration"), + expectedError: "unable to retrieve config information", + }, + { + name: "Unsupported algorithm RSA 2048", + algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-rsa", + expectedError: "base key algorithm is not supported for nano", + }, + } + + for _, tt := range tests { + s.Run(tt.name, func() { + // Create a mock wellknown configuration response + baseKey := createTestBaseKeyMap(&s.Suite, tt.algorithm, tt.kid, tt.publicKeyPem, tt.kasURI) + wellKnown := createWellKnown(baseKey) + mockClient := createMockWellKnownServiceClient(&s.Suite, wellKnown, tt.wellKnownError) + + // Create SDK with mocked wellknown client + sdk := &SDK{ + wellknownConfiguration: mockClient, + } + + // Call the real populateNanoBaseKey function + info, err := getNanoKasInfoFromBaseKey(sdk) + + // Check for expected errors + if tt.expectedError != "" { + s.Require().Error(err) + s.Require().Contains(err.Error(), tt.expectedError) + s.Require().Nil(info) + return + } + + // Check success case + s.Require().NoError(err) + s.Require().NotNil(info) + s.Require().Equal(tt.expectedInfo.URL, info.URL) + s.Require().Equal(tt.expectedInfo.PublicKey, info.PublicKey) + s.Require().Equal(tt.expectedInfo.KID, info.KID) + s.Require().Equal(tt.expectedInfo.Algorithm, info.Algorithm) + }) + } +} + +func createMockWellKnownServiceClient(s *suite.Suite, wellKnownConfig map[string]interface{}, wellKnownError error) *mockWellKnownServiceClient { + return &mockWellKnownServiceClient{ + mockResponse: func() (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) { + if wellKnownError != nil { + return nil, wellKnownError + } + + cfg, err := structpb.NewStruct(wellKnownConfig) + s.Require().NoError(err, "Failed to create struct from well-known configuration") + + return &wellknownconfiguration.GetWellKnownConfigurationResponse{ + Configuration: cfg, + }, nil + }, + } +} diff --git a/sdk/options.go b/sdk/options.go index 4c5fa29c40..7ad993388d 100644 --- a/sdk/options.go +++ b/sdk/options.go @@ -43,7 +43,6 @@ type config struct { entityResolutionConn *ConnectRPCConnection collectionStore *collectionStore shouldValidatePlatformConnectivity bool - isBaseKeyEnabled bool } // Options specific to TDF protocol features diff --git a/sdk/tdf.go b/sdk/tdf.go index 1b05c2211e..96feb7c9f4 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -169,8 +169,8 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, fmt.Errorf("NewTDFConfig failed: %w", err) } + g := granter{} if tdfConfig.autoconfigure { - var g granter if len(tdfConfig.attributeValues) > 0 { g, err = newGranterFromAttributes(s.kasKeyCache, tdfConfig.attributeValues...) } else if len(tdfConfig.attributes) > 0 { @@ -180,6 +180,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } + // * Bug, if base key is enabled we need to do split plan with no default kases if !tdfConfig.isBaseKeyEnabled { dk := s.defaultKases(tdfConfig) tdfConfig.splitPlan, err = g.plan(dk, func() string { @@ -188,35 +189,15 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R if err != nil { return nil, err } - } else if tdfConfig.isBaseKeyEnabled && len(g.grants) == 0 { - // Handle base key case. - if len(tdfConfig.kasInfoList) > 0 { - return nil, fmt.Errorf("base key is enabled, but kasInfoList is not empty") - } - // Get base key from the well-known configuration - key, err := s.getBaseKey(ctx) - if err != nil { - return nil, fmt.Errorf("failed to get base key: %w", err) - } - - algoString, err := formatAlg(key.GetPublicKey().GetAlgorithm()) - if err != nil { - return nil, fmt.Errorf("formatAlg failed: %w", err) - } - - // ? Maybe we shouldn't overwrite the key type - tdfConfig.keyType = ocrypto.KeyType(algoString) - tdfConfig.kasInfoList = []KASInfo{ - { - URL: key.GetKasUri(), - PublicKey: key.GetPublicKey().GetPem(), - KID: key.GetPublicKey().GetKid(), - Algorithm: algoString, - }, - } + } else { + // Calls Dave's plan function } } + if tdfConfig.isBaseKeyEnabled && len(g.grants) == 0 { + populateKasInfoFromBaseKey(ctx, s, tdfConfig) + } + tdfObject := &TDFObject{} err = s.prepareManifest(ctx, tdfObject, *tdfConfig) if err != nil { @@ -1412,3 +1393,35 @@ func isLessThanSemver(version, target string) (bool, error) { // Check if the provided version is less than the target version based on semantic versioning rules. return v1.LessThan(v2), nil } + +func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig) error { + if len(tdfConfig.kasInfoList) > 0 { + return fmt.Errorf("base key is enabled, but kasInfoList is not empty") + } + // Get base key from the well-known configuration + key, err := getBaseKey(ctx, s) + if err != nil { + return fmt.Errorf("failed to get base key: %w", err) + } + + algoString, err := formatAlg(key.GetPublicKey().GetAlgorithm()) + if err != nil { + return fmt.Errorf("formatAlg failed: %w", err) + } + + // ? Maybe we shouldn't overwrite the key type + if tdfConfig.keyType != ocrypto.KeyType(algoString) { + slog.Warn("Base key is enabled, setting key type", "keyType", algoString) + } + tdfConfig.keyType = ocrypto.KeyType(algoString) + tdfConfig.kasInfoList = []KASInfo{ + { + URL: key.GetKasUri(), + PublicKey: key.GetPublicKey().GetPem(), + KID: key.GetPublicKey().GetKid(), + Algorithm: algoString, + }, + } + + return nil +} diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index e63957bae8..a00499c131 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -91,7 +91,7 @@ func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { integrityAlgorithm: HS256, segmentIntegrityAlgorithm: GMAC, keyType: ocrypto.RSA2048Key, // default to RSA - isBaseKeyEnabled: true, // Default to true. + isBaseKeyEnabled: false, // Default to true. } for _, o := range opt { @@ -267,9 +267,9 @@ func WithTargetMode(mode string) TDFOption { } } -func WithBaseKeyEnabled(enabled bool) TDFOption { +func WithBaseKeyEnabled() TDFOption { return func(c *TDFConfig) error { - c.isBaseKeyEnabled = enabled + c.isBaseKeyEnabled = true return nil } } diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index fd40f38680..93793ce269 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -56,6 +56,9 @@ const ( hundredMB = 100 * oneMB oneGB = 10 * hundredMB // tenGB = 10 * oneGB + baseKeyKID = "base-key-kid" + baseKeyURL = "http://base-key.com/" + defaultKID = "r1" ) const ( @@ -293,11 +296,17 @@ type TDFSuite struct { sdk *SDK kases []FakeKas kasTestURLLookup map[string]string + fakeWellKnown map[string]interface{} + baseKeyURI string } func (s *TDFSuite) SetupSuite() { // Set up the test environment s.startBackend() + // Update well-known with the server URL + s.baseKeyURI = s.kasTestURLLookup[baseKeyURL] + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, s.baseKeyURI) + s.fakeWellKnown = createWellKnown(baseKey) } func (s *TDFSuite) SetupTest() { @@ -1598,7 +1607,7 @@ func (s *TDFSuite) Test_TDF() { }() // test encrypt - s.testEncrypt(s.sdk, kasInfoList, plaintTextFileName, tdfFileName, test) + s.testEncrypt(s.sdk, []TDFOption{WithKasInformation(kasInfoList...)}, plaintTextFileName, tdfFileName, test) // test decrypt with reader s.testDecryptWithReader(s.sdk, tdfFileName, decryptedTdfFileName, test) @@ -1606,6 +1615,38 @@ func (s *TDFSuite) Test_TDF() { } } +func (s *TDFSuite) Test_EncryptWithBaseKey() { + for index, test := range []tdfTest{ + { + n: "medium", + fileSize: hundredMB, + tdfFileSize: 104866427, + checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", + }, + } { + s.Run(test.n, func() { + // create .txt file + plaintTextFileName := test.n + "-" + strconv.Itoa(index) + ".txt" + tdfFileName := plaintTextFileName + ".tdf" + decryptedTdfFileName := tdfFileName + ".txt" + + defer func() { + // Remove the test files + _ = os.Remove(plaintTextFileName) + _ = os.Remove(tdfFileName) + }() + + // test encrypt + tdfObj := s.testEncrypt(s.sdk, []TDFOption{WithBaseKeyEnabled()}, plaintTextFileName, tdfFileName, test) + s.Require().Equal(baseKeyKID, tdfObj.manifest.KeyAccessObjs[0].KID, "Base key KID should match") + s.Require().Equal(s.baseKeyURI, tdfObj.manifest.KeyAccessObjs[0].KasURL, "KAS URI should match") + s.testDecryptWithReader(s.sdk, tdfFileName, decryptedTdfFileName, test) + }) + } +} + +// Need another test for when base key is enabled but attributes are provided, so a split plan is created. + func (s *TDFSuite) Test_KeyRotation() { for index, test := range []tdfTest{ { @@ -1632,7 +1673,7 @@ func (s *TDFSuite) Test_KeyRotation() { _ = os.Remove(tdf2Name) }() - tdo := s.testEncrypt(s.sdk, kasInfoList, plainTextFileName, tdfFileName, test) + tdo := s.testEncrypt(s.sdk, []TDFOption{WithKasInformation(kasInfoList...)}, plainTextFileName, tdfFileName, test) s.Equal("r1", tdo.manifest.EncryptionInformation.KeyAccessObjs[0].KID) defer rotateKey(&s.kases[0], "r2", mockRSAPrivateKey2, mockRSAPublicKey2)() @@ -1641,7 +1682,7 @@ func (s *TDFSuite) Test_KeyRotation() { kasInfoList[0].PublicKey = "" kasInfoList[0].KID = "" s.sdk.kasKeyCache.clear() - tdo2 := s.testEncrypt(s.sdk, kasInfoList, tdf2Name, tdfFileName, test) + tdo2 := s.testEncrypt(s.sdk, []TDFOption{WithKasInformation(kasInfoList...)}, tdf2Name, tdfFileName, test) s.Equal("r2", tdo2.manifest.EncryptionInformation.KeyAccessObjs[0].KID) defer rotateKey(&s.kases[0], "r3", mockRSAPrivateKey3, mockRSAPublicKey3)() @@ -1705,7 +1746,7 @@ func (s *TDFSuite) Test_KeySplits() { }() // test encrypt - tdo := s.testEncrypt(s.sdk, kasInfoList, plaintTextFileName, tdfFileName, test) + tdo := s.testEncrypt(s.sdk, []TDFOption{WithKasInformation(kasInfoList...)}, plaintTextFileName, tdfFileName, test) s.Equal(test.splitPlan[0].KAS, tdo.manifest.EncryptionInformation.KeyAccessObjs[0].KasURL) s.Len(tdo.manifest.EncryptionInformation.KeyAccessObjs, len(test.splitPlan)) @@ -1751,7 +1792,7 @@ func (s *TDFSuite) Test_Autoconfigure() { s.sdk.kasKeyCache.store(KASInfo{}) // test encrypt - tdo := s.testEncrypt(s.sdk, kasInfoList, plaintTextFileName, tdfFileName, test) + tdo := s.testEncrypt(s.sdk, []TDFOption{WithKasInformation(kasInfoList...)}, plaintTextFileName, tdfFileName, test) s.Len(tdo.manifest.EncryptionInformation.KeyAccessObjs, test.expectedPlanSize) // test decrypt with reader @@ -1760,6 +1801,45 @@ func (s *TDFSuite) Test_Autoconfigure() { } } +func (s *TDFSuite) Test_PopulateBaseKey_Success() { + ctx := s.T().Context() + tdfConfig := &TDFConfig{ + keyType: ocrypto.RSA2048Key, + kasInfoList: []KASInfo{}, + } + + // Call populateBaseKey, should succeed + err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) + s.NoError(err, "populateBaseKey should succeed with valid base key") + + // Verify KAS info list has been populated correctly + s.Equal(1, len(tdfConfig.kasInfoList), "KAS info list should have one entry") + s.Equal(s.baseKeyURI, tdfConfig.kasInfoList[0].URL, "KAS URL should match") + s.Equal(baseKeyKID, tdfConfig.kasInfoList[0].KID, "KAS KID should match") + s.Equal(string(ocrypto.RSA2048Key), tdfConfig.kasInfoList[0].Algorithm, "Algorithm should match") + s.Equal(mockRSAPublicKey1, tdfConfig.kasInfoList[0].PublicKey, "Public key should match") + s.Equal(ocrypto.KeyType("rsa:2048"), tdfConfig.keyType, "Key type should be set") +} + +func (s *TDFSuite) Test_PopulateBaseKey_KasInfoPassIn_Fail() { + ctx := s.T().Context() + tdfConfig := &TDFConfig{ + keyType: ocrypto.RSA2048Key, + kasInfoList: []KASInfo{ + { + URL: "http://localhost:65432/", + KID: baseKeyKID, + Algorithm: string(ocrypto.RSA2048Key), + PublicKey: mockRSAPublicKey1, + }, + }, + } + + // Call populateBaseKey, should succeed + err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) + s.Require().ErrorContains(err, "base key is enabled, but kasInfoList is not empty") +} + func rotateKey(k *FakeKas, kid, private, public string) func() { old := *k k.privateKey = private @@ -1775,7 +1855,7 @@ func rotateKey(k *FakeKas, kid, private, public string) func() { } // create tdf -func (s *TDFSuite) testEncrypt(sdk *SDK, kasInfoList []KASInfo, plainTextFilename, tdfFileName string, test tdfTest) *TDFObject { +func (s *TDFSuite) testEncrypt(sdk *SDK, encryptOpts []TDFOption, plainTextFilename, tdfFileName string, test tdfTest) *TDFObject { // create a plain text file s.createFileName(buffer, plainTextFilename, test.fileSize) @@ -1796,7 +1876,6 @@ func (s *TDFSuite) testEncrypt(sdk *SDK, kasInfoList []KASInfo, plainTextFilenam s.Require().NoError(err) }(fileWriter) // CreateTDF TDFConfig - encryptOpts := []TDFOption{WithKasInformation(kasInfoList...)} if test.mimeType != "" { encryptOpts = append(encryptOpts, WithMimeType(test.mimeType)) } @@ -1890,12 +1969,10 @@ func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { s.Require().NoError(err) } -func (s *TDFSuite) startBackend() { - defer resolver.SetDefaultScheme(resolver.GetDefaultScheme()) - resolver.SetDefaultScheme("passthrough") +func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { // Create a stub for wellknown - wellknownCfg := map[string]interface{}{ + return map[string]interface{}{ "configuration": map[string]interface{}{ "health": map[string]interface{}{ "endpoint": "/healthz", @@ -1903,32 +1980,42 @@ func (s *TDFSuite) startBackend() { "idp": map[string]interface{}{ "issuer": "http://localhost:65432/auth", }, + "base_key": baseKey, }, } +} - fwk := &FakeWellKnown{v: wellknownCfg} +func (s *TDFSuite) startBackend() { + defer resolver.SetDefaultScheme(resolver.GetDefaultScheme()) + resolver.SetDefaultScheme("passthrough") + + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, "") + s.fakeWellKnown = createWellKnown(baseKey) + fwk := &FakeWellKnown{s: s} fa := &FakeAttributes{s: s} + kasesToMake := []struct { - url, private, public string + url, private, public, kid string }{ - {"http://localhost:65432/", mockRSAPrivateKey1, mockRSAPublicKey1}, - {"http://[::1]:65432/", mockRSAPrivateKey1, mockRSAPublicKey1}, - {"https://a.kas/", mockRSAPrivateKey1, mockRSAPublicKey1}, - {"https://b.kas/", mockRSAPrivateKey2, mockRSAPublicKey2}, - {"https://c.kas/", mockRSAPrivateKey3, mockRSAPublicKey3}, - {"https://d.kas/", mockECPrivateKey1, mockECPublicKey1}, - {"https://e.kas/", mockECPrivateKey2, mockECPublicKey2}, - {kasAu, mockRSAPrivateKey1, mockRSAPublicKey1}, - {kasCa, mockRSAPrivateKey2, mockRSAPublicKey2}, - {kasUk, mockRSAPrivateKey2, mockRSAPublicKey2}, - {kasNz, mockRSAPrivateKey3, mockRSAPublicKey3}, - {kasUs, mockRSAPrivateKey1, mockRSAPublicKey1}, + {"http://localhost:65432/", mockRSAPrivateKey1, mockRSAPublicKey1, defaultKID}, + {"http://[::1]:65432/", mockRSAPrivateKey1, mockRSAPublicKey1, defaultKID}, + {"https://a.kas/", mockRSAPrivateKey1, mockRSAPublicKey1, defaultKID}, + {"https://b.kas/", mockRSAPrivateKey2, mockRSAPublicKey2, defaultKID}, + {"https://c.kas/", mockRSAPrivateKey3, mockRSAPublicKey3, defaultKID}, + {"https://d.kas/", mockECPrivateKey1, mockECPublicKey1, defaultKID}, + {"https://e.kas/", mockECPrivateKey2, mockECPublicKey2, defaultKID}, + {kasAu, mockRSAPrivateKey1, mockRSAPublicKey1, defaultKID}, + {kasCa, mockRSAPrivateKey2, mockRSAPublicKey2, defaultKID}, + {kasUk, mockRSAPrivateKey2, mockRSAPublicKey2, defaultKID}, + {kasNz, mockRSAPrivateKey3, mockRSAPublicKey3, defaultKID}, + {kasUs, mockRSAPrivateKey1, mockRSAPublicKey1, defaultKID}, + {baseKeyURL, mockRSAPrivateKey1, mockRSAPublicKey1, baseKeyKID}, } fkar := &FakeKASRegistry{kases: kasesToMake, s: s} - s.kases = make([]FakeKas, 12) + s.kases = make([]FakeKas, len(kasesToMake)) - s.kasTestURLLookup = make(map[string]string, 12) + s.kasTestURLLookup = make(map[string]string, len(kasesToMake)) var sdkPlatformURL string @@ -1937,7 +2024,7 @@ func (s *TDFSuite) startBackend() { s.kases[i] = FakeKas{ s: s, privateKey: ki.private, KASInfo: KASInfo{ - URL: ki.url, PublicKey: ki.public, KID: "r1", Algorithm: "rsa:2048", + URL: ki.url, PublicKey: ki.public, KID: ki.kid, Algorithm: "rsa:2048", }, legakeys: map[string]keyInfo{}, } @@ -1975,11 +2062,11 @@ func (s *TDFSuite) startBackend() { type FakeWellKnown struct { wellknownconnect.UnimplementedWellKnownServiceHandler - v map[string]interface{} + s *TDFSuite } func (f *FakeWellKnown) GetWellKnownConfiguration(_ context.Context, _ *connect.Request[wellknownpb.GetWellKnownConfigurationRequest]) (*connect.Response[wellknownpb.GetWellKnownConfigurationResponse], error) { - cfg, err := structpb.NewStruct(f.v) + cfg, err := structpb.NewStruct(f.s.fakeWellKnown) if err != nil { return nil, err } @@ -2018,7 +2105,7 @@ type FakeKASRegistry struct { kasregistryconnect.UnimplementedKeyAccessServerRegistryServiceHandler s *TDFSuite kases []struct { - url, private, public string + url, private, public, kid string } } @@ -2189,6 +2276,31 @@ func (s *TDFSuite) checkIdentical(file, checksum string) bool { return checksum == hex.EncodeToString(c) } +func createTestBaseKeyMap(s *suite.Suite, algorithm policy.Algorithm, kid string, pem string, kasURI string) map[string]any { + baseKey := &policy.SimpleKasKey{ + KasUri: kasURI, + PublicKey: &policy.SimpleKasPublicKey{ + Algorithm: algorithm, + Kid: kid, + Pem: pem, + }, + KasId: "", + } + keyMapBytes, err := json.Marshal(baseKey) + s.Require().NoError(err) + var keyMap map[string]any + err = json.Unmarshal(keyMapBytes, &keyMap) + s.Require().NoError(err) + algoStr, err := formatAlg(baseKey.GetPublicKey().GetAlgorithm()) + s.Require().NoError(err) + publicKey, ok := keyMap[baseKeyPublicKey].(map[string]any) + s.Require().True(ok) + publicKey[baseKeyAlg] = algoStr + keyMap[baseKeyPublicKey] = publicKey + + return keyMap +} + func TestIsLessThanSemver(t *testing.T) { tests := []struct { name string From 01f474a5b3e473bf9ace3b4b0d396feb415eb4bf Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 12:34:53 -0500 Subject: [PATCH 06/30] upgrade go. --- examples/go.mod | 2 +- lib/fixtures/go.mod | 2 +- lib/ocrypto/go.mod | 2 +- protocol/go/go.mod | 2 +- sdk/go.mod | 65 ++++++++++++++++++++++------------------ sdk/go.sum | 72 +++++++++++++++++++++++++++++++++++++++++++++ service/go.mod | 2 +- 7 files changed, 113 insertions(+), 34 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index 16da797724..43c0f0d797 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/examples go 1.24.0 -toolchain go1.24.2 +toolchain go1.24.4 require ( github.com/opentdf/platform/lib/ocrypto v0.2.0 diff --git a/lib/fixtures/go.mod b/lib/fixtures/go.mod index c05e3cf3fe..876c8b6b9f 100644 --- a/lib/fixtures/go.mod +++ b/lib/fixtures/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/lib/fixtures go 1.23.0 -toolchain go1.24.2 +toolchain go1.24.4 require github.com/Nerzal/gocloak/v13 v13.9.0 diff --git a/lib/ocrypto/go.mod b/lib/ocrypto/go.mod index f4f11e0c25..3666ef9ae3 100644 --- a/lib/ocrypto/go.mod +++ b/lib/ocrypto/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/lib/ocrypto go 1.23.0 -toolchain go1.24.2 +toolchain go1.24.4 require ( github.com/stretchr/testify v1.10.0 diff --git a/protocol/go/go.mod b/protocol/go/go.mod index 2572a688ba..382a1dc6da 100644 --- a/protocol/go/go.mod +++ b/protocol/go/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/protocol/go go 1.24.0 -toolchain go1.24.2 +toolchain go1.24.4 require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 diff --git a/sdk/go.mod b/sdk/go.mod index 7b00e94450..0462977af3 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/sdk go 1.24.0 -toolchain go1.24.2 +toolchain go1.24.4 require ( connectrpc.com/connect v1.18.1 @@ -24,75 +24,82 @@ require ( ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1 // indirect - dario.cat/mergo v1.0.1 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 // indirect + dario.cat/mergo v1.0.2 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Nerzal/gocloak/v13 v13.9.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.0.2+incompatible // indirect + github.com/docker/docker v28.2.2+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/ebitengine/purego v0.8.2 // indirect + github.com/ebitengine/purego v0.8.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-resty/resty/v2 v2.12.0 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-resty/resty/v2 v2.16.5 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect - github.com/klauspost/compress v1.17.9 // indirect - github.com/lestrrat-go/blackmagic v1.0.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/lestrrat-go/blackmagic v1.0.4 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/option v1.0.1 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect github.com/magiconair/properties v1.8.10 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.1.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect - github.com/moby/term v0.5.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect - github.com/shirou/gopsutil/v4 v4.25.1 // indirect + github.com/shirou/gopsutil/v4 v4.25.5 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/proto/otlp v1.6.0 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/net v0.41.0 // indirect golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.26.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/go.sum b/sdk/go.sum index 16df6e7e14..d71a5d05bc 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,13 +1,19 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1 h1:YhMSc48s25kr7kv31Z8vf7sPUIq5YJva9z1mn/hAt0M= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 h1:uwSqFkn8DDTzNlaV9TxgSXY5OCaNdb4rH+Axd2FujkE= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -16,6 +22,12 @@ github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzS github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= @@ -34,25 +46,37 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/docker v28.0.2+incompatible h1:9BILleFwug5FSSqWBgVevgL3ewDJfWWWyZVqlDMttE8= github.com/docker/docker v28.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= +github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0= +github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= +github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= @@ -70,16 +94,22 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4z github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs= github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= +github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= +github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k= @@ -92,20 +122,30 @@ github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNB github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= +github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -127,6 +167,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= @@ -135,6 +177,8 @@ github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= +github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -150,10 +194,16 @@ github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= @@ -167,22 +217,39 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -229,6 +296,7 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -269,8 +337,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/service/go.mod b/service/go.mod index a0bcad47ff..296f2b7f5b 100644 --- a/service/go.mod +++ b/service/go.mod @@ -2,7 +2,7 @@ module github.com/opentdf/platform/service go 1.24.0 -toolchain go1.24.2 +toolchain go1.24.4 require ( buf.build/go/protovalidate v0.12.0 From 85b398edb8d58841e03dda8b4d59d0780d4e35c3 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 12:42:41 -0500 Subject: [PATCH 07/30] upgrade go. --- .github/workflows/checks.yaml | 2 +- .github/workflows/vulnerability-check.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 4e7e54f255..0383a8708b 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -69,7 +69,7 @@ jobs: - name: govluncheck uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4 with: - go-version-input: "1.24.2" + go-version-input: "1.24.4" work-dir: ${{ matrix.directory }} - name: golangci-lint uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 diff --git a/.github/workflows/vulnerability-check.yaml b/.github/workflows/vulnerability-check.yaml index 6bd8936da9..ea44d3e61b 100644 --- a/.github/workflows/vulnerability-check.yaml +++ b/.github/workflows/vulnerability-check.yaml @@ -25,5 +25,5 @@ jobs: - name: govluncheck uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4 with: - go-version-input: "1.24.2" + go-version-input: "1.24.4" work-dir: ${{ matrix.directory }} From 1d38d460a4e662e546132ac2f6a31722bee84ceb Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 13:07:16 -0500 Subject: [PATCH 08/30] linting. --- sdk/basekey.go | 6 ++-- sdk/basekey_test.go | 77 +++++++++++++++++++++++---------------------- sdk/granter.go | 9 +++--- sdk/nanotdf.go | 5 ++- sdk/nanotdf_test.go | 11 ++++--- sdk/tdf.go | 11 ++++--- sdk/tdf_test.go | 15 +++++---- 7 files changed, 69 insertions(+), 65 deletions(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index ef93886bc9..e848f382cb 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -35,7 +35,7 @@ func getKasKeyAlg(alg string) policy.Algorithm { switch alg { case string(ocrypto.RSA2048Key): return policy.Algorithm_ALGORITHM_RSA_2048 - case "rsa:4096": + case "rsa:4096": //nolint:goconst // Will move to ocrypto return policy.Algorithm_ALGORITHM_RSA_4096 case string(ocrypto.EC256Key): return policy.Algorithm_ALGORITHM_EC_P256 @@ -69,8 +69,6 @@ func formatAlg(alg policy.Algorithm) (string, error) { } func getBaseKey(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { - simpleKasKey := &policy.SimpleKasKey{} - req := &wellknownconfiguration.GetWellKnownConfigurationRequest{} response, err := s.wellknownConfiguration.GetWellKnownConfiguration(ctx, req) if err != nil { @@ -90,7 +88,7 @@ func getBaseKey(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { return nil, errWellKnownConfigFormat } - simpleKasKey, err = parseSimpleKasKey(configMap) + simpleKasKey, err := parseSimpleKasKey(configMap) if err != nil { return nil, err } diff --git a/sdk/basekey_test.go b/sdk/basekey_test.go index 9b3aa3e027..b50cea2a21 100644 --- a/sdk/basekey_test.go +++ b/sdk/basekey_test.go @@ -9,6 +9,7 @@ import ( "github.com/opentdf/platform/protocol/go/policy" wellknownpb "github.com/opentdf/platform/protocol/go/wellknownconfiguration" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/protobuf/types/known/structpb" ) @@ -42,8 +43,8 @@ func newMockWellKnownService(configMap map[string]interface{}, err error) *mockW } func (m *mockWellKnownService) GetWellKnownConfiguration( - ctx context.Context, - req *wellknownpb.GetWellKnownConfigurationRequest, + _ context.Context, + _ *wellknownpb.GetWellKnownConfigurationRequest, ) (*wellknownpb.GetWellKnownConfigurationResponse, error) { m.called = true @@ -168,10 +169,10 @@ func TestFormatAlg(t *testing.T) { t.Run(test.name, func(t *testing.T) { result, err := formatAlg(test.alg) if test.expectError { - assert.Error(t, err) + require.NoError(t, err) } else { - assert.NoError(t, err) - assert.Equal(t, test.expected, result, "Algorithm string mismatch") + require.NoError(t, err) + require.Equal(t, test.expected, result, "Algorithm string mismatch") } }) } @@ -208,14 +209,14 @@ func (s *BaseKeyTestSuite) TestGetBaseKeySuccess() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.NoError(err) - s.True(mockService.called) - s.NotNil(baseKey) - s.Equal(testKasURI, baseKey.GetKasUri()) - s.NotNil(baseKey.GetPublicKey()) - s.Equal(testKid, baseKey.GetPublicKey().GetKid()) - s.Equal(policy.Algorithm_ALGORITHM_RSA_2048, baseKey.GetPublicKey().GetAlgorithm()) - s.Equal(testPem, baseKey.GetPublicKey().GetPem()) + s.Require().NoError(err) + s.Require().True(mockService.called) + s.Require().NotNil(baseKey) + s.Require().Equal(testKasURI, baseKey.GetKasUri()) + s.Require().NotNil(baseKey.GetPublicKey()) + s.Require().Equal(testKid, baseKey.GetPublicKey().GetKid()) + s.Require().Equal(policy.Algorithm_ALGORITHM_RSA_2048, baseKey.GetPublicKey().GetAlgorithm()) + s.Require().Equal(testPem, baseKey.GetPublicKey().GetPem()) } func (s *BaseKeyTestSuite) TestGetBaseKeyServiceError() { @@ -227,11 +228,11 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyServiceError() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.Contains(err.Error(), "unable to retrieve config information") - s.Contains(err.Error(), "service unavailable") + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().Contains(err.Error(), "unable to retrieve config information") + s.Require().Contains(err.Error(), "service unavailable") } func (s *BaseKeyTestSuite) TestGetBaseKeyMissingBaseKey() { @@ -249,10 +250,10 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyMissingBaseKey() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.Contains(err.Error(), errBaseKeyNotFound.Error()) + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().Contains(err.Error(), errBaseKeyNotFound.Error()) } func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidBaseKeyFormat() { @@ -269,10 +270,10 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidBaseKeyFormat() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().ErrorContains(err, errBaseKeyInvalidFormat.Error()) } func (s *BaseKeyTestSuite) TestGetBaseKeyEmptyBaseKey() { @@ -290,10 +291,10 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyEmptyBaseKey() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.ErrorContains(err, errBaseKeyEmpty.Error()) + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().ErrorContains(err, errBaseKeyEmpty.Error()) } func (s *BaseKeyTestSuite) TestGetBaseKeyMissingPublicKey() { @@ -314,10 +315,10 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyMissingPublicKey() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().ErrorContains(err, errBaseKeyInvalidFormat.Error()) } func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidPublicKey() { @@ -338,8 +339,8 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidPublicKey() { baseKey, err := getBaseKey(s.T().Context(), s.sdk) // Validate result - s.True(mockService.called) - s.Error(err) - s.Nil(baseKey) - s.ErrorContains(err, errBaseKeyInvalidFormat.Error()) + s.Require().True(mockService.called) + s.Require().Error(err) + s.Require().Nil(baseKey) + s.Require().ErrorContains(err, errBaseKeyInvalidFormat.Error()) } diff --git a/sdk/granter.go b/sdk/granter.go index b45c55b640..ecb2b1d822 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -10,6 +10,7 @@ import ( "sort" "strings" + "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/attributes" "github.com/opentdf/platform/sdk/sdkconnect" @@ -276,13 +277,13 @@ func newGranterFromService(ctx context.Context, keyCache *kasKeyCache, as sdkcon func algProto2String(e policy.KasPublicKeyAlgEnum) string { switch e { case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1: - return "ec:secp256r1" + return string(ocrypto.EC256Key) case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1: - return "ec:secp384r1" + return string(ocrypto.EC384Key) case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1: - return "ec:secp521r1" + return string(ocrypto.EC521Key) case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048: - return "rsa:2048" + return string(ocrypto.RSA2048Key) case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096: return "rsa:4096" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED: diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index e1eab23821..bc911e3f5b 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -1099,7 +1099,10 @@ func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { if err != nil { return nil, err } - config.kasURL.setURLWithIdentifier(ki.URL, ki.KID) + err = config.kasURL.setURLWithIdentifier(ki.URL, ki.KID) + if err != nil { + return nil, fmt.Errorf("config.kasURL setURLWithIdentifier failed:%w", err) + } config.bindCfg.eccMode, err = ocrypto.ECKeyTypeToMode(ocrypto.KeyType(ki.Algorithm)) if err != nil { return nil, fmt.Errorf("ocrypto.ECKeyTypeToMode failed: %w", err) diff --git a/sdk/nanotdf_test.go b/sdk/nanotdf_test.go index cc5e6178f0..ad60f9c583 100644 --- a/sdk/nanotdf_test.go +++ b/sdk/nanotdf_test.go @@ -410,7 +410,7 @@ type mockWellKnownServiceClient struct { mockResponse func() (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) } -func (m *mockWellKnownServiceClient) GetWellKnownConfiguration(ctx context.Context, req *wellknownconfiguration.GetWellKnownConfigurationRequest) (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) { +func (m *mockWellKnownServiceClient) GetWellKnownConfiguration(_ context.Context, _ *wellknownconfiguration.GetWellKnownConfigurationRequest) (*wellknownconfiguration.GetWellKnownConfigurationResponse, error) { if m.mockResponse != nil { return m.mockResponse() } @@ -423,10 +423,9 @@ func (s *NanoSuite) Test_CreateNanoTDF_BaseKey() { URL: "https://kas.example.com", PublicKey: mockECPublicKey1, KID: "key-p256", - Algorithm: "ec:secp256r1", } - baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_EC_P256, mockKASInfo.KID, mockECPublicKey1, mockKASInfo.URL) + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_EC_P256, mockKASInfo.KID, mockKASInfo.PublicKey, mockKASInfo.URL) wellKnown := createWellKnown(baseKey) mockClient := createMockWellKnownServiceClient(&s.Suite, wellKnown, nil) @@ -439,7 +438,8 @@ func (s *NanoSuite) Test_CreateNanoTDF_BaseKey() { s.Require().NoError(err) config.EnableBaseKey() - config.SetKasURL("http://should-change.com") + err = config.SetKasURL("http://should-change.com") + s.Require().NoError(err) // Mock writer and reader writer := new(bytes.Buffer) @@ -534,7 +534,8 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { config := NanoTDFConfig{ baseKeyEnabled: tt.baseKeyEnabled, } - config.SetKasURL("http://should-change.com") + err := config.SetKasURL("http://should-change.com") + s.Require().NoError(err) // Call the getKasInfoForNanoTDF function info, err := getKasInfoForNanoTDF(sdk, &config) diff --git a/sdk/tdf.go b/sdk/tdf.go index 96feb7c9f4..ac96704440 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -170,7 +170,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R } g := granter{} - if tdfConfig.autoconfigure { + if tdfConfig.autoconfigure { //nolint:nestif // Will refactor in the future if len(tdfConfig.attributeValues) > 0 { g, err = newGranterFromAttributes(s.kasKeyCache, tdfConfig.attributeValues...) } else if len(tdfConfig.attributes) > 0 { @@ -189,13 +189,14 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R if err != nil { return nil, err } - } else { - // Calls Dave's plan function } } if tdfConfig.isBaseKeyEnabled && len(g.grants) == 0 { - populateKasInfoFromBaseKey(ctx, s, tdfConfig) + err = populateKasInfoFromBaseKey(ctx, s, tdfConfig) + if err != nil { + return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) + } } tdfObject := &TDFObject{} @@ -1396,7 +1397,7 @@ func isLessThanSemver(version, target string) (bool, error) { func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig) error { if len(tdfConfig.kasInfoList) > 0 { - return fmt.Errorf("base key is enabled, but kasInfoList is not empty") + return errors.New("base key is enabled, but kasInfoList is not empty") } // Get base key from the well-known configuration key, err := getBaseKey(ctx, s) diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index 93793ce269..788816fc4a 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -1810,15 +1810,15 @@ func (s *TDFSuite) Test_PopulateBaseKey_Success() { // Call populateBaseKey, should succeed err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) - s.NoError(err, "populateBaseKey should succeed with valid base key") + s.Require().NoError(err, "populateBaseKey should succeed with valid base key") // Verify KAS info list has been populated correctly - s.Equal(1, len(tdfConfig.kasInfoList), "KAS info list should have one entry") - s.Equal(s.baseKeyURI, tdfConfig.kasInfoList[0].URL, "KAS URL should match") - s.Equal(baseKeyKID, tdfConfig.kasInfoList[0].KID, "KAS KID should match") - s.Equal(string(ocrypto.RSA2048Key), tdfConfig.kasInfoList[0].Algorithm, "Algorithm should match") - s.Equal(mockRSAPublicKey1, tdfConfig.kasInfoList[0].PublicKey, "Public key should match") - s.Equal(ocrypto.KeyType("rsa:2048"), tdfConfig.keyType, "Key type should be set") + s.Require().Len(tdfConfig.kasInfoList, 1, "KAS info list should have one entry") + s.Require().Equal(s.baseKeyURI, tdfConfig.kasInfoList[0].URL, "KAS URL should match") + s.Require().Equal(baseKeyKID, tdfConfig.kasInfoList[0].KID, "KAS KID should match") + s.Require().Equal(string(ocrypto.RSA2048Key), tdfConfig.kasInfoList[0].Algorithm, "Algorithm should match") + s.Require().Equal(mockRSAPublicKey1, tdfConfig.kasInfoList[0].PublicKey, "Public key should match") + s.Require().Equal(ocrypto.KeyType("rsa:2048"), tdfConfig.keyType, "Key type should be set") } func (s *TDFSuite) Test_PopulateBaseKey_KasInfoPassIn_Fail() { @@ -1970,7 +1970,6 @@ func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { } func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { - // Create a stub for wellknown return map[string]interface{}{ "configuration": map[string]interface{}{ From 98096a0d26896ad4e6f2b82ada0daa703148c1d5 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 14:33:05 -0500 Subject: [PATCH 09/30] linting. --- sdk/basekey.go | 2 +- sdk/granter.go | 3 ++- sdk/nanotdf_basekey_test.go | 0 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 sdk/nanotdf_basekey_test.go diff --git a/sdk/basekey.go b/sdk/basekey.go index e848f382cb..1602289838 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -35,7 +35,7 @@ func getKasKeyAlg(alg string) policy.Algorithm { switch alg { case string(ocrypto.RSA2048Key): return policy.Algorithm_ALGORITHM_RSA_2048 - case "rsa:4096": //nolint:goconst // Will move to ocrypto + case rsa4096: //nolint:goconst // Will move to ocrypto return policy.Algorithm_ALGORITHM_RSA_4096 case string(ocrypto.EC256Key): return policy.Algorithm_ALGORITHM_EC_P256 diff --git a/sdk/granter.go b/sdk/granter.go index ecb2b1d822..ad88175266 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -25,6 +25,7 @@ const ( anyOf = "anyOf" unspecified = "unspecified" emptyTerm = "DEFAULT" + rsa4096 = "rsa:4096" ) // keySplitStep represents a which KAS a split with the associated ID should be shared with. @@ -285,7 +286,7 @@ func algProto2String(e policy.KasPublicKeyAlgEnum) string { case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048: return string(ocrypto.RSA2048Key) case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096: - return "rsa:4096" + return rsa4096 case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED: return "" } diff --git a/sdk/nanotdf_basekey_test.go b/sdk/nanotdf_basekey_test.go new file mode 100644 index 0000000000..e69de29bb2 From e790de52f7716965cef2e923f3a53bf710d1e907 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 14:37:04 -0500 Subject: [PATCH 10/30] remove file. --- sdk/nanotdf_basekey_test.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sdk/nanotdf_basekey_test.go diff --git a/sdk/nanotdf_basekey_test.go b/sdk/nanotdf_basekey_test.go deleted file mode 100644 index e69de29bb2..0000000000 From 13ecb7eebf4c3229a57706129ea0c6e2472f4f4c Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 14:54:46 -0500 Subject: [PATCH 11/30] linting --- sdk/basekey.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 1602289838..8c374929cb 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -35,7 +35,7 @@ func getKasKeyAlg(alg string) policy.Algorithm { switch alg { case string(ocrypto.RSA2048Key): return policy.Algorithm_ALGORITHM_RSA_2048 - case rsa4096: //nolint:goconst // Will move to ocrypto + case rsa4096: return policy.Algorithm_ALGORITHM_RSA_4096 case string(ocrypto.EC256Key): return policy.Algorithm_ALGORITHM_EC_P256 From b22e072d9bf21eaef6be276e30afba51012c90f9 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 15:01:41 -0500 Subject: [PATCH 12/30] fix tests. --- sdk/basekey.go | 2 +- sdk/basekey_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 8c374929cb..459ef2e164 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -54,7 +54,7 @@ func formatAlg(alg policy.Algorithm) (string, error) { case policy.Algorithm_ALGORITHM_RSA_2048: return string(ocrypto.RSA2048Key), nil case policy.Algorithm_ALGORITHM_RSA_4096: - return "rsa:4096", nil + return rsa4096, nil case policy.Algorithm_ALGORITHM_EC_P256: return string(ocrypto.EC256Key), nil case policy.Algorithm_ALGORITHM_EC_P384: diff --git a/sdk/basekey_test.go b/sdk/basekey_test.go index b50cea2a21..cef25444b3 100644 --- a/sdk/basekey_test.go +++ b/sdk/basekey_test.go @@ -169,7 +169,7 @@ func TestFormatAlg(t *testing.T) { t.Run(test.name, func(t *testing.T) { result, err := formatAlg(test.alg) if test.expectError { - require.NoError(t, err) + require.Error(t, err) } else { require.NoError(t, err) require.Equal(t, test.expected, result, "Algorithm string mismatch") From ef6143125418790ab5fabc99bf9198c29d8bfe3d Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Wed, 11 Jun 2025 15:22:29 -0500 Subject: [PATCH 13/30] tidy --- sdk/go.mod | 6 +-- sdk/go.sum | 106 +++-------------------------------------------------- 2 files changed, 6 insertions(+), 106 deletions(-) diff --git a/sdk/go.mod b/sdk/go.mod index 0462977af3..0559519f40 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -26,12 +26,10 @@ require ( require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 // indirect dario.cat/mergo v1.0.2 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Nerzal/gocloak/v13 v13.9.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect @@ -64,6 +62,7 @@ require ( github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.1.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -87,12 +86,9 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect - go.opentelemetry.io/otel/sdk v1.36.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect - go.opentelemetry.io/proto/otlp v1.6.0 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/net v0.41.0 // indirect diff --git a/sdk/go.sum b/sdk/go.sum index d71a5d05bc..145045424c 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,17 +1,11 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1 h1:YhMSc48s25kr7kv31Z8vf7sPUIq5YJva9z1mn/hAt0M= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 h1:uwSqFkn8DDTzNlaV9TxgSXY5OCaNdb4rH+Axd2FujkE= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= @@ -44,37 +38,26 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvw github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.0.2+incompatible h1:9BILleFwug5FSSqWBgVevgL3ewDJfWWWyZVqlDMttE8= -github.com/docker/docker v28.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= -github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0= github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -83,7 +66,6 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -92,22 +74,16 @@ github.com/gowebpki/jcs v1.0.1 h1:Qjzg8EOkrOTuWP7DqQ1FbYtcpEbeTzUoTN9bptp8FOU= github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6+BrI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs= -github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -120,8 +96,6 @@ github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVf github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= @@ -132,18 +106,14 @@ github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -165,8 +135,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -175,8 +143,6 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= -github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -192,15 +158,10 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -210,70 +171,41 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= @@ -281,66 +213,38 @@ golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKl golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= @@ -353,5 +257,5 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= From af549771ef682432328feef8263458d48e037f71 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Thu, 12 Jun 2025 10:51:57 -0500 Subject: [PATCH 14/30] test. --- sdk/tdf_test.go | 53 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index 788816fc4a..fbfa21f4be 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -77,6 +77,13 @@ type tdfTest struct { expectedPlanSize int } +type baseKeyTest struct { + tdfTest + encryptOpts []TDFOption + expectedKID string + expectedURL string +} + const ( mockRSAPublicKey1 = `-----BEGIN CERTIFICATE----- MIICmDCCAYACCQC3BCaSANRhYzANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDDANr @@ -297,15 +304,13 @@ type TDFSuite struct { kases []FakeKas kasTestURLLookup map[string]string fakeWellKnown map[string]interface{} - baseKeyURI string } func (s *TDFSuite) SetupSuite() { // Set up the test environment s.startBackend() // Update well-known with the server URL - s.baseKeyURI = s.kasTestURLLookup[baseKeyURL] - baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, s.baseKeyURI) + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, s.kasTestURLLookup[baseKeyURL]) s.fakeWellKnown = createWellKnown(baseKey) } @@ -1616,12 +1621,28 @@ func (s *TDFSuite) Test_TDF() { } func (s *TDFSuite) Test_EncryptWithBaseKey() { - for index, test := range []tdfTest{ + for index, test := range []baseKeyTest{ { - n: "medium", - fileSize: hundredMB, - tdfFileSize: 104866427, - checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", + tdfTest: tdfTest{ + n: "medium", + fileSize: hundredMB, + tdfFileSize: 104866427, + checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", + }, + encryptOpts: []TDFOption{WithBaseKeyEnabled()}, + expectedKID: baseKeyKID, + expectedURL: baseKeyURL, + }, + { + tdfTest: tdfTest{ + n: "medium_attributes_skip_base_key", + fileSize: hundredMB, + tdfFileSize: 104866427, + checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", + }, + encryptOpts: []TDFOption{WithDataAttributes(rel2aus.key), WithBaseKeyEnabled()}, + expectedKID: defaultKID, + expectedURL: kasAu, }, } { s.Run(test.n, func() { @@ -1636,11 +1657,14 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { _ = os.Remove(tdfFileName) }() + expectedServerURL := s.kasTestURLLookup[test.expectedURL] + s.Require().NotEmpty(expectedServerURL, "Expected server URL should not be empty") + // test encrypt - tdfObj := s.testEncrypt(s.sdk, []TDFOption{WithBaseKeyEnabled()}, plaintTextFileName, tdfFileName, test) - s.Require().Equal(baseKeyKID, tdfObj.manifest.KeyAccessObjs[0].KID, "Base key KID should match") - s.Require().Equal(s.baseKeyURI, tdfObj.manifest.KeyAccessObjs[0].KasURL, "KAS URI should match") - s.testDecryptWithReader(s.sdk, tdfFileName, decryptedTdfFileName, test) + tdfObj := s.testEncrypt(s.sdk, test.encryptOpts, plaintTextFileName, tdfFileName, test.tdfTest) + s.Require().Equal(test.expectedKID, tdfObj.manifest.KeyAccessObjs[0].KID, "Base key KID should match") + s.Require().Equal(expectedServerURL, tdfObj.manifest.KeyAccessObjs[0].KasURL, "KAS URI should match") + s.testDecryptWithReader(s.sdk, tdfFileName, decryptedTdfFileName, test.tdfTest) }) } } @@ -1812,9 +1836,12 @@ func (s *TDFSuite) Test_PopulateBaseKey_Success() { err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) s.Require().NoError(err, "populateBaseKey should succeed with valid base key") + expectedURL := s.kasTestURLLookup[baseKeyURL] + s.Require().NotEmpty(expectedURL, "Expected KAS URL should not be empty") + // Verify KAS info list has been populated correctly s.Require().Len(tdfConfig.kasInfoList, 1, "KAS info list should have one entry") - s.Require().Equal(s.baseKeyURI, tdfConfig.kasInfoList[0].URL, "KAS URL should match") + s.Require().Equal(expectedURL, tdfConfig.kasInfoList[0].URL, "KAS URL should match") s.Require().Equal(baseKeyKID, tdfConfig.kasInfoList[0].KID, "KAS KID should match") s.Require().Equal(string(ocrypto.RSA2048Key), tdfConfig.kasInfoList[0].Algorithm, "Algorithm should match") s.Require().Equal(mockRSAPublicKey1, tdfConfig.kasInfoList[0].PublicKey, "Public key should match") From f8fea08bb4cb3dd68a65fa3e3e61b90a72f59f9e Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Fri, 13 Jun 2025 08:08:54 -0500 Subject: [PATCH 15/30] fix small keys bug. --- sdk/granter.go | 42 +++++-------------------------------- sdk/granter_test.go | 31 +++++++++++++++++++++++++++- sdk/tdf.go | 50 +++++++++++++++++++++++---------------------- sdk/tdf_test.go | 31 +++++++++++++++++++++------- 4 files changed, 85 insertions(+), 69 deletions(-) diff --git a/sdk/granter.go b/sdk/granter.go index a6d5c4659a..6949d2eb0b 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -10,7 +10,6 @@ import ( "sort" "strings" - "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/attributes" "github.com/opentdf/platform/sdk/sdkconnect" @@ -283,43 +282,12 @@ type grantableObject interface { // It returns a mask indicating whether grants or mapped keys were found. func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr *policy.Attribute) grantTypeMask { ok := noKeysFound - for _, k := range ag.GetKasKeys() { - if k == nil || k.GetKasUri() == "" { - slog.Debug("invalid KAS key in policy service", "simpleKasKey", k, "value", fqn) - continue - } - kasURI := k.GetKasUri() - r.typ |= mappedFound - ok |= mappedFound - err := r.addMappedKey(fqn, k) - if err != nil { - slog.Debug("failed to add mapped key", "fqn", fqn, "kas", kasURI, "error", err) - } - if _, present := r.grantTable[fqn.key]; !present { - r.grantTable[fqn.key] = &keyAccessGrant{attr, []string{kasURI}} - } else { - r.grantTable[fqn.key].kases = append(r.grantTable[fqn.key].kases, kasURI) - } - } - if ok != noKeysFound { - return ok - } - for _, g := range ag.GetGrants() { if g != nil && g.GetUri() != "" { //nolint:nestif // Simplify after grant removal kasURI := g.GetUri() r.typ |= grantsFound ok |= grantsFound r.addGrant(fqn, kasURI, attr) - if len(g.GetKasKeys()) != 0 { - for _, k := range g.GetKasKeys() { - err := r.addMappedKey(fqn, k) - if err != nil { - slog.Warn("failed to add mapped key", "fqn", fqn, "kas", kasURI, "error", err) - } - } - continue - } ks := g.GetPublicKey().GetCached().GetKeys() if len(ks) == 0 { slog.Debug("no cached key in policy service", "kas", kasURI, "value", fqn) @@ -413,15 +381,15 @@ func newGranterFromService(ctx context.Context, keyCache *kasKeyCache, as sdkcon func algProto2String(e policy.KasPublicKeyAlgEnum) string { switch e { case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1: - return string(ocrypto.EC256Key) + return "ec:secp256r1" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1: - return string(ocrypto.EC384Key) + return "ec:secp384r1" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1: - return string(ocrypto.EC521Key) + return "ec:secp521r1" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048: - return string(ocrypto.RSA2048Key) + return "rsa:2048" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096: - return rsa4096 + return "rsa:4096" case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED: return "" } diff --git a/sdk/granter_test.go b/sdk/granter_test.go index 20015749fc..98e73fcdf3 100644 --- a/sdk/granter_test.go +++ b/sdk/granter_test.go @@ -30,6 +30,7 @@ const ( specifiedKas = "https://attr.kas.com/" evenMoreSpecificKas = "https://value.kas.com/" lessSpecificKas = "https://namespace.kas.com/" + fakePem = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ...\n-----END PUBLIC KEY-----\n" ) var ( @@ -144,12 +145,16 @@ func mockAttributeFor(fqn AttributeNameFQN) *policy.Attribute { Fqn: fqn.String(), } case MP.key: + g := make([]*policy.KeyAccessServer, 1) + g[0] = mockGrant(specifiedKas, "r1") + g[0].PublicKey = createPublicKey("r1", fakePem, policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048) return &policy.Attribute{ Id: "MP", Namespace: &nsOne, Name: "Mapped", Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF, Fqn: fqn.String(), + Grants: g, KasKeys: []*policy.SimpleKasKey{mockSimpleKasKey(specifiedKas, "r1")}, } case N2K.key: @@ -217,6 +222,7 @@ func mockGrant(kas, kid string) *policy.KeyAccessServer { if kid == "" { return mockGrant(kas, "r0") } + return &policy.KeyAccessServer{ Uri: kas, Id: kas, @@ -226,7 +232,7 @@ func mockGrant(kas, kid string) *policy.KeyAccessServer { PublicKey: &policy.SimpleKasPublicKey{ Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, Kid: kid, - Pem: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ...\n-----END PUBLIC KEY-----\n", + Pem: fakePem, }, }, }, @@ -261,6 +267,22 @@ func mockSimpleKasKey(kas, kid string) *policy.SimpleKasKey { } } +func createPublicKey(kid, pem string, algorithm policy.KasPublicKeyAlgEnum) *policy.PublicKey { + return &policy.PublicKey{ + PublicKey: &policy.PublicKey_Cached{ + Cached: &policy.KasPublicKeySet{ + Keys: []*policy.KasPublicKey{ + { + Kid: kid, + Alg: policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048, + Pem: pem, + }, + }, + }, + }, + } +} + func mockValueFor(fqn AttributeValueFQN) *policy.Value { an := fqn.Prefix() a := mockAttributeFor(an) @@ -317,10 +339,17 @@ func mockValueFor(fqn AttributeValueFQN) *policy.Value { switch strings.ToLower(fqn.Value()) { case "a": p.KasKeys = make([]*policy.SimpleKasKey, 1) + p.Grants = make([]*policy.KeyAccessServer, 1) p.KasKeys[0] = mockSimpleKasKey(evenMoreSpecificKas, "r2") + p.Grants[0] = mockGrant(evenMoreSpecificKas, "r2") + p.Grants[0].PublicKey = createPublicKey("r2", fakePem, policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048) + case "b": p.KasKeys = make([]*policy.SimpleKasKey, 1) + p.Grants = make([]*policy.KeyAccessServer, 1) p.KasKeys[0] = mockSimpleKasKey(evenMoreSpecificKas, "e1") + p.Grants[0] = mockGrant(evenMoreSpecificKas, "e1") + p.Grants[0].PublicKey = createPublicKey("e1", fakePem, policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048) case "unspecified": // defaults only default: diff --git a/sdk/tdf.go b/sdk/tdf.go index ba4225aa84..4650c78a52 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -191,25 +191,21 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } - if g.typ&mappedFound == mappedFound { - tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) - if err != nil { - slog.Info("Failed to resolve kao template, using split plan / grant behavior", "error", err) - } - } - if g.typ == noKeysFound || g.typ == grantsFound && !tdfConfig.isBaseKeyEnabled { + if (g.typ == noKeysFound || g.typ == grantsFound) && !tdfConfig.isBaseKeyEnabled { dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) + } else if g.typ&grantsFound == grantsFound && tdfConfig.isBaseKeyEnabled { + tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) } if err != nil { - return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) + return nil, fmt.Errorf("failed generate plan: %w", err) } } // * Expresses the use case where no attributes were passed in or found. // * Replaces the defaultKases behavior. - if tdfConfig.isBaseKeyEnabled && len(tdfConfig.kaoTemplate) == 0 { + if tdfConfig.isBaseKeyEnabled && len(tdfConfig.attributeValues) == 0 && len(tdfConfig.attributes) == 0 { err = populateKasInfoFromBaseKey(ctx, s, tdfConfig) if err != nil { return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) @@ -471,20 +467,7 @@ func (s SDK) prepareManifest(ctx context.Context, t *TDFObject, tdfConfig TDFCon case len(tdfConfig.kasInfoList) > 0: // Default to split based on kasInfoList // To remove. This has been deprecated for some time. - tdfConfig.kaoTemplate = make([]kaoTpl, len(tdfConfig.kasInfoList)) - for i, kasInfo := range tdfConfig.kasInfoList { - splitID := "" - if len(tdfConfig.kasInfoList) > 1 { - splitID = fmt.Sprintf("s-%d", i) - } - tdfConfig.kaoTemplate[i] = kaoTpl{ - keySplitStep{ - KAS: kasInfo.URL, - SplitID: splitID, - }, - kasInfo.KID, - } - } + tdfConfig.kaoTemplate = createKaoTemplateFromKasInfo(tdfConfig.kasInfoList) } conjunction := make(map[string][]KASInfo) @@ -1464,6 +1447,7 @@ func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig slog.Warn("Base key is enabled, setting key type", "keyType", algoString) } tdfConfig.keyType = ocrypto.KeyType(algoString) + tdfConfig.splitPlan = nil tdfConfig.kasInfoList = []KASInfo{ { URL: key.GetKasUri(), @@ -1472,6 +1456,24 @@ func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig Algorithm: algoString, }, } - return nil } + +func createKaoTemplateFromKasInfo(kasInfoArr []KASInfo) []kaoTpl { + kaoTemplate := make([]kaoTpl, len(kasInfoArr)) + for i, kasInfo := range kasInfoArr { + splitID := "" + if len(kasInfoArr) > 1 { + splitID = fmt.Sprintf("s-%d", i) + } + kaoTemplate[i] = kaoTpl{ + keySplitStep{ + KAS: kasInfo.URL, + SplitID: splitID, + }, + kasInfo.KID, + } + } + + return kaoTemplate +} diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index fbfa21f4be..8f9bf0abc3 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -1621,6 +1621,26 @@ func (s *TDFSuite) Test_TDF() { } func (s *TDFSuite) Test_EncryptWithBaseKey() { + attrVal := mockValueFor(rel2aus) + cachedPublicKeySet := &policy.KasPublicKeySet{ + Keys: []*policy.KasPublicKey{ + { + Kid: defaultKID, + Pem: mockRSAPublicKey1, + Alg: policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048, + }, + }, + } + attrVal.Grants = []*policy.KeyAccessServer{ + { + Uri: s.kasTestURLLookup[kasAu], + PublicKey: &policy.PublicKey{ + PublicKey: &policy.PublicKey_Cached{ + Cached: cachedPublicKeySet, + }, + }, + }, + } for index, test := range []baseKeyTest{ { tdfTest: tdfTest{ @@ -1631,7 +1651,7 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { }, encryptOpts: []TDFOption{WithBaseKeyEnabled()}, expectedKID: baseKeyKID, - expectedURL: baseKeyURL, + expectedURL: s.kasTestURLLookup[baseKeyURL], }, { tdfTest: tdfTest{ @@ -1640,9 +1660,9 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { tdfFileSize: 104866427, checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", }, - encryptOpts: []TDFOption{WithDataAttributes(rel2aus.key), WithBaseKeyEnabled()}, + encryptOpts: []TDFOption{WithDataAttributeValues(attrVal), WithBaseKeyEnabled()}, expectedKID: defaultKID, - expectedURL: kasAu, + expectedURL: s.kasTestURLLookup[kasAu], }, } { s.Run(test.n, func() { @@ -1657,13 +1677,10 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { _ = os.Remove(tdfFileName) }() - expectedServerURL := s.kasTestURLLookup[test.expectedURL] - s.Require().NotEmpty(expectedServerURL, "Expected server URL should not be empty") - // test encrypt tdfObj := s.testEncrypt(s.sdk, test.encryptOpts, plaintTextFileName, tdfFileName, test.tdfTest) s.Require().Equal(test.expectedKID, tdfObj.manifest.KeyAccessObjs[0].KID, "Base key KID should match") - s.Require().Equal(expectedServerURL, tdfObj.manifest.KeyAccessObjs[0].KasURL, "KAS URI should match") + s.Require().Equal(test.expectedURL, tdfObj.manifest.KeyAccessObjs[0].KasURL, "KAS URI should match") s.testDecryptWithReader(s.sdk, tdfFileName, decryptedTdfFileName, test.tdfTest) }) } From b7d9a2823be11a3121ac40d53afd6f0a4f15e308 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Fri, 13 Jun 2025 09:05:03 -0500 Subject: [PATCH 16/30] linting. --- sdk/granter.go | 2 +- sdk/granter_test.go | 2 +- sdk/tdf.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/granter.go b/sdk/granter.go index 6949d2eb0b..5782227517 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -283,7 +283,7 @@ type grantableObject interface { func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr *policy.Attribute) grantTypeMask { ok := noKeysFound for _, g := range ag.GetGrants() { - if g != nil && g.GetUri() != "" { //nolint:nestif // Simplify after grant removal + if g != nil && g.GetUri() != "" { kasURI := g.GetUri() r.typ |= grantsFound ok |= grantsFound diff --git a/sdk/granter_test.go b/sdk/granter_test.go index 98e73fcdf3..4af6f43e5e 100644 --- a/sdk/granter_test.go +++ b/sdk/granter_test.go @@ -274,7 +274,7 @@ func createPublicKey(kid, pem string, algorithm policy.KasPublicKeyAlgEnum) *pol Keys: []*policy.KasPublicKey{ { Kid: kid, - Alg: policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048, + Alg: algorithm, Pem: pem, }, }, diff --git a/sdk/tdf.go b/sdk/tdf.go index 4650c78a52..fe6ae8e6f6 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -184,7 +184,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, errors.New("cannot set autoconfigure and splitPlan or kaoTemplate") } - if tdfConfig.autoconfigure { //nolint:nestif // simplify after removing support for splitPlan + if tdfConfig.autoconfigure { var g granter g, err = s.newGranter(ctx, tdfConfig, err) if err != nil { From d35e9d65c8b9e52cc08fbf787b99c704f49e8299 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Fri, 13 Jun 2025 10:27:26 -0500 Subject: [PATCH 17/30] fix underflow? --- sdk/nanotdf.go | 2 +- sdk/nanotdf_config.go | 27 +++++++++++++-------------- sdk/nanotdf_test.go | 2 +- sdk/tdf_config.go | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index bc911e3f5b..90dfd13333 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -1094,7 +1094,7 @@ func createNanoTDFSymmetricKey(config NanoTDFConfig) ([]byte, error) { } func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { - if config.baseKeyEnabled { + if config.isBaseKeyEnabled { ki, err := getNanoKasInfoFromBaseKey(s) if err != nil { return nil, err diff --git a/sdk/nanotdf_config.go b/sdk/nanotdf_config.go index dc14863589..f0e037dedd 100644 --- a/sdk/nanotdf_config.go +++ b/sdk/nanotdf_config.go @@ -17,17 +17,17 @@ import ( // ============================================================================================================ type NanoTDFConfig struct { - keyPair ocrypto.ECKeyPair - kasPublicKey *ecdh.PublicKey - attributes []AttributeValueFQN - cipher CipherMode - kasURL ResourceLocator - sigCfg signatureConfig - policy policyInfo - bindCfg bindingConfig - collectionCfg *collectionConfig - policyMode PolicyType // Added field for policy mode - baseKeyEnabled bool + keyPair ocrypto.ECKeyPair + kasPublicKey *ecdh.PublicKey + attributes []AttributeValueFQN + cipher CipherMode + kasURL ResourceLocator + sigCfg signatureConfig + policy policyInfo + bindCfg bindingConfig + collectionCfg *collectionConfig + policyMode PolicyType // Added field for policy mode + isBaseKeyEnabled bool // Added field to enable base key usage } type NanoTDFOption func(*NanoTDFConfig) error @@ -57,8 +57,7 @@ func (s SDK) NewNanoTDFConfig() (*NanoTDFConfig, error) { useCollection: false, header: []byte{}, }, - policyMode: NanoTDFPolicyModeDefault, - baseKeyEnabled: false, + policyMode: NanoTDFPolicyModeDefault, } return c, nil @@ -106,7 +105,7 @@ func (config *NanoTDFConfig) SetPolicyMode(mode PolicyType) error { // ! Enabling this option will cause the SDK to ignore any KAS information passed in // ! and instead use the base key from the well-known configuration. func (config *NanoTDFConfig) EnableBaseKey() { - config.baseKeyEnabled = true + config.isBaseKeyEnabled = true } // WithNanoDataAttributes appends the given data attributes to the bound policy diff --git a/sdk/nanotdf_test.go b/sdk/nanotdf_test.go index ad60f9c583..9f0566cad9 100644 --- a/sdk/nanotdf_test.go +++ b/sdk/nanotdf_test.go @@ -532,7 +532,7 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { // Create a NanoTDFConfig config := NanoTDFConfig{ - baseKeyEnabled: tt.baseKeyEnabled, + isBaseKeyEnabled: tt.baseKeyEnabled, } err := config.SetKasURL("http://should-change.com") s.Require().NoError(err) diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index 131961b253..c9cc76c864 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -92,7 +92,7 @@ func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { integrityAlgorithm: HS256, segmentIntegrityAlgorithm: GMAC, keyType: ocrypto.RSA2048Key, // default to RSA - isBaseKeyEnabled: false, // Default to true. + isBaseKeyEnabled: false, } for _, o := range opt { From e9bfc93b6db2eea6fdc33a7f3d6adfcbb494358d Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Fri, 13 Jun 2025 13:03:39 -0500 Subject: [PATCH 18/30] fix tests. --- sdk/basekey.go | 28 +++++++++++++--------------- sdk/basekey_test.go | 42 +++++++++++++++--------------------------- sdk/tdf_test.go | 14 ++++++-------- 3 files changed, 34 insertions(+), 50 deletions(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 459ef2e164..67da377faf 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -78,17 +78,23 @@ func getBaseKey(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { if configuration == nil { return nil, ErrWellKnowConfigEmpty } - configStructure, ok := configuration.AsMap()[wellKnownConfigKey] + + configMap := configuration.AsMap() + if len(configMap) == 0 { + return nil, ErrWellKnowConfigEmpty + } + + baseKeyStructure, ok := configMap[baseKeyWellKnown] if !ok { - return nil, err + return nil, errBaseKeyNotFound } - configMap, ok := configStructure.(map[string]interface{}) + baseKeyMap, ok := baseKeyStructure.(map[string]interface{}) if !ok { - return nil, errWellKnownConfigFormat + return nil, errBaseKeyInvalidFormat } - simpleKasKey, err := parseSimpleKasKey(configMap) + simpleKasKey, err := parseSimpleKasKey(baseKeyMap) if err != nil { return nil, err } @@ -96,17 +102,9 @@ func getBaseKey(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { return simpleKasKey, nil } -func parseSimpleKasKey(configMap map[string]interface{}) (*policy.SimpleKasKey, error) { +func parseSimpleKasKey(baseKeyMap map[string]interface{}) (*policy.SimpleKasKey, error) { simpleKasKey := &policy.SimpleKasKey{} - baseKey, ok := configMap[baseKeyWellKnown] - if !ok { - return nil, errBaseKeyNotFound - } - baseKeyMap, ok := baseKey.(map[string]interface{}) - if !ok { - return nil, errBaseKeyInvalidFormat - } if len(baseKeyMap) == 0 { return nil, errBaseKeyEmpty } @@ -122,7 +120,7 @@ func parseSimpleKasKey(configMap map[string]interface{}) (*policy.SimpleKasKey, } publicKey[baseKeyAlg] = getKasKeyAlg(alg) baseKeyMap[baseKeyPublicKey] = publicKey - configJSON, err := json.Marshal(baseKey) + configJSON, err := json.Marshal(baseKeyMap) if err != nil { return nil, errors.Join(errMarshalBaseKeyFailed, err) } diff --git a/sdk/basekey_test.go b/sdk/basekey_test.go index cef25444b3..9e97fc51d7 100644 --- a/sdk/basekey_test.go +++ b/sdk/basekey_test.go @@ -189,14 +189,12 @@ func TestBaseKeySuite(t *testing.T) { func (s *BaseKeyTestSuite) TestGetBaseKeySuccess() { // Create a valid base key configuration wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - baseKeyWellKnown: map[string]interface{}{ - "kas_uri": "https://test-kas.example.com", - baseKeyPublicKey: map[string]interface{}{ - baseKeyAlg: testRSAAlgorithm, - "kid": testKid, - "pem": testPem, - }, + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + baseKeyPublicKey: map[string]interface{}{ + baseKeyAlg: testRSAAlgorithm, + "kid": testKid, + "pem": testPem, }, }, } @@ -238,9 +236,7 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyServiceError() { func (s *BaseKeyTestSuite) TestGetBaseKeyMissingBaseKey() { // Create wellknown configuration without base key wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - "some_other_config": "value", - }, + "some_other_config": "value", } mockService := newMockWellKnownService(wellknownConfig, nil) @@ -258,9 +254,7 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyMissingBaseKey() { func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidBaseKeyFormat() { wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - baseKeyWellKnown: "invalid-base-key", - }, + baseKeyWellKnown: "invalid-base-key", } mockService := newMockWellKnownService(wellknownConfig, nil) @@ -279,9 +273,7 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidBaseKeyFormat() { func (s *BaseKeyTestSuite) TestGetBaseKeyEmptyBaseKey() { // Create empty base key map wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - baseKeyWellKnown: map[string]interface{}{}, - }, + baseKeyWellKnown: map[string]interface{}{}, } mockService := newMockWellKnownService(wellknownConfig, nil) @@ -300,11 +292,9 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyEmptyBaseKey() { func (s *BaseKeyTestSuite) TestGetBaseKeyMissingPublicKey() { // Create base key without public_key field wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - baseKeyWellKnown: map[string]interface{}{ - "kas_uri": "https://test-kas.example.com", - // Missing public_key field - }, + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + // Missing public_key field }, } @@ -324,11 +314,9 @@ func (s *BaseKeyTestSuite) TestGetBaseKeyMissingPublicKey() { func (s *BaseKeyTestSuite) TestGetBaseKeyInvalidPublicKey() { // Create base key with invalid public_key (string instead of map) wellknownConfig := map[string]interface{}{ - wellKnownConfigKey: map[string]interface{}{ - baseKeyWellKnown: map[string]interface{}{ - "kas_uri": "https://test-kas.example.com", - baseKeyPublicKey: "invalid-public-key", // Should be a map - }, + baseKeyWellKnown: map[string]interface{}{ + "kas_uri": "https://test-kas.example.com", + baseKeyPublicKey: "invalid-public-key", // Should be a map }, } diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index 8f9bf0abc3..db6c2fff7b 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -2016,15 +2016,13 @@ func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { // Create a stub for wellknown return map[string]interface{}{ - "configuration": map[string]interface{}{ - "health": map[string]interface{}{ - "endpoint": "/healthz", - }, - "idp": map[string]interface{}{ - "issuer": "http://localhost:65432/auth", - }, - "base_key": baseKey, + "health": map[string]interface{}{ + "endpoint": "/healthz", + }, + "idp": map[string]interface{}{ + "issuer": "http://localhost:65432/auth", }, + "base_key": baseKey, } } From d6d63cb8f1b7cfe1a06be4b32dd5dfd222743aae Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Fri, 13 Jun 2025 13:07:00 -0500 Subject: [PATCH 19/30] fix linting./ --- sdk/basekey.go | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/basekey.go b/sdk/basekey.go index 67da377faf..42a3567e52 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -22,7 +22,6 @@ const ( ) var ( - errWellKnownConfigFormat = errors.New("well-known configuration has invalid format") errBaseKeyNotFound = errors.New("base key not found in well-known configuration") errBaseKeyInvalidFormat = errors.New("base key has invalid format") errBaseKeyEmpty = errors.New("base key is empty or not provided") From 4711f7c531b339bf5ad43bb3516c6f31b836aa44 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 07:54:19 -0500 Subject: [PATCH 20/30] fix conditional. --- sdk/tdf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/tdf.go b/sdk/tdf.go index fe6ae8e6f6..44c5d843e4 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -205,7 +205,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R // * Expresses the use case where no attributes were passed in or found. // * Replaces the defaultKases behavior. - if tdfConfig.isBaseKeyEnabled && len(tdfConfig.attributeValues) == 0 && len(tdfConfig.attributes) == 0 { + if tdfConfig.isBaseKeyEnabled && len(tdfConfig.kaoTemplate) == 0 { err = populateKasInfoFromBaseKey(ctx, s, tdfConfig) if err != nil { return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) From d072160e3114ff85b771429a718fbc48f9915c60 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 08:13:47 -0500 Subject: [PATCH 21/30] fix conditional. --- sdk/granter.go | 3 +++ sdk/tdf.go | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sdk/granter.go b/sdk/granter.go index 5782227517..e2e4854cd8 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -314,6 +314,9 @@ func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr * } } } + if ag.GetKasKeys() != nil && len(ag.GetKasKeys()) > 0 { + r.typ |= mappedFound + } if ok == noKeysFound { if _, present := r.grantTable[fqn.key]; !present { r.grantTable[fqn.key] = &keyAccessGrant{attr, []string{}} diff --git a/sdk/tdf.go b/sdk/tdf.go index 44c5d843e4..57f110bf20 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -191,12 +191,12 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } - if (g.typ == noKeysFound || g.typ == grantsFound) && !tdfConfig.isBaseKeyEnabled { + if g.typ&mappedFound == mappedFound { + tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) + } else if g.typ == noKeysFound || g.typ == grantsFound { dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) - } else if g.typ&grantsFound == grantsFound && tdfConfig.isBaseKeyEnabled { - tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) } if err != nil { return nil, fmt.Errorf("failed generate plan: %w", err) From e84d98d2716005b0897a7e3d62a552f95035ef7f Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 08:25:52 -0500 Subject: [PATCH 22/30] fix conditional. --- sdk/tdf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/tdf.go b/sdk/tdf.go index 57f110bf20..348e1dd377 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -193,7 +193,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R if g.typ&mappedFound == mappedFound { tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) - } else if g.typ == noKeysFound || g.typ == grantsFound { + } else if (g.typ == noKeysFound || g.typ == grantsFound) && !tdfConfig.isBaseKeyEnabled { dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) From 9cf2de7f0d9e608e0c6ef38e2141d0ee8fa8435c Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 08:41:10 -0500 Subject: [PATCH 23/30] fix test. --- sdk/tdf_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index db6c2fff7b..00d576757b 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -1641,6 +1641,16 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { }, }, } + attrVal.KasKeys = []*policy.SimpleKasKey{ + { + KasUri: s.kasTestURLLookup[kasAu], + PublicKey: &policy.SimpleKasPublicKey{ + Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + Kid: defaultKID, + Pem: mockRSAPublicKey1, + }, + }, + } for index, test := range []baseKeyTest{ { tdfTest: tdfTest{ From eb5dad72aa9b50b6b92b7deb48703ece9d84ea49 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 12:52:06 -0500 Subject: [PATCH 24/30] refactor. --- sdk/basekey.go | 8 ------ sdk/basekeyerrors.go | 11 +++++++++ sdk/fuzz_test.go | 2 ++ sdk/granter.go | 36 ++++++++++++++++++++++++--- sdk/tdf.go | 47 ++++++++++++++++++++++++++--------- sdk/tdf_config.go | 9 ------- sdk/tdf_test.go | 58 ++++++++++++++++++++------------------------ 7 files changed, 106 insertions(+), 65 deletions(-) create mode 100644 sdk/basekeyerrors.go diff --git a/sdk/basekey.go b/sdk/basekey.go index 42a3567e52..a0e54229ee 100644 --- a/sdk/basekey.go +++ b/sdk/basekey.go @@ -21,14 +21,6 @@ const ( wellKnownConfigKey = "configuration" ) -var ( - errBaseKeyNotFound = errors.New("base key not found in well-known configuration") - errBaseKeyInvalidFormat = errors.New("base key has invalid format") - errBaseKeyEmpty = errors.New("base key is empty or not provided") - errMarshalBaseKeyFailed = errors.New("failed to marshal base key configuration") - errUnmarshalBaseKeyFailed = errors.New("failed to unmarshal base key configuration") -) - // TODO: Move this function to ocrypto? func getKasKeyAlg(alg string) policy.Algorithm { switch alg { diff --git a/sdk/basekeyerrors.go b/sdk/basekeyerrors.go new file mode 100644 index 0000000000..dc41194c87 --- /dev/null +++ b/sdk/basekeyerrors.go @@ -0,0 +1,11 @@ +package sdk + +import "errors" + +var ( + errBaseKeyNotFound = errors.New("base key not found in well-known configuration") + errBaseKeyInvalidFormat = errors.New("base key has invalid format") + errBaseKeyEmpty = errors.New("base key is empty or not provided") + errMarshalBaseKeyFailed = errors.New("failed to marshal base key configuration") + errUnmarshalBaseKeyFailed = errors.New("failed to unmarshal base key configuration") +) diff --git a/sdk/fuzz_test.go b/sdk/fuzz_test.go index ce4291eeb6..3faadb8a0d 100644 --- a/sdk/fuzz_test.go +++ b/sdk/fuzz_test.go @@ -58,7 +58,9 @@ func unverifiedBase64Bytes(str string) []byte { } func FuzzLoadTDF(f *testing.F) { + mockWellKnown := newMockWellKnownService(createWellKnown(nil), nil) sdk := newSDK() + sdk.wellknownConfiguration = mockWellKnown f.Add(writeBytes(func(writer io.Writer) error { reader := bytes.NewReader([]byte("AAA")) _, err := sdk.CreateTDF(writer, reader, func(tdfConfig *TDFConfig) error { diff --git a/sdk/granter.go b/sdk/granter.go index e2e4854cd8..6b8226d2e4 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -282,12 +282,43 @@ type grantableObject interface { // It returns a mask indicating whether grants or mapped keys were found. func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr *policy.Attribute) grantTypeMask { ok := noKeysFound + for _, k := range ag.GetKasKeys() { + if k == nil || k.GetKasUri() == "" { + slog.Debug("invalid KAS key in policy service", "simpleKasKey", k, "value", fqn) + continue + } + kasURI := k.GetKasUri() + r.typ |= mappedFound + ok |= mappedFound + err := r.addMappedKey(fqn, k) + if err != nil { + slog.Debug("failed to add mapped key", "fqn", fqn, "kas", kasURI, "error", err) + } + if _, present := r.grantTable[fqn.key]; !present { + r.grantTable[fqn.key] = &keyAccessGrant{attr, []string{kasURI}} + } else { + r.grantTable[fqn.key].kases = append(r.grantTable[fqn.key].kases, kasURI) + } + } + if ok != noKeysFound { + return ok + } + for _, g := range ag.GetGrants() { - if g != nil && g.GetUri() != "" { + if g != nil && g.GetUri() != "" { //nolint:nestif // Simplify after grant removal kasURI := g.GetUri() r.typ |= grantsFound ok |= grantsFound r.addGrant(fqn, kasURI, attr) + if len(g.GetKasKeys()) != 0 { + for _, k := range g.GetKasKeys() { + err := r.addMappedKey(fqn, k) + if err != nil { + slog.Warn("failed to add mapped key", "fqn", fqn, "kas", kasURI, "error", err) + } + } + continue + } ks := g.GetPublicKey().GetCached().GetKeys() if len(ks) == 0 { slog.Debug("no cached key in policy service", "kas", kasURI, "value", fqn) @@ -314,9 +345,6 @@ func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr * } } } - if ag.GetKasKeys() != nil && len(ag.GetKasKeys()) > 0 { - r.typ |= mappedFound - } if ok == noKeysFound { if _, present := r.grantTable[fqn.key]; !present { r.grantTable[fqn.key] = &keyAccessGrant{attr, []string{}} diff --git a/sdk/tdf.go b/sdk/tdf.go index 348e1dd377..98d32b5e5e 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -17,6 +17,7 @@ import ( "connectrpc.com/connect" "github.com/Masterminds/semver/v3" "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/google/uuid" @@ -184,6 +185,9 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, errors.New("cannot set autoconfigure and splitPlan or kaoTemplate") } + // * Get base key before autoconfigure to condition off of. + baseKey, baseKeyErr := getBaseKeyFromWellKnown(ctx, s) + isPlatformPre205 := errors.Is(baseKeyErr, errBaseKeyNotFound) if tdfConfig.autoconfigure { var g granter g, err = s.newGranter(ctx, tdfConfig, err) @@ -193,7 +197,10 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R if g.typ&mappedFound == mappedFound { tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) - } else if (g.typ == noKeysFound || g.typ == grantsFound) && !tdfConfig.isBaseKeyEnabled { + } else if g.typ&grantsFound == grantsFound { + tdfConfig.kaoTemplate = nil + tdfConfig.splitPlan, err = g.plan(make([]string, 0), uuidSplitIDGenerator) + } else if g.typ&noKeysFound == noKeysFound && isPlatformPre205 { dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) @@ -203,11 +210,20 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R } } - // * Expresses the use case where no attributes were passed in or found. - // * Replaces the defaultKases behavior. - if tdfConfig.isBaseKeyEnabled && len(tdfConfig.kaoTemplate) == 0 { - err = populateKasInfoFromBaseKey(ctx, s, tdfConfig) - if err != nil { + // * Expresses the use case where no grants or mappings were found, + // * and if the intended behavior of noKeyFound is to use the base + // * key or the default KAS. + // ! This is implicitly derived from whether or not the base_key + // ! k/v pair is present in the well-known configuration. + // ! The presence of the var means that we are at least using + // ! v2.0.5 of the platform. + if len(tdfConfig.kaoTemplate) == 0 && len(tdfConfig.splitPlan) == 0 && !isPlatformPre205 { + if baseKeyErr != nil { + return nil, err + } + + err = populateKasInfoFromBaseKey(baseKey, tdfConfig) + if err != nil && !errors.Is(err, errBaseKeyNotFound) { return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) } } @@ -1427,14 +1443,18 @@ func isLessThanSemver(version, target string) (bool, error) { return v1.LessThan(v2), nil } -func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig) error { - if len(tdfConfig.kasInfoList) > 0 { - return errors.New("base key is enabled, but kasInfoList is not empty") - } - // Get base key from the well-known configuration +func getBaseKeyFromWellKnown(ctx context.Context, s SDK) (*policy.SimpleKasKey, error) { key, err := getBaseKey(ctx, s) if err != nil { - return fmt.Errorf("failed to get base key: %w", err) + return nil, err + } + + return key, nil +} + +func populateKasInfoFromBaseKey(key *policy.SimpleKasKey, tdfConfig *TDFConfig) error { + if key == nil { + return fmt.Errorf("populateKasInfoFromBaseKey failed: key is nil") } algoString, err := formatAlg(key.GetPublicKey().GetAlgorithm()) @@ -1448,6 +1468,9 @@ func populateKasInfoFromBaseKey(ctx context.Context, s SDK, tdfConfig *TDFConfig } tdfConfig.keyType = ocrypto.KeyType(algoString) tdfConfig.splitPlan = nil + if len(tdfConfig.kasInfoList) > 0 { + slog.Warn("Base key is enabled, overwriting kasInfoList with base key info") + } tdfConfig.kasInfoList = []KASInfo{ { URL: key.GetKasUri(), diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index c9cc76c864..30535ec115 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -80,7 +80,6 @@ type TDFConfig struct { keyType ocrypto.KeyType useHex bool excludeVersionFromManifest bool - isBaseKeyEnabled bool } func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { @@ -92,7 +91,6 @@ func newTDFConfig(opt ...TDFOption) (*TDFConfig, error) { integrityAlgorithm: HS256, segmentIntegrityAlgorithm: GMAC, keyType: ocrypto.RSA2048Key, // default to RSA - isBaseKeyEnabled: false, } for _, o := range opt { @@ -268,13 +266,6 @@ func WithTargetMode(mode string) TDFOption { } } -func WithBaseKeyEnabled() TDFOption { - return func(c *TDFConfig) error { - c.isBaseKeyEnabled = true - return nil - } -} - // Schema Validation where 0 = none (skip), 1 = lax (allowing novel entries, 'falsy' values for unkowns), 2 = strict (rejecting novel entries, strict match to manifest schema) type SchemaValidationIntensity int diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index 00d576757b..e03247bd6b 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -310,12 +310,12 @@ func (s *TDFSuite) SetupSuite() { // Set up the test environment s.startBackend() // Update well-known with the server URL - baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, s.kasTestURLLookup[baseKeyURL]) - s.fakeWellKnown = createWellKnown(baseKey) + s.fakeWellKnown = createWellKnown(nil) } func (s *TDFSuite) SetupTest() { s.sdk.kasKeyCache.clear() + s.fakeWellKnown = createWellKnown(nil) } func TestTDF(t *testing.T) { @@ -1563,7 +1563,7 @@ func (s *TDFSuite) Test_ValidateSchema() { } } -func (s *TDFSuite) Test_TDF() { +func (s *TDFSuite) Test_DefaultTDF() { for index, test := range []tdfTest{ { n: "small", @@ -1620,7 +1620,9 @@ func (s *TDFSuite) Test_TDF() { } } -func (s *TDFSuite) Test_EncryptWithBaseKey() { +func (s *TDFSuite) Test_MixedBaseKeyTest() { + baseKey := createTestBaseKeyMap(&s.Suite, policy.Algorithm_ALGORITHM_RSA_2048, baseKeyKID, mockRSAPublicKey1, s.kasTestURLLookup[baseKeyURL]) + s.fakeWellKnown = createWellKnown(baseKey) attrVal := mockValueFor(rel2aus) cachedPublicKeySet := &policy.KasPublicKeySet{ Keys: []*policy.KasPublicKey{ @@ -1659,7 +1661,7 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { tdfFileSize: 104866427, checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", }, - encryptOpts: []TDFOption{WithBaseKeyEnabled()}, + encryptOpts: []TDFOption{}, expectedKID: baseKeyKID, expectedURL: s.kasTestURLLookup[baseKeyURL], }, @@ -1670,7 +1672,7 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { tdfFileSize: 104866427, checksum: "cee41e98d0a6ad65cc0ec77a2ba50bf26d64dc9007f7f1c7d7df68b8b71291a6", }, - encryptOpts: []TDFOption{WithDataAttributeValues(attrVal), WithBaseKeyEnabled()}, + encryptOpts: []TDFOption{WithDataAttributeValues(attrVal)}, expectedKID: defaultKID, expectedURL: s.kasTestURLLookup[kasAu], }, @@ -1696,8 +1698,6 @@ func (s *TDFSuite) Test_EncryptWithBaseKey() { } } -// Need another test for when base key is enabled but attributes are provided, so a split plan is created. - func (s *TDFSuite) Test_KeyRotation() { for index, test := range []tdfTest{ { @@ -1853,14 +1853,22 @@ func (s *TDFSuite) Test_Autoconfigure() { } func (s *TDFSuite) Test_PopulateBaseKey_Success() { - ctx := s.T().Context() tdfConfig := &TDFConfig{ keyType: ocrypto.RSA2048Key, kasInfoList: []KASInfo{}, } + baseKey := policy.SimpleKasKey{ + KasUri: s.kasTestURLLookup[baseKeyURL], + PublicKey: &policy.SimpleKasPublicKey{ + Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + Kid: baseKeyKID, + Pem: mockRSAPublicKey1, + }, + } + // Call populateBaseKey, should succeed - err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) + err := populateKasInfoFromBaseKey(&baseKey, tdfConfig) s.Require().NoError(err, "populateBaseKey should succeed with valid base key") expectedURL := s.kasTestURLLookup[baseKeyURL] @@ -1875,25 +1883,6 @@ func (s *TDFSuite) Test_PopulateBaseKey_Success() { s.Require().Equal(ocrypto.KeyType("rsa:2048"), tdfConfig.keyType, "Key type should be set") } -func (s *TDFSuite) Test_PopulateBaseKey_KasInfoPassIn_Fail() { - ctx := s.T().Context() - tdfConfig := &TDFConfig{ - keyType: ocrypto.RSA2048Key, - kasInfoList: []KASInfo{ - { - URL: "http://localhost:65432/", - KID: baseKeyKID, - Algorithm: string(ocrypto.RSA2048Key), - PublicKey: mockRSAPublicKey1, - }, - }, - } - - // Call populateBaseKey, should succeed - err := populateKasInfoFromBaseKey(ctx, *s.sdk, tdfConfig) - s.Require().ErrorContains(err, "base key is enabled, but kasInfoList is not empty") -} - func rotateKey(k *FakeKas, kid, private, public string) func() { old := *k k.privateKey = private @@ -2024,16 +2013,21 @@ func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { } func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { - // Create a stub for wellknown - return map[string]interface{}{ + wellKnown := map[string]interface{}{ "health": map[string]interface{}{ "endpoint": "/healthz", }, "idp": map[string]interface{}{ "issuer": "http://localhost:65432/auth", }, - "base_key": baseKey, } + + if baseKey != nil { + wellKnown[baseKeyWellKnown] = baseKey + } + + // Create a stub for wellknown + return wellKnown } func (s *TDFSuite) startBackend() { From c00a90f104814bec82503bdd1cc833d184aa5a45 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 13:11:45 -0500 Subject: [PATCH 25/30] refactor. --- sdk/tdf.go | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/sdk/tdf.go b/sdk/tdf.go index 98d32b5e5e..25b35b5984 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -178,7 +178,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R // - autoconfigure is true // - splitPlan is set // - kaoTemplate is set - if len(tdfConfig.splitPlan) > 0 && len(tdfConfig.kaoTemplate) > 0 { + if len(tdfConfig.splitPlan) > 0 && len(tdfConfig.kaoTemplate) > 0 { //nolint:nestif // refactor when grants are removed return nil, errors.New("cannot set both splitPlan and kaoTemplate") } if tdfConfig.autoconfigure && (len(tdfConfig.splitPlan) > 0 || len(tdfConfig.kaoTemplate) > 0) { @@ -195,39 +195,30 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } - if g.typ&mappedFound == mappedFound { + switch { + case g.typ&mappedFound == mappedFound: tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) - } else if g.typ&grantsFound == grantsFound { + case g.typ&grantsFound == grantsFound: tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(make([]string, 0), uuidSplitIDGenerator) - } else if g.typ&noKeysFound == noKeysFound && isPlatformPre205 { - dk := s.defaultKases(tdfConfig) - tdfConfig.kaoTemplate = nil - tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) + case g.typ == noKeysFound: + if isPlatformPre205 { + dk := s.defaultKases(tdfConfig) + tdfConfig.kaoTemplate = nil + tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) + } else { + if baseKeyErr != nil { + return nil, err + } + + err = populateKasInfoFromBaseKey(baseKey, tdfConfig) + } } if err != nil { return nil, fmt.Errorf("failed generate plan: %w", err) } } - // * Expresses the use case where no grants or mappings were found, - // * and if the intended behavior of noKeyFound is to use the base - // * key or the default KAS. - // ! This is implicitly derived from whether or not the base_key - // ! k/v pair is present in the well-known configuration. - // ! The presence of the var means that we are at least using - // ! v2.0.5 of the platform. - if len(tdfConfig.kaoTemplate) == 0 && len(tdfConfig.splitPlan) == 0 && !isPlatformPre205 { - if baseKeyErr != nil { - return nil, err - } - - err = populateKasInfoFromBaseKey(baseKey, tdfConfig) - if err != nil && !errors.Is(err, errBaseKeyNotFound) { - return nil, fmt.Errorf("populateKasInfoFromBaseKey failed: %w", err) - } - } - tdfObject := &TDFObject{} err = s.prepareManifest(ctx, tdfObject, *tdfConfig) if err != nil { @@ -1454,7 +1445,7 @@ func getBaseKeyFromWellKnown(ctx context.Context, s SDK) (*policy.SimpleKasKey, func populateKasInfoFromBaseKey(key *policy.SimpleKasKey, tdfConfig *TDFConfig) error { if key == nil { - return fmt.Errorf("populateKasInfoFromBaseKey failed: key is nil") + return errors.New("populateKasInfoFromBaseKey failed: key is nil") } algoString, err := formatAlg(key.GetPublicKey().GetAlgorithm()) From 5ed7eb6e583b70afa28b0c151d7cee0a54979a30 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 13:15:18 -0500 Subject: [PATCH 26/30] refactor. --- sdk/tdf.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/tdf.go b/sdk/tdf.go index 25b35b5984..5d7551538a 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -178,7 +178,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R // - autoconfigure is true // - splitPlan is set // - kaoTemplate is set - if len(tdfConfig.splitPlan) > 0 && len(tdfConfig.kaoTemplate) > 0 { //nolint:nestif // refactor when grants are removed + if len(tdfConfig.splitPlan) > 0 && len(tdfConfig.kaoTemplate) > 0 { return nil, errors.New("cannot set both splitPlan and kaoTemplate") } if tdfConfig.autoconfigure && (len(tdfConfig.splitPlan) > 0 || len(tdfConfig.kaoTemplate) > 0) { @@ -188,7 +188,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R // * Get base key before autoconfigure to condition off of. baseKey, baseKeyErr := getBaseKeyFromWellKnown(ctx, s) isPlatformPre205 := errors.Is(baseKeyErr, errBaseKeyNotFound) - if tdfConfig.autoconfigure { + if tdfConfig.autoconfigure { //nolint:nestif // refactor when grants are removed var g granter g, err = s.newGranter(ctx, tdfConfig, err) if err != nil { From c5922f330901ada7eb8e7b3fa36fdd22e5ffefad Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 13:41:39 -0500 Subject: [PATCH 27/30] update. --- sdk/tdf.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sdk/tdf.go b/sdk/tdf.go index 5d7551538a..25b97b76ed 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -186,10 +186,9 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R } // * Get base key before autoconfigure to condition off of. - baseKey, baseKeyErr := getBaseKeyFromWellKnown(ctx, s) - isPlatformPre205 := errors.Is(baseKeyErr, errBaseKeyNotFound) - if tdfConfig.autoconfigure { //nolint:nestif // refactor when grants are removed + if tdfConfig.autoconfigure { var g granter + var err error g, err = s.newGranter(ctx, tdfConfig, err) if err != nil { return nil, err @@ -202,16 +201,14 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(make([]string, 0), uuidSplitIDGenerator) case g.typ == noKeysFound: - if isPlatformPre205 { + var baseKey *policy.SimpleKasKey + baseKey, err = getBaseKeyFromWellKnown(ctx, s) + if err == nil { + err = populateKasInfoFromBaseKey(baseKey, tdfConfig) + } else { dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator) - } else { - if baseKeyErr != nil { - return nil, err - } - - err = populateKasInfoFromBaseKey(baseKey, tdfConfig) } } if err != nil { From c3c5d17fecfde0dd93821de97c5e5285209ec9b2 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 15:00:59 -0500 Subject: [PATCH 28/30] update to enum. --- sdk/granter.go | 34 ++++++++++++++++++---------------- sdk/tdf.go | 8 ++++---- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/sdk/granter.go b/sdk/granter.go index 6b8226d2e4..469b1bf535 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -203,7 +203,7 @@ type granter struct { mapTable map[string][]*ResourceLocator // The types of grants or mapped keys found. - typ grantTypeMask + typ grantType } type keyAccessGrant struct { @@ -265,12 +265,12 @@ func convertAlgEnum2Simple(a policy.KasPublicKeyAlgEnum) policy.Algorithm { } } -type grantTypeMask int +type grantType int const ( - noKeysFound grantTypeMask = 0 - grantsFound = 1 << iota - mappedFound + noKeysFound grantType = iota // No keys found + grantsFound // Only grants found + mappedFound // Only mapped keys found ) type grantableObject interface { @@ -279,17 +279,19 @@ type grantableObject interface { } // addAllGrants adds all grants from a list of KASes to the granter. -// It returns a mask indicating whether grants or mapped keys were found. -func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr *policy.Attribute) grantTypeMask { - ok := noKeysFound +// It returns an enum value indicating what types of keys were found. +func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr *policy.Attribute) grantType { + result := noKeysFound + + // Check for mapped keys for _, k := range ag.GetKasKeys() { if k == nil || k.GetKasUri() == "" { slog.Debug("invalid KAS key in policy service", "simpleKasKey", k, "value", fqn) continue } kasURI := k.GetKasUri() - r.typ |= mappedFound - ok |= mappedFound + r.typ = mappedFound + result = r.typ err := r.addMappedKey(fqn, k) if err != nil { slog.Debug("failed to add mapped key", "fqn", fqn, "kas", kasURI, "error", err) @@ -300,15 +302,15 @@ func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr * r.grantTable[fqn.key].kases = append(r.grantTable[fqn.key].kases, kasURI) } } - if ok != noKeysFound { - return ok + if result != noKeysFound { + return result } for _, g := range ag.GetGrants() { if g != nil && g.GetUri() != "" { //nolint:nestif // Simplify after grant removal kasURI := g.GetUri() - r.typ |= grantsFound - ok |= grantsFound + r.typ = grantsFound + result = grantsFound r.addGrant(fqn, kasURI, attr) if len(g.GetKasKeys()) != 0 { for _, k := range g.GetKasKeys() { @@ -345,12 +347,12 @@ func (r *granter) addAllGrants(fqn AttributeValueFQN, ag grantableObject, attr * } } } - if ok == noKeysFound { + if result == noKeysFound { if _, present := r.grantTable[fqn.key]; !present { r.grantTable[fqn.key] = &keyAccessGrant{attr, []string{}} } } - return ok + return result } func (r granter) byAttribute(fqn AttributeValueFQN) *keyAccessGrant { diff --git a/sdk/tdf.go b/sdk/tdf.go index 25b97b76ed..e34ba84112 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -194,13 +194,13 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, err } - switch { - case g.typ&mappedFound == mappedFound: + switch g.typ { + case mappedFound: tdfConfig.kaoTemplate, err = g.resolveTemplate(uuidSplitIDGenerator) - case g.typ&grantsFound == grantsFound: + case grantsFound: tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(make([]string, 0), uuidSplitIDGenerator) - case g.typ == noKeysFound: + case noKeysFound: var baseKey *policy.SimpleKasKey baseKey, err = getBaseKeyFromWellKnown(ctx, s) if err == nil { From 8d768739cfc28241bb869f2488d964a6fa9d385f Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Mon, 16 Jun 2025 15:07:38 -0500 Subject: [PATCH 29/30] linting --- sdk/granter.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/granter.go b/sdk/granter.go index 469b1bf535..1773345794 100644 --- a/sdk/granter.go +++ b/sdk/granter.go @@ -391,18 +391,18 @@ func newGranterFromService(ctx context.Context, keyCache *kasKeyCache, as sdkcon storeKeysToCache(def.GetGrants(), keyCache) } v := pair.GetValue() - grantType := noKeysFound + gType := noKeysFound if v != nil { - grantType |= grants.addAllGrants(fqn, v, def) + gType = grants.addAllGrants(fqn, v, def) storeKeysToCache(v.GetGrants(), keyCache) } // If no more specific grant was found, then add the value grants - if grantType == noKeysFound && def != nil { - grantType |= grants.addAllGrants(fqn, def, def) + if gType == noKeysFound && def != nil { + gType = grants.addAllGrants(fqn, def, def) storeKeysToCache(def.GetGrants(), keyCache) } - if grantType == noKeysFound && def.GetNamespace() != nil { + if gType == noKeysFound && def.GetNamespace() != nil { grants.addAllGrants(fqn, def.GetNamespace(), def) storeKeysToCache(def.GetNamespace().GetGrants(), keyCache) } From 347caa827cd51147f3f254bffb101d2ca5866ca8 Mon Sep 17 00:00:00 2001 From: Chris Reed Date: Tue, 17 Jun 2025 12:41:13 -0500 Subject: [PATCH 30/30] fix issues with nano. --- sdk/nanotdf.go | 38 +++++++++++++++++++----------- sdk/nanotdf_config.go | 28 ++++++++-------------- sdk/nanotdf_test.go | 54 +++++++++++++++++-------------------------- sdk/tdf.go | 1 + 4 files changed, 56 insertions(+), 65 deletions(-) diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index 90dfd13333..ef73743fcc 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -1094,22 +1094,18 @@ func createNanoTDFSymmetricKey(config NanoTDFConfig) ([]byte, error) { } func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { - if config.isBaseKeyEnabled { - ki, err := getNanoKasInfoFromBaseKey(s) - if err != nil { - return nil, err - } - err = config.kasURL.setURLWithIdentifier(ki.URL, ki.KID) - if err != nil { - return nil, fmt.Errorf("config.kasURL setURLWithIdentifier failed:%w", err) - } - config.bindCfg.eccMode, err = ocrypto.ECKeyTypeToMode(ocrypto.KeyType(ki.Algorithm)) - if err != nil { - return nil, fmt.Errorf("ocrypto.ECKeyTypeToMode failed: %w", err) + var err error + // * Attempt to use base key if present and ECC. + ki, err := getNanoKasInfoFromBaseKey(s) + if err == nil { + err = updateConfigWithBaseKey(ki, config) + if err == nil { + return ki, nil } - return ki, nil } + slog.Debug("getNanoKasInfoFromBaseKey failed, falling back to default kas", slog.String("error", err.Error())) + kasURL, err := config.kasURL.GetURL() if err != nil { return nil, fmt.Errorf("config.kasURL failed:%w", err) @@ -1117,7 +1113,7 @@ func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { if kasURL == "https://" || kasURL == "http://" { return nil, errors.New("config.kasUrl is empty") } - ki, err := s.getPublicKey(context.Background(), kasURL, config.bindCfg.eccMode.String()) + ki, err = s.getPublicKey(context.Background(), kasURL, config.bindCfg.eccMode.String()) if err != nil { return nil, fmt.Errorf("getECPublicKey failed:%w", err) } @@ -1133,6 +1129,20 @@ func getKasInfoForNanoTDF(s *SDK, config *NanoTDFConfig) (*KASInfo, error) { return ki, nil } +func updateConfigWithBaseKey(ki *KASInfo, config *NanoTDFConfig) error { + ecMode, err := ocrypto.ECKeyTypeToMode(ocrypto.KeyType(ki.Algorithm)) + if err != nil { + return fmt.Errorf("ocrypto.ECKeyTypeToMode failed: %w", err) + } + err = config.kasURL.setURLWithIdentifier(ki.URL, ki.KID) + if err != nil { + return fmt.Errorf("config.kasURL setURLWithIdentifier failed: %w", err) + } + config.bindCfg.eccMode = ecMode + + return nil +} + func getNanoKasInfoFromBaseKey(s *SDK) (*KASInfo, error) { baseKey, err := getBaseKey(context.Background(), *s) if err != nil { diff --git a/sdk/nanotdf_config.go b/sdk/nanotdf_config.go index f0e037dedd..5efde5663d 100644 --- a/sdk/nanotdf_config.go +++ b/sdk/nanotdf_config.go @@ -17,17 +17,16 @@ import ( // ============================================================================================================ type NanoTDFConfig struct { - keyPair ocrypto.ECKeyPair - kasPublicKey *ecdh.PublicKey - attributes []AttributeValueFQN - cipher CipherMode - kasURL ResourceLocator - sigCfg signatureConfig - policy policyInfo - bindCfg bindingConfig - collectionCfg *collectionConfig - policyMode PolicyType // Added field for policy mode - isBaseKeyEnabled bool // Added field to enable base key usage + keyPair ocrypto.ECKeyPair + kasPublicKey *ecdh.PublicKey + attributes []AttributeValueFQN + cipher CipherMode + kasURL ResourceLocator + sigCfg signatureConfig + policy policyInfo + bindCfg bindingConfig + collectionCfg *collectionConfig + policyMode PolicyType // Added field for policy mode } type NanoTDFOption func(*NanoTDFConfig) error @@ -101,13 +100,6 @@ func (config *NanoTDFConfig) SetPolicyMode(mode PolicyType) error { return nil } -// * Set that the sdk should use the base key when no attributes are present. -// ! Enabling this option will cause the SDK to ignore any KAS information passed in -// ! and instead use the base key from the well-known configuration. -func (config *NanoTDFConfig) EnableBaseKey() { - config.isBaseKeyEnabled = true -} - // WithNanoDataAttributes appends the given data attributes to the bound policy func WithNanoDataAttributes(attributes ...string) NanoTDFOption { return func(c *NanoTDFConfig) error { diff --git a/sdk/nanotdf_test.go b/sdk/nanotdf_test.go index 9f0566cad9..f13a349779 100644 --- a/sdk/nanotdf_test.go +++ b/sdk/nanotdf_test.go @@ -437,7 +437,6 @@ func (s *NanoSuite) Test_CreateNanoTDF_BaseKey() { config, err := sdk.NewNanoTDFConfig() s.Require().NoError(err) - config.EnableBaseKey() err = config.SetKasURL("http://should-change.com") s.Require().NoError(err) @@ -456,7 +455,6 @@ func (s *NanoSuite) Test_CreateNanoTDF_BaseKey() { func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { tests := []struct { name string - baseKeyEnabled bool algorithm policy.Algorithm kasURI string publicKeyPem string @@ -466,12 +464,11 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { expectedError string }{ { - name: "Base Key Enabled - EC P256 - Success", - baseKeyEnabled: true, - algorithm: policy.Algorithm_ALGORITHM_EC_P256, - kasURI: "https://kas.example.com", - publicKeyPem: nanoFakePem, - kid: "key-p256", + name: "Base Key Enabled - EC P256 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P256, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p256", expectedInfo: &KASInfo{ URL: "https://kas.example.com", PublicKey: nanoFakePem, @@ -480,12 +477,11 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { }, }, { - name: "Base Key Enabled - EC P384 - Success", - baseKeyEnabled: true, - algorithm: policy.Algorithm_ALGORITHM_EC_P384, - kasURI: "https://kas.example.com", - publicKeyPem: nanoFakePem, - kid: "key-p384", + name: "Base Key Enabled - EC P384 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P384, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p384", expectedInfo: &KASInfo{ URL: "https://kas.example.com", PublicKey: nanoFakePem, @@ -494,12 +490,11 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { }, }, { - name: "Base Key Enabled - EC P521 - Success", - baseKeyEnabled: true, - algorithm: policy.Algorithm_ALGORITHM_EC_P521, - kasURI: "https://kas.example.com", - publicKeyPem: nanoFakePem, - kid: "key-p521", + name: "Base Key Enabled - EC P521 - Success", + algorithm: policy.Algorithm_ALGORITHM_EC_P521, + kasURI: "https://kas.example.com", + publicKeyPem: nanoFakePem, + kid: "key-p521", expectedInfo: &KASInfo{ URL: "https://kas.example.com", PublicKey: nanoFakePem, @@ -507,15 +502,6 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { Algorithm: "ec:secp521r1", }, }, - { - name: "Base Key Enabled - Unsupported algorithm RSA 2048", - baseKeyEnabled: true, - algorithm: policy.Algorithm_ALGORITHM_RSA_2048, - kasURI: "https://kas.example.com", - publicKeyPem: nanoFakePem, - kid: "key-rsa", - expectedError: "base key algorithm is not supported for nano", - }, } for _, tt := range tests { @@ -532,9 +518,12 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { // Create a NanoTDFConfig config := NanoTDFConfig{ - isBaseKeyEnabled: tt.baseKeyEnabled, + bindCfg: bindingConfig{ + eccMode: ocrypto.ECCModeSecp384r1, + }, } - err := config.SetKasURL("http://should-change.com") + kasURL := "https://should-not-change.com" + err := config.SetKasURL(kasURL) s.Require().NoError(err) // Call the getKasInfoForNanoTDF function @@ -543,7 +532,6 @@ func (s *NanoSuite) Test_GetKasInfoForNanoTDF_BaseKey() { // Check for expected errors if tt.expectedError != "" { s.Require().Error(err) - s.Require().Contains(err.Error(), tt.expectedError) s.Require().Nil(info) return } @@ -627,7 +615,7 @@ func (s *NanoSuite) Test_PopulateNanoBaseKeyWithMockWellKnown() { { name: "Unsupported algorithm RSA 2048", algorithm: policy.Algorithm_ALGORITHM_RSA_2048, - kasURI: "https://kas.example.com", + kasURI: "https://localhost:8080", publicKeyPem: nanoFakePem, kid: "key-rsa", expectedError: "base key algorithm is not supported for nano", diff --git a/sdk/tdf.go b/sdk/tdf.go index e34ba84112..2d311fbe65 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -206,6 +206,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R if err == nil { err = populateKasInfoFromBaseKey(baseKey, tdfConfig) } else { + slog.Debug("Error getting base key, falling back to default kas.", "error", err) dk := s.defaultKases(tdfConfig) tdfConfig.kaoTemplate = nil tdfConfig.splitPlan, err = g.plan(dk, uuidSplitIDGenerator)