diff --git a/examples/cmd/encrypt.go b/examples/cmd/encrypt.go index ada8585f79..5ae768c23e 100644 --- a/examples/cmd/encrypt.go +++ b/examples/cmd/encrypt.go @@ -110,7 +110,7 @@ func encrypt(cmd *cobra.Command, args []string) error { if err != nil { return err } - opts = append(opts, sdk.WithWrappingKeyAlg(kt)) + opts = append(opts, sdk.WithWrappingKeyAlg(kt)) //nolint:staticcheck // Example code demonstrating legacy API usage } tdf, err := client.CreateTDF(out, in, opts...) if err != nil { diff --git a/examples/cmd/examples.go b/examples/cmd/examples.go index 32d7f403a3..5e83f5a034 100644 --- a/examples/cmd/examples.go +++ b/examples/cmd/examples.go @@ -56,7 +56,7 @@ func newSDK() (*sdk.SDK, error) { opts = append(opts, sdk.WithClientCredentials(clientCredentials[:i], clientCredentials[i+1:], nil)) } if tokenEndpoint != "" { - opts = append(opts, sdk.WithTokenEndpoint(tokenEndpoint)) + opts = append(opts, sdk.WithTokenEndpoint(tokenEndpoint)) //nolint:staticcheck // Example code demonstrating legacy API usage } if noKIDInKAO { opts = append(opts, sdk.WithNoKIDInKAO()) diff --git a/lib/ocrypto/asym_encryption.go b/lib/ocrypto/asym_encryption.go index b0136ddb45..c44aa64cce 100644 --- a/lib/ocrypto/asym_encryption.go +++ b/lib/ocrypto/asym_encryption.go @@ -98,6 +98,7 @@ func newECIES(pub *ecdh.PublicKey, salt, info []byte) (ECEncryptor, error) { } // NewAsymEncryption creates and returns a new AsymEncryption. +// // Deprecated: Use FromPublicPEM instead. func NewAsymEncryption(publicKeyInPem string) (AsymEncryption, error) { pub, err := getPublicPart(publicKeyInPem) diff --git a/lib/ocrypto/interfaces.go b/lib/ocrypto/interfaces.go index b9d74ae18d..fbdac0c325 100644 --- a/lib/ocrypto/interfaces.go +++ b/lib/ocrypto/interfaces.go @@ -27,6 +27,7 @@ type ProtectedKey interface { VerifyBinding(ctx context.Context, policy, policyBinding []byte) error // Export returns the raw key data, optionally encrypting it with the provided encapsulator + // // Deprecated: Use the Encapsulator's Encapsulate method instead Export(encapsulator Encapsulator) ([]byte, error) diff --git a/lib/ocrypto/protected_key.go b/lib/ocrypto/protected_key.go index e885a67b55..6cd128b617 100644 --- a/lib/ocrypto/protected_key.go +++ b/lib/ocrypto/protected_key.go @@ -55,6 +55,7 @@ func (k *AESProtectedKey) DecryptAESGCM(iv []byte, body []byte, tagSize int) ([] } // Export returns the raw key data, optionally encrypting it with the provided Encapsulator +// // Deprecated: Use the Encapsulator's Encapsulate method instead func (k *AESProtectedKey) Export(encapsulator Encapsulator) ([]byte, error) { if encapsulator == nil { diff --git a/sdk/codegen/runner/generate.go b/sdk/codegen/runner/generate.go index 5d663cb051..87b945f0b0 100644 --- a/sdk/codegen/runner/generate.go +++ b/sdk/codegen/runner/generate.go @@ -7,6 +7,7 @@ import ( "os" "path" "path/filepath" + "strings" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -120,7 +121,8 @@ func generateWrapper(interfaceName string, interfaceType *ast.InterfaceType, pac connectPackageName := packageName + "connect" // Start generating the wrapper code - wrapperCode := fmt.Sprintf(`// Wrapper for %s%s (generated code) DO NOT EDIT + var wrapperCode strings.Builder + wrapperCode.WriteString(fmt.Sprintf(`// Wrapper for %s%s (generated code) DO NOT EDIT package sdkconnect import ( @@ -158,30 +160,31 @@ func New%s%s%sConnectWrapper(httpClient connect.HTTPClient, baseURL string, opts suffix, interfaceName, connectPackageName, - interfaceName) + interfaceName)) // Generate the interface type definition - wrapperCode += generateInterfaceType(interfaceName, methods, packageName, prefix, suffix) + wrapperCode.WriteString(generateInterfaceType(interfaceName, methods, packageName, prefix, suffix)) // Now generate a wrapper function for each method in the interface for _, method := range methods { - wrapperCode += generateWrapperMethod(interfaceName, method, packageName, prefix, suffix) + wrapperCode.WriteString(generateWrapperMethod(interfaceName, method, packageName, prefix, suffix)) } // Output the generated wrapper code - return wrapperCode + return wrapperCode.String() } func generateInterfaceType(interfaceName string, methods []string, packageName, prefix, suffix string) string { // Generate the interface type definition - interfaceType := fmt.Sprintf(` + var interfaceType strings.Builder + interfaceType.WriteString(fmt.Sprintf(` type %s%s%s interface { -`, prefix, interfaceName, suffix) +`, prefix, interfaceName, suffix)) for _, method := range methods { - interfaceType += fmt.Sprintf(` %s(ctx context.Context, req *%s.%sRequest) (*%s.%sResponse, error) -`, method, packageName, method, packageName, method) + interfaceType.WriteString(fmt.Sprintf(` %s(ctx context.Context, req *%s.%sRequest) (*%s.%sResponse, error) +`, method, packageName, method, packageName, method)) } - interfaceType += "}\n" - return interfaceType + interfaceType.WriteString("}\n") + return interfaceType.String() } // Generate the wrapper method for a specific method in the interface diff --git a/sdk/granter_test.go b/sdk/granter_test.go index a47c7d6a57..07abcda17d 100644 --- a/sdk/granter_test.go +++ b/sdk/granter_test.go @@ -163,7 +163,7 @@ func mockAttributeFor(fqn AttributeNameFQN) *policy.Attribute { case MP.key: g := make([]*policy.KeyAccessServer, 1) g[0] = mockGrant(specifiedKas, "r1") - g[0].PublicKey = createPublicKey("r1", mockRSAPublicKey1, policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048) + g[0].PublicKey = createPublicKey("r1", mockRSAPublicKey1, policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048) //nolint:staticcheck // Using deprecated field for test compatibility with legacy protocol return &policy.Attribute{ Id: "MP", Namespace: &nsOne, diff --git a/sdk/internal/zipstream/crc32combine_test.go b/sdk/internal/zipstream/crc32combine_test.go index fe7eca1ad2..5b162089ab 100644 --- a/sdk/internal/zipstream/crc32combine_test.go +++ b/sdk/internal/zipstream/crc32combine_test.go @@ -4,16 +4,16 @@ package zipstream import ( "hash/crc32" - "math/rand" + "math/rand/v2" "testing" ) func TestCRC32CombineIEEE_Basic(t *testing.T) { - rand.Seed(42) + rng := rand.NewChaCha8([32]byte{42}) a := make([]byte, 1024) b := make([]byte, 2048) - rand.Read(a) - rand.Read(b) + _, _ = rng.Read(a) + _, _ = rng.Read(b) crcA := crc32.ChecksumIEEE(a) crcB := crc32.ChecksumIEEE(b) @@ -28,12 +28,12 @@ func TestCRC32CombineIEEE_Basic(t *testing.T) { } func TestCRC32CombineIEEE_MultiChunks(t *testing.T) { - rand.Seed(42) + rng := rand.NewChaCha8([32]byte{42}) chunks := make([][]byte, 10) for i := range chunks { - n := 1 + rand.Intn(8192) + n := 1 + int(rng.Uint64()%8192) chunks[i] = make([]byte, n) - rand.Read(chunks[i]) + _, _ = rng.Read(chunks[i]) } // Combine sequentially diff --git a/sdk/internal/zipstream/segment_writer_test.go b/sdk/internal/zipstream/segment_writer_test.go index 8636778fc5..f60c1f27c8 100644 --- a/sdk/internal/zipstream/segment_writer_test.go +++ b/sdk/internal/zipstream/segment_writer_test.go @@ -426,12 +426,14 @@ func TestSegmentWriter_LargeNumberOfSegments(t *testing.T) { // Store in logical order for final assembly if i == 0 { + //nolint:staticcheck // SA4010: simplified test code, result intentionally unused allBytes = append([]byte{}, bytes...) // Segment 0 goes first for j := 1; j < segmentCount; j++ { allBytes = append(allBytes, make([]byte, 0)...) // Placeholder } } else { // This is simplified - in practice you'd need proper ordering + //nolint:staticcheck // SA4010: simplified test code, result intentionally unused allBytes = append(allBytes, bytes...) } } diff --git a/sdk/kas_client_test.go b/sdk/kas_client_test.go index e1f0ecd8c8..bd52ba9013 100644 --- a/sdk/kas_client_test.go +++ b/sdk/kas_client_test.go @@ -46,6 +46,7 @@ func getTokenSource(t *testing.T) FakeAccessTokenSource { dpopPEM, _ := dpopKey.PrivateKeyInPemFormat() decryption, _ := ocrypto.NewAsymDecryption(dpopPEM) dpopPEMPublic, _ := dpopKey.PublicKeyInPemFormat() + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code encryption, _ := ocrypto.NewAsymEncryption(dpopPEMPublic) dpopJWK, err := jwk.ParseKey([]byte(dpopPEM), jwk.WithPEM(true)) if err != nil { @@ -115,6 +116,7 @@ func TestCreatingRequest(t *testing.T) { require.NoError(t, protojson.Unmarshal([]byte(requestBodyJSON), &requestBody), "error unmarshaling request body") + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code _, err = ocrypto.NewAsymEncryption(requestBody.GetClientPublicKey()) require.NoError(t, err, "NewAsymEncryption failed, incorrect public key include") @@ -465,6 +467,7 @@ func Test_processRSAResponse(t *testing.T) { // Create a mock AsymEncryption to create the wrapped key publicKeyPEM, err := mockPrivateKey.PublicKeyInPemFormat() require.NoError(t, err) + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code mockEncryptor, err := ocrypto.NewAsymEncryption(publicKeyPEM) require.NoError(t, err) diff --git a/sdk/options.go b/sdk/options.go index df36a7a9f1..7022c4e389 100644 --- a/sdk/options.go +++ b/sdk/options.go @@ -104,6 +104,7 @@ func WithTLSCredentials(tls *tls.Config, audience []string) Option { } // WithTokenEndpoint When we implement service discovery using a .well-known endpoint this option may become deprecated +// // Deprecated: SDK will discover the token endpoint from the platform configuration func WithTokenEndpoint(tokenEndpoint string) Option { return func(c *config) { diff --git a/sdk/tdf.go b/sdk/tdf.go index aba570aa9b..629fc8f8a7 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 } var readPos int64 - var aggregateHash string + var aggregateHash strings.Builder readBuf := bytes.NewBuffer(make([]byte, 0, tdfConfig.defaultSegmentSize)) for totalSegments != 0 { // adjust read size readSize := segmentSize @@ -238,7 +238,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R return nil, fmt.Errorf("splitKey.GetSignaturefailed: %w", err) } - aggregateHash += segmentSig + aggregateHash.WriteString(segmentSig) segmentInfo := Segment{ Hash: string(ocrypto.Base64Encode([]byte(segmentSig))), Size: readSize, @@ -251,7 +251,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R readPos += readSize } - rootSignature, err := calculateSignature([]byte(aggregateHash), tdfObject.payloadKey[:], + rootSignature, err := calculateSignature([]byte(aggregateHash.String()), tdfObject.payloadKey[:], tdfConfig.integrityAlgorithm, tdfConfig.useHex) if err != nil { return nil, fmt.Errorf("splitKey.GetSignaturefailed: %w", err) @@ -319,7 +319,7 @@ func (s SDK) CreateTDFContext(ctx context.Context, writer io.Writer, reader io.R } var completeHashBuilder strings.Builder - completeHashBuilder.WriteString(aggregateHash) + completeHashBuilder.WriteString(aggregateHash.String()) if tdfConfig.useHex { completeHashBuilder.Write(hashOfAssertionAsHex) } else { @@ -702,6 +702,7 @@ func generateWrapKeyWithEC(mode ocrypto.ECCMode, kasPublicKey string, symKey []b } func generateWrapKeyWithRSA(publicKey string, symKey []byte) (string, error) { + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but required for backward compatibility with existing TDF files asymEncrypt, err := ocrypto.NewAsymEncryption(publicKey) if err != nil { return "", fmt.Errorf("generateWrapKeyWithRSA: ocrypto.NewAsymEncryption failed:%w", err) diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index cd0c9178dd..da6ec51aea 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -2433,121 +2433,6 @@ func rotateKey(k *FakeKas, kid, private, public string) func() { } } -// create tdf -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) - - // open file - readSeeker, err := os.Open(plainTextFilename) - s.Require().NoError(err) - - defer func(readSeeker *os.File) { - err := readSeeker.Close() - s.Require().NoError(err) - }(readSeeker) - - fileWriter, err := os.Create(tdfFileName) - s.Require().NoError(err) - - defer func(fileWriter *os.File) { - err := fileWriter.Close() - s.Require().NoError(err) - }(fileWriter) // CreateTDF TDFConfig - - if test.mimeType != "" { - encryptOpts = append(encryptOpts, WithMimeType(test.mimeType)) - } - switch { - case len(test.policy) > 0: - da := make([]string, len(test.policy)) - for i := 0; i < len(da); i++ { - da[i] = test.policy[i].String() - } - encryptOpts = append(encryptOpts, WithDataAttributes(da...)) - case len(test.splitPlan) > 0: - encryptOpts = append(encryptOpts, withSplitPlan(test.splitPlan...)) - } - - tdfObj, err := sdk.CreateTDF(fileWriter, readSeeker, encryptOpts...) - s.Require().NoError(err) - - s.InDelta(float64(test.tdfFileSize), float64(tdfObj.size), .04*float64(test.tdfFileSize)) - return tdfObj -} - -func (s *TDFSuite) testDecryptWithReader(sdk *SDK, tdfFile, decryptedTdfFileName string, test tdfTest) { - readSeeker, err := os.Open(tdfFile) - s.Require().NoError(err) - - defer func(readSeeker *os.File) { - err := readSeeker.Close() - s.Require().NoError(err) - }(readSeeker) - - r, err := sdk.LoadTDF(readSeeker, test.opts...) - s.Require().NoError(err) - - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(300*time.Minute)) - defer cancel() - err = r.Init(ctx) - s.Require().NoError(err) - s.Require().NotNil(r.payloadKey) - - if test.mimeType != "" { - s.Equal(test.mimeType, r.Manifest().MimeType, "mimeType does not match") - } - - { - fileWriter, err := os.Create(decryptedTdfFileName) - s.Require().NoError(err) - - defer func(fileWriter *os.File) { - err := fileWriter.Close() - s.Require().NoError(err) - }(fileWriter) - - _, err = io.Copy(fileWriter, r) - s.Require().NoError(err) - } - - s.True(s.checkIdentical(decryptedTdfFileName, test.checksum), "decrypted text didn't match plain text") - - var bufSize int64 = 5 - buf := make([]byte, bufSize) - resultBuf := bytes.Repeat([]byte{char}, int(bufSize)) - - // read last 5 bytes - n, err := r.ReadAt(buf, test.fileSize-(bufSize)) - if err != nil { - s.Require().ErrorIs(err, io.EOF) - } - s.Equal(resultBuf[:n], buf[:n], "decrypted text didn't match plain text with ReadAt interface") - - _ = os.Remove(decryptedTdfFileName) -} - -func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { - f, err := os.Create(filename) - s.Require().NoError(err) - - totalBytes := size - var bytesToWrite int64 - for totalBytes > 0 { - if totalBytes >= stepSize { - totalBytes -= stepSize - bytesToWrite = stepSize - } else { - bytesToWrite = totalBytes - totalBytes = 0 - } - _, err := f.Write(buf[:bytesToWrite]) - s.Require().NoError(err) - } - err = f.Close() - s.Require().NoError(err) -} - func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { wellKnown := map[string]interface{}{ "health": map[string]interface{}{ @@ -2566,85 +2451,6 @@ func createWellKnown(baseKey map[string]interface{}) map[string]interface{} { return wellKnown } -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, kid string - }{ - {"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, "e1"}, - {"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}, - {evenMoreSpecificKas, mockRSAPrivateKey3, mockRSAPublicKey3, "r3"}, - {obligationKas, mockRSAPrivateKey3, mockRSAPublicKey3, "r3"}, - } - fkar := &FakeKASRegistry{kases: kasesToMake, s: s} - - s.kases = make([]FakeKas, len(kasesToMake)) - - s.kasTestURLLookup = make(map[string]string, len(kasesToMake)) - - var sdkPlatformURL string - - for i, ki := range kasesToMake { - mux := http.NewServeMux() - - s.kases[i] = FakeKas{ - s: s, privateKey: ki.private, KASInfo: KASInfo{ - URL: ki.url, PublicKey: ki.public, KID: ki.kid, Algorithm: "rsa:2048", - }, - legakeys: map[string]keyInfo{}, - attrToRequiredObligations: obligationMap, - } - path, handler := attributesconnect.NewAttributesServiceHandler(fa) - mux.Handle(path, handler) - kasPath, kasHandler := kasconnect.NewAccessServiceHandler(&s.kases[i]) - mux.Handle(kasPath, kasHandler) - path, handler = wellknownconnect.NewWellKnownServiceHandler(fwk) - mux.Handle(path, handler) - path, handler = kasregistryconnect.NewKeyAccessServerRegistryServiceHandler(fkar) - mux.Handle(path, handler) - - server := httptest.NewServer(mux) - - // add to lookup reg - s.kasTestURLLookup[s.kases[i].URL] = server.URL - // replace kasinfo url with httptest server url - s.kases[i].URL = server.URL - - if i == 0 { - sdkPlatformURL = server.URL - } - } - - ats := getTokenSource(s.T()) - - sdk, err := New(sdkPlatformURL, - WithClientCredentials("test", "test", nil), - withCustomAccessTokenSource(&ats), - WithTokenEndpoint("http://localhost:65432/auth/token"), - WithInsecurePlaintextConn(), - ) - s.Require().NoError(err) - s.sdk = sdk -} - type FakeWellKnown struct { wellknownconnect.UnimplementedWellKnownServiceHandler s *TDFSuite @@ -2872,6 +2678,7 @@ func (f *FakeKas) getRewrapResponse(rewrapRequest string, fulfillableObligations f.s.Require().NoError(err, "ocrypto.NewAsymDecryption failed") symmetricKey, err := asymDecrypt.Decrypt(wrappedKey) f.s.Require().NoError(err, "ocrypto.Decrypt failed for kao:[%s # %s (%s)] kas:[%s # %s (%s)]", kao.GetKasUrl(), kao.GetKid(), kao.GetSplitId(), f.URL, f.KID, f.Algorithm) + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code asymEncrypt, err := ocrypto.NewAsymEncryption(bodyData.GetClientPublicKey()) f.s.Require().NoError(err, "ocrypto.NewAsymEncryption failed") entityWrappedKey, err = asymEncrypt.Encrypt(symmetricKey) @@ -2894,58 +2701,6 @@ func (f *FakeKas) getRewrapResponse(rewrapRequest string, fulfillableObligations return resp } -func (s *TDFSuite) checkPolicyObligations(obligationsMap map[string]string, req *kaspb.UnsignedRewrapRequest_WithPolicyRequest) []string { - var requiredObligations []string - sDecPolicy, policyErr := base64.StdEncoding.DecodeString(req.GetPolicy().GetBody()) - policy := &Policy{} - if policyErr == nil { - policyErr = json.Unmarshal(sDecPolicy, policy) - if policyErr != nil { - return requiredObligations - } - } - for _, attr := range policy.Body.DataAttributes { - if val, found := obligationsMap[attr.URI]; found { - requiredObligations = append(requiredObligations, val) - } - } - return requiredObligations -} - -func (s *TDFSuite) checkObligationsFulfillment(requiredObligations, fulfillableObligations []string) bool { - // Create a set of fulfillable obligations for fast lookup - fulfillableSet := make(map[string]bool) - for _, obligation := range fulfillableObligations { - fulfillableSet[obligation] = true - } - - // Check if all required obligations are in the fulfillable set - for _, required := range requiredObligations { - if !fulfillableSet[required] { - return false - } - } - - return true -} - -func (s *TDFSuite) checkIdentical(file, checksum string) bool { - f, err := os.Open(file) - s.Require().NoError(err, "os.Open failed") - - defer func(f *os.File) { - err := f.Close() - s.Require().NoError(err, "os.Close failed") - }(f) - - h := sha256.New() - _, err = io.Copy(h, f) - s.Require().NoError(err, "io.Copy failed") - - c := h.Sum(nil) - 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, @@ -3152,3 +2907,249 @@ func (s *TDFSuite) Test_LargeManifest_WithMaxManifest() { s.Require().Error(err, "Manifest above max size should fail to load") s.Require().ErrorContains(err, "size too large") } + +// create tdf +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) + + // open file + readSeeker, err := os.Open(plainTextFilename) + s.Require().NoError(err) + + defer func(readSeeker *os.File) { + err := readSeeker.Close() + s.Require().NoError(err) + }(readSeeker) + + fileWriter, err := os.Create(tdfFileName) + s.Require().NoError(err) + + defer func(fileWriter *os.File) { + err := fileWriter.Close() + s.Require().NoError(err) + }(fileWriter) // CreateTDF TDFConfig + + if test.mimeType != "" { + encryptOpts = append(encryptOpts, WithMimeType(test.mimeType)) + } + switch { + case len(test.policy) > 0: + da := make([]string, len(test.policy)) + for i := 0; i < len(da); i++ { + da[i] = test.policy[i].String() + } + encryptOpts = append(encryptOpts, WithDataAttributes(da...)) + case len(test.splitPlan) > 0: + encryptOpts = append(encryptOpts, withSplitPlan(test.splitPlan...)) + } + + tdfObj, err := sdk.CreateTDF(fileWriter, readSeeker, encryptOpts...) + s.Require().NoError(err) + + s.InDelta(float64(test.tdfFileSize), float64(tdfObj.size), .04*float64(test.tdfFileSize)) + return tdfObj +} + +func (s *TDFSuite) testDecryptWithReader(sdk *SDK, tdfFile, decryptedTdfFileName string, test tdfTest) { + readSeeker, err := os.Open(tdfFile) + s.Require().NoError(err) + + defer func(readSeeker *os.File) { + err := readSeeker.Close() + s.Require().NoError(err) + }(readSeeker) + + r, err := sdk.LoadTDF(readSeeker, test.opts...) + s.Require().NoError(err) + + ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(300*time.Minute)) + defer cancel() + err = r.Init(ctx) + s.Require().NoError(err) + s.Require().NotNil(r.payloadKey) + + if test.mimeType != "" { + s.Equal(test.mimeType, r.Manifest().MimeType, "mimeType does not match") + } + + { + fileWriter, err := os.Create(decryptedTdfFileName) + s.Require().NoError(err) + + defer func(fileWriter *os.File) { + err := fileWriter.Close() + s.Require().NoError(err) + }(fileWriter) + + _, err = io.Copy(fileWriter, r) + s.Require().NoError(err) + } + + s.True(s.checkIdentical(decryptedTdfFileName, test.checksum), "decrypted text didn't match plain text") + + var bufSize int64 = 5 + buf := make([]byte, bufSize) + resultBuf := bytes.Repeat([]byte{char}, int(bufSize)) + + // read last 5 bytes + n, err := r.ReadAt(buf, test.fileSize-(bufSize)) + if err != nil { + s.Require().ErrorIs(err, io.EOF) + } + s.Equal(resultBuf[:n], buf[:n], "decrypted text didn't match plain text with ReadAt interface") + + _ = os.Remove(decryptedTdfFileName) +} + +func (s *TDFSuite) createFileName(buf []byte, filename string, size int64) { + f, err := os.Create(filename) + s.Require().NoError(err) + + totalBytes := size + var bytesToWrite int64 + for totalBytes > 0 { + if totalBytes >= stepSize { + totalBytes -= stepSize + bytesToWrite = stepSize + } else { + bytesToWrite = totalBytes + totalBytes = 0 + } + _, err := f.Write(buf[:bytesToWrite]) + s.Require().NoError(err) + } + err = f.Close() + s.Require().NoError(err) +} + +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, kid string + }{ + {"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, "e1"}, + {"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}, + {evenMoreSpecificKas, mockRSAPrivateKey3, mockRSAPublicKey3, "r3"}, + {obligationKas, mockRSAPrivateKey3, mockRSAPublicKey3, "r3"}, + } + fkar := &FakeKASRegistry{kases: kasesToMake, s: s} + + s.kases = make([]FakeKas, len(kasesToMake)) + + s.kasTestURLLookup = make(map[string]string, len(kasesToMake)) + + var sdkPlatformURL string + + for i, ki := range kasesToMake { + mux := http.NewServeMux() + + s.kases[i] = FakeKas{ + s: s, privateKey: ki.private, KASInfo: KASInfo{ + URL: ki.url, PublicKey: ki.public, KID: ki.kid, Algorithm: "rsa:2048", + }, + legakeys: map[string]keyInfo{}, + attrToRequiredObligations: obligationMap, + } + path, handler := attributesconnect.NewAttributesServiceHandler(fa) + mux.Handle(path, handler) + kasPath, kasHandler := kasconnect.NewAccessServiceHandler(&s.kases[i]) + mux.Handle(kasPath, kasHandler) + path, handler = wellknownconnect.NewWellKnownServiceHandler(fwk) + mux.Handle(path, handler) + path, handler = kasregistryconnect.NewKeyAccessServerRegistryServiceHandler(fkar) + mux.Handle(path, handler) + + server := httptest.NewServer(mux) + + // add to lookup reg + s.kasTestURLLookup[s.kases[i].URL] = server.URL + // replace kasinfo url with httptest server url + s.kases[i].URL = server.URL + + if i == 0 { + sdkPlatformURL = server.URL + } + } + + ats := getTokenSource(s.T()) + + sdk, err := New(sdkPlatformURL, + WithClientCredentials("test", "test", nil), + withCustomAccessTokenSource(&ats), + WithTokenEndpoint("http://localhost:65432/auth/token"), + WithInsecurePlaintextConn(), + ) + s.Require().NoError(err) + s.sdk = sdk +} + +func (s *TDFSuite) checkPolicyObligations(obligationsMap map[string]string, req *kaspb.UnsignedRewrapRequest_WithPolicyRequest) []string { + var requiredObligations []string + sDecPolicy, policyErr := base64.StdEncoding.DecodeString(req.GetPolicy().GetBody()) + policy := &Policy{} + if policyErr == nil { + policyErr = json.Unmarshal(sDecPolicy, policy) + if policyErr != nil { + return requiredObligations + } + } + for _, attr := range policy.Body.DataAttributes { + if val, found := obligationsMap[attr.URI]; found { + requiredObligations = append(requiredObligations, val) + } + } + return requiredObligations +} + +func (s *TDFSuite) checkObligationsFulfillment(requiredObligations, fulfillableObligations []string) bool { + // Create a set of fulfillable obligations for fast lookup + fulfillableSet := make(map[string]bool) + for _, obligation := range fulfillableObligations { + fulfillableSet[obligation] = true + } + + // Check if all required obligations are in the fulfillable set + for _, required := range requiredObligations { + if !fulfillableSet[required] { + return false + } + } + + return true +} + +func (s *TDFSuite) checkIdentical(file, checksum string) bool { + f, err := os.Open(file) + s.Require().NoError(err, "os.Open failed") + + defer func(f *os.File) { + err := f.Close() + s.Require().NoError(err, "os.Close failed") + }(f) + + h := sha256.New() + _, err = io.Copy(h, f) + s.Require().NoError(err, "io.Copy failed") + + c := h.Sum(nil) + return checksum == hex.EncodeToString(c) +} diff --git a/service/authorization/authorization.go b/service/authorization/authorization.go index 26f7673b3a..4469d4107d 100644 --- a/service/authorization/authorization.go +++ b/service/authorization/authorization.go @@ -13,7 +13,7 @@ import ( "github.com/creasty/defaults" "github.com/go-playground/validator/v10" "github.com/go-viper/mapstructure/v2" - "github.com/open-policy-agent/opa/rego" + "github.com/open-policy-agent/opa/rego" //nolint:staticcheck // SA1019: v0.x compatibility package used for OPA rego functionality "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/authorization/authorizationconnect" "github.com/opentdf/platform/protocol/go/common" diff --git a/service/authorization/authorization_test.go b/service/authorization/authorization_test.go index 2011ea3046..a83bb4017e 100644 --- a/service/authorization/authorization_test.go +++ b/service/authorization/authorization_test.go @@ -9,7 +9,7 @@ import ( "go.opentelemetry.io/otel/trace/noop" "connectrpc.com/connect" - "github.com/open-policy-agent/opa/rego" + "github.com/open-policy-agent/opa/rego" //nolint:staticcheck // SA1019: v0.x compatibility package used for OPA rego functionality "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/protocol/go/policy" diff --git a/service/authorization/authorization_test_structures.go b/service/authorization/authorization_test_structures.go index e9f4d764f5..65b380c488 100644 --- a/service/authorization/authorization_test_structures.go +++ b/service/authorization/authorization_test_structures.go @@ -75,18 +75,22 @@ func (*myAttributesClient) DeactivateAttributeValue(_ context.Context, _ *attr.D return &attr.DeactivateAttributeValueResponse{}, nil } +//nolint:staticcheck // SA1019: AssignKeyAccessServerToAttribute is deprecated but required for test mock func (*myAttributesClient) AssignKeyAccessServerToAttribute(_ context.Context, _ *attr.AssignKeyAccessServerToAttributeRequest) (*attr.AssignKeyAccessServerToAttributeResponse, error) { return &attr.AssignKeyAccessServerToAttributeResponse{}, nil } +//nolint:staticcheck // SA1019: RemoveKeyAccessServerFromAttribute is deprecated but required for test mock func (*myAttributesClient) RemoveKeyAccessServerFromAttribute(_ context.Context, _ *attr.RemoveKeyAccessServerFromAttributeRequest) (*attr.RemoveKeyAccessServerFromAttributeResponse, error) { return &attr.RemoveKeyAccessServerFromAttributeResponse{}, nil } +//nolint:staticcheck // SA1019: AssignKeyAccessServerToValue is deprecated but required for test mock func (*myAttributesClient) AssignKeyAccessServerToValue(_ context.Context, _ *attr.AssignKeyAccessServerToValueRequest) (*attr.AssignKeyAccessServerToValueResponse, error) { return &attr.AssignKeyAccessServerToValueResponse{}, nil } +//nolint:staticcheck // SA1019: RemoveKeyAccessServerFromValue is deprecated but required for test mock func (*myAttributesClient) RemoveKeyAccessServerFromValue(_ context.Context, _ *attr.RemoveKeyAccessServerFromValueRequest) (*attr.RemoveKeyAccessServerFromValueResponse, error) { return &attr.RemoveKeyAccessServerFromValueResponse{}, nil } @@ -301,18 +305,22 @@ func (*paginatedMockAttributesClient) DeactivateAttributeValue(_ context.Context return &attr.DeactivateAttributeValueResponse{}, nil } +//nolint:staticcheck // SA1019: AssignKeyAccessServerToAttribute is deprecated but required for test mock func (*paginatedMockAttributesClient) AssignKeyAccessServerToAttribute(_ context.Context, _ *attr.AssignKeyAccessServerToAttributeRequest) (*attr.AssignKeyAccessServerToAttributeResponse, error) { return &attr.AssignKeyAccessServerToAttributeResponse{}, nil } +//nolint:staticcheck // SA1019: RemoveKeyAccessServerFromAttribute is deprecated but required for test mock func (*paginatedMockAttributesClient) RemoveKeyAccessServerFromAttribute(_ context.Context, _ *attr.RemoveKeyAccessServerFromAttributeRequest) (*attr.RemoveKeyAccessServerFromAttributeResponse, error) { return &attr.RemoveKeyAccessServerFromAttributeResponse{}, nil } +//nolint:staticcheck // SA1019: AssignKeyAccessServerToValue is deprecated but required for test mock func (*paginatedMockAttributesClient) AssignKeyAccessServerToValue(_ context.Context, _ *attr.AssignKeyAccessServerToValueRequest) (*attr.AssignKeyAccessServerToValueResponse, error) { return &attr.AssignKeyAccessServerToValueResponse{}, nil } +//nolint:staticcheck // SA1019: RemoveKeyAccessServerFromValue is deprecated but required for test mock func (*paginatedMockAttributesClient) RemoveKeyAccessServerFromValue(_ context.Context, _ *attr.RemoveKeyAccessServerFromValueRequest) (*attr.RemoveKeyAccessServerFromValueResponse, error) { return &attr.RemoveKeyAccessServerFromValueResponse{}, nil } diff --git a/service/entityresolution/integration/claims_test.go b/service/entityresolution/integration/claims_test.go index 076ba55f72..947479e65f 100644 --- a/service/entityresolution/integration/claims_test.go +++ b/service/entityresolution/integration/claims_test.go @@ -377,6 +377,7 @@ func (a *ClaimsTestAdapter) createTestJWT(clientID, username, email string, addi _ = token.Set("email", email) // Additional custom claims + //nolint:staticcheck // S1031: nil check is intentional for optional parameter handling if additionalClaims != nil { for key, value := range additionalClaims { _ = token.Set(key, value) @@ -417,6 +418,7 @@ func (a *ClaimsTestAdapter) createUnsignedTestJWT(clientID, username, email stri } // Add additional claims + //nolint:staticcheck // S1031: nil check is intentional for optional parameter handling if additionalClaims != nil { for key, value := range additionalClaims { claims[key] = value diff --git a/service/entityresolution/integration/internal/chain_contract_tests.go b/service/entityresolution/integration/internal/chain_contract_tests.go index 31189a7bd4..a9767ee1cf 100644 --- a/service/entityresolution/integration/internal/chain_contract_tests.go +++ b/service/entityresolution/integration/internal/chain_contract_tests.go @@ -1,9 +1,7 @@ package internal import ( - "errors" "fmt" - "strings" "testing" "connectrpc.com/connect" @@ -182,42 +180,12 @@ func (suite *ChainContractTestSuite) executeChainRequest(t *testing.T, implement return nil, err } - if suite.handleConnectionErrors(t, err) { - return nil, err - } - require.NoError(t, err, "Unexpected error: %v", err) require.NotNil(t, resp, "Response should not be nil") return resp.Msg.GetEntityChains(), nil } -// handleConnectionErrors checks for connection-related errors and skips tests if service unavailable -func (suite *ChainContractTestSuite) handleConnectionErrors(t *testing.T, err error) bool { - if err == nil { - return false - } - - var connectErr *connect.Error - if !errors.As(err, &connectErr) { - return false - } - - if connectErr.Code() != connect.CodeInternal { - return false - } - - errorMsg := connectErr.Message() - if strings.Contains(errorMsg, "connection refused") || - strings.Contains(errorMsg, "could not get token") || - strings.Contains(errorMsg, "failed to login") { - t.Skipf("Service unavailable (likely connection issue): %v", errorMsg) - return true - } - - return false -} - // validateSingleChain validates a single entity chain according to the validation rule func (suite *ChainContractTestSuite) validateSingleChain(t *testing.T, chains []*entity.EntityChain, validationRule EntityChainValidationRule) { matchingChain := suite.findChainByEphemeralID(chains, validationRule.EphemeralID) diff --git a/service/entityresolution/keycloak/entity_resolution_test.go b/service/entityresolution/keycloak/entity_resolution_test.go index 2875439d6a..2ab4b54d49 100644 --- a/service/entityresolution/keycloak/entity_resolution_test.go +++ b/service/entityresolution/keycloak/entity_resolution_test.go @@ -678,7 +678,8 @@ func Test_GetConnectorTokenRefresh(t *testing.T) { service := &KeycloakEntityResolutionService{ idpConfig: kcconfig, logger: logger.CreateTestLogger(), - Tracer: trace.NewNoopTracerProvider().Tracer("test"), + //nolint:staticcheck // SA1019: trace.NewNoopTracerProvider is deprecated but required for test setup + Tracer: trace.NewNoopTracerProvider().Tracer("test"), } req := &connect.Request[entityresolution.ResolveEntitiesRequest]{ diff --git a/service/entityresolution/keycloak/v2/entity_resolution_test.go b/service/entityresolution/keycloak/v2/entity_resolution_test.go index b4ecc07099..ff47c731dd 100644 --- a/service/entityresolution/keycloak/v2/entity_resolution_test.go +++ b/service/entityresolution/keycloak/v2/entity_resolution_test.go @@ -166,7 +166,8 @@ func Test_GetConnectorTokenRefresh(t *testing.T) { service := &EntityResolutionServiceV2{ idpConfig: testConfig(server), logger: logger.CreateTestLogger(), - Tracer: trace.NewNoopTracerProvider().Tracer("test"), + //nolint:staticcheck // SA1019: trace.NewNoopTracerProvider is deprecated but required for test setup + Tracer: trace.NewNoopTracerProvider().Tracer("test"), } // First call to trigger initial token acquisition diff --git a/service/entityresolution/multi-strategy/providers/ldap/ldap_mapper.go b/service/entityresolution/multi-strategy/providers/ldap/ldap_mapper.go index 690aedfc89..0bd3fcb56c 100644 --- a/service/entityresolution/multi-strategy/providers/ldap/ldap_mapper.go +++ b/service/entityresolution/multi-strategy/providers/ldap/ldap_mapper.go @@ -146,6 +146,7 @@ func isValidTemplateVariable(name string) bool { } // Must start with letter or underscore + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_') { return false } @@ -153,6 +154,7 @@ func isValidTemplateVariable(name string) bool { // Rest must be letters, digits, or underscores for i := 1; i < len(name); i++ { char := name[i] + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9') || char == '_') { return false } @@ -169,12 +171,14 @@ func isValidLDAPAttribute(name string) bool { // LDAP attribute names can contain letters, digits, and hyphens // Must start with a letter + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z')) { return false } for i := 1; i < len(name); i++ { char := name[i] + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9') || char == '-') { return false } diff --git a/service/entityresolution/multi-strategy/providers/sql/sql_mapper.go b/service/entityresolution/multi-strategy/providers/sql/sql_mapper.go index a629a7820d..9bf4a5b88e 100644 --- a/service/entityresolution/multi-strategy/providers/sql/sql_mapper.go +++ b/service/entityresolution/multi-strategy/providers/sql/sql_mapper.go @@ -155,6 +155,7 @@ func isValidSQLIdentifier(name string) bool { } // Must start with letter or underscore + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_') { return false } @@ -162,6 +163,7 @@ func isValidSQLIdentifier(name string) bool { // Rest must be letters, digits, or underscores for i := 1; i < len(name); i++ { char := name[i] + //nolint:staticcheck // QF1001: De Morgan's law would make this less readable if !((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9') || char == '_') { return false } diff --git a/service/entityresolution/multi-strategy/types/errors.go b/service/entityresolution/multi-strategy/types/errors.go index 77c5713009..b49b046f99 100644 --- a/service/entityresolution/multi-strategy/types/errors.go +++ b/service/entityresolution/multi-strategy/types/errors.go @@ -1,3 +1,4 @@ +//nolint:revive,nolintlint // var-naming: package name "types" is generic but required for organizational clarity package types import ( diff --git a/service/entityresolution/multi-strategy/types/types.go b/service/entityresolution/multi-strategy/types/types.go index f92213b95a..098897bb5b 100644 --- a/service/entityresolution/multi-strategy/types/types.go +++ b/service/entityresolution/multi-strategy/types/types.go @@ -1,3 +1,4 @@ +//nolint:revive,nolintlint // var-naming: package name "types" is generic but required for organizational clarity package types import ( diff --git a/service/integration/subject_mappings_test.go b/service/integration/subject_mappings_test.go index ac631375a7..135bfd9421 100644 --- a/service/integration/subject_mappings_test.go +++ b/service/integration/subject_mappings_test.go @@ -265,6 +265,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectMapping_DeprecatedProtoEnums_Fai s.Require().Error(err) s.Require().ErrorIs(err, db.ErrMissingValue) + //nolint:staticcheck // SA1019: Action.Value field is deprecated but tested here to ensure proper error handling newSubjectMapping.GetActions()[0].Value = &policy.Action_Standard{ Standard: policy.Action_STANDARD_ACTION_TRANSMIT, } @@ -420,6 +421,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_Actions_DeprecatedProtoE s.Require().Error(err) s.Require().ErrorIs(err, db.ErrMissingValue) + //nolint:staticcheck // SA1019: Action.Value field is deprecated but tested here to ensure proper error handling updateReq.Actions[0].Value = &policy.Action_Standard{ Standard: policy.Action_STANDARD_ACTION_TRANSMIT, } diff --git a/service/internal/security/basic_manager.go b/service/internal/security/basic_manager.go index 29a93ae6e2..c4f44569fc 100644 --- a/service/internal/security/basic_manager.go +++ b/service/internal/security/basic_manager.go @@ -151,6 +151,7 @@ type OCEncapsulator struct { func (e *OCEncapsulator) Encapsulate(dek ocrypto.ProtectedKey) ([]byte, error) { // Delegate to the ProtectedKey to avoid exposing raw key material + //nolint:staticcheck // SA1019: dek.Export is deprecated but required for backward compatibility with legacy key encapsulation return dek.Export(e) } diff --git a/service/internal/security/basic_manager_test.go b/service/internal/security/basic_manager_test.go index d5915d1cdf..02758d8706 100644 --- a/service/internal/security/basic_manager_test.go +++ b/service/internal/security/basic_manager_test.go @@ -118,6 +118,7 @@ type noOpEncapsulator struct{} func (n *noOpEncapsulator) Encapsulate(pk ocrypto.ProtectedKey) ([]byte, error) { // Delegate to ProtectedKey to avoid accessing raw key directly + //nolint:staticcheck // SA1019: pk.Export is deprecated but required for test code return pk.Export(n) } @@ -309,6 +310,7 @@ func TestBasicManager_Decrypt(t *testing.T) { mockDetails.On("Algorithm").Return(mockDetails.MAlgorithm) mockDetails.On("ExportPrivateKey").Return(&trust.PrivateKey{WrappingKeyID: trust.KeyIdentifier(mockDetails.MPrivateKey.GetKeyId()), WrappedKey: mockDetails.MPrivateKey.GetWrappedKey()}, nil) + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code rsaEncryptor, err := ocrypto.NewAsymEncryption(rsaPubKey) require.NoError(t, err) ciphertext, err := rsaEncryptor.Encrypt(samplePayload) @@ -320,6 +322,7 @@ func TestBasicManager_Decrypt(t *testing.T) { // Use noOpEncapsulator to get raw key data for testing noOpEnc := &noOpEncapsulator{} + //nolint:staticcheck // SA1019: protectedKey.Export is deprecated but required for test code decryptedPayload, err := protectedKey.Export(noOpEnc) require.NoError(t, err) assert.Equal(t, samplePayload, decryptedPayload) @@ -348,6 +351,7 @@ func TestBasicManager_Decrypt(t *testing.T) { // Use noOpEncapsulator to get raw key data for testing noOpEnc := &noOpEncapsulator{} + //nolint:staticcheck // SA1019: protectedKey.Export is deprecated but required for test code decryptedPayload, err := protectedKey.Export(noOpEnc) require.NoError(t, err) assert.Equal(t, samplePayload, decryptedPayload) @@ -471,6 +475,7 @@ func TestBasicManager_DeriveKey(t *testing.T) { // Use noOpEncapsulator to get raw key data for testing noOpEnc := &noOpEncapsulator{} + //nolint:staticcheck // SA1019: protectedKey.Export is deprecated but required for test code actualDerivedKey, err := protectedKey.Export(noOpEnc) require.NoError(t, err) assert.Equal(t, expectedDerivedKey, actualDerivedKey) diff --git a/service/internal/security/in_process_provider.go b/service/internal/security/in_process_provider.go index 45a615ad18..2b926bf4f3 100644 --- a/service/internal/security/in_process_provider.go +++ b/service/internal/security/in_process_provider.go @@ -291,6 +291,8 @@ func (a *InProcessProvider) DeriveKey(_ context.Context, keyDetails trust.KeyDet } // GenerateECSessionKey generates a session key for NanoTDF +// +//nolint:staticcheck // SA1019: trust.Encapsulator is deprecated but required for backward compatibility with legacy key generation func (a *InProcessProvider) GenerateECSessionKey(_ context.Context, ephemeralPublicKey string) (trust.Encapsulator, error) { pke, err := ocrypto.FromPublicPEMWithSalt(ephemeralPublicKey, NanoVersionSalt(), nil) if err != nil { diff --git a/service/internal/security/standard_crypto.go b/service/internal/security/standard_crypto.go index ff4ec1c197..f3538abc4d 100644 --- a/service/internal/security/standard_crypto.go +++ b/service/internal/security/standard_crypto.go @@ -160,6 +160,7 @@ func loadKey(k KeyPairInfo) (any, error) { if err != nil { return nil, fmt.Errorf("ocrypto.NewAsymDecryption failed: %w", err) } + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but required for backward compatibility with legacy crypto operations asymEncryption, err := ocrypto.NewAsymEncryption(string(certPEM)) if err != nil { return nil, fmt.Errorf("ocrypto.NewAsymEncryption failed: %w", err) @@ -201,6 +202,7 @@ func loadDeprecatedKeys(rsaKeys map[string]StandardKeyInfo, ecKeys map[string]St return nil, fmt.Errorf("failed to rsa public key file: %w", err) } + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but required for backward compatibility with legacy crypto operations asymEncryption, err := ocrypto.NewAsymEncryption(string(publicPemData)) if err != nil { return nil, fmt.Errorf("ocrypto.NewAsymEncryption failed: %w", err) diff --git a/service/internal/subjectmappingbuiltin/subject_mapping_builtin.go b/service/internal/subjectmappingbuiltin/subject_mapping_builtin.go index c66f62ac77..4e74f77def 100644 --- a/service/internal/subjectmappingbuiltin/subject_mapping_builtin.go +++ b/service/internal/subjectmappingbuiltin/subject_mapping_builtin.go @@ -8,9 +8,9 @@ import ( "log/slog" "strings" - "github.com/open-policy-agent/opa/ast" - "github.com/open-policy-agent/opa/rego" - "github.com/open-policy-agent/opa/types" + "github.com/open-policy-agent/opa/ast" //nolint:staticcheck // SA1019: v0.x compatibility package used for OPA custom builtin + "github.com/open-policy-agent/opa/rego" //nolint:staticcheck // SA1019: v0.x compatibility package used for OPA custom builtin + "github.com/open-policy-agent/opa/types" //nolint:staticcheck // SA1019: v0.x compatibility package used for OPA custom builtin "github.com/opentdf/platform/lib/flattening" "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/protocol/go/policy" diff --git a/service/kas/access/publicKey_test.go b/service/kas/access/publicKey_test.go index a9be66def2..39745b76aa 100644 --- a/service/kas/access/publicKey_test.go +++ b/service/kas/access/publicKey_test.go @@ -154,6 +154,7 @@ func (m *MockSecurityProvider) DeriveKey(_ context.Context, _ trust.KeyDetails, return nil, errors.New("not implemented for tests") } +//nolint:staticcheck // SA1019: Encapsulator is deprecated but used in test mock func (m *MockSecurityProvider) GenerateECSessionKey(_ context.Context, _ string) (trust.Encapsulator, error) { return nil, errors.New("not implemented for tests") } diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go index 92d4efadea..84a9925b25 100644 --- a/service/kas/access/rewrap.go +++ b/service/kas/access/rewrap.go @@ -1095,6 +1095,7 @@ func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*kaspb.Unsigned failedKAORewrapWithObligations(kaoResults, kao, err403("forbidden"), requiredObligationsForPolicy) continue } + //nolint:staticcheck // SA1019: Export is deprecated but required for backward compatibility cipherText, err := kaoInfo.DEK.Export(sessionKey) if err != nil { p.Logger.Audit.RewrapFailure(ctx, auditEventParams) diff --git a/service/kas/access/rewrap_test.go b/service/kas/access/rewrap_test.go index 269051468c..4ff849036a 100644 --- a/service/kas/access/rewrap_test.go +++ b/service/kas/access/rewrap_test.go @@ -394,6 +394,7 @@ type PolicyBinding struct { func keyAccessWrappedRaw(t *testing.T, policyBindingAsString bool) kaspb.UnsignedRewrapRequest_WithKeyAccessObject { policyBytes := fauxPolicyBytes(t) + //nolint:staticcheck // SA1019: NewAsymEncryption is deprecated but used in test code asym, err := ocrypto.NewAsymEncryption(rsaPublicAlt) require.NoError(t, err, "rewrap: NewAsymEncryption failed") wrappedKey, err := asym.Encrypt([]byte(plainKey)) diff --git a/service/kas/kas.go b/service/kas/kas.go index 2e0960862e..073ea40024 100644 --- a/service/kas/kas.go +++ b/service/kas/kas.go @@ -95,8 +95,9 @@ func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] } else { // Set up both the legacy CryptoProvider and the new SecurityProvider kasCfg.UpgradeMapToKeyring(srp.OTDF.CryptoProvider) + //nolint:staticcheck // SA1019: CryptoProvider is deprecated but still supported for backward compatibility p.CryptoProvider = srp.OTDF.CryptoProvider - + //nolint:staticcheck // SA1019: CryptoProvider is deprecated but still supported for backward compatibility inProcessService := initSecurityProviderAdapter(p.CryptoProvider, kasCfg, srp.Logger) p.KeyDelegator = trust.NewDelegatingKeyService(inProcessService, srp.Logger, nil) diff --git a/service/kas/key_indexer_test.go b/service/kas/key_indexer_test.go index abd8f7f200..8f9b6dd829 100644 --- a/service/kas/key_indexer_test.go +++ b/service/kas/key_indexer_test.go @@ -39,6 +39,7 @@ func (m *MockKeyAccessServerRegistryClient) DeleteKeyAccessServer(context.Contex return nil, errors.New("not implemented") } +//nolint:staticcheck // SA1019: ListKeyAccessServerGrantsRequest is deprecated but used in test mock func (m *MockKeyAccessServerRegistryClient) ListKeyAccessServerGrants(context.Context, *kasregistry.ListKeyAccessServerGrantsRequest) (*kasregistry.ListKeyAccessServerGrantsResponse, error) { return nil, errors.New("not implemented") } diff --git a/service/pkg/server/start.go b/service/pkg/server/start.go index 1cf129c3d2..7beb8230a2 100644 --- a/service/pkg/server/start.go +++ b/service/pkg/server/start.go @@ -255,6 +255,7 @@ func Start(f ...StartOptions) error { } // provide token endpoint -- sdk cannot discover it since well-known service isnt running yet + //nolint:staticcheck // SA1019: WithTokenEndpoint is deprecated but required during startup before well-known service is available sdkOptions = append(sdkOptions, sdk.WithTokenEndpoint(oidcconfig.TokenEndpoint)) } diff --git a/service/policy/attributes/attributes.go b/service/policy/attributes/attributes.go index 6eabaf1f75..0a80f62494 100644 --- a/service/policy/attributes/attributes.go +++ b/service/policy/attributes/attributes.go @@ -374,10 +374,12 @@ func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *c return connect.NewResponse(rsp), nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (s *AttributesService) AssignKeyAccessServerToAttribute(_ context.Context, _ *connect.Request[attributes.AssignKeyAccessServerToAttributeRequest]) (*connect.Response[attributes.AssignKeyAccessServerToAttributeResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("this compatibility stub will be removed entirely in the following release")) } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromAttributeRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromAttributeResponse], error) { rsp := &attributes.RemoveKeyAccessServerFromAttributeResponse{} @@ -402,10 +404,12 @@ func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Conte return connect.NewResponse(rsp), nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (s *AttributesService) AssignKeyAccessServerToValue(_ context.Context, _ *connect.Request[attributes.AssignKeyAccessServerToValueRequest]) (*connect.Response[attributes.AssignKeyAccessServerToValueResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("this compatibility stub will be removed entirely in the following release")) } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (s *AttributesService) RemoveKeyAccessServerFromValue(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromValueRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromValueResponse], error) { rsp := &attributes.RemoveKeyAccessServerFromValueResponse{} diff --git a/service/policy/db/attribute_values.go b/service/policy/db/attribute_values.go index 3fe5189d35..fa8c9b95d9 100644 --- a/service/policy/db/attribute_values.go +++ b/service/policy/db/attribute_values.go @@ -324,6 +324,7 @@ func (c PolicyDBClient) UnsafeDeleteAttributeValue(ctx context.Context, toDelete }, nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (c PolicyDBClient) RemoveKeyAccessServerFromValue(ctx context.Context, k *attributes.ValueKeyAccessServer) (*attributes.ValueKeyAccessServer, error) { count, err := c.queries.removeKeyAccessServerFromAttributeValue(ctx, removeKeyAccessServerFromAttributeValueParams{ AttributeValueID: k.GetValueId(), diff --git a/service/policy/db/attributes.go b/service/policy/db/attributes.go index f9a069cae6..fd7793a212 100644 --- a/service/policy/db/attributes.go +++ b/service/policy/db/attributes.go @@ -568,6 +568,7 @@ func (c PolicyDBClient) UnsafeDeleteAttribute(ctx context.Context, existing *pol /// Key Access Server assignments /// +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (c PolicyDBClient) RemoveKeyAccessServerFromAttribute(ctx context.Context, k *attributes.AttributeKeyAccessServer) (*attributes.AttributeKeyAccessServer, error) { count, err := c.queries.removeKeyAccessServerFromAttribute(ctx, removeKeyAccessServerFromAttributeParams{ AttributeDefinitionID: k.GetAttributeId(), diff --git a/service/policy/db/grant_mappings.go b/service/policy/db/grant_mappings.go index 11cd413e9d..4e4f5a0908 100644 --- a/service/policy/db/grant_mappings.go +++ b/service/policy/db/grant_mappings.go @@ -64,6 +64,7 @@ func mapKasKeysToGrants(keys []*policy.SimpleKasKey, existingGrants []*policy.Ke // KAS URI already exists, merge/add the public key if existingKas.GetPublicKey().GetCached() == nil { // Initialize if PublicKey or Cached part is missing + //nolint:staticcheck // Using deprecated protobuf field for backward compatibility existingKas.PublicKey = &policy.PublicKey{ PublicKey: &policy.PublicKey_Cached{ Cached: &policy.KasPublicKeySet{Keys: []*policy.KasPublicKey{}}, diff --git a/service/policy/db/key_access_server_registry.go b/service/policy/db/key_access_server_registry.go index 1f35df3b27..57fc004a53 100644 --- a/service/policy/db/key_access_server_registry.go +++ b/service/policy/db/key_access_server_registry.go @@ -75,6 +75,7 @@ func (c PolicyDBClient) ListKeyAccessServers(ctx context.Context, r *kasregistry keyAccessServer.Id = kas.ID keyAccessServer.Uri = kas.Uri + //nolint:staticcheck // Using deprecated protobuf field for backward compatibility keyAccessServer.PublicKey = publicKey keyAccessServer.Name = kas.KasName.String keyAccessServer.Metadata = metadata @@ -293,6 +294,7 @@ func (c PolicyDBClient) DeleteKeyAccessServer(ctx context.Context, id string) (* }, nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (c PolicyDBClient) ListKeyAccessServerGrants(ctx context.Context, r *kasregistry.ListKeyAccessServerGrantsRequest) (*kasregistry.ListKeyAccessServerGrantsResponse, error) { limit, offset := c.getRequestedLimitOffset(r.GetPagination()) maxLimit := c.listCfg.limitMax @@ -349,6 +351,7 @@ func (c PolicyDBClient) ListKeyAccessServerGrants(ctx context.Context, r *kasreg total = int32(listRows[0].Total) nextOffset = getNextOffset(offset, limit, total) } + //nolint:staticcheck // Using deprecated protobuf field for backward compatibility return &kasregistry.ListKeyAccessServerGrantsResponse{ Grants: grants, Pagination: &policy.PageResponse{ diff --git a/service/policy/db/namespaces.go b/service/policy/db/namespaces.go index 0d03ba1903..396a2cbcc1 100644 --- a/service/policy/db/namespaces.go +++ b/service/policy/db/namespaces.go @@ -350,6 +350,7 @@ func (c PolicyDBClient) UnsafeDeleteNamespace(ctx context.Context, existing *pol }, nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (c PolicyDBClient) RemoveKeyAccessServerFromNamespace(ctx context.Context, k *namespaces.NamespaceKeyAccessServer) (*namespaces.NamespaceKeyAccessServer, error) { count, err := c.queries.removeKeyAccessServerFromNamespace(ctx, removeKeyAccessServerFromNamespaceParams{ NamespaceID: k.GetNamespaceId(), diff --git a/service/policy/kasregistry/key_access_server_registry.go b/service/policy/kasregistry/key_access_server_registry.go index 53d12a84c6..96efc8c25f 100644 --- a/service/policy/kasregistry/key_access_server_registry.go +++ b/service/policy/kasregistry/key_access_server_registry.go @@ -215,6 +215,7 @@ func (s KeyAccessServerRegistry) DeleteKeyAccessServer(ctx context.Context, return connect.NewResponse(rsp), nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (s KeyAccessServerRegistry) ListKeyAccessServerGrants(ctx context.Context, req *connect.Request[kasr.ListKeyAccessServerGrantsRequest], ) (*connect.Response[kasr.ListKeyAccessServerGrantsResponse], error) { diff --git a/service/policy/namespaces/namespaces.go b/service/policy/namespaces/namespaces.go index 231630399a..5486b9e837 100644 --- a/service/policy/namespaces/namespaces.go +++ b/service/policy/namespaces/namespaces.go @@ -222,10 +222,12 @@ func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *connec return connect.NewResponse(rsp), nil } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (ns NamespacesService) AssignKeyAccessServerToNamespace(_ context.Context, _ *connect.Request[namespaces.AssignKeyAccessServerToNamespaceRequest]) (*connect.Response[namespaces.AssignKeyAccessServerToNamespaceResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("this compatibility stub will be removed entirely in the following release")) } +//nolint:staticcheck // Using deprecated protobuf field for backward compatibility func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Context, req *connect.Request[namespaces.RemoveKeyAccessServerFromNamespaceRequest]) (*connect.Response[namespaces.RemoveKeyAccessServerFromNamespaceResponse], error) { rsp := &namespaces.RemoveKeyAccessServerFromNamespaceResponse{}