From d6a1e6d6bf60e970afe8fc26c483cfe2e340fdd4 Mon Sep 17 00:00:00 2001 From: Sean Trantalis Date: Tue, 12 Nov 2024 14:21:29 -0500 Subject: [PATCH 01/32] fix: update GetType to check the first 4 bytes (#1736) ### Proposed Changes This pull request updates the GetType to only check max first 4 bytes of the reader to see if we a nanotdf or zip(tdf). ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- sdk/sdk.go | 33 ++++++++++++++++++++++++++++----- sdk/sdk_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/sdk/sdk.go b/sdk/sdk.go index 7704dcc5b..1fce360d5 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -1,6 +1,7 @@ package sdk import ( + "bytes" "context" "crypto/tls" _ "embed" @@ -291,21 +292,43 @@ func (t TdfType) String() string { return string(t) } +var ( + // ZIP file Signature + zipSignature = []byte{0x50, 0x4B, 0x03, 0x04} + // Nano TDF Signature + nanoSignature = []byte{0x4C, 0x31, 0x4C} +) + // GetTdfType returns the type of TDF based on the reader. // Reader is reset after the check. func GetTdfType(reader io.ReadSeeker) TdfType { - isValidNanoTdf, _ := IsValidNanoTdf(reader) + numBytes := 4 + buffer := make([]byte, numBytes) + n, err := reader.Read(buffer) + if err != nil { + return Invalid + } - if isValidNanoTdf { - return Nano + // Reset the reader to its original position + _, err = reader.Seek(0, io.SeekStart) + if err != nil { + return Invalid } - isValidStandardTdf, _ := IsValidTdf(reader) + if n < numBytes { + return Invalid + } - if isValidStandardTdf { + // Check if the first 4 bytes match the ZIP signature + if bytes.Equal(buffer, zipSignature) { return Standard } + // Check if the first 3 bytes match the Nano signature + if bytes.Equal(buffer[:3], nanoSignature) { + return Nano + } + return Invalid } diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 35d1c7831..878f28287 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -330,3 +330,43 @@ func Test_ShouldSanitizePlatformEndpoint(t *testing.T) { }) } } + +func Test_GetType_NanoTDF(t *testing.T) { + nano := "TDFMABJsb2NhbGhvc3Q6ODA4MC9rYXOAAQIA2qvjMRfg7b27lT2kf9SwHRkDIg8ZXtfRoiIvdMUHq/gL5AUMfmv4Di8sKCyLkmUm/WITVj5hDeV/z4JmQ0JL7ZxqSmgZoK6TAHvkKhUly4zMEWMRXH8IktKhFKy1+fD+3qwDopqWAO5Nm2nYQqi75atEFckstulpNKg3N+Ul22OHr/ZuR127oPObBDYNRfktBdzoZbEQcPlr8q1B57q6y5SPZFjEzL9weK+uS5bUJWkF3nsHASo2bZw7IPhTZxoFVmCDjwvj6MbxNa7zG6aClHJ162zKxLLnD9TtIHuZ59R7LgiSieipXeExj+ky9OgIw5DfwyUuxsQLtKpMIAFPmLY9Hy2naUJxke0MT1EUBgastCq+YtFGslV9LJo/A8FtrRqludwtM0O+Z9FlAkZ1oNL7M7uOkLrh7eRrv+C1AAAX6FaBQoOtqnmyu6Jp+VzkxDddEeLRUyI=" + nanoDecoded, err := base64.StdEncoding.DecodeString(nano) + require.NoError(t, err) + + in := bytes.NewReader(nanoDecoded) + tdfType := sdk.GetTdfType(in) + + assert.Equal(t, sdk.Nano, tdfType) +} + +func Test_GetType_TDF(t *testing.T) { + tdf := "UEsDBC0ACAAAAJ2TFTEAAAAAAAAAAAAAAAAJAAAAMC5wYXlsb2Fktu4m+vdwl0mtjhY3U5e7TG2o1s8ifK+RAhFNjRjGTLJ7V3w5UEsHCGiY7skkAAAAJAAAAFBLAwQtAAgAAACdkxUxAAAAAAAAAAAAAAAADwAAADAubWFuaWZlc3QuanNvbnsiZW5jcnlwdGlvbkluZm9ybWF0aW9uIjp7InR5cGUiOiJzcGxpdCIsInBvbGljeSI6ImV5SjFkV2xrSWpvaU1HTTFORGsyWlRZdE5EYzRaaTB4TVdWbUxXSXlOakV0WWpJMVl6UmhORE14TjJFM0lpd2lZbTlrZVNJNmV5SmtZWFJoUVhSMGNtbGlkWFJsY3lJNlczc2lZWFIwY21saWRYUmxJam9pYUhSMGNITTZMeTlsZUdGdGNHeGxMbU52YlM5aGRIUnlMMkYwZEhJeEwzWmhiSFZsTDNaaGJIVmxNU0lzSW1ScGMzQnNZWGxPWVcxbElqb2lJaXdpYVhORVpXWmhkV3gwSWpwbVlXeHpaU3dpY0hWaVMyVjVJam9pSWl3aWEyRnpWVkpNSWpvaUluMWRMQ0prYVhOelpXMGlPbHRkZlgwPSIsImtleUFjY2VzcyI6W3sidHlwZSI6IndyYXBwZWQiLCJ1cmwiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJwcm90b2NvbCI6ImthcyIsIndyYXBwZWRLZXkiOiJ0VVMvUE9TaVBtOGV6OGhyL2dMVGN6Y1lOT0trcUNEclZiQTBWdHZna29QbHB0M1BDZVpTdDNndnlQNVZKZXBNMmNqdVBhUWJJUGlyMjlWdVJ2T1RXZmQzRUh1KzgyVCtFNEVZbEpBM25VbDdGQTRMUGZhUEtXWk1zTExHUkJJVUxZT0VhMWJma1MvUm9Xb0EwK283WlFFVkNhYmdJN2JFRDJKV2Q2aG1yam1iUnM2d0lwOVFXNUs4Q3dJWjZVZjlGMXEwRDViTmlrbGxHaCtiaVJsV1NucEwxbHBPaFdva1gxdUJsU0VRSDNvM2JtVXFTNVVaUjRmYUxuTW5xOGR0bS8wYnJjTjUwaFNiK0xTTlZkd2daTEszTTRHTmxEeGdzcDkxY0VuYjZoZktLemdSY0VCS0tMQTF1b3BXNHdCRG9BamFuWWplQlZVT3ZBZEI5ek45T3c9PSIsInBvbGljeUJpbmRpbmciOnsiYWxnIjoiSFMyNTYiLCJoYXNoIjoiWmpBek1HWXlZekl4WlRCbU16Tm1NamhoTWpGalpqSTJaRE5oWlRrMk5ERTNaREJoWlRrM05ESTJNREExTnpVMU1UVTFNV0ZpTTJSak9EUTFabU0yWWc9PSJ9LCJraWQiOiJyMSJ9XSwibWV0aG9kIjp7ImFsZ29yaXRobSI6IkFFUy0yNTYtR0NNIiwiaXYiOiIiLCJpc1N0cmVhbWFibGUiOnRydWV9LCJpbnRlZ3JpdHlJbmZvcm1hdGlvbiI6eyJyb290U2lnbmF0dXJlIjp7ImFsZyI6IkhTMjU2Iiwic2lnIjoiWkdWaFltRmtNRGhsTURCbU1UVm1ZekJtTVdFME0ySmhOamhrTmpBMVpUazFNVGRtWmpoa1pETmtNekk0Tldaa01XUXhOVFZsWXpjME1EVXhPRE13Tmc9PSJ9LCJzZWdtZW50SGFzaEFsZyI6IkdNQUMiLCJzZWdtZW50U2l6ZURlZmF1bHQiOjIwOTcxNTIsImVuY3J5cHRlZFNlZ21lbnRTaXplRGVmYXVsdCI6MjA5NzE4MCwic2VnbWVudHMiOlt7Imhhc2giOiJNakkzWTJGbU9URXdNakV4TkdRNFpERTRZelkwWTJJeU4ySTFOemRqTXprPSIsInNlZ21lbnRTaXplIjo4LCJlbmNyeXB0ZWRTZWdtZW50U2l6ZSI6MzZ9XX19LCJwYXlsb2FkIjp7InR5cGUiOiJyZWZlcmVuY2UiLCJ1cmwiOiIwLnBheWxvYWQiLCJwcm90b2NvbCI6InppcCIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwiaXNFbmNyeXB0ZWQiOnRydWV9fVBLBwgwpFOlrwUAAK8FAABQSwECLQAtAAgAAACdkxUxaJjuySQAAAAkAAAACQAAAAAAAAAAAAAAAAAAAAAAMC5wYXlsb2FkUEsBAi0ALQAIAAAAnZMVMTCkU6WvBQAArwUAAA8AAAAAAAAAAAAAAAAAWwAAADAubWFuaWZlc3QuanNvblBLBQYAAAAAAgACAHQAAABHBgAAAAA=" + tdfDecoded, err := base64.StdEncoding.DecodeString(tdf) + require.NoError(t, err) + + in := bytes.NewReader(tdfDecoded) + tdfType := sdk.GetTdfType(in) + + assert.Equal(t, sdk.Standard, tdfType) +} + +func Test_GetType_InvalidTDF(t *testing.T) { + tdf := "" + in := bytes.NewReader([]byte(tdf)) + + tdfType := sdk.GetTdfType(in) + + assert.Equal(t, sdk.Invalid, tdfType) +} + +func Test_GetType_Invalid2Bytes(t *testing.T) { + tdf := "UE" + in := bytes.NewReader([]byte(tdf)) + + tdfType := sdk.GetTdfType(in) + + assert.Equal(t, sdk.Invalid, tdfType) +} From 88496cdb36d015fddffa2383c742350e3ed373b3 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:42:53 +0000 Subject: [PATCH 02/32] chore(main): release sdk 0.3.19 (#1737) :robot: I have created a release *beep* *boop* --- ## [0.3.19](https://github.com/opentdf/platform/compare/sdk/v0.3.18...sdk/v0.3.19) (2024-11-12) ### Bug Fixes * update GetType to check the first 4 bytes ([#1736](https://github.com/opentdf/platform/issues/1736)) ([d6a1e6d](https://github.com/opentdf/platform/commit/d6a1e6d6bf60e970afe8fc26c483cfe2e340fdd4)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- sdk/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f4e3c6c4f..54ab6d67b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -3,6 +3,6 @@ "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", "protocol/go": "0.2.20", - "sdk": "0.3.18", + "sdk": "0.3.19", "service": "0.4.26" } diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index d6ed2c2d2..1ada8b556 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.3.19](https://github.com/opentdf/platform/compare/sdk/v0.3.18...sdk/v0.3.19) (2024-11-12) + + +### Bug Fixes + +* update GetType to check the first 4 bytes ([#1736](https://github.com/opentdf/platform/issues/1736)) ([d6a1e6d](https://github.com/opentdf/platform/commit/d6a1e6d6bf60e970afe8fc26c483cfe2e340fdd4)) + ## [0.3.18](https://github.com/opentdf/platform/compare/sdk/v0.3.17...sdk/v0.3.18) (2024-11-06) From ae931d02f347edea468d4c5d48ab3e07ce7d3abe Mon Sep 17 00:00:00 2001 From: Elizabeth Healy <35498075+elizabethhealy@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:29:09 -0500 Subject: [PATCH 03/32] feat(authz): Remove org-admin role, move privileges to admin role (#1740) ### Proposed Changes * dont need a separate org-admin role, remove it from keycloak setup and casbin config ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- docs/configuration.md | 11 +- lib/fixtures/keycloak.go | 14 +-- opentdf-dev.yaml | 7 +- opentdf-example.yaml | 7 +- opentdf-with-hsm.yaml | 7 +- service/cmd/keycloak_data.yaml | 5 +- service/internal/auth/casbin.go | 57 ++-------- service/internal/auth/casbin_test.go | 163 ++++++++------------------- service/pkg/server/options.go | 2 +- 9 files changed, 67 insertions(+), 206 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index fb2f8b5f6..b9ffd50e6 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -256,19 +256,10 @@ server: map: standard: opentdf-standard admin: opentdf-admin - org-admin: opentdf-org-admin ## Custom policy (see examples https://github.com/casbin/casbin/tree/master/examples) csv: | - p, role:org-admin, policy:attributes, *, *, allow - p, role:org-admin, policy:subject-mappings, *, *, allow - p, role:org-admin, policy:resource-mappings, *, *, allow - p, role:org-admin, policy:kas-registry, *, *, allow - p, role:org-admin, policy:unsafe, *, *, allow - p, role:admin, policy:attributes, read, allow - p, role:admin, policy:subject-mappings, read, allow - p, role:admin, policy:resource-mappings, read, allow - p, role:admin, policy:kas-registry, read, allow + p, role:admin, *, *, allow p, role:standard, policy:attributes, read, allow p, role:standard, policy:subject-mappings, read, allow p, role:standard, policy:resource-mappings, read, allow diff --git a/lib/fixtures/keycloak.go b/lib/fixtures/keycloak.go index 57e860e1c..00df88dd3 100644 --- a/lib/fixtures/keycloak.go +++ b/lib/fixtures/keycloak.go @@ -120,7 +120,6 @@ func SetupKeycloak(ctx context.Context, kcConnectParams KeycloakConnectParams) e opentdfClientID := "opentdf" opentdfSdkClientID := "opentdf-sdk" - opentdfOrgAdminRoleName := "opentdf-org-admin" opentdfAdminRoleName := "opentdf-admin" opentdfStandardRoleName := "opentdf-standard" testingOnlyRoleName := "opentdf-testing-role" @@ -155,7 +154,7 @@ func SetupKeycloak(ctx context.Context, kcConnectParams KeycloakConnectParams) e } // Create Roles - roles := []string{opentdfOrgAdminRoleName, opentdfAdminRoleName, opentdfStandardRoleName, testingOnlyRoleName} + roles := []string{opentdfAdminRoleName, opentdfStandardRoleName, testingOnlyRoleName} for _, role := range roles { _, err := client.CreateRealmRole(ctx, token.AccessToken, kcConnectParams.Realm, gocloak.Role{ Name: gocloak.StringP(role), @@ -173,8 +172,7 @@ func SetupKeycloak(ctx context.Context, kcConnectParams KeycloakConnectParams) e } // Get the roles - var opentdfOrgAdminRole *gocloak.Role - // var opentdfAdminRole *gocloak.Role + var opentdfAdminRole *gocloak.Role var opentdfStandardRole *gocloak.Role var testingOnlyRole *gocloak.Role realmRoles, err := client.GetRealmRoles(ctx, token.AccessToken, kcConnectParams.Realm, gocloak.GetRoleParams{ @@ -187,10 +185,8 @@ func SetupKeycloak(ctx context.Context, kcConnectParams KeycloakConnectParams) e slog.Info(fmt.Sprintf("✅ Roles found: %d", len(realmRoles))) // , slog.String("roles", fmt.Sprintf("%v", realmRoles)) for _, role := range realmRoles { switch *role.Name { - case opentdfOrgAdminRoleName: - opentdfOrgAdminRole = role - // case opentdfAdminRoleName: - // opentdfAdminRole = role + case opentdfAdminRoleName: + opentdfAdminRole = role case opentdfStandardRoleName: opentdfStandardRole = role case testingOnlyRoleName: @@ -207,7 +203,7 @@ func SetupKeycloak(ctx context.Context, kcConnectParams KeycloakConnectParams) e ClientAuthenticatorType: gocloak.StringP("client-secret"), Secret: gocloak.StringP("secret"), ProtocolMappers: &protocolMappers, - }, []gocloak.Role{*opentdfOrgAdminRole}, nil) + }, []gocloak.Role{*opentdfAdminRole}, nil) if err != nil { return err } diff --git a/opentdf-dev.yaml b/opentdf-dev.yaml index d415dfa55..4a8509647 100644 --- a/opentdf-dev.yaml +++ b/opentdf-dev.yaml @@ -49,15 +49,10 @@ server: map: # standard: opentdf-standard # admin: opentdf-admin - # org-admin: opentdf-org-admin ## Custom policy (see examples https://github.com/casbin/casbin/tree/master/examples) csv: #| - # p, role:org-admin, policy:attributes, *, *, allow - # p, role:org-admin, policy:subject-mappings, *, *, allow - # p, role:org-admin, policy:resource-mappings, *, *, allow - # p, role:org-admin, policy:kas-registry, *, *, allow - # p, role:org-admin, policy:unsafe, *, *, allow + # p, role:admin, *, *, allow ## Custom model (see https://casbin.org/docs/syntax-for-models/) model: #| diff --git a/opentdf-example.yaml b/opentdf-example.yaml index 8050abcfa..6fd6549ae 100644 --- a/opentdf-example.yaml +++ b/opentdf-example.yaml @@ -40,15 +40,10 @@ server: map: # standard: opentdf-standard # admin: opentdf-admin - # org-admin: opentdf-org-admin ## Custom policy (see examples https://github.com/casbin/casbin/tree/master/examples) csv: #| - # p, role:org-admin, policy:attributes, *, *, allow - # p, role:org-admin, policy:subject-mappings, *, *, allow - # p, role:org-admin, policy:resource-mappings, *, *, allow - # p, role:org-admin, policy:kas-registry, *, *, allow - # p, role:org-admin, policy:unsafe, *, *, allow + # p, role:admin, *, *, allow ## Custom model (see https://casbin.org/docs/syntax-for-models/) model: #| # [request_definition] diff --git a/opentdf-with-hsm.yaml b/opentdf-with-hsm.yaml index 8ac69e9c7..476a45922 100644 --- a/opentdf-with-hsm.yaml +++ b/opentdf-with-hsm.yaml @@ -47,14 +47,9 @@ server: map: # standard: opentdf-standard # admin: opentdf-admin - # org-admin: opentdf-org-admin ## Custom policy (see examples https://github.com/casbin/casbin/tree/master/examples) csv: #| - # p, role:org-admin, policy:attributes, *, *, allow - # p, role:org-admin, policy:subject-mappings, *, *, allow - # p, role:org-admin, policy:resource-mappings, *, *, allow - # p, role:org-admin, policy:kas-registry, *, *, allow - # p, role:org-admin, policy:unsafe, *, *, allow + # p, role:admin, *, *, allow ## Custom model (see https://casbin.org/docs/syntax-for-models/) model: #| # [request_definition] diff --git a/service/cmd/keycloak_data.yaml b/service/cmd/keycloak_data.yaml index 006a326b2..201a2b654 100644 --- a/service/cmd/keycloak_data.yaml +++ b/service/cmd/keycloak_data.yaml @@ -13,7 +13,6 @@ realms: realm: opentdf enabled: true custom_realm_roles: - - name: opentdf-org-admin - name: opentdf-admin - name: opentdf-standard custom_client_roles: @@ -35,7 +34,7 @@ realms: protocolMappers: - *customAudMapper sa_realm_roles: - - opentdf-org-admin + - opentdf-admin - client: clientID: opentdf-sdk enabled: true @@ -98,7 +97,7 @@ realms: groups: - mygroup realmRoles: - - opentdf-org-admin + - opentdf-admin clientRoles: realm-management: - view-clients diff --git a/service/internal/auth/casbin.go b/service/internal/auth/casbin.go index 62ff9fd33..8bc392b49 100644 --- a/service/internal/auth/casbin.go +++ b/service/internal/auth/casbin.go @@ -24,14 +24,12 @@ var ( var defaultRoleClaim = "realm_access.roles" var defaultRoleMap = map[string]string{ - "standard": "opentdf-standard", - "admin": "opentdf-admin", - "org-admin": "opentdf-org-admin", + "standard": "opentdf-standard", + "admin": "opentdf-admin", } var defaultPolicy = ` ## Roles (prefixed with role:) -# org-admin - organization admin # admin - admin # standard - standard # unknown - unknown role or no role @@ -46,51 +44,19 @@ var defaultPolicy = ` # delete - delete the resource # unsafe - unsafe actions -# Role: Org-Admin -## gRPC routes -p, role:org-admin, policy.*, *, allow -p, role:org-admin, kasregistry.*, *, allow -p, role:org-admin, kas.AccessService/Rewrap, *, allow -p, role:org-admin, authorization.*, *, allow -## HTTP routes -p, role:org-admin, /attributes*, *, allow -p, role:org-admin, /namespaces*, *, allow -p, role:org-admin, /subject-mappings*, *, allow -p, role:org-admin, /resource-mappings*, *, allow -p, role:org-admin, /key-access-servers*, *, allow -p, role:org-admin, /kas/v2/rewrap, *, allow -p, role:org-admin, /unsafe*, *, allow -p, role:org-admin, /v1/entitlements, *, allow -p, role:org-admin, /v1/authorization, *, allow -p, role:org-admin, /v1/token/authorization, *, allow # Role: Admin -## gRPC routes -p, role:admin, policy.*, read, allow -p, role:admin, policy.*, write, allow -p, role:admin, policy.*, delete, allow -p, role:admin, kasregistry.*, *, allow -p, role:admin, kas.AccessService/Rewrap, *, allow -p, role:admin, authorization.*, *, allow -## HTTP routes -p, role:admin, /attributes*, *, allow -p, role:admin, /namespaces*, *, allow -p, role:admin, /subject-mappings*, *, allow -p, role:admin, /resource-mappings*, *, allow -p, role:admin, /key-access-servers*, *, allow -p, role:admin, /kas/v2/rewrap, *, allow -p, role:admin, /v1/entitlements, *, allow -p, role:admin, /v1/authorization, *, allow -p, role:admin, /v1/token/authorization, *, allow - +## gRPC and HTTP routes +p, role:admin, *, *, allow ## Role: Standard ## gRPC routes p, role:standard, policy.*, read, allow p, role:standard, kasregistry.*, read, allow -p, role:standard, kas.AccessService/Rewrap, *, allow -p, role:standard, authorization.AuthorizationService/GetDecisions, read, allow -p, role:standard, authorization.AuthorizationService/GetDecisionsByToken, read, allow +p, role:standard, kas.AccessService/Rewrap, *, allow +p, role:standard, authorization.AuthorizationService/GetDecisions, read, allow +p, role:standard, authorization.AuthorizationService/GetDecisionsByToken, read, allow + ## HTTP routes p, role:standard, /attributes*, read, allow p, role:standard, /namespaces*, read, allow @@ -98,18 +64,15 @@ p, role:standard, /subject-mappings*, read, allow p, role:standard, /resource-mappings*, read, allow p, role:standard, /key-access-servers*, read, allow p, role:standard, /kas/v2/rewrap, write, allow -p, role:standard, /entityresolution/resolve, write, allow -p, role:standard, /v1/authorization, write, allow -p, role:standard, /v1/token/authorization, write, allow +p, role:standard, /v1/authorization, write, allow +p, role:standard, /v1/token/authorization, write, allow # Public routes ## gRPC routes ## for ERS, right now we don't care about requester role, just that a valid jwt is provided when the OPA engine calls (enforced in the ERS itself, not casbin) -p, role:unknown, entityresolution.EntityResolutionService.ResolveEntities, write, allow p, role:unknown, kas.AccessService/Rewrap, *, allow ## HTTP routes ## for ERS, right now we don't care about requester role, just that a valid jwt is provided when the OPA engine calls (enforced in the ERS itself, not casbin) -p, role:unknown, /entityresolution/resolve, write, allow p, role:unknown, /kas/v2/rewrap, *, allow ` diff --git a/service/internal/auth/casbin_test.go b/service/internal/auth/casbin_test.go index 2ded15f85..8a013f0d0 100644 --- a/service/internal/auth/casbin_test.go +++ b/service/internal/auth/casbin_test.go @@ -24,27 +24,19 @@ type AuthnCasbinSuite struct { suite.Suite } -func (s *AuthnCasbinSuite) buildTokenRoles(orgAdmin bool, admin bool, standard bool, roleMaps []string) []interface{} { - orgAdminRole := "opentdf-org-admin" - if len(roleMaps) > 0 { - orgAdminRole = roleMaps[0] - } +func (s *AuthnCasbinSuite) buildTokenRoles(admin bool, standard bool, roleMaps []string) []interface{} { adminRole := "opentdf-admin" - if len(roleMaps) > 1 { - adminRole = roleMaps[1] + if len(roleMaps) > 0 { + adminRole = roleMaps[0] } standardRole := "opentdf-standard" - if len(roleMaps) > 2 { - standardRole = roleMaps[2] + if len(roleMaps) > 1 { + standardRole = roleMaps[1] } i := 0 - roles := make([]interface{}, 3) + roles := make([]interface{}, 2) - if orgAdmin { - roles[i] = orgAdminRole - i++ - } if admin { roles[i] = adminRole i++ @@ -56,27 +48,27 @@ func (s *AuthnCasbinSuite) buildTokenRoles(orgAdmin bool, admin bool, standard b return roles } -func (s *AuthnCasbinSuite) newTokWithDefaultClaim(orgAdmin bool, admin bool, standard bool) jwt.Token { +func (s *AuthnCasbinSuite) newTokWithDefaultClaim(admin bool, standard bool) jwt.Token { tok := jwt.New() - tokenRoles := s.buildTokenRoles(orgAdmin, admin, standard, nil) + tokenRoles := s.buildTokenRoles(admin, standard, nil) if err := tok.Set("realm_access", map[string]interface{}{"roles": tokenRoles}); err != nil { s.T().Fatal(err) } return tok } -func (s *AuthnCasbinSuite) newTokenWithCustomClaim(orgAdmin bool, admin bool, standard bool) (string, jwt.Token) { +func (s *AuthnCasbinSuite) newTokenWithCustomClaim(admin bool, standard bool) (string, jwt.Token) { tok := jwt.New() - tokenRoles := s.buildTokenRoles(orgAdmin, admin, standard, nil) + tokenRoles := s.buildTokenRoles(admin, standard, nil) if err := tok.Set("test", map[string]interface{}{"test_roles": map[string]interface{}{"roles": tokenRoles}}); err != nil { s.T().Fatal(err) } return "test.test_roles.roles", tok } -func (s *AuthnCasbinSuite) newTokenWithCustomRoleMap(orgAdmin bool, admin bool, standard bool) (string, jwt.Token) { +func (s *AuthnCasbinSuite) newTokenWithCustomRoleMap(admin bool, standard bool) (string, jwt.Token) { tok := jwt.New() - tokenRoles := s.buildTokenRoles(orgAdmin, admin, standard, []string{"test-org-admin", "test-admin", "test-standard"}) + tokenRoles := s.buildTokenRoles(admin, standard, []string{"test-admin", "test-standard"}) if err := tok.Set("realm_access", map[string]interface{}{"roles": tokenRoles}); err != nil { s.T().Fatal(err) } @@ -154,10 +146,9 @@ func (s *AuthnCasbinSuite) Test_NewEnforcerWithBadCustomModel() { } func (s *AuthnCasbinSuite) Test_Enforcement() { - orgadmin := []bool{true, false, false} - admin := []bool{false, true, false} - standard := []bool{false, false, true} - unknown := []bool{false, false, false} + admin := []bool{true, false} + standard := []bool{false, true} + unknown := []bool{false, false} tests := []struct { name string @@ -166,38 +157,6 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { resource string action string }{ - // // org-admin role - { - allowed: true, - roles: orgadmin, - resource: "policy.attributes.DoSomething", - action: "read", - }, - { - allowed: true, - roles: orgadmin, - resource: "policy.attributes.DoSomething", - action: "write", - }, - { - allowed: true, - roles: orgadmin, - resource: "/attributes/do/something", - action: "read", - }, - { - allowed: true, - roles: orgadmin, - resource: "/attributes/do/something", - action: "write", - }, - { - allowed: false, - roles: orgadmin, - resource: "non-existent", - action: "read", - }, - // admin role { allowed: true, @@ -224,7 +183,7 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { action: "write", }, { - allowed: false, + allowed: true, roles: admin, resource: "non-existent", action: "read", @@ -318,10 +277,8 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { var actor string switch { case test.roles[0]: - actor = "org-admin" - case test.roles[1]: actor = "admin" - case test.roles[2]: + case test.roles[1]: actor = "standard" default: actor = "undefined" @@ -331,7 +288,7 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { slog.Info("running test w/ default claim", slog.String("name", name)) enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) s.Require().NoError(err) - tok := s.newTokWithDefaultClaim(test.roles[0], test.roles[1], test.roles[2]) + tok := s.newTokWithDefaultClaim(test.roles[0], test.roles[1]) allowed, err := enforcer.Enforce(tok, test.resource, test.action) if !test.allowed { s.Require().Error(err) @@ -347,7 +304,7 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { }, }, logger.CreateTestLogger()) s.Require().NoError(err) - _, tok = s.newTokenWithCustomClaim(test.roles[0], test.roles[1], test.roles[2]) + _, tok = s.newTokenWithCustomClaim(test.roles[0], test.roles[1]) allowed, err = enforcer.Enforce(tok, test.resource, test.action) if !test.allowed { s.Require().Error(err) @@ -360,14 +317,13 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { enforcer, err = NewCasbinEnforcer(CasbinConfig{ PolicyConfig: PolicyConfig{ RoleMap: map[string]string{ - "org-admin": "test-org-admin", - "admin": "test-admin", - "standard": "test-standard", + "admin": "test-admin", + "standard": "test-standard", }, }, }, logger.CreateTestLogger()) s.Require().NoError(err) - _, tok = s.newTokenWithCustomRoleMap(test.roles[0], test.roles[1], test.roles[2]) + _, tok = s.newTokenWithCustomRoleMap(test.roles[0], test.roles[1]) allowed, err = enforcer.Enforce(tok, test.resource, test.action) if !test.allowed { s.Require().Error(err) @@ -378,12 +334,9 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { slog.Info("running test w/ client_id", slog.String("name", name)) roleMap := make(map[string]string) if test.roles[0] { - roleMap["org-admin"] = "test" - } - if test.roles[1] { roleMap["admin"] = "test" } - if test.roles[2] { + if test.roles[1] { roleMap["standard"] = "test" } @@ -408,39 +361,22 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies() { enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) s.Require().NoError(err) - tok := s.newTokWithDefaultClaim(true, false, false) - - // Org-admin role - err = enforcer.ExtendDefaultPolicy([][]string{{"p", "role:org-admin", "new.service.*", "*", "allow"}}) - s.Require().NoError(err) - - // original org-admin policy still evaluates correctly - allowed, err := enforcer.Enforce(tok, "policy.attributes.DoSomething", "write") - s.Require().NoError(err) - s.True(allowed) - - // allowed role for new policy is allowed - allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") + // other roles denied new policy: admin + tok := s.newTokWithDefaultClaim(true, false) + allowed, err := enforcer.Enforce(tok, "new.service.DoSomething", "read") s.Require().NoError(err) s.True(allowed) allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") s.Require().NoError(err) s.True(allowed) - // other roles denied new policy: admin - tok = s.newTokWithDefaultClaim(false, true, false) - allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") - s.Require().Error(err) - s.False(allowed) - allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") - s.Require().Error(err) - s.False(allowed) - // other roles denied new policy: standard - tok = s.newTokWithDefaultClaim(false, false, true) + tok = s.newTokWithDefaultClaim(false, true) + err = enforcer.ExtendDefaultPolicy([][]string{{"p", "role:standard", "new.service.*", "read", "allow"}}) + s.Require().NoError(err) allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") - s.Require().Error(err) - s.False(allowed) + s.Require().NoError(err) + s.True(allowed) allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") s.Require().Error(err) s.False(allowed) @@ -450,16 +386,14 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MultipleExtensions() { enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) s.Require().NoError(err) - // Org-admin role err = enforcer.ExtendDefaultPolicy([][]string{ - {"p", "role:org-admin", "new.service.*", "*", "allow"}, - {"p", "role:admin", "new.hello.*", "*", "allow"}, + {"p", "role:standard", "new.service.*", "write", "allow"}, + {"p", "role:standard", "new.hello.*", "read", "allow"}, }) s.Require().NoError(err) - orgAdminTok := s.newTokWithDefaultClaim(true, false, false) - adminTok := s.newTokWithDefaultClaim(false, true, false) - standardTok := s.newTokWithDefaultClaim(false, false, true) + adminTok := s.newTokWithDefaultClaim(true, false) + standardTok := s.newTokWithDefaultClaim(false, true) cases := []struct { tok jwt.Token expectedAllowed bool @@ -467,25 +401,18 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MultipleExtensions() { action string }{ // original default policy still evaluates correctly - {orgAdminTok, true, "policy.attributes.CreateAttribute", "write"}, - // both new policies are evaluated correctly - {orgAdminTok, true, "new.service.ActionableObject", "read"}, - {orgAdminTok, true, "new.service.ActionableObject", "write"}, - {orgAdminTok, false, "new.hello.World", "read"}, - {orgAdminTok, false, "new.hello.World", "write"}, - {orgAdminTok, false, "new.hello.SomethingElse", "read"}, - {orgAdminTok, false, "new.hello.SomethingElse", "write"}, - {adminTok, false, "new.service.ActionableObject", "read"}, - {adminTok, false, "new.service.ActionableObject", "write"}, + {adminTok, true, "policy.attributes.CreateAttribute", "write"}, + {adminTok, true, "new.service.ActionableObject", "read"}, + {adminTok, true, "new.service.ActionableObject", "write"}, {adminTok, true, "new.hello.World", "read"}, {adminTok, true, "new.hello.World", "write"}, {adminTok, true, "new.hello.SomethingElse", "read"}, {adminTok, true, "new.hello.SomethingElse", "write"}, {standardTok, false, "new.service.ActionableObject", "read"}, - {standardTok, false, "new.service.ActionableObject", "write"}, - {standardTok, false, "new.hello.World", "read"}, + {standardTok, true, "new.service.ActionableObject", "write"}, + {standardTok, true, "new.hello.World", "read"}, {standardTok, false, "new.hello.World", "write"}, - {standardTok, false, "new.hello.SomethingElse", "read"}, + {standardTok, true, "new.hello.SomethingElse", "read"}, {standardTok, false, "new.hello.SomethingElse", "write"}, } @@ -503,18 +430,18 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MultipleExtensions() { func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MalformedErrors() { enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) s.Require().NoError(err) - tok := s.newTokWithDefaultClaim(true, false, false) + tok := s.newTokWithDefaultClaim(true, false) allowed, err := enforcer.Enforce(tok, "policy.attributes.DoSomething", "read") s.Require().NoError(err) s.True(allowed) // missing 'p' - err = enforcer.ExtendDefaultPolicy([][]string{{"role:org-admin", "new.service.DoSomething", "*"}}) + err = enforcer.ExtendDefaultPolicy([][]string{{"role:admin", "new.service.DoSomething", "*"}}) s.Require().Error(err) s.Require().ErrorIs(err, ErrPolicyMalformed) // missing effect - err = enforcer.ExtendDefaultPolicy([][]string{{"p", "role:org-admin", "new.service.DoSomething", "*"}}) + err = enforcer.ExtendDefaultPolicy([][]string{{"p", "role:admin", "new.service.DoSomething", "*"}}) s.Require().Error(err) s.Require().ErrorIs(err, ErrPolicyMalformed) @@ -524,7 +451,7 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MalformedErrors() { s.Require().ErrorIs(err, ErrPolicyMalformed) // missing role prefix - err = enforcer.ExtendDefaultPolicy([][]string{{"p", "org-admin", "new.service.DoSomething", "*"}}) + err = enforcer.ExtendDefaultPolicy([][]string{{"p", "admin", "new.service.DoSomething", "*"}}) s.Require().Error(err) s.Require().ErrorIs(err, ErrPolicyMalformed) } diff --git a/service/pkg/server/options.go b/service/pkg/server/options.go index 6a44e268f..a570f957d 100644 --- a/service/pkg/server/options.go +++ b/service/pkg/server/options.go @@ -62,7 +62,7 @@ func WithPublicRoutes(routes []string) StartOptions { // Example: // // opentdf.WithAuthZDefaultPolicyExtension([][]string{ -// {"p","role:org-admin", "pep*", "*","allow"), +// {"p","role:admin", "pep*", "*","allow"), // }), func WithAuthZDefaultPolicyExtension(policies [][]string) StartOptions { return func(c StartConfig) StartConfig { From d10ba3cb22175a000ba5d156987c9f201749ae88 Mon Sep 17 00:00:00 2001 From: Sean Trantalis Date: Wed, 13 Nov 2024 14:43:20 -0500 Subject: [PATCH 04/32] feat: backend migration to connect-rpc (#1733) ### Proposed Changes Implementation of the following adr https://github.com/opentdf/platform/issues/1524 The breaking changes are from changing the Idempontency Level. This is required if we would like to support GET request on some of our services. https://connectrpc.com/docs/go/get-requests-and-caching ### Checklist - [x] I have added or updated unit tests - [x] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --------- Co-authored-by: Jake Van Vorhis <83739412+jakedoublev@users.noreply.github.com> --- docs/grpc/index.html | 217 ++++++++++ go.work.sum | 1 + protocol/go/kas/kas.pb.go | 63 +-- protocol/go/kas/kasconnect/kas.connect.go | 4 + .../go/policy/attributes/attributes.pb.go | 313 +++++++------- .../attributesconnect/attributes.connect.go | 8 + .../key_access_server_registry.connect.go | 6 + .../key_access_server_registry.pb.go | 130 +++--- .../go/policy/namespaces/namespaces.pb.go | 161 ++++---- .../namespacesconnect/namespaces.connect.go | 4 + .../resourcemapping/resource_mapping.pb.go | 239 +++++------ .../resource_mapping.connect.go | 10 + .../subjectmapping/subject_mapping.pb.go | 251 +++++------ .../subject_mapping.connect.go | 8 + .../wellknown_configuration.pb.go | 40 +- .../wellknown_configuration.connect.go | 2 + sdk/audit/context_keys.go | 4 + service/authorization/authorization.go | 99 ++--- service/authorization/authorization_test.go | 390 ++++++++++-------- .../claims/claims_entity_resolution.go | 23 +- service/entityresolution/entityresolution.go | 21 +- .../keycloak/keycloak_entity_resolution.go | 64 ++- .../keycloak_entity_resolution_test.go | 176 ++++---- service/go.mod | 5 +- service/go.sum | 6 + service/health/health.go | 50 ++- service/health/health_test.go | 33 +- service/internal/auth/authn.go | 95 +++-- service/internal/auth/authn_test.go | 71 ++-- service/internal/server/realip/realip.go | 6 +- service/internal/server/server.go | 282 +++++++------ service/kas/access/publicKey.go | 39 +- service/kas/access/publicKey_test.go | 61 +-- service/kas/access/rewrap.go | 31 +- service/kas/access/rewrap_test.go | 9 +- service/kas/kas.go | 23 +- service/kas/kas.proto | 2 + .../logger/audit/contextServerInterceptor.go | 86 ++-- service/logger/audit/getDecision_test.go | 3 +- service/logger/audit/helpers_test.go | 12 +- service/logger/audit/policy_test.go | 4 +- service/logger/audit/rewrap_test.go | 3 +- service/logger/audit/utils.go | 13 +- service/logger/audit/utils_test.go | 10 +- service/pkg/db/errors.go | 17 +- service/pkg/server/services.go | 31 +- service/pkg/server/services_test.go | 8 +- service/pkg/server/start.go | 2 +- service/pkg/server/start_test.go | 2 +- .../pkg/serviceregistry/serviceregistry.go | 45 +- service/policy/attributes/attributes.go | 229 +++++----- service/policy/attributes/attributes.proto | 4 + .../kasregistry/key_access_server_registry.go | 126 +++--- .../key_access_server_registry.proto | 3 + service/policy/namespaces/namespaces.go | 90 ++-- service/policy/namespaces/namespaces.proto | 2 + .../resourcemapping/resource_mapping.go | 198 +++++---- .../resourcemapping/resource_mapping.proto | 5 + .../policy/subjectmapping/subject_mapping.go | 154 +++---- .../subjectmapping/subject_mapping.proto | 4 + service/policy/unsafe/unsafe.go | 93 +++-- .../wellknown_configuration.go | 29 +- .../wellknown_configuration.proto | 1 + 63 files changed, 2309 insertions(+), 1812 deletions(-) diff --git a/docs/grpc/index.html b/docs/grpc/index.html index e97dd32d9..30670c641 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -3483,6 +3483,32 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + +
Method NameOption
PublicKey

NO_SIDE_EFFECTS

LegacyPublicKey

NO_SIDE_EFFECTS

+ +
@@ -5106,6 +5132,42 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListAttributes

NO_SIDE_EFFECTS

ListAttributeValues

NO_SIDE_EFFECTS

GetAttribute

NO_SIDE_EFFECTS

GetAttributeValuesByFqns

NO_SIDE_EFFECTS

+ +
@@ -5714,6 +5776,37 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListKeyAccessServers

NO_SIDE_EFFECTS

GetKeyAccessServer

NO_SIDE_EFFECTS

ListKeyAccessServerGrants

NO_SIDE_EFFECTS

+ +
@@ -6265,6 +6358,32 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + +
Method NameOption
GetNamespace

NO_SIDE_EFFECTS

ListNamespaces

NO_SIDE_EFFECTS

+ +
@@ -7214,6 +7333,47 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListResourceMappingGroups

NO_SIDE_EFFECTS

GetResourceMappingGroup

NO_SIDE_EFFECTS

ListResourceMappings

NO_SIDE_EFFECTS

ListResourceMappingsByGroupFqns

NO_SIDE_EFFECTS

GetResourceMapping

NO_SIDE_EFFECTS

+ +
@@ -8157,6 +8317,42 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListSubjectMappings

NO_SIDE_EFFECTS

GetSubjectMapping

NO_SIDE_EFFECTS

ListSubjectConditionSets

NO_SIDE_EFFECTS

GetSubjectConditionSet

NO_SIDE_EFFECTS

+ +
@@ -9009,6 +9205,27 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + +
Method NameOption
GetWellKnownConfiguration

NO_SIDE_EFFECTS

+ +

Scalar Value Types

diff --git a/go.work.sum b/go.work.sum index b473435b0..3b76f7b56 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,6 +1,7 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 h1:SRsZGA7aFnCZETmov57jwPrWuTmaZK6+4R4v5FUe1/c= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= +buf.build/gen/go/bufbuild/protovalidate-testing/protocolbuffers/go v1.31.0-20230824200732-8bc04916caea.1/go.mod h1:cJ4gQkiW4uPTUTI3+O2862OzMSTnzrFNwMauHLwPDPg= cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= diff --git a/protocol/go/kas/kas.pb.go b/protocol/go/kas/kas.pb.go index d2ebb9b6c..eee98539a 100644 --- a/protocol/go/kas/kas.pb.go +++ b/protocol/go/kas/kas.pb.go @@ -452,42 +452,43 @@ var file_kas_kas_proto_rawDesc = []byte{ 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xc8, 0x02, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xce, 0x02, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x6b, 0x61, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x12, 0x75, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x27, - 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x6b, 0x61, 0x73, 0x5f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x58, 0x0a, 0x06, 0x52, 0x65, 0x77, 0x72, 0x61, - 0x70, 0x12, 0x12, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, - 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x92, 0x41, 0x09, 0x4a, - 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, - 0x2a, 0x22, 0x0e, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x77, 0x72, 0x61, - 0x70, 0x42, 0xe2, 0x01, 0x92, 0x41, 0x73, 0x12, 0x71, 0x0a, 0x1a, 0x4f, 0x70, 0x65, 0x6e, 0x54, - 0x44, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2a, 0x4c, 0x0a, 0x12, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, - 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x12, 0x36, 0x68, 0x74, 0x74, - 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, - 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, - 0x4e, 0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, - 0x6b, 0x61, 0x73, 0x42, 0x08, 0x4b, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, - 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x61, 0x73, 0xa2, 0x02, 0x03, 0x4b, - 0x58, 0x58, 0xaa, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xca, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xe2, 0x02, - 0x0f, 0x4b, 0x61, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x03, 0x4b, 0x61, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x90, 0x02, 0x01, 0x12, 0x78, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x2a, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x6b, 0x61, 0x73, 0x5f, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x90, 0x02, 0x01, 0x12, 0x58, 0x0a, + 0x06, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x12, 0x12, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, + 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6b, 0x61, + 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x25, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, + 0x2f, 0x72, 0x65, 0x77, 0x72, 0x61, 0x70, 0x42, 0xe2, 0x01, 0x92, 0x41, 0x73, 0x12, 0x71, 0x0a, + 0x1a, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x44, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2a, 0x4c, 0x0a, 0x12, 0x42, + 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x43, 0x6c, 0x65, 0x61, + 0x72, 0x12, 0x36, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x62, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, + 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x35, 0x2e, 0x30, + 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, 0x6b, 0x61, 0x73, 0x42, 0x08, 0x4b, 0x61, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, + 0x61, 0x73, 0xa2, 0x02, 0x03, 0x4b, 0x58, 0x58, 0xaa, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xca, 0x02, + 0x03, 0x4b, 0x61, 0x73, 0xe2, 0x02, 0x0f, 0x4b, 0x61, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x03, 0x4b, 0x61, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/kas/kasconnect/kas.connect.go b/protocol/go/kas/kasconnect/kas.connect.go index 7af392004..fb443bfd9 100644 --- a/protocol/go/kas/kasconnect/kas.connect.go +++ b/protocol/go/kas/kasconnect/kas.connect.go @@ -73,12 +73,14 @@ func NewAccessServiceClient(httpClient connect.HTTPClient, baseURL string, opts httpClient, baseURL+AccessServicePublicKeyProcedure, connect.WithSchema(accessServicePublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), legacyPublicKey: connect.NewClient[kas.LegacyPublicKeyRequest, wrapperspb.StringValue]( httpClient, baseURL+AccessServiceLegacyPublicKeyProcedure, connect.WithSchema(accessServiceLegacyPublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), rewrap: connect.NewClient[kas.RewrapRequest, kas.RewrapResponse]( @@ -130,12 +132,14 @@ func NewAccessServiceHandler(svc AccessServiceHandler, opts ...connect.HandlerOp AccessServicePublicKeyProcedure, svc.PublicKey, connect.WithSchema(accessServicePublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) accessServiceLegacyPublicKeyHandler := connect.NewUnaryHandler( AccessServiceLegacyPublicKeyProcedure, svc.LegacyPublicKey, connect.WithSchema(accessServiceLegacyPublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) accessServiceRewrapHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/attributes/attributes.pb.go b/protocol/go/policy/attributes/attributes.pb.go index 959297d55..818857614 100644 --- a/protocol/go/policy/attributes/attributes.pb.go +++ b/protocol/go/policy/attributes/attributes.pb.go @@ -2094,176 +2094,177 @@ var file_policy_attributes_attributes_proto_rawDesc = []byte{ 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x32, 0xc1, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x72, 0x32, 0xcd, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, - 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x79, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, - 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x66, 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0x8e, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x91, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, + 0x74, 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x95, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, + 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x7c, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0xa1, 0x01, 0x0a, + 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, + 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, - 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, - 0x2a, 0x32, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, - 0x18, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x66, 0x71, 0x6e, 0x90, 0x02, 0x01, + 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, 0x0a, 0x13, + 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, 0x19, 0x2f, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, + 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, - 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, - 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, - 0x1c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, - 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, + 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, - 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, - 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, - 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, - 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, - 0x50, 0x41, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, 0x1c, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, + 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, + 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x0f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, + 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x41, 0x58, 0xaa, + 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/attributes/attributesconnect/attributes.connect.go b/protocol/go/policy/attributes/attributesconnect/attributes.connect.go index bcb8fb964..ba84fcead 100644 --- a/protocol/go/policy/attributes/attributesconnect/attributes.connect.go +++ b/protocol/go/policy/attributes/attributesconnect/attributes.connect.go @@ -142,24 +142,28 @@ func NewAttributesServiceClient(httpClient connect.HTTPClient, baseURL string, o httpClient, baseURL+AttributesServiceListAttributesProcedure, connect.WithSchema(attributesServiceListAttributesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listAttributeValues: connect.NewClient[attributes.ListAttributeValuesRequest, attributes.ListAttributeValuesResponse]( httpClient, baseURL+AttributesServiceListAttributeValuesProcedure, connect.WithSchema(attributesServiceListAttributeValuesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getAttribute: connect.NewClient[attributes.GetAttributeRequest, attributes.GetAttributeResponse]( httpClient, baseURL+AttributesServiceGetAttributeProcedure, connect.WithSchema(attributesServiceGetAttributeMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getAttributeValuesByFqns: connect.NewClient[attributes.GetAttributeValuesByFqnsRequest, attributes.GetAttributeValuesByFqnsResponse]( httpClient, baseURL+AttributesServiceGetAttributeValuesByFqnsProcedure, connect.WithSchema(attributesServiceGetAttributeValuesByFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createAttribute: connect.NewClient[attributes.CreateAttributeRequest, attributes.CreateAttributeResponse]( @@ -367,24 +371,28 @@ func NewAttributesServiceHandler(svc AttributesServiceHandler, opts ...connect.H AttributesServiceListAttributesProcedure, svc.ListAttributes, connect.WithSchema(attributesServiceListAttributesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceListAttributeValuesHandler := connect.NewUnaryHandler( AttributesServiceListAttributeValuesProcedure, svc.ListAttributeValues, connect.WithSchema(attributesServiceListAttributeValuesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceGetAttributeHandler := connect.NewUnaryHandler( AttributesServiceGetAttributeProcedure, svc.GetAttribute, connect.WithSchema(attributesServiceGetAttributeMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceGetAttributeValuesByFqnsHandler := connect.NewUnaryHandler( AttributesServiceGetAttributeValuesByFqnsProcedure, svc.GetAttributeValuesByFqns, connect.WithSchema(attributesServiceGetAttributeValuesByFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceCreateAttributeHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go b/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go index 3cfc542bc..ca127cf8a 100644 --- a/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go +++ b/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go @@ -91,12 +91,14 @@ func NewKeyAccessServerRegistryServiceClient(httpClient connect.HTTPClient, base httpClient, baseURL+KeyAccessServerRegistryServiceListKeyAccessServersProcedure, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServersMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getKeyAccessServer: connect.NewClient[kasregistry.GetKeyAccessServerRequest, kasregistry.GetKeyAccessServerResponse]( httpClient, baseURL+KeyAccessServerRegistryServiceGetKeyAccessServerProcedure, connect.WithSchema(keyAccessServerRegistryServiceGetKeyAccessServerMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createKeyAccessServer: connect.NewClient[kasregistry.CreateKeyAccessServerRequest, kasregistry.CreateKeyAccessServerResponse]( @@ -121,6 +123,7 @@ func NewKeyAccessServerRegistryServiceClient(httpClient connect.HTTPClient, base httpClient, baseURL+KeyAccessServerRegistryServiceListKeyAccessServerGrantsProcedure, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServerGrantsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), } @@ -192,12 +195,14 @@ func NewKeyAccessServerRegistryServiceHandler(svc KeyAccessServerRegistryService KeyAccessServerRegistryServiceListKeyAccessServersProcedure, svc.ListKeyAccessServers, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServersMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) keyAccessServerRegistryServiceGetKeyAccessServerHandler := connect.NewUnaryHandler( KeyAccessServerRegistryServiceGetKeyAccessServerProcedure, svc.GetKeyAccessServer, connect.WithSchema(keyAccessServerRegistryServiceGetKeyAccessServerMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) keyAccessServerRegistryServiceCreateKeyAccessServerHandler := connect.NewUnaryHandler( @@ -222,6 +227,7 @@ func NewKeyAccessServerRegistryServiceHandler(svc KeyAccessServerRegistryService KeyAccessServerRegistryServiceListKeyAccessServerGrantsProcedure, svc.ListKeyAccessServerGrants, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServerGrantsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) return "/policy.kasregistry.KeyAccessServerRegistryService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go index 0a9200e73..3700049e5 100644 --- a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go +++ b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go @@ -1101,9 +1101,9 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x6e, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, - 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xe4, 0x07, 0x0a, 0x1e, 0x4b, 0x65, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xed, 0x07, 0x0a, 0x1e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x96, 0x01, 0x0a, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x99, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, @@ -1111,74 +1111,74 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, - 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, - 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, + 0x72, 0x76, 0x65, 0x72, 0x73, 0x90, 0x02, 0x01, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x9e, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, + 0x90, 0x02, 0x01, 0x12, 0x9c, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, + 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0xac, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, - 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, + 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, + 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, - 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, - 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, - 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, + 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x90, 0x02, 0x01, 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/namespaces/namespaces.pb.go b/protocol/go/policy/namespaces/namespaces.pb.go index e942ccd79..7e77fce39 100644 --- a/protocol/go/policy/namespaces/namespaces.pb.go +++ b/protocol/go/policy/namespaces/namespaces.pb.go @@ -930,95 +930,96 @@ var file_policy_namespaces_namespaces_proto_rawDesc = []byte{ 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xab, 0x09, 0x0a, 0x10, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xb1, 0x09, 0x0a, 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x84, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x12, 0x87, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, 0x74, + 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, - 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x90, 0x01, - 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, - 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x99, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, - 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xef, 0x01, 0x0a, - 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0x88, 0x01, 0x0a, 0x0e, 0x4c, + 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x4c, 0x3a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, - 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xd8, - 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, - 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x2a, 0x2d, 0x2f, 0x61, 0x74, 0x74, + 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x42, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0xa2, 0x02, 0x03, 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xe2, - 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x12, 0x90, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x99, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0xef, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x3a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, + 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x12, 0xd8, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, + 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, + 0x2a, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, + 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x42, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, + 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go b/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go index 8df0903b6..a10698140 100644 --- a/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go +++ b/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go @@ -96,12 +96,14 @@ func NewNamespaceServiceClient(httpClient connect.HTTPClient, baseURL string, op httpClient, baseURL+NamespaceServiceGetNamespaceProcedure, connect.WithSchema(namespaceServiceGetNamespaceMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listNamespaces: connect.NewClient[namespaces.ListNamespacesRequest, namespaces.ListNamespacesResponse]( httpClient, baseURL+NamespaceServiceListNamespacesProcedure, connect.WithSchema(namespaceServiceListNamespacesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createNamespace: connect.NewClient[namespaces.CreateNamespaceRequest, namespaces.CreateNamespaceResponse]( @@ -209,12 +211,14 @@ func NewNamespaceServiceHandler(svc NamespaceServiceHandler, opts ...connect.Han NamespaceServiceGetNamespaceProcedure, svc.GetNamespace, connect.WithSchema(namespaceServiceGetNamespaceMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) namespaceServiceListNamespacesHandler := connect.NewUnaryHandler( NamespaceServiceListNamespacesProcedure, svc.ListNamespaces, connect.WithSchema(namespaceServiceListNamespacesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) namespaceServiceCreateNamespaceHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/resourcemapping/resource_mapping.pb.go b/protocol/go/policy/resourcemapping/resource_mapping.pb.go index 4a1916bd2..874040674 100644 --- a/protocol/go/policy/resourcemapping/resource_mapping.pb.go +++ b/protocol/go/policy/resourcemapping/resource_mapping.pb.go @@ -1600,9 +1600,9 @@ var file_policy_resourcemapping_resource_mapping_proto_rawDesc = []byte{ 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x32, 0xbd, 0x0f, 0x0a, 0x16, 0x52, 0x65, + 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x32, 0xcc, 0x0f, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x76, 0x69, 0x63, 0x65, 0x12, 0xb5, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, @@ -1611,135 +1611,136 @@ var file_policy_resourcemapping_resource_mapping_proto_rawDesc = []byte{ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xb1, 0x01, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb8, 0x01, - 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xbd, 0x01, 0x0a, 0x1a, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x32, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xba, 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x90, 0x02, 0x01, 0x12, 0xb4, 0x01, 0x0a, + 0x17, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x90, 0x02, 0x01, 0x12, 0xb8, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x2a, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x33, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x14, 0x12, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xc9, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xbd, + 0x01, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x32, + 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xba, + 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x2a, 0x1d, 0x2f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa0, 0x01, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x90, 0x02, 0x01, 0x12, 0xcc, + 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x6e, 0x73, 0x12, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, + 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, + 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x66, 0x71, 0x6e, 0x73, 0x90, 0x02, 0x01, 0x12, 0x9f, 0x01, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, + 0xa3, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x66, 0x71, 0x6e, - 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, + 0x2a, 0x22, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, + 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x32, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0xa3, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x12, 0xa5, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, - 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x32, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, - 0x2a, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xeb, 0x01, 0x0a, 0x1a, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, - 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0xa2, 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, - 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x22, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, + 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xeb, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, + 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xa2, + 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, 0x02, + 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x22, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go b/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go index 415ba7fa1..c5589908e 100644 --- a/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go +++ b/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go @@ -115,12 +115,14 @@ func NewResourceMappingServiceClient(httpClient connect.HTTPClient, baseURL stri httpClient, baseURL+ResourceMappingServiceListResourceMappingGroupsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingGroupsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getResourceMappingGroup: connect.NewClient[resourcemapping.GetResourceMappingGroupRequest, resourcemapping.GetResourceMappingGroupResponse]( httpClient, baseURL+ResourceMappingServiceGetResourceMappingGroupProcedure, connect.WithSchema(resourceMappingServiceGetResourceMappingGroupMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createResourceMappingGroup: connect.NewClient[resourcemapping.CreateResourceMappingGroupRequest, resourcemapping.CreateResourceMappingGroupResponse]( @@ -145,18 +147,21 @@ func NewResourceMappingServiceClient(httpClient connect.HTTPClient, baseURL stri httpClient, baseURL+ResourceMappingServiceListResourceMappingsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listResourceMappingsByGroupFqns: connect.NewClient[resourcemapping.ListResourceMappingsByGroupFqnsRequest, resourcemapping.ListResourceMappingsByGroupFqnsResponse]( httpClient, baseURL+ResourceMappingServiceListResourceMappingsByGroupFqnsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingsByGroupFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getResourceMapping: connect.NewClient[resourcemapping.GetResourceMappingRequest, resourcemapping.GetResourceMappingResponse]( httpClient, baseURL+ResourceMappingServiceGetResourceMappingProcedure, connect.WithSchema(resourceMappingServiceGetResourceMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createResourceMapping: connect.NewClient[resourcemapping.CreateResourceMappingRequest, resourcemapping.CreateResourceMappingResponse]( @@ -282,12 +287,14 @@ func NewResourceMappingServiceHandler(svc ResourceMappingServiceHandler, opts .. ResourceMappingServiceListResourceMappingGroupsProcedure, svc.ListResourceMappingGroups, connect.WithSchema(resourceMappingServiceListResourceMappingGroupsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceGetResourceMappingGroupHandler := connect.NewUnaryHandler( ResourceMappingServiceGetResourceMappingGroupProcedure, svc.GetResourceMappingGroup, connect.WithSchema(resourceMappingServiceGetResourceMappingGroupMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceCreateResourceMappingGroupHandler := connect.NewUnaryHandler( @@ -312,18 +319,21 @@ func NewResourceMappingServiceHandler(svc ResourceMappingServiceHandler, opts .. ResourceMappingServiceListResourceMappingsProcedure, svc.ListResourceMappings, connect.WithSchema(resourceMappingServiceListResourceMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceListResourceMappingsByGroupFqnsHandler := connect.NewUnaryHandler( ResourceMappingServiceListResourceMappingsByGroupFqnsProcedure, svc.ListResourceMappingsByGroupFqns, connect.WithSchema(resourceMappingServiceListResourceMappingsByGroupFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceGetResourceMappingHandler := connect.NewUnaryHandler( ResourceMappingServiceGetResourceMappingProcedure, svc.GetResourceMapping, connect.WithSchema(resourceMappingServiceGetResourceMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceCreateResourceMappingHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/subjectmapping/subject_mapping.pb.go b/protocol/go/policy/subjectmapping/subject_mapping.pb.go index 978ca54b4..e0653a135 100644 --- a/protocol/go/policy/subjectmapping/subject_mapping.pb.go +++ b/protocol/go/policy/subjectmapping/subject_mapping.pb.go @@ -1589,7 +1589,7 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x1b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x14, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, - 0x74, 0x73, 0x32, 0xca, 0x10, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x74, 0x73, 0x32, 0xd6, 0x10, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x14, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, @@ -1602,7 +1602,7 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x12, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x74, 0x63, 0x68, 0x12, 0x9a, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, @@ -1610,133 +1610,134 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x96, 0x01, - 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, - 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, - 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa2, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, - 0x3a, 0x01, 0x2a, 0x32, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9f, 0x01, 0x0a, 0x14, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xac, 0x01, - 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, 0xab, 0x01, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x90, 0x02, 0x01, + 0x12, 0x99, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x18, 0x12, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0x9d, 0x01, 0x0a, + 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa2, 0x01, 0x0a, + 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x32, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, + 0x7d, 0x12, 0x9f, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, + 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, - 0xb7, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, + 0x74, 0x73, 0x90, 0x02, 0x01, 0x12, 0xae, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, + 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, + 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x32, 0x1c, 0x2f, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, - 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x19, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0xdc, 0x01, 0x0a, 0x25, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, - 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x43, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x44, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, - 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x2a, 0x20, 0x2f, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x42, - 0xe4, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x13, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, - 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0xca, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x21, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, + 0x01, 0x2a, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, 0xb7, 0x01, 0x0a, 0x19, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x32, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, + 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xdc, 0x01, 0x0a, + 0x25, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, + 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x43, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, + 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x2a, 0x20, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, + 0x74, 0x73, 0x2f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x42, 0xe4, 0x01, 0x0a, 0x19, + 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x13, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xa2, + 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x15, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x21, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x3a, 0x3a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go b/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go index ddce80141..a4ca383de 100644 --- a/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go +++ b/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go @@ -127,12 +127,14 @@ func NewSubjectMappingServiceClient(httpClient connect.HTTPClient, baseURL strin httpClient, baseURL+SubjectMappingServiceListSubjectMappingsProcedure, connect.WithSchema(subjectMappingServiceListSubjectMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getSubjectMapping: connect.NewClient[subjectmapping.GetSubjectMappingRequest, subjectmapping.GetSubjectMappingResponse]( httpClient, baseURL+SubjectMappingServiceGetSubjectMappingProcedure, connect.WithSchema(subjectMappingServiceGetSubjectMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createSubjectMapping: connect.NewClient[subjectmapping.CreateSubjectMappingRequest, subjectmapping.CreateSubjectMappingResponse]( @@ -157,12 +159,14 @@ func NewSubjectMappingServiceClient(httpClient connect.HTTPClient, baseURL strin httpClient, baseURL+SubjectMappingServiceListSubjectConditionSetsProcedure, connect.WithSchema(subjectMappingServiceListSubjectConditionSetsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getSubjectConditionSet: connect.NewClient[subjectmapping.GetSubjectConditionSetRequest, subjectmapping.GetSubjectConditionSetResponse]( httpClient, baseURL+SubjectMappingServiceGetSubjectConditionSetProcedure, connect.WithSchema(subjectMappingServiceGetSubjectConditionSetMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createSubjectConditionSet: connect.NewClient[subjectmapping.CreateSubjectConditionSetRequest, subjectmapping.CreateSubjectConditionSetResponse]( @@ -307,12 +311,14 @@ func NewSubjectMappingServiceHandler(svc SubjectMappingServiceHandler, opts ...c SubjectMappingServiceListSubjectMappingsProcedure, svc.ListSubjectMappings, connect.WithSchema(subjectMappingServiceListSubjectMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceGetSubjectMappingHandler := connect.NewUnaryHandler( SubjectMappingServiceGetSubjectMappingProcedure, svc.GetSubjectMapping, connect.WithSchema(subjectMappingServiceGetSubjectMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceCreateSubjectMappingHandler := connect.NewUnaryHandler( @@ -337,12 +343,14 @@ func NewSubjectMappingServiceHandler(svc SubjectMappingServiceHandler, opts ...c SubjectMappingServiceListSubjectConditionSetsProcedure, svc.ListSubjectConditionSets, connect.WithSchema(subjectMappingServiceListSubjectConditionSetsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceGetSubjectConditionSetHandler := connect.NewUnaryHandler( SubjectMappingServiceGetSubjectConditionSetProcedure, svc.GetSubjectConditionSet, connect.WithSchema(subjectMappingServiceGetSubjectConditionSetMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceCreateSubjectConditionSetHandler := connect.NewUnaryHandler( diff --git a/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go b/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go index 383c7df67..8933ce80a 100644 --- a/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go +++ b/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go @@ -187,8 +187,8 @@ var file_wellknownconfiguration_wellknown_configuration_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x32, 0xd1, 0x01, 0x0a, 0x10, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbc, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, + 0x69, 0x6f, 0x6e, 0x32, 0xd4, 0x01, 0x0a, 0x10, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, + 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbf, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, @@ -197,26 +197,26 @@ var file_wellknownconfiguration_wellknown_configuration_proto_rawDesc = []byte{ 0x1a, 0x39, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x2d, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0xf1, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, - 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x1b, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x77, - 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x57, 0x58, 0x58, 0xaa, 0x02, 0x16, 0x57, 0x65, - 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x22, - 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x90, 0x02, 0x01, 0x42, 0xf1, 0x01, 0x0a, 0x1a, 0x63, + 0x6f, 0x6d, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x1b, 0x57, 0x65, 0x6c, 0x6c, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, + 0x6f, 0x2f, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x57, 0x58, 0x58, 0xaa, 0x02, + 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0xe2, 0x02, 0x22, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, + 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go b/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go index ac0b4ae29..35ce65869 100644 --- a/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go +++ b/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go @@ -63,6 +63,7 @@ func NewWellKnownServiceClient(httpClient connect.HTTPClient, baseURL string, op httpClient, baseURL+WellKnownServiceGetWellKnownConfigurationProcedure, connect.WithSchema(wellKnownServiceGetWellKnownConfigurationMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), } @@ -95,6 +96,7 @@ func NewWellKnownServiceHandler(svc WellKnownServiceHandler, opts ...connect.Han WellKnownServiceGetWellKnownConfigurationProcedure, svc.GetWellKnownConfiguration, connect.WithSchema(wellKnownServiceGetWellKnownConfigurationMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) return "/wellknownconfiguration.WellKnownService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/sdk/audit/context_keys.go b/sdk/audit/context_keys.go index 86104c0e9..149b4f1d4 100644 --- a/sdk/audit/context_keys.go +++ b/sdk/audit/context_keys.go @@ -17,3 +17,7 @@ const ( RequestIPHeaderKey RequestHeader = "x-forwarded-request-ip" ActorIDHeaderKey RequestHeader = "x-forwarded-actor-id" ) + +func (r RequestHeader) String() string { + return string(r) +} diff --git a/service/authorization/authorization.go b/service/authorization/authorization.go index 8031fa780..711293444 100644 --- a/service/authorization/authorization.go +++ b/service/authorization/authorization.go @@ -8,15 +8,14 @@ import ( "os" "strings" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "connectrpc.com/connect" "github.com/creasty/defaults" "github.com/go-playground/validator/v10" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/mitchellh/mapstructure" "github.com/open-policy-agent/opa/rego" "github.com/opentdf/platform/protocol/go/authorization" + "github.com/opentdf/platform/protocol/go/authorization/authorizationconnect" "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/protocol/go/policy" attr "github.com/opentdf/platform/protocol/go/policy/attributes" @@ -35,7 +34,6 @@ import ( const EntityIDPrefix string = "entity_idx_" type AuthorizationService struct { //nolint:revive // AuthorizationService is a valid name for this struct - authorization.UnimplementedAuthorizationServiceServer sdk *otdf.SDK config Config logger *logger.Logger @@ -54,12 +52,14 @@ type CustomRego struct { Query string `mapstructure:"query" json:"query" default:"data.opentdf.entitlements.attributes"` } -func NewRegistration() *serviceregistry.Service[AuthorizationService] { - return &serviceregistry.Service[AuthorizationService]{ - ServiceOptions: serviceregistry.ServiceOptions[AuthorizationService]{ - Namespace: "authorization", - ServiceDesc: &authorization.AuthorizationService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*AuthorizationService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[authorizationconnect.AuthorizationServiceHandler] { + return &serviceregistry.Service[authorizationconnect.AuthorizationServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[authorizationconnect.AuthorizationServiceHandler]{ + Namespace: "authorization", + ServiceDesc: &authorization.AuthorizationService_ServiceDesc, + ConnectRPCFunc: authorizationconnect.NewAuthorizationServiceHandler, + GRPCGateayFunc: authorization.RegisterAuthorizationServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (authorizationconnect.AuthorizationServiceHandler, serviceregistry.HandlerServer) { var ( err error entitlementRego []byte @@ -134,9 +134,7 @@ func NewRegistration() *serviceregistry.Service[AuthorizationService] { as.config = *authZCfg - return as, func(ctx context.Context, mux *runtime.ServeMux) error { - return authorization.RegisterAuthorizationServiceHandlerServer(ctx, mux, as) - } + return as, nil }, }, } @@ -148,10 +146,10 @@ func (as AuthorizationService) IsReady(ctx context.Context) error { return nil } -func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *authorization.GetDecisionsByTokenRequest) (*authorization.GetDecisionsByTokenResponse, error) { +func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *connect.Request[authorization.GetDecisionsByTokenRequest]) (*connect.Response[authorization.GetDecisionsByTokenResponse], error) { decisionsRequests := []*authorization.DecisionRequest{} // for each token decision request - for _, tdr := range req.GetDecisionRequests() { + for _, tdr := range req.Msg.GetDecisionRequests() { ecResp, err := as.sdk.EntityResoution.CreateEntityChainFromJwt(ctx, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: tdr.GetTokens()}) if err != nil { as.logger.Error("Error calling ERS to get entity chains from jwts") @@ -166,23 +164,27 @@ func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *au }) } - resp, err := as.GetDecisions(ctx, &authorization.GetDecisionsRequest{ - DecisionRequests: decisionsRequests, + resp, err := as.GetDecisions(ctx, &connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: decisionsRequests, + }, }) if err != nil { return nil, err } - return &authorization.GetDecisionsByTokenResponse{DecisionResponses: resp.GetDecisionResponses()}, err + return connect.NewResponse(&authorization.GetDecisionsByTokenResponse{ + DecisionResponses: resp.Msg.GetDecisionResponses(), + }), err } -func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authorization.GetDecisionsRequest) (*authorization.GetDecisionsResponse, error) { +func (as *AuthorizationService) GetDecisions(ctx context.Context, req *connect.Request[authorization.GetDecisionsRequest]) (*connect.Response[authorization.GetDecisionsResponse], error) { as.logger.DebugContext(ctx, "getting decisions") // Temporary canned echo response with permit decision for all requested decision/entity/ra combos rsp := &authorization.GetDecisionsResponse{ DecisionResponses: make([]*authorization.DecisionResponse, 0), } - for _, dr := range req.GetDecisionRequests() { + for _, dr := range req.Msg.GetDecisionRequests() { for _, ra := range dr.GetResourceAttributes() { as.logger.DebugContext(ctx, "getting resource attributes", slog.String("FQNs", strings.Join(ra.GetAttributeValueFqns(), ", "))) @@ -226,7 +228,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza attrDefs, err = populateAttrDefValueFqns(attrDefs) if err != nil { - return nil, err + return nil, connect.NewError(connect.CodeInternal, err) } // get the relevant resource attribute fqns @@ -246,9 +248,11 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza // TODO: we should already have the subject mappings here and be able to just use OPA to trim down the known data attr values to the ones matched up with the entities // entities := ec.GetEntities() - req := authorization.GetEntitlementsRequest{ - Entities: entities, - Scope: &allPertinentFqnsRA, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: entities, + Scope: &allPertinentFqnsRA, + }, } auditECEntitlements := make([]audit.EntityChainEntitlement, 0) @@ -271,7 +275,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza // TODO this might cause errors if multiple entities dont have ids // currently just adding each entity returned to same list - for idx, e := range ecEntitlements.GetEntitlements() { + for idx, e := range ecEntitlements.Msg.GetEntitlements() { entityID := e.GetEntityId() if entityID == "" { entityID = EntityIDPrefix + fmt.Sprint(idx) @@ -357,7 +361,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza } } } - return rsp, nil + return connect.NewResponse(rsp), nil } // makeSubMapsByValLookup creates a lookup map of subject mappings by attribute value ID. @@ -438,20 +442,20 @@ func makeScopeMap(scope *authorization.ResourceAttribute) map[string]bool { return scopeMap } -func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *authorization.GetEntitlementsRequest) (*authorization.GetEntitlementsResponse, error) { +func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *connect.Request[authorization.GetEntitlementsRequest]) (*connect.Response[authorization.GetEntitlementsResponse], error) { as.logger.DebugContext(ctx, "getting entitlements") attrsRes, err := as.sdk.Attributes.ListAttributes(ctx, &attr.ListAttributesRequest{}) if err != nil { as.logger.ErrorContext(ctx, "failed to list attributes", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to list attributes") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to list attributes")) } subMapsRes, err := as.sdk.SubjectMapping.ListSubjectMappings(ctx, &subjectmapping.ListSubjectMappingsRequest{}) if err != nil { as.logger.ErrorContext(ctx, "failed to list subject mappings", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to list subject mappings") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to list subject mappings")) } // create a lookup map of attribute value FQNs (based on request scope) - scopeMap := makeScopeMap(req.GetScope()) + scopeMap := makeScopeMap(req.Msg.GetScope()) // create a lookup map of subject mappings by attribute value ID subMapsByVal := makeSubMapsByValLookup(subMapsRes.GetSubjectMappings()) // create a lookup map of attribute values by FQN (for rego query) @@ -462,18 +466,18 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author subjectMappings := avf.GetFqnAttributeValues() as.logger.DebugContext(ctx, fmt.Sprintf("retrieved %d subject mappings", len(subjectMappings))) // TODO: this could probably be moved to proto validation https://github.com/opentdf/platform/issues/1057 - if req.Entities == nil { + if req.Msg.Entities == nil { as.logger.ErrorContext(ctx, "requires entities") - return nil, status.Error(codes.InvalidArgument, "requires entities") + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("requires entities")) } rsp := &authorization.GetEntitlementsResponse{ - Entitlements: make([]*authorization.EntityEntitlements, len(req.GetEntities())), + Entitlements: make([]*authorization.EntityEntitlements, len(req.Msg.GetEntities())), } // call ERS on all entities - ersResp, err := as.sdk.EntityResoution.ResolveEntities(ctx, &entityresolution.ResolveEntitiesRequest{Entities: req.GetEntities()}) + ersResp, err := as.sdk.EntityResoution.ResolveEntities(ctx, &entityresolution.ResolveEntitiesRequest{Entities: req.Msg.GetEntities()}) if err != nil { - as.logger.ErrorContext(ctx, "error calling ERS to resolve entities", "entities", req.GetEntities()) + as.logger.ErrorContext(ctx, "error calling ERS to resolve entities", "entities", req.Msg.GetEntities()) return nil, err } @@ -481,40 +485,43 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author in, err := entitlements.OpaInput(subjectMappings, ersResp) if err != nil { as.logger.ErrorContext(ctx, "failed to build rego input", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to build rego input") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to build rego input")) } results, err := as.eval.Eval(ctx, rego.EvalInput(in), ) if err != nil { - return nil, status.Error(codes.Internal, "failed to evaluate entitlements policy") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to evaluate entitlements policy")) } + + resp := connect.NewResponse(rsp) + // If we get no results and no error then we assume that the entity is not entitled to anything if len(results) == 0 { as.logger.DebugContext(ctx, "no entitlement results") - return rsp, nil + return resp, nil } // I am not sure how we would end up with multiple results but lets return an empty entitlement set for now if len(results) > 1 { as.logger.WarnContext(ctx, "multiple entitlement results", slog.Any("results", results)) - return rsp, nil + return resp, nil } // If we get no expressions then we assume that the entity is not entitled to anything if len(results[0].Expressions) == 0 { as.logger.WarnContext(ctx, "no entitlement expressions", slog.Any("results", results)) - return rsp, nil + return resp, nil } resultsEntitlements, entitlementsMapOk := results[0].Expressions[0].Value.(map[string]interface{}) if !entitlementsMapOk { as.logger.ErrorContext(ctx, "entitlements is not a map[string]interface", slog.Any("value", resultsEntitlements)) - return rsp, nil + return resp, nil } as.logger.DebugContext(ctx, "rego results", slog.Any("results", results)) - for idx, entity := range req.GetEntities() { + for idx, entity := range req.Msg.GetEntities() { // Ensure the entity has an ID entityID := entity.GetId() if entityID == "" { @@ -524,7 +531,7 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author entityEntitlements, valueListOk := resultsEntitlements[entityID].([]interface{}) if !valueListOk { as.logger.ErrorContext(ctx, "entitlements is not a map[string]interface", slog.Any("value", resultsEntitlements)) - return rsp, nil + return resp, nil } // map for attributes for optional comprehensive @@ -541,20 +548,20 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author continue } // if comprehensive and a hierarchy attribute is entitled then add the lower entitlements - if req.GetWithComprehensiveHierarchy() { + if req.Msg.GetWithComprehensiveHierarchy() { entitlements = getComprehensiveHierarchy(attributesMap, avf, entitlement, as, entitlements) } // Add entitlement to entitlements array entitlements[valueIDX] = entitlement } // Update the entity with its entitlements - rsp.Entitlements[idx] = &authorization.EntityEntitlements{ + resp.Msg.Entitlements[idx] = &authorization.EntityEntitlements{ EntityId: entity.GetId(), AttributeValueFqns: entitlements, } } - return rsp, nil + return resp, nil } func retrieveAttributeDefinitions(ctx context.Context, ra *authorization.ResourceAttribute, sdk *otdf.SDK) (map[string]*attr.GetAttributeValuesByFqnsResponse_AttributeAndValue, error) { diff --git a/service/authorization/authorization_test.go b/service/authorization/authorization_test.go index 59940559f..e64f849b7 100644 --- a/service/authorization/authorization_test.go +++ b/service/authorization/authorization_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "connectrpc.com/connect" "github.com/open-policy-agent/opa/rego" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" @@ -63,6 +64,7 @@ func (*mySubjectMappingClient) ListSubjectMappings(_ context.Context, _ *sm.List func (*myERSClient) CreateEntityChainFromJwt(_ context.Context, _ *entityresolution.CreateEntityChainFromJwtRequest, _ ...grpc.CallOption) (*entityresolution.CreateEntityChainFromJwtResponse, error) { return &createEntityChainResp, nil } + func (*myERSClient) ResolveEntities(_ context.Context, _ *entityresolution.ResolveEntitiesRequest, _ ...grpc.CallOption) (*entityresolution.ResolveEntitiesResponse, error) { return &resolveEntitiesResp, nil } @@ -177,13 +179,14 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -200,27 +203,34 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -228,42 +238,46 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) // run again with two attribute values throughout // set the request - req = authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req = connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, - }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, - }, - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, - }, }, - }} + } attrDef.Values = append(attrDef.Values, &policy.Value{ Value: mockAttrValue2, }) @@ -288,9 +302,9 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { resp, err = as.GetDecisions(ctxb, &req) require.NoError(t, err) - assert.Len(t, resp.GetDecisionResponses(), 2) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[1].GetDecision()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 2) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[1].GetDecision()) } func Test_GetDecisions_AllOf_Fail(t *testing.T) { @@ -331,32 +345,37 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, - }, }, - }} + } ctxb := context.Background() @@ -371,10 +390,13 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { prepared, err := testrego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -384,9 +406,9 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { // NOTE: there should be two decision responses, one for each data attribute value, but authorization service // only responds with one permit/deny at the moment // entitlements only contain the first FQN, so we have a deny decision - as.logger.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.GetDecisionResponses()[0].GetDecision()) + as.logger.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.Msg.GetDecisionResponses()[0].GetDecision()) } // Subject entitled and environment entity not entitled -- still pass @@ -421,13 +443,14 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -444,28 +467,35 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, - {Id: "e2", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, + {Id: "e2", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -473,9 +503,9 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) } // Subject not entitled and environment entity entitled -- still fail @@ -510,13 +540,14 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -533,28 +564,35 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e2", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e2", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -562,9 +600,9 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.Msg.GetDecisionResponses()[0].GetDecision()) } func Test_GetEntitlementsSimple(t *testing.T) { @@ -600,13 +638,14 @@ func Test_GetEntitlementsSimple(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -622,23 +661,28 @@ func Test_GetEntitlementsSimple(t *testing.T) { prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + }, } resp, err := as.GetEntitlements(ctxb, &req) require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func Test_GetEntitlementsFqnCasing(t *testing.T) { @@ -667,13 +711,14 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -689,18 +734,23 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - // Using mixed case here - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/VaLuE1"}}, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + // Using mixed case here + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/VaLuE1"}}, + }, } - for fqn := range makeScopeMap(req.GetScope()) { + for fqn := range makeScopeMap(req.Msg.GetScope()) { assert.Equal(t, fqn, strings.ToLower(fqn)) } @@ -708,9 +758,9 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { @@ -747,13 +797,14 @@ func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -768,25 +819,30 @@ func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { // Run evaluation. prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } withHierarchy := true - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, - WithComprehensiveHierarchy: &withHierarchy, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + WithComprehensiveHierarchy: &withHierarchy, + }, } resp, err := as.GetEntitlements(ctxb, &req) require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1", "https://www.example.org/attr/foo/value/value2"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1", "https://www.example.org/attr/foo/value/value2"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func TestFqnBuilder(t *testing.T) { diff --git a/service/entityresolution/claims/claims_entity_resolution.go b/service/entityresolution/claims/claims_entity_resolution.go index 07ca34fd4..090d2b676 100644 --- a/service/entityresolution/claims/claims_entity_resolution.go +++ b/service/entityresolution/claims/claims_entity_resolution.go @@ -5,7 +5,7 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" @@ -24,20 +24,17 @@ type ClaimsEntityResolutionService struct { func RegisterClaimsERS(_ serviceregistry.ServiceConfig, logger *logger.Logger) (ClaimsEntityResolutionService, serviceregistry.HandlerServer) { claimsSVC := ClaimsEntityResolutionService{logger: logger} - return claimsSVC, - func(ctx context.Context, mux *runtime.ServeMux) error { - return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, claimsSVC) - } + return claimsSVC, nil } -func (s ClaimsEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { - resp, err := EntityResolution(ctx, req, s.logger) - return &resp, err +func (s ClaimsEntityResolutionService) ResolveEntities(ctx context.Context, req *connect.Request[entityresolution.ResolveEntitiesRequest]) (*connect.Response[entityresolution.ResolveEntitiesResponse], error) { + resp, err := EntityResolution(ctx, req.Msg, s.logger) + return connect.NewResponse(&resp), err } -func (s ClaimsEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { - resp, err := CreateEntityChainFromJwt(ctx, req, s.logger) - return &resp, err +func (s ClaimsEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *connect.Request[entityresolution.CreateEntityChainFromJwtRequest]) (*connect.Response[entityresolution.CreateEntityChainFromJwtResponse], error) { + resp, err := CreateEntityChainFromJwt(ctx, req.Msg, s.logger) + return connect.NewResponse(&resp), err } func CreateEntityChainFromJwt( @@ -72,14 +69,14 @@ func EntityResolution(_ context.Context, if claims != nil { err := claims.UnmarshalTo(entityStruct) if err != nil { - return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("error unpacking anypb.Any to structpb.Struct: %w", err) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("error unpacking anypb.Any to structpb.Struct: %w", err)) } } default: retrievedStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("unable to make entity struct: %w", err) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, fmt.Errorf("unable to make entity struct: %w", err)) } entityStruct = retrievedStruct } diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index d66c2dc6b..cd09205c0 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -3,6 +3,7 @@ package entityresolution import ( "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/entityresolution" + "github.com/opentdf/platform/protocol/go/entityresolution/entityresolutionconnect" claims "github.com/opentdf/platform/service/entityresolution/claims" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" "github.com/opentdf/platform/service/pkg/serviceregistry" @@ -18,15 +19,17 @@ const ( ) type EntityResolution struct { - entityresolution.EntityResolutionServiceServer + entityresolutionconnect.EntityResolutionServiceHandler } -func NewRegistration() *serviceregistry.Service[EntityResolution] { - return &serviceregistry.Service[EntityResolution]{ - ServiceOptions: serviceregistry.ServiceOptions[EntityResolution]{ - Namespace: "entityresolution", - ServiceDesc: &entityresolution.EntityResolutionService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*EntityResolution, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityResolutionServiceHandler] { + return &serviceregistry.Service[entityresolutionconnect.EntityResolutionServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[entityresolutionconnect.EntityResolutionServiceHandler]{ + Namespace: "entityresolution", + ServiceDesc: &entityresolution.EntityResolutionService_ServiceDesc, + ConnectRPCFunc: entityresolutionconnect.NewEntityResolutionServiceHandler, + GRPCGateayFunc: entityresolution.RegisterEntityResolutionServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (entityresolutionconnect.EntityResolutionServiceHandler, serviceregistry.HandlerServer) { var inputConfig ERSConfig if err := mapstructure.Decode(srp.Config, &inputConfig); err != nil { @@ -34,12 +37,12 @@ func NewRegistration() *serviceregistry.Service[EntityResolution] { } if inputConfig.Mode == ClaimsMode { claimsSVC, claimsHandler := claims.RegisterClaimsERS(srp.Config, srp.Logger) - return &EntityResolution{EntityResolutionServiceServer: claimsSVC}, claimsHandler + return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } // Default to keycloak ERS kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger) - return &EntityResolution{EntityResolutionServiceServer: kcSVC}, kcHandler + return EntityResolution{EntityResolutionServiceHandler: kcSVC}, kcHandler }, }, } diff --git a/service/entityresolution/keycloak/keycloak_entity_resolution.go b/service/entityresolution/keycloak/keycloak_entity_resolution.go index 16d3ba7e2..14a5caf4e 100644 --- a/service/entityresolution/keycloak/keycloak_entity_resolution.go +++ b/service/entityresolution/keycloak/keycloak_entity_resolution.go @@ -8,8 +8,8 @@ import ( "log/slog" "strings" + "connectrpc.com/connect" "github.com/Nerzal/gocloak/v13" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/authorization" @@ -18,15 +18,14 @@ import ( "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" ) -const ( - ErrTextCreationFailed = "resource creation failed" - ErrTextGetRetrievalFailed = "resource retrieval failed" - ErrTextNotFound = "resource not found" +var ( + ErrCreationFailed = errors.New("resource creation failed") + ErrGetRetrievalFailed = errors.New("resource retrieval failed") + ErrNotFound = errors.New("resource not found") ) const ( @@ -59,20 +58,17 @@ func RegisterKeycloakERS(config serviceregistry.ServiceConfig, logger *logger.Lo } logger.Debug("entity_resolution configuration", "config", inputIdpConfig) keycloakSVC := &KeycloakEntityResolutionService{idpConfig: inputIdpConfig, logger: logger} - return keycloakSVC, - func(ctx context.Context, mux *runtime.ServeMux) error { - return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, keycloakSVC) - } + return keycloakSVC, nil } -func (s KeycloakEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { - resp, err := EntityResolution(ctx, req, s.idpConfig, s.logger) - return &resp, err +func (s KeycloakEntityResolutionService) ResolveEntities(ctx context.Context, req *connect.Request[entityresolution.ResolveEntitiesRequest]) (*connect.Response[entityresolution.ResolveEntitiesResponse], error) { + resp, err := EntityResolution(ctx, req.Msg, s.idpConfig, s.logger) + return connect.NewResponse(&resp), err } -func (s KeycloakEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { - resp, err := CreateEntityChainFromJwt(ctx, req, s.idpConfig, s.logger) - return &resp, err +func (s KeycloakEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *connect.Request[entityresolution.CreateEntityChainFromJwtRequest]) (*connect.Response[entityresolution.CreateEntityChainFromJwtResponse], error) { + resp, err := CreateEntityChainFromJwt(ctx, req.Msg, s.idpConfig, s.logger) + return connect.NewResponse(&resp), err } func (c KeycloakConfig) LogValue() slog.Value { @@ -127,7 +123,7 @@ func EntityResolution(ctx context.Context, connector, err := getKCClient(ctx, kcConfig, logger) if err != nil { return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } payload := req.GetEntities() @@ -148,7 +144,7 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error getting client info", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) } var jsonEntities []*structpb.Struct for _, client := range clients { @@ -156,13 +152,13 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error serializing entity representation!", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } mystruct, structErr := structpb.NewStruct(json) if structErr != nil { logger.Error("error making struct!", slog.String("error", structErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, mystruct) } @@ -171,7 +167,7 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } @@ -200,7 +196,7 @@ func EntityResolution(ctx context.Context, case err != nil: logger.Error(err.Error()) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) case len(users) == 1: user := users[0] logger.Debug("user found", slog.String("user", *user.ID), slog.String("entity", ident.String())) @@ -221,14 +217,14 @@ func EntityResolution(ctx context.Context, case groupErr != nil: logger.Error("error getting group", slog.String("group", groupErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) case len(groups) == 1: logger.Info("group found for", slog.String("entity", ident.String())) group := groups[0] expandedRepresentations, exErr := expandGroup(ctx, *group.ID, connector, &kcConfig, logger) if exErr != nil { return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextNotFound) + connect.NewError(connect.CodeNotFound, ErrNotFound) } else { keycloakEntities = expandedRepresentations } @@ -237,15 +233,15 @@ func EntityResolution(ctx context.Context, var entityNotFoundErr entityresolution.EntityNotFoundError switch ident.GetEntityType().(type) { case *authorization.Entity_EmailAddress: - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetEmailAddress()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(connect.CodeNotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetEmailAddress()} case *authorization.Entity_UserName: - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetUserName()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(connect.CodeNotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetUserName()} // case "": // return &entityresolution.IdpPluginResponse{}, // status.Error(codes.InvalidArgument, db.ErrTextNotFound) default: logger.Error("unsupported/unknown type for", slog.String("entity", ident.String())) - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.String()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.String()} } logger.Error(entityNotFoundErr.String()) if kcConfig.InferID.From.Email || kcConfig.InferID.From.Username { @@ -253,11 +249,11 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct from email or username", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } else { - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Code(entityNotFoundErr.GetCode()), entityNotFoundErr.GetMessage()) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.Code(entityNotFoundErr.GetCode()), ErrGetRetrievalFailed) } } } else if ident.GetUserName() != "" { @@ -266,12 +262,12 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct from username", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } else { - entityNotFoundErr := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetUserName()} - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Code(entityNotFoundErr.GetCode()), entityNotFoundErr.GetMessage()) + entityNotFoundErr := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetUserName()} + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.Code(entityNotFoundErr.GetCode()), ErrGetRetrievalFailed) } } } @@ -281,13 +277,13 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error serializing entity representation!", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } mystruct, structErr := structpb.NewStruct(json) if structErr != nil { logger.Error("error making struct!", slog.String("error", structErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, mystruct) } diff --git a/service/entityresolution/keycloak/keycloak_entity_resolution_test.go b/service/entityresolution/keycloak/keycloak_entity_resolution_test.go index 4024e8cb4..b41d35bed 100644 --- a/service/entityresolution/keycloak/keycloak_entity_resolution_test.go +++ b/service/entityresolution/keycloak/keycloak_entity_resolution_test.go @@ -10,6 +10,7 @@ import ( "strings" "testing" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" @@ -17,7 +18,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) const tokenResp string = ` @@ -31,6 +31,7 @@ const byEmailBobResp = `[ {"id": "bobid", "username":"bob.smith"} ] ` + const byEmailAliceResp = `[ {"id": "aliceid", "username":"alice.smith"} ] @@ -48,27 +49,32 @@ const groupSubmemberResp = `[ {"id": "bobid", "username":"bob.smith"}, {"id": "aliceid", "username":"alice.smith"} ]` + const groupResp = `{ "id": "group1-uuid", "name": "group1" }` + const byClientIDOpentdfSdkResp = `[ {"id": "opentdfsdkclient", "clientId":"opentdf-sdk"} ] ` + const byClientIDTDFEntityResResp = `[ {"id": "tdf-entity-resolution", "clientId":"tdf-entity-resolution"} ] ` -const clientCredentialsJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE2MDQsImlhdCI6MTcxNTA5MTMwNCwianRpIjoiMTE3MTYzMjYtNWQyNS00MjlmLWFjMDItNmU0MjE2OWFjMGJhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiOTljOWVlZDItOTM1Ni00ZjE2LWIwODQtZTgyZDczZjViN2QyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxOTIuMTY4LjI0MC4xIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LXRkZi1lbnRpdHktcmVzb2x1dGlvbiIsImNsaWVudEFkZHJlc3MiOiIxOTIuMTY4LjI0MC4xIiwiY2xpZW50X2lkIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIn0.h29QLo-QvIc67KKqU_e1-x6G_o5YQccOyW9AthMdB7xhn9C1dBrcScytaWq1RfETPmnM8MXGezqN4OpXrYr-zbkHhq9ha0Ib-M1VJXNgA5sbgKW9JxGQyudmYPgn4fimDCJtAsXo7C-e3mYNm6DJS0zhGQ3msmjLTcHmIPzWlj7VjtPgKhYV75b7yr_yZNBdHjf3EZqfynU2sL8bKa1w7DYDNQve7ThtD4MeKLiuOQHa3_23dECs_ptvPVks7pLGgRKfgGHBC-KQuopjtxIhwkz2vOWRzugDl0aBJMHfwBajYhgZ2YRlV9dqSxmy8BOj4OEXuHbiyfIpY0rCRpSrGg" -const passwordPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0ODAsImlhdCI6MTcxNTA5MTE4MCwianRpIjoiZmI5MmM2MTAtYmI0OC00ZDgyLTljZGQtOWFhZjllNzEyNzc3IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uLXB1YmxpYyIsInNlc3Npb25fc3RhdGUiOiIzN2E3YjdiOS0xZmNlLTQxMmYtOTI1OS1lYzUxMTY3MGVhMGYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjM3YTdiN2I5LTFmY2UtNDEyZi05MjU5LWVjNTExNjcwZWEwZiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InNhbXBsZSB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2FtcGxlLXVzZXIiLCJnaXZlbl9uYW1lIjoic2FtcGxlIiwiZmFtaWx5X25hbWUiOiJ1c2VyIiwiZW1haWwiOiJzYW1wbGV1c2VyQHNhbXBsZS5jb20ifQ.Gd_OvPNY7UfY7sBKh55TcvWQHmAkYZ2Jb2VyK1lYgse9EBEa_y3uoepZYrGMGkmYdwApg4eauQjxzT_BZYVBc7u9ch3HY_IUuSh3A6FkDDXZIziByP63FYiI4vKTp0w7e2-oYAdaUTDJ1Y50-l_VvRWjdc4fqi-OKH4t8D1rlq0GJ-P7uOl44Ta43YdBMuXI146-eLqx_zLIC49Pg5Y7MD_Lv23QfGTHTP47ckUQueXoGegNLQNE9nPTuD6lNzHD5_MOqse4IKzoWVs_hs4S8SqVxVlN_ZWXkcGhPllfQtf1qxLyFm51eYH3LGxqyNbGr4nQc8djPV0yWqOTrg8IYQ" -const passwordPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0MjMsImlhdCI6MTcxNTA5MTEyMywianRpIjoiMTNhNDljZmQtOGRiZC00NTA2LTk1NGMtZWFmZGRkNGE4ZTdjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwic2Vzc2lvbl9zdGF0ZSI6ImNmZjYwZDZmLWI2M2MtNDBhYy1hYjI3LWFjZmU4MjY5OWQyYSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJjZmY2MGQ2Zi1iNjNjLTQwYWMtYWIyNy1hY2ZlODI2OTlkMmEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JFWKf7GZq1f8raP3Jm6rszpwPCh0JnaeZcHyC_AwcsNS6sJ9_qSY9wrbyHmvV9KIGMIPv23fymADZXb0ng7maeAv9NR34KiJqnKbmPeeWwL0cPoGOGOUICL6H5x1iTw7XaMDN2WQRrBRFuUkudybEF8n6fEGsAvcsXViaHjYwJyIEYCnHKPzuTvM1RjyGFsERpFXKls4UB_KhMBEonr4JOskupmX1pADBuicTNx_4whnd6ZDfiF5SSBohFV1ikwFOXK-qZ7znQfE-RJ-jV1CXBgEK8O66TMbMw9MbasS25xKoO0mH1_Ohf9niSXsY02o2qjGFZA9sWRk7K7pNgsxUw" -const authPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI2NDcsImlhdCI6MTcxNTA5MjM0NywiYXV0aF90aW1lIjoxNzE1MDkyMzQ3LCJqdGkiOiI3NzkwZmVhNC1hNzcyLTRhZTMtOTcyMi0yMTU2MmQyZGM5YmYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImFmNmViOTRiLWU4ZDQtNDNlYi1hYzYwLTI3YmZiYjNiOTQxZSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiYWY2ZWI5NGItZThkNC00M2ViLWFjNjAtMjdiZmJiM2I5NDFlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.BfCX_fq2Q6cv5qb6TWzyCNiJf1vFw_iA4UTKr21ahUiNItNSW5ozET2jSLwKNAuMdBNrooU--OV1NniDcviIAMReaAEgjmAyBz6OSwAh3SmxzIU9Zy7f4V032FLDcVVoJ7CefItfBNu7WnWFGS7CYahNX_M2a6LXKhk7WRO4gQ2Ig11gtODlAP8jwLLAMU4_H9mVHD3LXd-IeOsnA8ZuBCq1DeFcn5T9tNZEGe0_21lp8spxoub0MRl-vYbgxEIoaeqxoSipb2hOjF7h0h1uaNhZT4m5ynHdd5yfspD8XjjjwlbXQn9Z8vrZUQQS6HLAi2pJIFNEoYxQk9lHal6VUA" -const authPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI3NDAsImlhdCI6MTcxNTA5MjQ0MCwiYXV0aF90aW1lIjoxNzE1MDkyNDQwLCJqdGkiOiIzZjk2ZDhjNC0yMjRkLTQyNjAtYmVkMy1lOGY2N2IwYTJjM2EiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiZDI1ZjhhZTMtYzE0Yy00ZWFmLTkzOWMtZjhlNGIyYmE1NDY3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJkMjVmOGFlMy1jMTRjLTRlYWYtOTM5Yy1mOGU0YjJiYTU0NjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JphgIUbUeEEd25-Ji0o6_pcWvLzcQasCfr1z8WRt3xb1QrkN_d0_rmIpOJ9drhp8LjJPQRhFVxEU2TnAlYJ225IjPYolCrnEtKWsBbPJH9dP0cIJlilYplN4RZbmI9VbF578zAgVAs40n8aalNyxqYbPq_JViHDl_ufl4VEQ4Entzlp980I8whx3kfTygu0Yfl4eHLghPGt4LNPUmfeOIy8NKHbhmjHwKufrTmd0NV07cAOMUWl1NAF_4QWqmSqAY0SIcamwE7YlpuImzhj5PQH9tlyJMLr5m-k8CgKRfhpQ0H9cfVGUzWGG2A-lcNvxNmsk1kobmfHczjw13ajLKg" -const implicitPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTM4MzgsImlhdCI6MTcxNTA5MjkzOCwiYXV0aF90aW1lIjoxNzE1MDkyOTM4LCJqdGkiOiI0ZWIzY2I1OS05ZDRhLTQwNjctYmI0YS1iMjNjNDVhMDIyYTIiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiYmE1OWFmOTgtNmE3YS00YjRhLTliOTItODU1M2ZkM2EwMTNjIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJiYTU5YWY5OC02YTdhLTRiNGEtOWI5Mi04NTUzZmQzYTAxM2MiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.KQasyQ-f9KBRWRDXg4NikiHlragVil1nlYTQ8czPKku_uncpHZb7PMJhyPrwy72mwC10EJMpBIWGDVRfRjBRHxdzIbjozcGg3vusX748NMiDSlF4KoB5Fz-qExszcszEP5Qm_fvMRFcW7m9RPW9St1aaHcjAOW5Vee9ACJI56YffgqrTn1xp7ha2Z2X8d_NJfJOFdP3cqgxjR7DV5RezkDLRPfxHwJLk3anavSuDScXIO1w1C6AlTUQFVQUEX0DKZIt-RbzKcd6HWBfyDvHUSlfodEI_diWQIL1hEfrBXV6ThuhTqhrghHyIbb2e-zoC20arjMAK0Tr7hMAY4acxgQ" -const implicitPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUxNTE0MTMsImlhdCI6MTcxNTE1MDUxMywiYXV0aF90aW1lIjoxNzE1MTUwNTEzLCJqdGkiOiJlYTRmOGZiYS01ZjljLTRiMzQtYmU1ZC1jNTk2ZGI4YzNlYzkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImRlM2U2ZDc1LTI3ODItNDg4NS1iYzU4LTU0MmJmYzEzNWNkNSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiZGUzZTZkNzUtMjc4Mi00ODg1LWJjNTgtNTQyYmZjMTM1Y2Q1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.jH60V3ZkuiN6cuEmbRTspnxyOvQs_wNkgoBw9IEZ8E8yGzXDayouduxEd_O-DG6vjT4KPDxGC2lA0V4i-ke7KChkZhRYLkaSuqt2hTlKoLXotepJPq8GBlXhWjCmFMqaXEB8lMAlAEoCT7CWmg03eTBGzwynj0S4rjMuOj6TLf3HIIN0DP7bgtG9uIc0Ah_mTVJ4L6Y5yjv6LC9bMZ7YNpUIkFn-CZTudquxHkLYgxHgaRAfELBvmS5xn0pTrpIfZSdYQK7hGhjhm9fUg4J06Pg6QW-xZe1U7awyNl7pOeeGQ2lVTo1CWrAlOz9lAmzKzAwQakEOMXFxAjJeHsXTWg" -const tokenExchangeJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6ImE1NThkYzg0NzYzNDVjY2QyZWFhNjEzNjg4YmI2YTNkIn0.eyJleHAiOjE3MTU3OTA5MTAsImlhdCI6MTcxNTc5MDYxMCwianRpIjoiNjEyOTI2NzQtMDhmOS00ZmQ1LTk3Y2MtZDg3M2RhODRkZjllIiwiaXNzIjoiaHR0cHM6Ly9sb2NhbC1kc3AudmlydHJ1LmNvbTo4NDQzL2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwiYWNjb3VudCIsIm9wZW50ZGYtc2RrIl0sInN1YiI6ImU2ZWI0YWU1LThjMDUtNDI3NC04ZmExLTFmMGY1ZmJjY2JkZiIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZW50ZGYiLCJzZXNzaW9uX3N0YXRlIjoiZTQ0YzMxNWMtNjk5Yy00NGFkLTk2NDUtNmRkMmIyMjgzN2JlIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLXJlYWRvbmx5IiwiZGVmYXVsdC1yb2xlcy1vcGVudGRmIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJlNDRjMzE1Yy02OTljLTQ0YWQtOTY0NS02ZGQyYjIyODM3YmUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1vcGVudGRmLXNkayJ9.dmAulsUNfdPXVyWmVPsbGqaztshyHTD-m2hh1l2hmhwuNISJZjON0e1kXNxYXRLABr_PJzIpGYQCXz98yxOyiw" +const ( + clientCredentialsJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE2MDQsImlhdCI6MTcxNTA5MTMwNCwianRpIjoiMTE3MTYzMjYtNWQyNS00MjlmLWFjMDItNmU0MjE2OWFjMGJhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiOTljOWVlZDItOTM1Ni00ZjE2LWIwODQtZTgyZDczZjViN2QyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxOTIuMTY4LjI0MC4xIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LXRkZi1lbnRpdHktcmVzb2x1dGlvbiIsImNsaWVudEFkZHJlc3MiOiIxOTIuMTY4LjI0MC4xIiwiY2xpZW50X2lkIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIn0.h29QLo-QvIc67KKqU_e1-x6G_o5YQccOyW9AthMdB7xhn9C1dBrcScytaWq1RfETPmnM8MXGezqN4OpXrYr-zbkHhq9ha0Ib-M1VJXNgA5sbgKW9JxGQyudmYPgn4fimDCJtAsXo7C-e3mYNm6DJS0zhGQ3msmjLTcHmIPzWlj7VjtPgKhYV75b7yr_yZNBdHjf3EZqfynU2sL8bKa1w7DYDNQve7ThtD4MeKLiuOQHa3_23dECs_ptvPVks7pLGgRKfgGHBC-KQuopjtxIhwkz2vOWRzugDl0aBJMHfwBajYhgZ2YRlV9dqSxmy8BOj4OEXuHbiyfIpY0rCRpSrGg" + passwordPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0ODAsImlhdCI6MTcxNTA5MTE4MCwianRpIjoiZmI5MmM2MTAtYmI0OC00ZDgyLTljZGQtOWFhZjllNzEyNzc3IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uLXB1YmxpYyIsInNlc3Npb25fc3RhdGUiOiIzN2E3YjdiOS0xZmNlLTQxMmYtOTI1OS1lYzUxMTY3MGVhMGYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjM3YTdiN2I5LTFmY2UtNDEyZi05MjU5LWVjNTExNjcwZWEwZiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InNhbXBsZSB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2FtcGxlLXVzZXIiLCJnaXZlbl9uYW1lIjoic2FtcGxlIiwiZmFtaWx5X25hbWUiOiJ1c2VyIiwiZW1haWwiOiJzYW1wbGV1c2VyQHNhbXBsZS5jb20ifQ.Gd_OvPNY7UfY7sBKh55TcvWQHmAkYZ2Jb2VyK1lYgse9EBEa_y3uoepZYrGMGkmYdwApg4eauQjxzT_BZYVBc7u9ch3HY_IUuSh3A6FkDDXZIziByP63FYiI4vKTp0w7e2-oYAdaUTDJ1Y50-l_VvRWjdc4fqi-OKH4t8D1rlq0GJ-P7uOl44Ta43YdBMuXI146-eLqx_zLIC49Pg5Y7MD_Lv23QfGTHTP47ckUQueXoGegNLQNE9nPTuD6lNzHD5_MOqse4IKzoWVs_hs4S8SqVxVlN_ZWXkcGhPllfQtf1qxLyFm51eYH3LGxqyNbGr4nQc8djPV0yWqOTrg8IYQ" + passwordPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0MjMsImlhdCI6MTcxNTA5MTEyMywianRpIjoiMTNhNDljZmQtOGRiZC00NTA2LTk1NGMtZWFmZGRkNGE4ZTdjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwic2Vzc2lvbl9zdGF0ZSI6ImNmZjYwZDZmLWI2M2MtNDBhYy1hYjI3LWFjZmU4MjY5OWQyYSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJjZmY2MGQ2Zi1iNjNjLTQwYWMtYWIyNy1hY2ZlODI2OTlkMmEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JFWKf7GZq1f8raP3Jm6rszpwPCh0JnaeZcHyC_AwcsNS6sJ9_qSY9wrbyHmvV9KIGMIPv23fymADZXb0ng7maeAv9NR34KiJqnKbmPeeWwL0cPoGOGOUICL6H5x1iTw7XaMDN2WQRrBRFuUkudybEF8n6fEGsAvcsXViaHjYwJyIEYCnHKPzuTvM1RjyGFsERpFXKls4UB_KhMBEonr4JOskupmX1pADBuicTNx_4whnd6ZDfiF5SSBohFV1ikwFOXK-qZ7znQfE-RJ-jV1CXBgEK8O66TMbMw9MbasS25xKoO0mH1_Ohf9niSXsY02o2qjGFZA9sWRk7K7pNgsxUw" + authPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI2NDcsImlhdCI6MTcxNTA5MjM0NywiYXV0aF90aW1lIjoxNzE1MDkyMzQ3LCJqdGkiOiI3NzkwZmVhNC1hNzcyLTRhZTMtOTcyMi0yMTU2MmQyZGM5YmYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImFmNmViOTRiLWU4ZDQtNDNlYi1hYzYwLTI3YmZiYjNiOTQxZSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiYWY2ZWI5NGItZThkNC00M2ViLWFjNjAtMjdiZmJiM2I5NDFlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.BfCX_fq2Q6cv5qb6TWzyCNiJf1vFw_iA4UTKr21ahUiNItNSW5ozET2jSLwKNAuMdBNrooU--OV1NniDcviIAMReaAEgjmAyBz6OSwAh3SmxzIU9Zy7f4V032FLDcVVoJ7CefItfBNu7WnWFGS7CYahNX_M2a6LXKhk7WRO4gQ2Ig11gtODlAP8jwLLAMU4_H9mVHD3LXd-IeOsnA8ZuBCq1DeFcn5T9tNZEGe0_21lp8spxoub0MRl-vYbgxEIoaeqxoSipb2hOjF7h0h1uaNhZT4m5ynHdd5yfspD8XjjjwlbXQn9Z8vrZUQQS6HLAi2pJIFNEoYxQk9lHal6VUA" + authPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI3NDAsImlhdCI6MTcxNTA5MjQ0MCwiYXV0aF90aW1lIjoxNzE1MDkyNDQwLCJqdGkiOiIzZjk2ZDhjNC0yMjRkLTQyNjAtYmVkMy1lOGY2N2IwYTJjM2EiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiZDI1ZjhhZTMtYzE0Yy00ZWFmLTkzOWMtZjhlNGIyYmE1NDY3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJkMjVmOGFlMy1jMTRjLTRlYWYtOTM5Yy1mOGU0YjJiYTU0NjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JphgIUbUeEEd25-Ji0o6_pcWvLzcQasCfr1z8WRt3xb1QrkN_d0_rmIpOJ9drhp8LjJPQRhFVxEU2TnAlYJ225IjPYolCrnEtKWsBbPJH9dP0cIJlilYplN4RZbmI9VbF578zAgVAs40n8aalNyxqYbPq_JViHDl_ufl4VEQ4Entzlp980I8whx3kfTygu0Yfl4eHLghPGt4LNPUmfeOIy8NKHbhmjHwKufrTmd0NV07cAOMUWl1NAF_4QWqmSqAY0SIcamwE7YlpuImzhj5PQH9tlyJMLr5m-k8CgKRfhpQ0H9cfVGUzWGG2A-lcNvxNmsk1kobmfHczjw13ajLKg" + implicitPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTM4MzgsImlhdCI6MTcxNTA5MjkzOCwiYXV0aF90aW1lIjoxNzE1MDkyOTM4LCJqdGkiOiI0ZWIzY2I1OS05ZDRhLTQwNjctYmI0YS1iMjNjNDVhMDIyYTIiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiYmE1OWFmOTgtNmE3YS00YjRhLTliOTItODU1M2ZkM2EwMTNjIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJiYTU5YWY5OC02YTdhLTRiNGEtOWI5Mi04NTUzZmQzYTAxM2MiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.KQasyQ-f9KBRWRDXg4NikiHlragVil1nlYTQ8czPKku_uncpHZb7PMJhyPrwy72mwC10EJMpBIWGDVRfRjBRHxdzIbjozcGg3vusX748NMiDSlF4KoB5Fz-qExszcszEP5Qm_fvMRFcW7m9RPW9St1aaHcjAOW5Vee9ACJI56YffgqrTn1xp7ha2Z2X8d_NJfJOFdP3cqgxjR7DV5RezkDLRPfxHwJLk3anavSuDScXIO1w1C6AlTUQFVQUEX0DKZIt-RbzKcd6HWBfyDvHUSlfodEI_diWQIL1hEfrBXV6ThuhTqhrghHyIbb2e-zoC20arjMAK0Tr7hMAY4acxgQ" + implicitPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUxNTE0MTMsImlhdCI6MTcxNTE1MDUxMywiYXV0aF90aW1lIjoxNzE1MTUwNTEzLCJqdGkiOiJlYTRmOGZiYS01ZjljLTRiMzQtYmU1ZC1jNTk2ZGI4YzNlYzkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImRlM2U2ZDc1LTI3ODItNDg4NS1iYzU4LTU0MmJmYzEzNWNkNSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiZGUzZTZkNzUtMjc4Mi00ODg1LWJjNTgtNTQyYmZjMTM1Y2Q1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.jH60V3ZkuiN6cuEmbRTspnxyOvQs_wNkgoBw9IEZ8E8yGzXDayouduxEd_O-DG6vjT4KPDxGC2lA0V4i-ke7KChkZhRYLkaSuqt2hTlKoLXotepJPq8GBlXhWjCmFMqaXEB8lMAlAEoCT7CWmg03eTBGzwynj0S4rjMuOj6TLf3HIIN0DP7bgtG9uIc0Ah_mTVJ4L6Y5yjv6LC9bMZ7YNpUIkFn-CZTudquxHkLYgxHgaRAfELBvmS5xn0pTrpIfZSdYQK7hGhjhm9fUg4J06Pg6QW-xZe1U7awyNl7pOeeGQ2lVTo1CWrAlOz9lAmzKzAwQakEOMXFxAjJeHsXTWg" + tokenExchangeJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6ImE1NThkYzg0NzYzNDVjY2QyZWFhNjEzNjg4YmI2YTNkIn0.eyJleHAiOjE3MTU3OTA5MTAsImlhdCI6MTcxNTc5MDYxMCwianRpIjoiNjEyOTI2NzQtMDhmOS00ZmQ1LTk3Y2MtZDg3M2RhODRkZjllIiwiaXNzIjoiaHR0cHM6Ly9sb2NhbC1kc3AudmlydHJ1LmNvbTo4NDQzL2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwiYWNjb3VudCIsIm9wZW50ZGYtc2RrIl0sInN1YiI6ImU2ZWI0YWU1LThjMDUtNDI3NC04ZmExLTFmMGY1ZmJjY2JkZiIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZW50ZGYiLCJzZXNzaW9uX3N0YXRlIjoiZTQ0YzMxNWMtNjk5Yy00NGFkLTk2NDUtNmRkMmIyMjgzN2JlIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLXJlYWRvbmx5IiwiZGVmYXVsdC1yb2xlcy1vcGVudGRmIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJlNDRjMzE1Yy02OTljLTQ0YWQtOTY0NS02ZGQyYjIyODM3YmUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1vcGVudGRmLXNkayJ9.dmAulsUNfdPXVyWmVPsbGqaztshyHTD-m2hh1l2hmhwuNISJZjON0e1kXNxYXRLABr_PJzIpGYQCXz98yxOyiw" +) func testKeycloakConfig(server *httptest.Server) keycloak.KeycloakConfig { return keycloak.KeycloakConfig{ @@ -108,8 +114,10 @@ func testServerResp(t *testing.T, w http.ResponseWriter, r *http.Request, k stri t.Errorf("UnExpected Request, got: %s", r.URL.Path) } } + func testServer(t *testing.T, userSearchQueryAndResp map[string]string, groupSearchQueryAndResp map[string]string, - groupByIDAndResponse map[string]string, groupMemberQueryAndResponse map[string]string, clientsSearchQueryAndResp map[string]string) *httptest.Server { + groupByIDAndResponse map[string]string, groupMemberQueryAndResponse map[string]string, clientsSearchQueryAndResp map[string]string, +) *httptest.Server { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { case r.URL.Path == "/realms/tdf/protocol/openid-connect/token": @@ -141,22 +149,22 @@ func Test_KCEntityResolutionByClientId(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}}) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody csqr := map[string]string{ "clientId=opentdf": byEmailBobResp, } server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) _ = json.NewEncoder(os.Stdout).Encode(&resp) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) } @@ -172,24 +180,24 @@ func Test_KCEntityResolutionByEmail(t *testing.T) { validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "bob@sample.org"}}) validBody = append(validBody, &authorization.Entity{Id: "1235", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "alice@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 2) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) assert.Equal(t, "1235", entityRepresentations[1].GetOriginalId()) @@ -210,24 +218,24 @@ func Test_KCEntityResolutionByUsername(t *testing.T) { validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}}) validBody = append(validBody, &authorization.Entity{Id: "1235", EntityType: &authorization.Entity_UserName{UserName: "alice.smith"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 2) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) assert.Equal(t, "1235", entityRepresentations[1].GetOriginalId()) @@ -252,24 +260,24 @@ func Test_KCEntityResolutionByGroupEmail(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "123456", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "group1@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "123456", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 2) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) propMap = entityRepresentations[0].GetAdditionalProps()[1].AsMap() assert.Equal(t, "aliceid", propMap["id"]) @@ -290,19 +298,19 @@ func Test_KCEntityResolutionNotFoundError(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "random@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.Error(t, reserr) assert.Equal(t, &entityresolution.ResolveEntitiesResponse{}, &resp) - var entityNotFound = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrTextGetRetrievalFailed, Entity: "random@sample.org"} - var expectedError = status.Error(codes.Code(entityNotFound.GetCode()), entityNotFound.GetMessage()) + entityNotFound := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrGetRetrievalFailed.Error(), Entity: "random@sample.org"} + expectedError := connect.NewError(connect.Code(entityNotFound.GetCode()), keycloak.ErrGetRetrievalFailed) assert.Equal(t, expectedError, reserr) } @@ -313,13 +321,13 @@ func Test_JwtClientAndUsernameClientCredentials(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: clientCredentialsJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -335,13 +343,13 @@ func Test_JwtClientAndUsernamePasswordPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: passwordPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -357,13 +365,13 @@ func Test_JwtClientAndUsernamePasswordPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: passwordPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -379,13 +387,13 @@ func Test_JwtClientAndUsernameAuthPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: authPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -401,13 +409,13 @@ func Test_JwtClientAndUsernameAuthPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: authPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -423,13 +431,13 @@ func Test_JwtClientAndUsernameImplicitPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: implicitPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -445,13 +453,13 @@ func Test_JwtClientAndUsernameImplicitPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: implicitPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -470,13 +478,13 @@ func Test_JwtClientAndClientTokenExchange(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: tokenExchangeJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -495,13 +503,13 @@ func Test_JwtMultiple(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: tokenExchangeJwt, Id: "tok1"}, {Jwt: authPrivClientJwt, Id: "tok2"}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -534,24 +542,24 @@ func Test_KCEntityResolutionNotFoundInferEmail(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "random@sample.org"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "random@sample.org", propMap["emailAddress"]) assert.Equal(t, "1234", propMap["id"]) } @@ -566,24 +574,24 @@ func Test_KCEntityResolutionNotFoundInferClientId(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_ClientId{ClientId: "random"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "random", propMap["clientId"]) assert.Equal(t, "1234", propMap["id"]) } @@ -597,18 +605,18 @@ func Test_KCEntityResolutionNotFoundNotInferUsername(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_UserName{UserName: "randomuser"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.Error(t, reserr) assert.Equal(t, &entityresolution.ResolveEntitiesResponse{}, &resp) - var entityNotFound = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrTextGetRetrievalFailed, Entity: "randomuser"} - var expectedError = status.Error(codes.Code(entityNotFound.GetCode()), entityNotFound.GetMessage()) + entityNotFound := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrGetRetrievalFailed.Error(), Entity: "randomuser"} + expectedError := connect.NewError(connect.Code(entityNotFound.GetCode()), keycloak.ErrGetRetrievalFailed) assert.Equal(t, expectedError, reserr) } diff --git a/service/go.mod b/service/go.mod index 3056b9d5f..4d865f955 100644 --- a/service/go.mod +++ b/service/go.mod @@ -4,6 +4,8 @@ go 1.22 require ( connectrpc.com/connect v1.17.0 + connectrpc.com/grpcreflect v1.2.0 + connectrpc.com/validate v0.1.0 github.com/Masterminds/squirrel v1.5.4 github.com/Nerzal/gocloak/v13 v13.9.0 github.com/bmatcuk/doublestar v1.3.4 @@ -13,7 +15,6 @@ require ( github.com/go-chi/cors v1.2.1 github.com/go-playground/validator/v10 v10.22.0 github.com/google/uuid v1.6.0 - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa github.com/jackc/pgx/v5 v5.5.5 @@ -60,6 +61,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gowebpki/jcs v1.0.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -147,6 +149,7 @@ require ( ) require ( + connectrpc.com/grpchealth v1.3.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect diff --git a/service/go.sum b/service/go.sum index e64f2e4af..582e2af09 100644 --- a/service/go.sum +++ b/service/go.sum @@ -2,6 +2,12 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-2024050820065 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1/go.mod h1:XF+P8+RmfdufmIYpGUC+6bF7S+IlmHDEnCrO3OXaUAQ= connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= +connectrpc.com/grpchealth v1.3.0 h1:FA3OIwAvuMokQIXQrY5LbIy8IenftksTP/lG4PbYN+E= +connectrpc.com/grpchealth v1.3.0/go.mod h1:3vpqmX25/ir0gVgW6RdnCPPZRcR6HvqtXX5RNPmDXHM= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +connectrpc.com/validate v0.1.0 h1:r55jirxMK7HO/xZwVHj3w2XkVFarsUM77ZDy367NtH4= +connectrpc.com/validate v0.1.0/go.mod h1:GU47c9/x/gd+u9wRSPkrQOP46gx2rMN+Wo37EHgI3Ow= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= diff --git a/service/health/health.go b/service/health/health.go index 053da5dff..01489f3a7 100644 --- a/service/health/health.go +++ b/service/health/health.go @@ -4,7 +4,7 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/grpchealth" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" @@ -15,64 +15,62 @@ import ( var serviceHealthChecks = make(map[string]func(context.Context) error) type HealthService struct { //nolint:revive // HealthService is a valid name for this struct - healthpb.UnimplementedHealthServer logger *logger.Logger } -func NewRegistration() *serviceregistry.Service[HealthService] { - return &serviceregistry.Service[HealthService]{ - ServiceOptions: serviceregistry.ServiceOptions[HealthService]{ - Namespace: "health", - ServiceDesc: &healthpb.Health_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*HealthService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[grpchealth.Checker] { + return &serviceregistry.Service[grpchealth.Checker]{ + ServiceOptions: serviceregistry.ServiceOptions[grpchealth.Checker]{ + Namespace: "health", + ServiceDesc: &healthpb.Health_ServiceDesc, + ConnectRPCFunc: grpchealth.NewHandler, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (grpchealth.Checker, serviceregistry.HandlerServer) { err := srp.WellKnownConfig("health", map[string]any{ "endpoint": "/healthz", }) if err != nil { srp.Logger.Error("failed to set well-known config", slog.String("error", err.Error())) } - return &HealthService{logger: srp.Logger}, func(_ context.Context, _ *runtime.ServeMux) error { - return nil - } + return HealthService{logger: srp.Logger}, nil }, }, } } -func (s HealthService) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - if req.GetService() == "" { - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVING, +func (s HealthService) Check(ctx context.Context, req *grpchealth.CheckRequest) (*grpchealth.CheckResponse, error) { + if req.Service == "" { + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusServing, }, nil } - switch req.GetService() { + switch req.Service { case "all": for service, check := range serviceHealthChecks { if err := check(ctx); err != nil { s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", service), slog.String("error", err.Error())) - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_NOT_SERVING, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusNotServing, }, nil } } default: - if check, ok := serviceHealthChecks[req.GetService()]; ok { + if check, ok := serviceHealthChecks[req.Service]; ok { if err := check(ctx); err != nil { - s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", req.GetService()), slog.String("error", err.Error())) - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_NOT_SERVING, + s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", req.Service), slog.String("error", err.Error())) + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusNotServing, }, nil } } else { - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVICE_UNKNOWN, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusUnknown, }, nil } } - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVING, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusServing, }, nil } diff --git a/service/health/health_test.go b/service/health/health_test.go index db39936c8..f7b45b835 100644 --- a/service/health/health_test.go +++ b/service/health/health_test.go @@ -2,10 +2,12 @@ package health import ( "context" + "testing" + "connectrpc.com/grpchealth" + "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - "google.golang.org/grpc/health/grpc_health_v1" ) type HealthCheckSuite struct { @@ -20,6 +22,10 @@ func (s *HealthCheckSuite) TearDownTest() { serviceHealthChecks = make(map[string]func(context.Context) error) } +func TestHealthCheckSuite(t *testing.T) { + suite.Run(t, new(HealthCheckSuite)) +} + func (s *HealthCheckSuite) TestRegisterReadinessCheck() { // TestRegisterReadinessCheck tests the registration of a health check. @@ -67,11 +73,11 @@ func (s *HealthCheckSuite) TestCheck() { s.Require().NoError(err) // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "all", }) s.Require().NoError(err) - s.Equal("SERVING", result.GetStatus().String()) + s.Equal(grpchealth.StatusServing, result.Status) } func (s *HealthCheckSuite) TestCheckServiceUnknown() { @@ -79,28 +85,37 @@ func (s *HealthCheckSuite) TestCheckServiceUnknown() { hs := &HealthService{} // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "unknown", }) s.Require().NoError(err) - s.Equal("SERVICE_UNKNOWN", result.GetStatus().String()) + s.Equal(grpchealth.StatusUnknown, result.Status) } func (s *HealthCheckSuite) TestCheckNotServing() { // TestCheckNotServing tests the health check when a service is not serving. - hs := &HealthService{} + lgr, err := logger.NewLogger(logger.Config{ + Output: "stdout", + Level: "info", + Type: "json", + }) + s.Require().NoError(err) + + hs := &HealthService{ + logger: lgr, + } // Register the health check. - err := RegisterReadinessCheck("failing", func(context.Context) error { + err = RegisterReadinessCheck("failing", func(context.Context) error { return assert.AnError }) s.Require().NoError(err) // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "failing", }) s.Require().NoError(err) - s.Equal("NOT_SERVING", result.GetStatus().String()) + s.Equal(grpchealth.StatusNotServing, result.Status) } diff --git a/service/internal/auth/authn.go b/service/internal/auth/authn.go index b2eb4cc76..556ecdaa8 100644 --- a/service/internal/auth/authn.go +++ b/service/internal/auth/authn.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "connectrpc.com/connect" "github.com/bmatcuk/doublestar" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" @@ -22,9 +23,7 @@ import ( sdkAudit "github.com/opentdf/platform/sdk/audit" "github.com/opentdf/platform/service/logger" - "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -266,57 +265,57 @@ func (a Authentication) MuxHandler(handler http.Handler) http.Handler { } // UnaryServerInterceptor is a grpc interceptor that verifies the token in the metadata -func (a Authentication) UnaryServerInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { - // Allow health checks and other public routes to pass through - if slices.ContainsFunc(a.publicRoutes, a.isPublicRoute(info.FullMethod)) { //nolint:contextcheck // There is no way to pass a context here - return handler(ctx, req) - } - - // Get the metadata from the context - // The keys within metadata.MD are normalized to lowercase. - // See: https://godoc.org/google.golang.org/grpc/metadata#New - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, status.Error(codes.Unauthenticated, "missing metadata") - } +func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptorFunc { + interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { + return connect.UnaryFunc(func( + ctx context.Context, + req connect.AnyRequest, + ) (connect.AnyResponse, error) { + // Interceptor Logic + // Allow health checks and other public routes to pass through + if slices.ContainsFunc(a.publicRoutes, a.isPublicRoute(req.Spec().Procedure)) { //nolint:contextcheck // There is no way to pass a context here + return next(ctx, req) + } - // Verify the token - header := md["authorization"] - if len(header) < 1 { - return nil, status.Error(codes.Unauthenticated, "missing authorization header") - } + header := req.Header()["Authorization"] + if len(header) < 1 { + return nil, status.Error(codes.Unauthenticated, "missing authorization header") + } - // parse the rpc method - p := strings.Split(info.FullMethod, "/") - resource := p[1] + "/" + p[2] - action := getAction(p[2]) + // parse the rpc method + p := strings.Split(req.Spec().Procedure, "/") + resource := p[1] + "/" + p[2] + action := getAction(p[2]) + + token, newCtx, err := a.checkToken( + ctx, + header, + receiverInfo{ + u: req.Spec().Procedure, + m: http.MethodPost, + }, + req.Header()["Dpop"], + ) + if err != nil { + return nil, status.Errorf(codes.Unauthenticated, "unauthenticated") + } - token, newCtx, err := a.checkToken( - ctx, - header, - receiverInfo{ - u: info.FullMethod, - m: http.MethodPost, - }, - md["dpop"], - ) - if err != nil { - return nil, status.Errorf(codes.Unauthenticated, "unauthenticated") - } + // Check if the token is allowed to access the resource + if allowed, err := a.enforcer.Enforce(token, resource, action); err != nil { + if err.Error() == "permission denied" { + a.logger.Warn("permission denied", slog.String("azp", token.Subject()), slog.String("error", err.Error())) + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + return nil, err + } else if !allowed { + a.logger.Warn("permission denied", slog.String("azp", token.Subject())) + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } - // Check if the token is allowed to access the resource - if allowed, err := a.enforcer.Enforce(token, resource, action); err != nil { - if err.Error() == "permission denied" { - a.logger.Warn("permission denied", slog.String("azp", token.Subject()), slog.String("error", err.Error())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") - } - return nil, err - } else if !allowed { - a.logger.Warn("permission denied", slog.String("azp", token.Subject())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") + return next(newCtx, req) + }) } - - return handler(newCtx, req) + return connect.UnaryInterceptorFunc(interceptor) } // getAction returns the action based on the rpc name diff --git a/service/internal/auth/authn_test.go b/service/internal/auth/authn_test.go index 875c818a0..a7d5ed86a 100644 --- a/service/internal/auth/authn_test.go +++ b/service/internal/auth/authn_test.go @@ -20,12 +20,15 @@ import ( "testing" "time" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jws" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/kas/kasconnect" sdkauth "github.com/opentdf/platform/sdk/auth" + "github.com/opentdf/platform/service/internal/server/memhttp" "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -33,9 +36,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "google.golang.org/grpc/test/bufconn" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -57,24 +58,19 @@ type FakeAccessServiceServer struct { kas.UnimplementedAccessServiceServer } -func (f *FakeAccessServiceServer) Info(context.Context, *kas.InfoRequest) (*kas.InfoResponse, error) { - return &kas.InfoResponse{}, nil +func (f *FakeAccessServiceServer) PublicKey(_ context.Context, _ *connect.Request[kas.PublicKeyRequest]) (*connect.Response[kas.PublicKeyResponse], error) { + return &connect.Response[kas.PublicKeyResponse]{Msg: &kas.PublicKeyResponse{}}, status.Error(codes.Unauthenticated, "no public key for you") } -func (f *FakeAccessServiceServer) PublicKey(context.Context, *kas.PublicKeyRequest) (*kas.PublicKeyResponse, error) { - return &kas.PublicKeyResponse{}, status.Error(codes.Unauthenticated, "no public key for you") +func (f *FakeAccessServiceServer) LegacyPublicKey(_ context.Context, _ *connect.Request[kas.LegacyPublicKeyRequest]) (*connect.Response[wrapperspb.StringValue], error) { + return &connect.Response[wrapperspb.StringValue]{Msg: &wrapperspb.StringValue{}}, nil } -func (f *FakeAccessServiceServer) LegacyPublicKey(context.Context, *kas.LegacyPublicKeyRequest) (*wrapperspb.StringValue, error) { - return &wrapperspb.StringValue{}, nil -} +func (f *FakeAccessServiceServer) Rewrap(ctx context.Context, req *connect.Request[kas.RewrapRequest]) (*connect.Response[kas.RewrapResponse], error) { + f.accessToken = req.Header()["Authorization"] + f.dpopKey = GetJWKFromContext(ctx, logger.CreateTestLogger()) -func (f *FakeAccessServiceServer) Rewrap(ctx context.Context, _ *kas.RewrapRequest) (*kas.RewrapResponse, error) { - if md, ok := metadata.FromIncomingContext(ctx); ok { - f.accessToken = md.Get("authorization") - f.dpopKey = GetJWKFromContext(ctx, logger.CreateTestLogger()) - } - return &kas.RewrapResponse{}, nil + return &connect.Response[kas.RewrapResponse]{Msg: &kas.RewrapResponse{}}, nil } type FakeTokenSource struct { @@ -230,11 +226,22 @@ func (s *AuthSuite) Test_MuxHandler_When_Authorization_Header_Missing_Expect_Err } func (s *AuthSuite) Test_UnaryServerInterceptor_When_Authorization_Header_Missing_Expect_Error() { - md := metadata.New(map[string]string{}) - ctx := metadata.NewIncomingContext(context.Background(), md) - _, err := s.auth.UnaryServerInterceptor(ctx, "test", &grpc.UnaryServerInfo{ - FullMethod: "/test", - }, nil) + // Create the interceptor + interceptor := s.auth.ConnectUnaryServerInterceptor() + + // Create a dummy next handler + next := func(_ context.Context, _ connect.AnyRequest) (connect.AnyResponse, error) { + // Return a dummy response + return connect.NewResponse[string](nil), nil + } + + // Create a request + req := connect.NewRequest[string](nil) + + _, err := interceptor(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + return next(ctx, req) + })(context.Background(), req) + s.Require().Error(err) s.Require().ErrorIs(err, status.Error(codes.Unauthenticated, "missing authorization header")) } @@ -430,20 +437,16 @@ func (s *AuthSuite) TestDPoPEndToEnd_GRPC() { signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key)) s.Require().NoError(err) - buffer := 1024 * 1024 - listener := bufconn.Listen(buffer) - - server := grpc.NewServer(grpc.UnaryInterceptor(s.auth.UnaryServerInterceptor)) - defer server.Stop() + interceptor := connect.WithInterceptors(s.auth.ConnectUnaryServerInterceptor()) fakeServer := &FakeAccessServiceServer{} - kas.RegisterAccessServiceServer(server, fakeServer) - go func() { - err := server.Serve(listener) - if err != nil { - panic(err) - } - }() + + mux := http.NewServeMux() + path, handler := kasconnect.NewAccessServiceHandler(fakeServer, interceptor) + mux.Handle(path, handler) + + server := memhttp.New(mux) + defer server.Close() addingInterceptor := sdkauth.NewTokenAddingInterceptor(&FakeTokenSource{ key: dpopKey, @@ -452,8 +455,8 @@ func (s *AuthSuite) TestDPoPEndToEnd_GRPC() { MinVersion: tls.VersionTLS12, }) - conn, _ := grpc.NewClient("passthrough://bufconn", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { - return listener.Dial() + conn, _ := grpc.NewClient("passthrough://bufconn", grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + return server.Listener.DialContext(ctx, "tcp", "http://localhost:8080") }), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(addingInterceptor.AddCredentials)) client := kas.NewAccessServiceClient(conn) diff --git a/service/internal/server/realip/realip.go b/service/internal/server/realip/realip.go index 80bd68058..5ecdbc7be 100644 --- a/service/internal/server/realip/realip.go +++ b/service/internal/server/realip/realip.go @@ -16,7 +16,7 @@ const ( TrueClientIP = "True-Client-Ip" ) -type clientIP struct{} +type ClientIP struct{} func ConnectRealIPUnaryInterceptor() connect.UnaryInterceptorFunc { interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { @@ -26,7 +26,7 @@ func ConnectRealIPUnaryInterceptor() connect.UnaryInterceptorFunc { ) (connect.AnyResponse, error) { ip := getIP(ctx, req.Peer(), req.Header()) - ctx = context.WithValue(ctx, clientIP{}, ip) + ctx = context.WithValue(ctx, ClientIP{}, ip) return next(ctx, req) }) @@ -54,7 +54,7 @@ func getIP(_ context.Context, peer connect.Peer, headers http.Header) net.IP { } func FromContext(ctx context.Context) net.IP { - ip, ok := ctx.Value(clientIP{}).(net.IP) + ip, ok := ctx.Value(ClientIP{}).(net.IP) if !ok { return net.IP{} } diff --git a/service/internal/server/server.go b/service/internal/server/server.go index f923730e7..b1aa79032 100644 --- a/service/internal/server/server.go +++ b/service/internal/server/server.go @@ -9,14 +9,14 @@ import ( "net" "net/http" "net/http/pprof" - "net/netip" + "regexp" "strings" "time" - "github.com/bufbuild/protovalidate-go" + "connectrpc.com/connect" + "connectrpc.com/grpcreflect" + "connectrpc.com/validate" "github.com/go-chi/cors" - protovalidate_middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/protovalidate" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" sdkAudit "github.com/opentdf/platform/sdk/audit" "github.com/opentdf/platform/service/internal/auth" @@ -27,10 +27,7 @@ import ( "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" - healthpb "google.golang.org/grpc/health/grpc_health_v1" - "google.golang.org/grpc/reflection" ) const ( @@ -104,13 +101,19 @@ type CORSConfig struct { MaxAge int `mapstructure:"maxage" json:"maxage" default:"3600"` } +type ConnectRPC struct { + Mux *http.ServeMux + Interceptors []connect.HandlerOption + ServiceReflection []string +} + type OpenTDFServer struct { - AuthN *auth.Authentication - Mux *runtime.ServeMux - HTTPServer *http.Server - GRPCServer *grpc.Server - GRPCInProcess *inProcessServer - CryptoProvider security.CryptoProvider + AuthN *auth.Authentication + GRPCGatewayMux *runtime.ServeMux + HTTPServer *http.Server + ConnectRPCInProcess *inProcessServer + ConnectRPC *ConnectRPC + CryptoProvider security.CryptoProvider logger *logger.Logger } @@ -122,11 +125,10 @@ https://github.com/heroku/x/blob/master/grpc/grpcserver/inprocess.go https://github.com/valyala/fasthttp/blob/master/fasthttputil/inmemory_listener.go */ type inProcessServer struct { - ln *memhttp.Server - srv *grpc.Server - + srv *memhttp.Server maxCallRecvMsgSize int maxCallSendMsgSize int + *ConnectRPC } func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, error) { @@ -152,37 +154,37 @@ func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, err logger.Warn("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") } - // Create grpc server and in process grpc server - grpcServer, err := newGrpcServer(config, authN, logger) + connectRPCIpc, err := newConnectRPCIPC() if err != nil { - return nil, fmt.Errorf("failed to create grpc server: %w", err) + return nil, fmt.Errorf("failed to create connect rpc ipc server: %w", err) } - grpcInProcessServer := newGrpcInProcessServer() - - grpcIPCServer := &inProcessServer{ - ln: memhttp.New(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { grpcInProcessServer.ServeHTTP(w, r) })), - srv: grpcInProcessServer, - maxCallRecvMsgSize: config.GRPC.MaxCallRecvMsgSizeBytes, - maxCallSendMsgSize: config.GRPC.MaxCallSendMsgSizeBytes, + connectRPC, err := newConnectRPC(config, authN, logger) + if err != nil { + return nil, fmt.Errorf("failed to create connect rpc server: %w", err) } + // GRPC Gateway Mux + grpcGatewayMux := runtime.NewServeMux() + // Create http server - mux := runtime.NewServeMux( - runtime.WithHealthzEndpoint(healthpb.NewHealthClient(grpcIPCServer.Conn())), - ) - httpServer, err := newHTTPServer(config, mux, authN, grpcServer, logger) + httpServer, err := newHTTPServer(config, connectRPC.Mux, grpcGatewayMux, authN, logger) if err != nil { return nil, fmt.Errorf("failed to create http server: %w", err) } o := OpenTDFServer{ - AuthN: authN, - Mux: mux, - HTTPServer: httpServer, - GRPCServer: grpcServer, - GRPCInProcess: grpcIPCServer, - logger: logger, + AuthN: authN, + GRPCGatewayMux: grpcGatewayMux, + HTTPServer: httpServer, + ConnectRPC: connectRPC, + ConnectRPCInProcess: &inProcessServer{ + srv: memhttp.New(connectRPCIpc.Mux), + maxCallRecvMsgSize: config.GRPC.MaxCallRecvMsgSizeBytes, + maxCallSendMsgSize: config.GRPC.MaxCallSendMsgSizeBytes, + ConnectRPC: connectRPCIpc, + }, + logger: logger, } // Create crypto provider @@ -195,25 +197,52 @@ func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, err return &o, nil } +// Custom response writer to add deprecation header +type grpcGatewayResponseWriter struct { + w http.ResponseWriter + code int + wroteHeader bool +} + +func (rw *grpcGatewayResponseWriter) Header() http.Header { + return rw.w.Header() +} + +func (rw *grpcGatewayResponseWriter) WriteHeader(statusCode int) { + gRPCGatewayDeprecationDate := fmt.Sprintf("@%d", time.Date(2025, time.March, 25, 0, 0, 0, 0, time.UTC).Unix()) + if !rw.wroteHeader { + rw.w.Header().Set("Deprecation", gRPCGatewayDeprecationDate) + rw.wroteHeader = true + rw.w.WriteHeader(statusCode) + } + rw.code = statusCode +} + +func (rw *grpcGatewayResponseWriter) Write(data []byte) (int, error) { + // Ensure headers are written before any data + if !rw.wroteHeader { + rw.WriteHeader(http.StatusOK) + } + return rw.w.Write(data) +} + // newHTTPServer creates a new http server with the given handler and grpc server -func newHTTPServer(c Config, h http.Handler, a *auth.Authentication, g *grpc.Server, l *logger.Logger) (*http.Server, error) { +func newHTTPServer(c Config, connectRPC http.Handler, originalGrpcGateway http.Handler, a *auth.Authentication, l *logger.Logger) (*http.Server, error) { var ( err error tc *tls.Config writeTimeoutOverride = writeTimeout ) - // Add authN interceptor - // This is needed because we are leveraging RegisterXServiceHandlerServer instead of RegisterXServiceHandlerFromEndpoint - if c.Auth.Enabled { - h = a.MuxHandler(h) - } else { - l.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") - } + // Adds deprecation header to any grpcGateway responses. + var grpcGateway http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + grpcRW := &grpcGatewayResponseWriter{w: w, code: http.StatusOK} + originalGrpcGateway.ServeHTTP(grpcRW, r) + }) // CORS if c.CORS.Enabled { - h = cors.New(cors.Options{ + corsHandler := cors.New(cors.Options{ AllowOriginFunc: func(_ *http.Request, origin string) bool { for _, allowedOrigin := range c.CORS.AllowedOrigins { if allowedOrigin == "*" { @@ -230,37 +259,60 @@ func newHTTPServer(c Config, h http.Handler, a *auth.Authentication, g *grpc.Ser ExposedHeaders: c.CORS.ExposedHeaders, AllowCredentials: c.CORS.AllowCredentials, MaxAge: c.CORS.MaxAge, - }).Handler(h) + }) + + // Apply CORS to connectRPC and extra handlers + connectRPC = corsHandler.Handler(connectRPC) + grpcGateway = corsHandler.Handler(grpcGateway) + } + + // Add authN interceptor to extra handlers + if c.Auth.Enabled { + grpcGateway = a.MuxHandler(grpcGateway) + } else { + l.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") } // Enable pprof if c.EnablePprof { - h = pprofHandler(h) + grpcGateway = pprofHandler(grpcGateway) // Need to extend write timeout to collect pprof data. writeTimeoutOverride = 30 * time.Second //nolint:mnd // easier to read that we are overriding the default } - // Add grpc handler - h2 := httpGrpcHandlerFunc(h, g, l) - + var handler http.Handler if !c.TLS.Enabled { - h2 = h2c.NewHandler(h2, &http2.Server{}) + handler = h2c.NewHandler(routeConnectRPCRequests(connectRPC, grpcGateway), &http2.Server{}) } else { tc, err = loadTLSConfig(c.TLS) if err != nil { return nil, fmt.Errorf("failed to load tls config: %w", err) } + handler = routeConnectRPCRequests(connectRPC, grpcGateway) } return &http.Server{ Addr: fmt.Sprintf("%s:%d", c.Host, c.Port), WriteTimeout: writeTimeoutOverride, ReadTimeout: readTimeout, - Handler: h2, + Handler: handler, TLSConfig: tc, }, nil } +var rpcPathRegex = regexp.MustCompile(`^/[\w\.]+\.[\w\.]+/[\w]+$`) + +func routeConnectRPCRequests(connectRPC http.Handler, httpHandler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // contentType := r.Header.Get("Content-Type") + if (r.Method == http.MethodPost || r.Method == http.MethodGet) && rpcPathRegex.MatchString(r.URL.Path) { + connectRPC.ServeHTTP(w, r) + } else { + httpHandler.ServeHTTP(w, r) + } + }) +} + // ppprof handler func pprofHandler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -283,91 +335,58 @@ func pprofHandler(h http.Handler) http.Handler { }) } -// httpGrpcHandlerFunc returns a http.Handler that delegates to the grpc server if the request is a grpc request -func httpGrpcHandlerFunc(h http.Handler, g *grpc.Server, l *logger.Logger) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - l.TraceContext(r.Context(), "grpc handler func", slog.Int("proto_major", r.ProtoMajor), slog.String("content_type", r.Header.Get("Content-Type"))) - if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { - g.ServeHTTP(w, r) - } else { - h.ServeHTTP(w, r) - } - }) -} - -func newGrpcInProcessServer() *grpc.Server { - var interceptors []grpc.UnaryServerInterceptor - var serverOptions []grpc.ServerOption +func newConnectRPCIPC() (*ConnectRPC, error) { + interceptors := make([]connect.HandlerOption, 0) - // Add audit to in process server - interceptors = append(interceptors, audit.ContextServerInterceptor) + // Add protovalidate interceptor + vaidationInterceptor, err := validate.NewInterceptor() + if err != nil { + return nil, fmt.Errorf("failed to create validation interceptor: %w", err) + } - // FIXME: this should probably use existing IP address instead of local? - // Add RealIP interceptor to in process server - // trustedPeers := []netip.Prefix{} // TODO: add this as a config option? - // headers := []string{realip.XForwardedFor, realip.XRealIp} - // interceptors = append(interceptors, realip.UnaryServerInterceptor(trustedPeers, headers)) + interceptors = append(interceptors, connect.WithInterceptors(vaidationInterceptor, audit.ContextServerInterceptor())) - // Add interceptors to server options - serverOptions = append(serverOptions, grpc.ChainUnaryInterceptor(interceptors...)) - return grpc.NewServer(serverOptions...) + return &ConnectRPC{ + Interceptors: interceptors, + Mux: http.NewServeMux(), + }, nil } -// newGrpcServer creates a new grpc server with the given config and authN interceptor -func newGrpcServer(c Config, a *auth.Authentication, logger *logger.Logger) (*grpc.Server, error) { - var i []grpc.UnaryServerInterceptor - var o []grpc.ServerOption +func newConnectRPC(c Config, a *auth.Authentication, logger *logger.Logger) (*ConnectRPC, error) { + interceptors := make([]connect.HandlerOption, 0) - // Enable proto validation - validator, err := protovalidate.New() + // Add protovalidate interceptor + vaidationInterceptor, err := validate.NewInterceptor() if err != nil { - logger.Warn("failed to create proto validator", slog.String("error", err.Error())) + return nil, fmt.Errorf("failed to create validation interceptor: %w", err) } - // Add Audit Unary Server Interceptor - i = append(i, audit.ContextServerInterceptor) + interceptors = append(interceptors, connect.WithInterceptors(vaidationInterceptor, audit.ContextServerInterceptor())) if c.Auth.Enabled { - i = append(i, a.UnaryServerInterceptor) + interceptors = append(interceptors, connect.WithInterceptors(a.ConnectUnaryServerInterceptor())) } else { logger.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP you can set `enforceDpop = false`") } - // Add tls creds if tls is not nil - if c.TLS.Enabled { - c, err := loadTLSConfig(c.TLS) - if err != nil { - return nil, fmt.Errorf("failed to load tls config: %w", err) - } - o = append(o, grpc.Creds(credentials.NewTLS(c))) - } - - // Add proto validation interceptor - i = append(i, protovalidate_middleware.UnaryServerInterceptor(validator)) - - o = append(o, grpc.ChainUnaryInterceptor( - i..., - )) - - // Chain relaip interceptor - trustedPeers := []netip.Prefix{} // TODO: add this as a config option? - headers := []string{realip.XForwardedFor, realip.XRealIp} - - o = append(o, grpc.ChainUnaryInterceptor( - realip.UnaryServerInterceptor(trustedPeers, headers), - )) + return &ConnectRPC{ + Interceptors: interceptors, + Mux: http.NewServeMux(), + }, nil +} - s := grpc.NewServer(o...) +func (s OpenTDFServer) Start() error { + // Add reflection api to connect-rpc + reflector := grpcreflect.NewStaticReflector( + s.ConnectRPC.ServiceReflection..., + ) - // Enable grpc reflection - if c.GRPC.ReflectionEnabled { - reflection.Register(s) - } + s.ConnectRPC.Mux.Handle(grpcreflect.NewHandlerV1(reflector)) + s.ConnectRPC.Mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector)) - return s, nil -} + s.ConnectRPCInProcess.Mux.Handle(grpcreflect.NewHandlerV1(reflector)) + s.ConnectRPCInProcess.Mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector)) -func (s OpenTDFServer) Start() error { // Start Http Server ln, err := s.openHTTPServerPort() if err != nil { @@ -375,8 +394,6 @@ func (s OpenTDFServer) Start() error { } go s.startHTTPServer(ln) - // Start In Process Grpc Server - go s.startInProcessGrpcServer() return nil } @@ -390,15 +407,14 @@ func (s OpenTDFServer) Stop() { } s.logger.Info("shutting down in process grpc server") - s.GRPCInProcess.srv.GracefulStop() + if err := s.ConnectRPCInProcess.srv.Shutdown(ctx); err != nil { + s.logger.Error("failed to shutdown in process connect-rpc server", slog.String("error", err.Error())) + return + } s.logger.Info("shutdown complete") } -func (s inProcessServer) GetGrpcServer() *grpc.Server { - return s.srv -} - func (s inProcessServer) Conn() *grpc.ClientConn { var clientInterceptors []grpc.UnaryClientInterceptor @@ -411,7 +427,7 @@ func (s inProcessServer) Conn() *grpc.ClientConn { grpc.MaxCallSendMsgSize(s.maxCallSendMsgSize), ), grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { - conn, err := s.ln.Listener.DialContext(ctx, "inprocess", "") + conn, err := s.srv.Listener.DialContext(ctx, "tcp", "http://localhost:8080") if err != nil { return nil, fmt.Errorf("failed to dial in process grpc server: %w", err) } @@ -425,12 +441,14 @@ func (s inProcessServer) Conn() *grpc.ClientConn { return conn } -func (s OpenTDFServer) startInProcessGrpcServer() { - s.logger.Info("starting in process grpc server") - if err := s.GRPCInProcess.srv.Serve(s.GRPCInProcess.ln.Listener); err != nil { - s.logger.Error("failed to serve in process grpc", slog.String("error", err.Error())) - panic(err) - } +func (s *inProcessServer) WithContextDialer() grpc.DialOption { + return grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + conn, err := s.srv.Listener.DialContext(ctx, "tcp", "http://localhost:8080") + if err != nil { + return nil, fmt.Errorf("failed to dial in process grpc server: %w", err) + } + return conn, nil + }) } func (s OpenTDFServer) openHTTPServerPort() (net.Listener, error) { diff --git a/service/kas/access/publicKey.go b/service/kas/access/publicKey.go index 19dde9b9d..ca810c53c 100644 --- a/service/kas/access/publicKey.go +++ b/service/kas/access/publicKey.go @@ -8,6 +8,7 @@ import ( "encoding/pem" "errors" + "connectrpc.com/connect" kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/service/internal/security" "google.golang.org/grpc/codes" @@ -23,7 +24,7 @@ const ( func (p Provider) lookupKid(ctx context.Context, algorithm string) (string, error) { if len(p.KASConfig.Keyring) == 0 { p.Logger.WarnContext(ctx, "no default keys found", "algorithm", algorithm) - return "", errors.Join(ErrConfig, status.Error(codes.NotFound, "no default keys configured")) + return "", connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("no default keys configured"))) } for _, k := range p.KASConfig.Keyring { @@ -32,18 +33,18 @@ func (p Provider) lookupKid(ctx context.Context, algorithm string) (string, erro } } p.Logger.WarnContext(ctx, "no (non-legacy) key for requested algorithm", "algorithm", algorithm) - return "", errors.Join(ErrConfig, status.Error(codes.NotFound, "no default key for algorithm")) + return "", connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("no default key for algorithm"))) } -func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKeyRequest) (*wrapperspb.StringValue, error) { - algorithm := in.GetAlgorithm() +func (p Provider) LegacyPublicKey(ctx context.Context, req *connect.Request[kaspb.LegacyPublicKeyRequest]) (*connect.Response[wrapperspb.StringValue], error) { + algorithm := req.Msg.GetAlgorithm() if algorithm == "" { algorithm = security.AlgorithmRSA2048 } var pem string var err error if p.CryptoProvider == nil { - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } kid, err := p.lookupKid(ctx, algorithm) if err != nil { @@ -55,7 +56,7 @@ func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKey pem, err = p.CryptoProvider.ECCertificate(kid) if err != nil { p.Logger.ErrorContext(ctx, "CryptoProvider.ECPublicKey failed", "err", err) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } case security.AlgorithmRSA2048: fallthrough @@ -63,38 +64,38 @@ func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKey pem, err = p.CryptoProvider.RSAPublicKey(kid) if err != nil { p.Logger.ErrorContext(ctx, "CryptoProvider.RSAPublicKey failed", "err", err) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } default: - return nil, errors.Join(ErrConfig, status.Error(codes.NotFound, "invalid algorithm")) + return nil, connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("invalid algorithm"))) } - return &wrapperspb.StringValue{Value: pem}, nil + return connect.NewResponse(&wrapperspb.StringValue{Value: pem}), nil } -func (p Provider) PublicKey(ctx context.Context, in *kaspb.PublicKeyRequest) (*kaspb.PublicKeyResponse, error) { - algorithm := in.GetAlgorithm() +func (p Provider) PublicKey(ctx context.Context, req *connect.Request[kaspb.PublicKeyRequest]) (*connect.Response[kaspb.PublicKeyResponse], error) { + algorithm := req.Msg.GetAlgorithm() if algorithm == "" { algorithm = security.AlgorithmRSA2048 } - fmt := in.GetFmt() + fmt := req.Msg.GetFmt() kid, err := p.lookupKid(ctx, algorithm) if err != nil { return nil, err } - r := func(value, kid string, err error) (*kaspb.PublicKeyResponse, error) { + r := func(value, kid string, err error) (*connect.Response[kaspb.PublicKeyResponse], error) { if errors.Is(err, security.ErrCertNotFound) { p.Logger.ErrorContext(ctx, "no key found for", "err", err, "kid", kid, "algorithm", algorithm, "fmt", fmt) - return nil, errors.Join(err, status.Error(codes.NotFound, "no such key")) + return nil, connect.NewError(connect.CodeNotFound, err) } else if err != nil { p.Logger.ErrorContext(ctx, "configuration error for key lookup", "err", err, "kid", kid, "algorithm", algorithm, "fmt", fmt) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, err) } - if in.GetV() == "1" { - p.Logger.WarnContext(ctx, "hiding kid in public key response for legacy client", "kid", kid, "v", in.GetV()) - return &kaspb.PublicKeyResponse{PublicKey: value}, nil + if req.Msg.GetV() == "1" { + p.Logger.WarnContext(ctx, "hiding kid in public key response for legacy client", "kid", kid, "v", req.Msg.GetV()) + return connect.NewResponse(&kaspb.PublicKeyResponse{PublicKey: value}), nil } - return &kaspb.PublicKeyResponse{PublicKey: value, Kid: kid}, nil + return connect.NewResponse(&kaspb.PublicKeyResponse{PublicKey: value, Kid: kid}), nil } switch algorithm { diff --git a/service/kas/access/publicKey_test.go b/service/kas/access/publicKey_test.go index e469ddd5e..a01e74a7c 100644 --- a/service/kas/access/publicKey_test.go +++ b/service/kas/access/publicKey_test.go @@ -13,13 +13,12 @@ import ( "os" "testing" + "connectrpc.com/connect" kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/service/internal/security" "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) func TestExportRsaPublicKeyAsPemStrSuccess(t *testing.T) { @@ -101,7 +100,7 @@ func TestStandardCertificateHandlerEmpty(t *testing.T) { Logger: logger.CreateTestLogger(), } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Fmt: "pkcs8"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{Fmt: "pkcs8"}}) require.Error(t, err, "not found") assert.Nil(t, result) } @@ -147,10 +146,10 @@ func TestStandardPublicKeyHandlerV2(t *testing.T) { }, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{}}) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerV2Failure(t *testing.T) { @@ -166,7 +165,7 @@ func TestStandardPublicKeyHandlerV2Failure(t *testing.T) { Logger: logger.CreateTestLogger(), } - k, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{}) + k, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{}}) assert.Nil(t, k) require.Error(t, err) } @@ -192,14 +191,16 @@ func TestStandardPublicKeyHandlerV2NotFound(t *testing.T) { Logger: logger.CreateTestLogger(), } - k, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{ - Algorithm: "algorithm:unknown", + k, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "algorithm:unknown", + }, }) assert.Nil(t, k) require.Error(t, err) - status, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.NotFound, status.Code()) + + status := connect.CodeOf(err) + assert.Equal(t, connect.CodeNotFound, status) } func TestStandardPublicKeyHandlerV2WithJwk(t *testing.T) { @@ -230,14 +231,16 @@ func TestStandardPublicKeyHandlerV2WithJwk(t *testing.T) { }, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{ - Algorithm: "rsa:2048", - V: "2", - Fmt: "jwk", + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "rsa:2048", + V: "2", + Fmt: "jwk", + }, }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "\"kty\"") + assert.Contains(t, result.Msg.GetPublicKey(), "\"kty\"") } func TestStandardCertificateHandlerWithEc256(t *testing.T) { @@ -261,10 +264,14 @@ func TestStandardCertificateHandlerWithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.LegacyPublicKey(context.Background(), &kaspb.LegacyPublicKeyRequest{Algorithm: "ec:secp256r1"}) + result, err := kas.LegacyPublicKey(context.Background(), &connect.Request[kaspb.LegacyPublicKeyRequest]{ + Msg: &kaspb.LegacyPublicKeyRequest{ + Algorithm: "ec:secp256r1", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetValue(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetValue(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerWithEc256(t *testing.T) { @@ -288,10 +295,14 @@ func TestStandardPublicKeyHandlerWithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Algorithm: "ec:secp256r1"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "ec:secp256r1", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerV2WithEc256(t *testing.T) { @@ -315,9 +326,13 @@ func TestStandardPublicKeyHandlerV2WithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Algorithm: "ec:secp256r1", - V: "2"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "ec:secp256r1", + V: "2", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go index bec70fb6c..178a7ed10 100644 --- a/service/kas/access/rewrap.go +++ b/service/kas/access/rewrap.go @@ -16,9 +16,11 @@ import ( "errors" "fmt" "log/slog" + "net/http" "strings" "time" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jwt" @@ -32,7 +34,6 @@ import ( "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -63,15 +64,15 @@ const ( ) func err400(s string) error { - return errors.Join(ErrUser, status.Error(codes.InvalidArgument, s)) + return connect.NewError(connect.CodeInvalidArgument, errors.Join(ErrUser, status.Error(codes.InvalidArgument, s))) } func err401(s string) error { - return errors.Join(ErrUser, status.Error(codes.Unauthenticated, s)) + return connect.NewError(connect.CodeUnauthenticated, errors.Join(ErrUser, status.Error(codes.Unauthenticated, s))) } func err403(s string) error { - return errors.Join(ErrUser, status.Error(codes.PermissionDenied, s)) + return connect.NewError(connect.CodePermissionDenied, errors.Join(ErrUser, status.Error(codes.PermissionDenied, s))) } func generateHMACDigest(ctx context.Context, msg, key []byte, logger logger.Logger) ([]byte, error) { @@ -119,14 +120,9 @@ func justRequestBody(ctx context.Context, token jwt.Token, logger logger.Logger) return rbString, nil } -func extractSRTBody(ctx context.Context, in *kaspb.RewrapRequest, logger logger.Logger) (*RequestBody, error) { +func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRequest, logger logger.Logger) (*RequestBody, error) { // First load legacy method for verifying SRT - md, exists := metadata.FromIncomingContext(ctx) - if !exists { - logger.WarnContext(ctx, "missing metadata for srt validation") - return nil, errors.New("missing metadata") - } - if vpk, ok := md["X-Virtrupubkey"]; ok && len(vpk) == 1 { + if vpk, ok := headers["X-Virtrupubkey"]; ok && len(vpk) == 1 { logger.InfoContext(ctx, "Legacy Client: Processing X-Virtrupubkey") } @@ -190,6 +186,7 @@ func extractSRTBody(ctx context.Context, in *kaspb.RewrapRequest, logger logger. return nil, err400("clientPublicKey unsupported type") } } + func extractPolicyBinding(policyBinding interface{}) (string, error) { switch v := policyBinding.(type) { case string: @@ -203,6 +200,7 @@ func extractPolicyBinding(policyBinding interface{}) (string, error) { return "", fmt.Errorf("unsupported policy binding type") } } + func verifyAndParsePolicy(ctx context.Context, requestBody *RequestBody, k []byte, logger logger.Logger) (*Policy, error) { actualHMAC, err := generateHMACDigest(ctx, []byte(requestBody.Policy), k, logger) if err != nil { @@ -246,7 +244,7 @@ func verifyAndParsePolicy(ctx context.Context, requestBody *RequestBody, k []byt } func getEntityInfo(ctx context.Context, logger *logger.Logger) (*entityInfo, error) { - var info = new(entityInfo) + info := new(entityInfo) token := auth.GetAccessTokenFromContext(ctx, logger) if token == nil { @@ -269,10 +267,11 @@ func getEntityInfo(ctx context.Context, logger *logger.Logger) (*entityInfo, err return info, nil } -func (p *Provider) Rewrap(ctx context.Context, in *kaspb.RewrapRequest) (*kaspb.RewrapResponse, error) { +func (p *Provider) Rewrap(ctx context.Context, req *connect.Request[kaspb.RewrapRequest]) (*connect.Response[kaspb.RewrapResponse], error) { + in := req.Msg p.Logger.DebugContext(ctx, "REWRAP") - body, err := extractSRTBody(ctx, in, *p.Logger) + body, err := extractSRTBody(ctx, req.Header(), in, *p.Logger) if err != nil { p.Logger.DebugContext(ctx, "unverifiable srt", "err", err) return nil, err @@ -295,13 +294,13 @@ func (p *Provider) Rewrap(ctx context.Context, in *kaspb.RewrapRequest) (*kaspb. p.Logger.ErrorContext(ctx, "rewrap nano", "err", err) } p.Logger.DebugContext(ctx, "rewrap nano", "rsp", rsp) - return rsp, err + return connect.NewResponse(rsp), err } rsp, err := p.tdf3Rewrap(ctx, body, entityInfo) if err != nil { p.Logger.ErrorContext(ctx, "rewrap tdf3", "err", err) } - return rsp, err + return connect.NewResponse(rsp), err } func (p *Provider) tdf3Rewrap(ctx context.Context, body *RequestBody, entity *entityInfo) (*kaspb.RewrapResponse, error) { diff --git a/service/kas/access/rewrap_test.go b/service/kas/access/rewrap_test.go index 74ad90290..f75348a09 100644 --- a/service/kas/access/rewrap_test.go +++ b/service/kas/access/rewrap_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "encoding/pem" "log/slog" + "net/http" "testing" "github.com/lestrrat-go/jwx/v2/jwa" @@ -154,7 +155,7 @@ func privateKey(t *testing.T) *rsa.PrivateKey { return k } -func publicKey(t *testing.T) *rsa.PublicKey { +func publicKeyTest(t *testing.T) *rsa.PublicKey { b, rest := pem.Decode([]byte(rsaPublic)) require.NotNil(t, b) assert.Empty(t, rest) @@ -298,7 +299,7 @@ func TestParseAndVerifyRequest(t *testing.T) { srt2 := makeRewrapBody(t, fauxPolicyBytes(t), true) badPolicySrt := makeRewrapBody(t, emptyPolicyBytes(), true) - var tests = []struct { + tests := []struct { name string body []byte goodDPoP bool @@ -322,7 +323,7 @@ func TestParseAndVerifyRequest(t *testing.T) { if tt.goodDPoP { key, err = jwk.FromRaw(entityPublicKey(t)) } else { - key, err = jwk.FromRaw(publicKey(t)) + key, err = jwk.FromRaw(publicKeyTest(t)) } require.NoError(t, err, "couldn't get JWK from key") err = key.Set(jwk.AlgorithmKey, jwa.RS256) // Check the error return value @@ -337,6 +338,7 @@ func TestParseAndVerifyRequest(t *testing.T) { verified, err := extractSRTBody( ctx, + http.Header{}, &kaspb.RewrapRequest{ SignedRequestToken: string(tt.body), }, @@ -375,6 +377,7 @@ func Test_SignedRequestBody_When_Bad_Signature_Expect_Failure(t *testing.T) { verified, err := extractSRTBody( ctx, + http.Header{}, &kaspb.RewrapRequest{ SignedRequestToken: string(makeRewrapBody(t, fauxPolicyBytes(t), false)), }, diff --git a/service/kas/kas.go b/service/kas/kas.go index 280a068ec..6d42c5cba 100644 --- a/service/kas/kas.go +++ b/service/kas/kas.go @@ -1,26 +1,27 @@ package kas import ( - "context" "fmt" "log/slog" "net/url" "strings" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/mitchellh/mapstructure" kaspb "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/kas/kasconnect" "github.com/opentdf/platform/service/internal/security" "github.com/opentdf/platform/service/kas/access" "github.com/opentdf/platform/service/pkg/serviceregistry" ) -func NewRegistration() *serviceregistry.Service[access.Provider] { - return &serviceregistry.Service[access.Provider]{ - ServiceOptions: serviceregistry.ServiceOptions[access.Provider]{ - Namespace: "kas", - ServiceDesc: &kaspb.AccessService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*access.Provider, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] { + return &serviceregistry.Service[kasconnect.AccessServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[kasconnect.AccessServiceHandler]{ + Namespace: "kas", + ServiceDesc: &kaspb.AccessService_ServiceDesc, + ConnectRPCFunc: kasconnect.NewAccessServiceHandler, + GRPCGateayFunc: kaspb.RegisterAccessServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (kasconnect.AccessServiceHandler, serviceregistry.HandlerServer) { // FIXME msg="mismatched key access url" keyAccessURL=http://localhost:9000 kasURL=https://:9000 hostWithPort := srp.OTDF.HTTPServer.Addr if strings.HasPrefix(hostWithPort, ":") { @@ -65,7 +66,7 @@ func NewRegistration() *serviceregistry.Service[access.Provider] { kasCfg.Keyring = append(kasCfg.Keyring, inferLegacyKeys(kasCfg.Keyring)...) } - p := access.Provider{ + p := &access.Provider{ URI: *kasURI, AttributeSvc: nil, CryptoProvider: srp.OTDF.CryptoProvider, @@ -80,9 +81,7 @@ func NewRegistration() *serviceregistry.Service[access.Provider] { srp.Logger.Error("failed to register kas readiness check", slog.String("error", err.Error())) } - return &p, func(ctx context.Context, mux *runtime.ServeMux) error { - return kaspb.RegisterAccessServiceHandlerServer(ctx, mux, &p) - } + return p, nil }, }, } diff --git a/service/kas/kas.proto b/service/kas/kas.proto index ee6555d94..8f0528d05 100644 --- a/service/kas/kas.proto +++ b/service/kas/kas.proto @@ -63,6 +63,7 @@ service AccessService { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { responses: {key: "200"} }; + option idempotency_level = NO_SIDE_EFFECTS; } // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME @@ -72,6 +73,7 @@ service AccessService { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { responses: {key: "200"} }; + option idempotency_level = NO_SIDE_EFFECTS; } rpc Rewrap(RewrapRequest) returns (RewrapResponse) { diff --git a/service/logger/audit/contextServerInterceptor.go b/service/logger/audit/contextServerInterceptor.go index 5c3e61a59..94984f883 100644 --- a/service/logger/audit/contextServerInterceptor.go +++ b/service/logger/audit/contextServerInterceptor.go @@ -2,56 +2,58 @@ package audit import ( "context" + "net/http" + "connectrpc.com/connect" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" ) // The audit unary server interceptor is a gRPC interceptor that adds metadata // to the context of incoming requests. This metadata is used to log audit // audit events. -func ContextServerInterceptor(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { - // Get metadata from the context - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, status.Error(codes.InvalidArgument, "missing metadata") +func ContextServerInterceptor() connect.UnaryInterceptorFunc { + interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { + return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + // Get metadata from the context + headers := req.Header() + + // Add request ID from existing header or create a new one + var requestID uuid.UUID + var err error + + requestIDFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.RequestIDHeaderKey.String())] + if len(requestIDFromMetadata) > 0 { + requestID, err = uuid.Parse(requestIDFromMetadata[0]) + if err != nil { + requestID = uuid.New() + } + } else { + requestID = uuid.New() + } + ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, requestID) + + // Get the request IP from the metadata header + requestIPFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.RequestIPHeaderKey.String())] + if len(requestIPFromMetadata) > 0 { + ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, requestIPFromMetadata[0]) + } + + // Get the actor ID from the metadata header + actorIDFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.ActorIDHeaderKey.String())] + if len(actorIDFromMetadata) > 0 { + ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, actorIDFromMetadata[0]) + } + + // Sets the user agent header on the context if it is present in the metadata + userAgent := headers[http.CanonicalHeaderKey(sdkAudit.UserAgentHeaderKey.String())] + if len(userAgent) > 0 { + ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, userAgent[0]) + } + + return next(ctx, req) + }) } - // Add request ID from existing header or create a new one - var requestID uuid.UUID - var err error - requestIDFromMetadata := md[string(sdkAudit.RequestIDHeaderKey)] - if len(requestIDFromMetadata) > 0 { - requestID, err = uuid.Parse(requestIDFromMetadata[0]) - if err != nil { - requestID = uuid.New() - } - } else { - requestID = uuid.New() - } - ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, requestID) - - // Get the request IP from the metadata header - requestIPFromMetadata := md[string(sdkAudit.RequestIPHeaderKey)] - if len(requestIPFromMetadata) > 0 { - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, requestIPFromMetadata[0]) - } - - // Get the actor ID from the metadata header - actorIDFromMetadata := md[string(sdkAudit.ActorIDHeaderKey)] - if len(actorIDFromMetadata) > 0 { - ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, actorIDFromMetadata[0]) - } - - // Sets the user agent header on the context if it is present in the metadata - userAgent := md[string(sdkAudit.UserAgentHeaderKey)] - if len(userAgent) > 0 { - ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, userAgent[0]) - } - - return handler(ctx, req) + return connect.UnaryInterceptorFunc(interceptor) } diff --git a/service/logger/audit/getDecision_test.go b/service/logger/audit/getDecision_test.go index a442128a0..9fcee5da3 100644 --- a/service/logger/audit/getDecision_test.go +++ b/service/logger/audit/getDecision_test.go @@ -33,7 +33,6 @@ func TestCreateGetDecisionEventHappyPathSuccess(t *testing.T) { } event, err := CreateGetDecisionEvent(createTestContext(), params) - if err != nil { t.Fatalf("error creating get decision audit event: %v", err) } @@ -73,7 +72,7 @@ func TestCreateGetDecisionEventHappyPathSuccess(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "authorization", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) diff --git a/service/logger/audit/helpers_test.go b/service/logger/audit/helpers_test.go index 3b4aeebc6..3cd0271fc 100644 --- a/service/logger/audit/helpers_test.go +++ b/service/logger/audit/helpers_test.go @@ -2,29 +2,33 @@ package audit import ( "context" + "net" "testing" "time" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) const ( - TestUserAgent = "test-user-agent" - TestActorID = "test-actor-id" - TestRequestIP = "192.168.1.1" + TestUserAgent = "test-user-agent" + TestActorID = "test-actor-id" + TestTDFFormat = "nano" TestAlgorithm = "rsa" TestPolicyBinding = "test-policy-binding" ) +var TestRequestIP = net.ParseIP("192.168.1.1") + var TestRequestID = uuid.New() func createTestContext() context.Context { ctx := context.Background() ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, TestRequestID) ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, TestUserAgent) - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, TestRequestIP) + ctx = context.WithValue(ctx, realip.ClientIP{}, TestRequestIP) ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, TestActorID) return ctx } diff --git a/service/logger/audit/policy_test.go b/service/logger/audit/policy_test.go index 15bfca110..d65c4fb0f 100644 --- a/service/logger/audit/policy_test.go +++ b/service/logger/audit/policy_test.go @@ -42,7 +42,6 @@ func Test_CreatePolicyEvent_HappyPath(t *testing.T) { } event, err := CreatePolicyEvent(createTestContext(), true, params) - if err != nil { t.Fatalf("error creating policy audit event: %v", err) } @@ -74,7 +73,7 @@ func Test_CreatePolicyEvent_HappyPath(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "policy", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) @@ -99,7 +98,6 @@ func Test_CreatePolicyEvent_WithOriginal(t *testing.T) { } event, err := CreatePolicyEvent(createTestContext(), true, params) - if err != nil { t.Fatalf("error creating policy audit event: %v", err) } diff --git a/service/logger/audit/rewrap_test.go b/service/logger/audit/rewrap_test.go index 4a1570a5c..6fa36b482 100644 --- a/service/logger/audit/rewrap_test.go +++ b/service/logger/audit/rewrap_test.go @@ -28,7 +28,6 @@ func TestCreateRewrapAuditEventHappyPath(t *testing.T) { } event, err := CreateRewrapAuditEvent(createTestContext(), params) - if err != nil { t.Fatalf("error creating rewrap audit event: %v", err) } @@ -75,7 +74,7 @@ func TestCreateRewrapAuditEventHappyPath(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "kas", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) diff --git a/service/logger/audit/utils.go b/service/logger/audit/utils.go index 6929eac99..fc3880c15 100644 --- a/service/logger/audit/utils.go +++ b/service/logger/audit/utils.go @@ -5,8 +5,8 @@ import ( "log/slog" "github.com/google/uuid" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) // Common Strings @@ -155,14 +155,9 @@ func getContextValue(ctx context.Context, key sdkAudit.ContextKey) string { // can pass the custom X-Forwarded-Request-IP header for internal requests. If // that is not present, it falls back to the realip package. func getRequestIPFromContext(ctx context.Context) string { - requestIPFromContextKey, isOK := ctx.Value(sdkAudit.RequestIPContextKey).(string) - if isOK { - return requestIPFromContextKey - } - - requestIPFromRealip, ipOK := realip.FromContext(ctx) - if ipOK { - return requestIPFromRealip.String() + ip := realip.FromContext(ctx) + if ip.String() != "" && ip.String() != "" { + return ip.String() } return defaultNone diff --git a/service/logger/audit/utils_test.go b/service/logger/audit/utils_test.go index 1d0c75574..b87d31147 100644 --- a/service/logger/audit/utils_test.go +++ b/service/logger/audit/utils_test.go @@ -4,23 +4,25 @@ import ( "context" "fmt" "log/slog" + "net" "testing" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) func TestGetAuditDataFromContextHappyPath(t *testing.T) { ctx := context.Background() testRequestID := uuid.New() testUserAgent := "test-user-agent" - testRequestIP := "192.168.0.1" + testRequestIP := net.ParseIP("192.168.0.1") testActorID := "test-actor-id" // Set relevant context keys ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, testRequestID) ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, testUserAgent) - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, testRequestIP) + ctx = context.WithValue(ctx, realip.ClientIP{}, testRequestIP) ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, testActorID) slog.Info(fmt.Sprintf("Test: %v", ctx.Value(sdkAudit.RequestIDContextKey))) @@ -35,7 +37,7 @@ func TestGetAuditDataFromContextHappyPath(t *testing.T) { t.Fatalf("UserAgent did not match: %v", auditData.UserAgent) } - if auditData.RequestIP != testRequestIP { + if auditData.RequestIP != testRequestIP.String() { t.Fatalf("RequestIP did not match: %v", auditData.RequestIP) } @@ -65,6 +67,7 @@ func TestGetAuditDataFromContextDefaultsPath(t *testing.T) { t.Fatalf("ActorID did not match: %v", auditData.ActorID) } } + func TestGetAuditDataFromContextWithNoKeys(t *testing.T) { ctx := context.Background() auditData := GetAuditDataFromContext(ctx) @@ -85,6 +88,7 @@ func TestGetAuditDataFromContextWithNoKeys(t *testing.T) { t.Fatalf("ActorID did not match: %v", auditData.ActorID) } } + func TestGetAuditDataFromContextWithPartialKeys(t *testing.T) { ctx := context.Background() testUserAgent := "partial-user-agent" diff --git a/service/pkg/db/errors.go b/service/pkg/db/errors.go index 0299b7a43..49188f14d 100644 --- a/service/pkg/db/errors.go +++ b/service/pkg/db/errors.go @@ -6,11 +6,10 @@ import ( "log/slog" "strings" + "connectrpc.com/connect" "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) var ( @@ -104,28 +103,28 @@ func StatusifyError(err error, fallbackErr string, log ...any) error { l := append([]any{"error", err}, log...) if errors.Is(err, ErrUniqueConstraintViolation) { slog.Error(ErrTextConflict, l...) - return status.Error(codes.AlreadyExists, ErrTextConflict) + return connect.NewError(connect.CodeAlreadyExists, errors.New(ErrTextConflict)) } if errors.Is(err, ErrNotFound) { slog.Error(ErrTextNotFound, l...) - return status.Error(codes.NotFound, ErrTextNotFound) + return connect.NewError(connect.CodeNotFound, errors.New(ErrTextNotFound)) } if errors.Is(err, ErrForeignKeyViolation) { slog.Error(ErrTextRelationInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextRelationInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextRelationInvalid)) } if errors.Is(err, ErrEnumValueInvalid) { slog.Error(ErrTextEnumValueInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextEnumValueInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextEnumValueInvalid)) } if errors.Is(err, ErrUUIDInvalid) { slog.Error(ErrTextUUIDInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextUUIDInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextUUIDInvalid)) } if errors.Is(err, ErrRestrictViolation) { slog.Error(ErrTextRestrictViolation, l...) - return status.Error(codes.InvalidArgument, ErrTextRestrictViolation) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextRestrictViolation)) } slog.Error(err.Error(), l...) - return status.Error(codes.Internal, fallbackErr) + return connect.NewError(connect.CodeInternal, errors.New(fallbackErr)) } diff --git a/service/pkg/server/services.go b/service/pkg/server/services.go index 14d4e8f60..8760a5fbd 100644 --- a/service/pkg/server/services.go +++ b/service/pkg/server/services.go @@ -21,6 +21,8 @@ import ( "github.com/opentdf/platform/service/pkg/serviceregistry" "github.com/opentdf/platform/service/policy" wellknown "github.com/opentdf/platform/service/wellknownconfiguration" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) const ( @@ -163,20 +165,29 @@ func startServices(ctx context.Context, cfg config.Config, otdf *server.OpenTDFS if err != nil { return err } - // Register the service with the gRPC server - if err := svc.RegisterGRPCServer(otdf.GRPCServer); err != nil { - return err + + // Register Connect RPC Services + if err := svc.RegisterConnectRPCServiceHandler(ctx, otdf.ConnectRPC); err != nil { + logger.Info("service did not register a connect-rpc handler", slog.String("namespace", ns)) } - // Register the service with in process gRPC server - if err := svc.RegisterGRPCServer(otdf.GRPCInProcess.GetGrpcServer()); err != nil { - return err + // Register In Process Connect RPC Services + if err := svc.RegisterConnectRPCServiceHandler(ctx, otdf.ConnectRPCInProcess.ConnectRPC); err != nil { + logger.Info("service did not register a connect-rpc handler", slog.String("namespace", ns)) } - // Register the service with the gRPC gateway - if err := svc.RegisterHTTPServer(ctx, otdf.Mux); err != nil { - logger.Error("failed to register service to grpc gateway", slog.String("namespace", ns), slog.String("error", err.Error())) - return err + // Register GRPC Gateway + grpcGatewayDialOptions := make([]grpc.DialOption, 0) + if !cfg.Server.TLS.Enabled { + grpcGatewayDialOptions = append(grpcGatewayDialOptions, grpc.WithTransportCredentials(insecure.NewCredentials())) + } + if err := svc.RegisterGRPCGatewayHandler(ctx, otdf.GRPCGatewayMux, fmt.Sprintf("localhost:%d", cfg.Server.Port), grpcGatewayDialOptions); err != nil { + logger.Info("service did not register a grpc gateway handler", slog.String("namespace", ns)) + } + + // Register Extra Handlers + if err := svc.RegisterHTTPHandlers(ctx, otdf.GRPCGatewayMux); err != nil { + logger.Info("service did not register extra http handlers", slog.String("namespace", ns)) } logger.Info( diff --git a/service/pkg/server/services_test.go b/service/pkg/server/services_test.go index 1f9037f40..97248da3a 100644 --- a/service/pkg/server/services_test.go +++ b/service/pkg/server/services_test.go @@ -59,10 +59,10 @@ func mockTestServiceRegistry(opts mockTestServiceOptions) (serviceregistry.IServ ServiceName: serviceName, HandlerType: serviceHandlerType, }, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*TestService, serviceregistry.HandlerServer) { - var ts *TestService + RegisterFunc: func(srp serviceregistry.RegistrationParams) (TestService, serviceregistry.HandlerServer) { + var ts TestService var ok bool - if ts, ok = opts.serviceObject.(*TestService); !ok { + if ts, ok = opts.serviceObject.(TestService); !ok { panic("serviceObject is not a TestService") } return ts, func(ctx context.Context, mux *runtime.ServeMux) error { @@ -196,7 +196,7 @@ func (suite *ServiceTestSuite) TestStartServicesWithVariousCases() { // Test service which will be enabled registerTest, testSpy := mockTestServiceRegistry(mockTestServiceOptions{ - serviceObject: &TestService{}, + serviceObject: TestService{}, }) err := registry.RegisterService(registerTest, "test") suite.Require().NoError(err) diff --git a/service/pkg/server/start.go b/service/pkg/server/start.go index 8a82dec64..dbbdf190b 100644 --- a/service/pkg/server/start.go +++ b/service/pkg/server/start.go @@ -156,7 +156,7 @@ func Start(f ...StartOptions) error { if slices.Contains(cfg.Mode, "all") || slices.Contains(cfg.Mode, "core") { // Use IPC for the SDK client sdkOptions = append(sdkOptions, sdk.WithIPC()) - sdkOptions = append(sdkOptions, sdk.WithCustomCoreConnection(otdf.GRPCInProcess.Conn())) + sdkOptions = append(sdkOptions, sdk.WithCustomCoreConnection(otdf.ConnectRPCInProcess.Conn())) client, err = sdk.New("", sdkOptions...) if err != nil { diff --git a/service/pkg/server/start_test.go b/service/pkg/server/start_test.go index 5ab8ed314..db66b50b2 100644 --- a/service/pkg/server/start_test.go +++ b/service/pkg/server/start_test.go @@ -99,7 +99,7 @@ func (suite *StartTestSuite) Test_Start_When_Extra_Service_Registered_Expect_Res require.NoError(t, err) // Register Test Service - ts := &TestService{} + ts := TestService{} registerTestService, _ := mockTestServiceRegistry(mockTestServiceOptions{ serviceObject: ts, serviceHandler: func(_ context.Context, mux *runtime.ServeMux) error { diff --git a/service/pkg/serviceregistry/serviceregistry.go b/service/pkg/serviceregistry/serviceregistry.go index 2d9ca082e..a00218a60 100644 --- a/service/pkg/serviceregistry/serviceregistry.go +++ b/service/pkg/serviceregistry/serviceregistry.go @@ -9,9 +9,9 @@ import ( "slices" "connectrpc.com/connect" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/opentdf/platform/sdk" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/opentdf/platform/service/internal/server" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/db" @@ -51,7 +51,7 @@ type RegistrationParams struct { } type ( HandlerServer func(ctx context.Context, mux *runtime.ServeMux) error - RegisterFunc[S any] func(RegistrationParams) (Impl *S, HandlerServer HandlerServer) + RegisterFunc[S any] func(RegistrationParams) (impl S, HandlerServer HandlerServer) ) // DBRegister is a struct that holds the information needed to register a service with a database @@ -72,15 +72,16 @@ type IService interface { Start(ctx context.Context, params RegistrationParams) error IsStarted() bool Shutdown() error - RegisterGRPCServer(server *grpc.Server) error - RegisterHTTPServer(ctx context.Context, mux *runtime.ServeMux) error + RegisterConnectRPCServiceHandler(context.Context, *server.ConnectRPC) error + RegisterGRPCGatewayHandler(context.Context, *runtime.ServeMux, string, []grpc.DialOption) error + RegisterHTTPHandlers(context.Context, *runtime.ServeMux) error } // Service is a struct that holds the registration information for a service as well as the state // of the service within the instance of the platform. type Service[S any] struct { // Registration - impl *S + impl S // Started is a flag that indicates whether the service has been started Started bool // Close is a function that can be called to close the service @@ -97,10 +98,13 @@ type ServiceOptions[S any] struct { // but at minimum, the ServiceName field must be set ServiceDesc *grpc.ServiceDesc // RegisterFunc is the function that will be called to register the service - RegisterFunc RegisterFunc[S] + RegisterFunc RegisterFunc[S] + // HTTPHandlerFunc is the function that will be called to register extra http handlers httpHandlerFunc HandlerServer // ConnectRPCServiceHandler is the function that will be called to register the service with the ConnectRPCFunc func(S, ...connect.HandlerOption) (string, http.Handler) + // Deprecated: Registers a gRPC service with the gRPC gateway + GRPCGateayFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) // DB is optional and used to register the service with a database DB DBRegister } @@ -155,14 +159,13 @@ func (s *Service[S]) Start(ctx context.Context, params RegistrationParams) error return nil } -// RegisterGRPCServer registers the gRPC server with the service implementation. -// It checks if the service implementation is registered and then registers the service with the server. -// It returns an error if the service implementation is not registered. -func (s *Service[S]) RegisterGRPCServer(server *grpc.Server) error { - if s.impl == nil { - return fmt.Errorf("service did not register an implementation") +func (s Service[S]) RegisterConnectRPCServiceHandler(_ context.Context, connectRPC *server.ConnectRPC) error { + if s.ConnectRPCFunc == nil { + return fmt.Errorf("service did not register a handler") } - server.RegisterService(s.ServiceDesc, s.impl) + connectRPC.ServiceReflection = append(connectRPC.ServiceReflection, s.GetServiceDesc().ServiceName) + path, handler := s.ConnectRPCFunc(s.impl, connectRPC.Interceptors...) + connectRPC.Mux.Handle(path, handler) return nil } @@ -171,13 +174,25 @@ func (s *Service[S]) RegisterGRPCServer(server *grpc.Server) error { // RegisterHTTPServer registers an HTTP server with the service. // It takes a context, a ServeMux, and an implementation function as parameters. // If the service did not register a handler, it returns an error. -func (s *Service[S]) RegisterHTTPServer(ctx context.Context, mux *runtime.ServeMux) error { +func (s *Service[S]) RegisterHTTPHandlers(ctx context.Context, mux *runtime.ServeMux) error { if s.httpHandlerFunc == nil { - return fmt.Errorf("service did not register a handler") + return fmt.Errorf("service did not register any handlers") } return s.httpHandlerFunc(ctx, mux) } +// Deprecated: RegisterConnectRPCServiceHandler is deprecated and should not be used going forward. +// We will be looking onto other alternatives like bufconnect to replace this. +// RegisterConnectRPCServiceHandler registers an HTTP server with the service. +// It takes a context, a ServeMux, and an implementation function as parameters. +// If the service did not register a handler, it returns an error. +func (s Service[S]) RegisterGRPCGatewayHandler(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error { + if s.GRPCGateayFunc == nil { + return fmt.Errorf("service did not register a handler") + } + return s.GRPCGateayFunc(ctx, mux, endpoint, opts) +} + // namespace represents a namespace in the service registry. type Namespace struct { Mode string diff --git a/service/policy/attributes/attributes.go b/service/policy/attributes/attributes.go index c3d31aa83..8ca210ac0 100644 --- a/service/policy/attributes/attributes.go +++ b/service/policy/attributes/attributes.go @@ -5,9 +5,10 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/attributes" + "github.com/opentdf/platform/protocol/go/policy/attributes/attributesconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -16,31 +17,30 @@ import ( ) type AttributesService struct { //nolint:revive // AttributesService is a valid name for this struct - attributes.UnimplementedAttributesServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[AttributesService] { - return &serviceregistry.Service[AttributesService]{ - ServiceOptions: serviceregistry.ServiceOptions[AttributesService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &attributes.AttributesService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*AttributesService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[attributesconnect.AttributesServiceHandler] { + return &serviceregistry.Service[attributesconnect.AttributesServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[attributesconnect.AttributesServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &attributes.AttributesService_ServiceDesc, + ConnectRPCFunc: attributesconnect.NewAttributesServiceHandler, + GRPCGateayFunc: attributes.RegisterAttributesServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (attributesconnect.AttributesServiceHandler, serviceregistry.HandlerServer) { as := &AttributesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return as, func(ctx context.Context, mux *runtime.ServeMux) error { - return attributes.RegisterAttributesServiceHandlerServer(ctx, mux, as) - } + return as, nil }, }, } } func (s AttributesService) CreateAttribute(ctx context.Context, - req *attributes.CreateAttributeRequest, -) (*attributes.CreateAttributeResponse, error) { - s.logger.Debug("creating new attribute definition", slog.String("name", req.GetName())) + req *connect.Request[attributes.CreateAttributeRequest], +) (*connect.Response[attributes.CreateAttributeResponse], error) { + s.logger.Debug("creating new attribute definition", slog.String("name", req.Msg.GetName())) rsp := &attributes.CreateAttributeResponse{} auditParams := audit.PolicyEventParams{ @@ -48,27 +48,27 @@ func (s AttributesService) CreateAttribute(ctx context.Context, ActionType: audit.ActionTypeCreate, } - item, err := s.dbClient.CreateAttribute(ctx, req) + item, err := s.dbClient.CreateAttribute(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attribute", req.Msg.String())) } - s.logger.Debug("created new attribute definition", slog.String("name", req.GetName())) + s.logger.Debug("created new attribute definition", slog.String("name", req.Msg.GetName())) auditParams.ObjectID = item.GetId() auditParams.Original = item s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) rsp.Attribute = item - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) ListAttributes(ctx context.Context, - req *attributes.ListAttributesRequest, -) (*attributes.ListAttributesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) - namespace := req.GetNamespace() + req *connect.Request[attributes.ListAttributesRequest], +) (*connect.Response[attributes.ListAttributesResponse], error) { + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + namespace := req.Msg.GetNamespace() s.logger.Debug("listing attribute definitions", slog.String("state", state)) rsp := &attributes.ListAttributesResponse{} @@ -78,43 +78,43 @@ func (s *AttributesService) ListAttributes(ctx context.Context, } rsp.Attributes = list - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) GetAttribute(ctx context.Context, - req *attributes.GetAttributeRequest, -) (*attributes.GetAttributeResponse, error) { + req *connect.Request[attributes.GetAttributeRequest], +) (*connect.Response[attributes.GetAttributeResponse], error) { rsp := &attributes.GetAttributeResponse{} - item, err := s.dbClient.GetAttribute(ctx, req.GetId()) + item, err := s.dbClient.GetAttribute(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.Attribute = item - return rsp, err + return connect.NewResponse(rsp), err } func (s *AttributesService) GetAttributeValuesByFqns(ctx context.Context, - req *attributes.GetAttributeValuesByFqnsRequest, -) (*attributes.GetAttributeValuesByFqnsResponse, error) { + req *connect.Request[attributes.GetAttributeValuesByFqnsRequest], +) (*connect.Response[attributes.GetAttributeValuesByFqnsResponse], error) { rsp := &attributes.GetAttributeValuesByFqnsResponse{} - fqnsToAttributes, err := s.dbClient.GetAttributesByValueFqns(ctx, req) + fqnsToAttributes, err := s.dbClient.GetAttributesByValueFqns(ctx, req.Msg) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.GetFqns()))) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.Msg.GetFqns()))) } rsp.FqnAttributeValues = fqnsToAttributes - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) UpdateAttribute(ctx context.Context, - req *attributes.UpdateAttributeRequest, -) (*attributes.UpdateAttributeResponse, error) { + req *connect.Request[attributes.UpdateAttributeRequest], +) (*connect.Response[attributes.UpdateAttributeResponse], error) { rsp := &attributes.UpdateAttributeResponse{} - attributeID := req.GetId() + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeAttributeDefinition, @@ -127,10 +127,10 @@ func (s *AttributesService) UpdateAttribute(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", attributeID)) } - updated, err := s.dbClient.UpdateAttribute(ctx, attributeID, req) + updated, err := s.dbClient.UpdateAttribute(ctx, attributeID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("attribute", req.Msg.String())) } auditParams.Original = original @@ -141,15 +141,15 @@ func (s *AttributesService) UpdateAttribute(ctx context.Context, Id: attributeID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) DeactivateAttribute(ctx context.Context, - req *attributes.DeactivateAttributeRequest, -) (*attributes.DeactivateAttributeResponse, error) { + req *connect.Request[attributes.DeactivateAttributeRequest], +) (*connect.Response[attributes.DeactivateAttributeResponse], error) { rsp := &attributes.DeactivateAttributeResponse{} - attributeID := req.GetId() + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeDefinition, ActionType: audit.ActionTypeUpdate, @@ -175,60 +175,67 @@ func (s *AttributesService) DeactivateAttribute(ctx context.Context, rsp.Attribute = &policy.Attribute{ Id: attributeID, } - return rsp, nil + return connect.NewResponse(rsp), nil } /// /// Attribute Values /// -func (s *AttributesService) CreateAttributeValue(ctx context.Context, req *attributes.CreateAttributeValueRequest) (*attributes.CreateAttributeValueResponse, error) { +func (s *AttributesService) CreateAttributeValue(ctx context.Context, req *connect.Request[attributes.CreateAttributeValueRequest]) (*connect.Response[attributes.CreateAttributeValueResponse], error) { + rsp := &attributes.CreateAttributeValueResponse{} + auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeValue, ActionType: audit.ActionTypeCreate, } - item, err := s.dbClient.CreateAttributeValue(ctx, req.GetAttributeId(), req) + item, err := s.dbClient.CreateAttributeValue(ctx, req.Msg.GetAttributeId(), req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeId", req.GetAttributeId()), slog.String("value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeId", req.Msg.GetAttributeId()), slog.String("value", req.Msg.String())) } auditParams.ObjectID = item.GetId() auditParams.Original = item s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.CreateAttributeValueResponse{ - Value: item, - }, nil + rsp.Value = item + return connect.NewResponse(rsp), nil } -func (s *AttributesService) ListAttributeValues(ctx context.Context, req *attributes.ListAttributeValuesRequest) (*attributes.ListAttributeValuesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) - s.logger.Debug("listing attribute values", slog.String("attributeId", req.GetAttributeId()), slog.String("state", state)) - list, err := s.dbClient.ListAttributeValues(ctx, req.GetAttributeId(), state) +func (s *AttributesService) ListAttributeValues(ctx context.Context, req *connect.Request[attributes.ListAttributeValuesRequest]) (*connect.Response[attributes.ListAttributeValuesResponse], error) { + rsp := &attributes.ListAttributeValuesResponse{} + + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + s.logger.Debug("listing attribute values", slog.String("attributeId", req.Msg.GetAttributeId()), slog.String("state", state)) + list, err := s.dbClient.ListAttributeValues(ctx, req.Msg.GetAttributeId(), state) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.String("attributeId", req.GetAttributeId())) + return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.String("attributeId", req.Msg.GetAttributeId())) } - return &attributes.ListAttributeValuesResponse{ - Values: list, - }, nil + rsp.Values = list + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) GetAttributeValue(ctx context.Context, req *attributes.GetAttributeValueRequest) (*attributes.GetAttributeValueResponse, error) { - item, err := s.dbClient.GetAttributeValue(ctx, req.GetId()) +func (s *AttributesService) GetAttributeValue(ctx context.Context, req *connect.Request[attributes.GetAttributeValueRequest]) (*connect.Response[attributes.GetAttributeValueResponse], error) { + rsp := &attributes.GetAttributeValueResponse{} + + item, err := s.dbClient.GetAttributeValue(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &attributes.GetAttributeValueResponse{ - Value: item, - }, nil + rsp.Value = item + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *attributes.UpdateAttributeValueRequest) (*attributes.UpdateAttributeValueResponse, error) { - attributeID := req.GetId() +func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *connect.Request[attributes.UpdateAttributeValueRequest]) (*connect.Response[attributes.UpdateAttributeValueResponse], error) { + rsp := &attributes.UpdateAttributeValueResponse{} + + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeAttributeValue, @@ -241,25 +248,27 @@ func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *attri return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", attributeID)) } - updated, err := s.dbClient.UpdateAttributeValue(ctx, req) + updated, err := s.dbClient.UpdateAttributeValue(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("value", req.Msg.String())) } auditParams.Original = original auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.UpdateAttributeValueResponse{ - Value: &policy.Value{ - Id: attributeID, - }, - }, nil + rsp.Value = &policy.Value{ + Id: attributeID, + } + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *attributes.DeactivateAttributeValueRequest) (*attributes.DeactivateAttributeValueResponse, error) { - attributeID := req.GetId() +func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *connect.Request[attributes.DeactivateAttributeValueRequest]) (*connect.Response[attributes.DeactivateAttributeValueResponse], error) { + rsp := &attributes.DeactivateAttributeValueResponse{} + + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeValue, ActionType: audit.ActionTypeDelete, @@ -282,83 +291,91 @@ func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *a auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.DeactivateAttributeValueResponse{ - Value: updated, - }, nil + rsp.Value = updated + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) AssignKeyAccessServerToAttribute(ctx context.Context, req *attributes.AssignKeyAccessServerToAttributeRequest) (*attributes.AssignKeyAccessServerToAttributeResponse, error) { +func (s *AttributesService) AssignKeyAccessServerToAttribute(ctx context.Context, req *connect.Request[attributes.AssignKeyAccessServerToAttributeRequest]) (*connect.Response[attributes.AssignKeyAccessServerToAttributeResponse], error) { + rsp := &attributes.AssignKeyAccessServerToAttributeResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeDefinitionAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetAttributeKeyAccessServer().GetAttributeId(), req.GetAttributeKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetAttributeKeyAccessServer().GetAttributeId(), req.Msg.GetAttributeKeyAccessServer().GetKeyAccessServerId()), } - attributeKas, err := s.dbClient.AssignKeyAccessServerToAttribute(ctx, req.GetAttributeKeyAccessServer()) + attributeKas, err := s.dbClient.AssignKeyAccessServerToAttribute(ctx, req.Msg.GetAttributeKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeKas", req.GetAttributeKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeKas", req.Msg.GetAttributeKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.AssignKeyAccessServerToAttributeResponse{ - AttributeKeyAccessServer: attributeKas, - }, nil + rsp.AttributeKeyAccessServer = attributeKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Context, req *attributes.RemoveKeyAccessServerFromAttributeRequest) (*attributes.RemoveKeyAccessServerFromAttributeResponse, error) { +func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromAttributeRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromAttributeResponse], error) { + rsp := &attributes.RemoveKeyAccessServerFromAttributeResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeDefinitionAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetAttributeKeyAccessServer().GetAttributeId(), req.GetAttributeKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetAttributeKeyAccessServer().GetAttributeId(), req.Msg.GetAttributeKeyAccessServer().GetKeyAccessServerId()), } - attributeKas, err := s.dbClient.RemoveKeyAccessServerFromAttribute(ctx, req.GetAttributeKeyAccessServer()) + attributeKas, err := s.dbClient.RemoveKeyAccessServerFromAttribute(ctx, req.Msg.GetAttributeKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeKas", req.GetAttributeKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeKas", req.Msg.GetAttributeKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.RemoveKeyAccessServerFromAttributeResponse{ - AttributeKeyAccessServer: attributeKas, - }, nil + rsp.AttributeKeyAccessServer = attributeKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) AssignKeyAccessServerToValue(ctx context.Context, req *attributes.AssignKeyAccessServerToValueRequest) (*attributes.AssignKeyAccessServerToValueResponse, error) { +func (s *AttributesService) AssignKeyAccessServerToValue(ctx context.Context, req *connect.Request[attributes.AssignKeyAccessServerToValueRequest]) (*connect.Response[attributes.AssignKeyAccessServerToValueResponse], error) { + rsp := &attributes.AssignKeyAccessServerToValueResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeValueAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetValueKeyAccessServer().GetValueId(), req.GetValueKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetValueKeyAccessServer().GetValueId(), req.Msg.GetValueKeyAccessServer().GetKeyAccessServerId()), } - valueKas, err := s.dbClient.AssignKeyAccessServerToValue(ctx, req.GetValueKeyAccessServer()) + valueKas, err := s.dbClient.AssignKeyAccessServerToValue(ctx, req.Msg.GetValueKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeValueKas", req.GetValueKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeValueKas", req.Msg.GetValueKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.AssignKeyAccessServerToValueResponse{ - ValueKeyAccessServer: valueKas, - }, nil + rsp.ValueKeyAccessServer = valueKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) RemoveKeyAccessServerFromValue(ctx context.Context, req *attributes.RemoveKeyAccessServerFromValueRequest) (*attributes.RemoveKeyAccessServerFromValueResponse, error) { +func (s *AttributesService) RemoveKeyAccessServerFromValue(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromValueRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromValueResponse], error) { + rsp := &attributes.RemoveKeyAccessServerFromValueResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeValueAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetValueKeyAccessServer().GetValueId(), req.GetValueKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetValueKeyAccessServer().GetValueId(), req.Msg.GetValueKeyAccessServer().GetKeyAccessServerId()), } - valueKas, err := s.dbClient.RemoveKeyAccessServerFromValue(ctx, req.GetValueKeyAccessServer()) + valueKas, err := s.dbClient.RemoveKeyAccessServerFromValue(ctx, req.Msg.GetValueKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeValueKas", req.GetValueKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeValueKas", req.Msg.GetValueKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.RemoveKeyAccessServerFromValueResponse{ - ValueKeyAccessServer: valueKas, - }, nil + rsp.ValueKeyAccessServer = valueKas + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/attributes/attributes.proto b/service/policy/attributes/attributes.proto index 2a339a67f..6609d6ba2 100644 --- a/service/policy/attributes/attributes.proto +++ b/service/policy/attributes/attributes.proto @@ -293,16 +293,20 @@ service AttributesService { *---------------------------------------*/ rpc ListAttributes(ListAttributesRequest) returns (ListAttributesResponse) { option (google.api.http) = {get: "/attributes"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListAttributeValues(ListAttributeValuesRequest) returns (ListAttributeValuesResponse) { option (google.api.http) = {get: "/attributes/*/values"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetAttribute(GetAttributeRequest) returns (GetAttributeResponse) { option (google.api.http) = {get: "/attributes/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetAttributeValuesByFqns(GetAttributeValuesByFqnsRequest) returns (GetAttributeValuesByFqnsResponse) { option (google.api.http) = {get: "/attributes/*/fqn"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateAttribute(CreateAttributeRequest) returns (CreateAttributeResponse) { diff --git a/service/policy/kasregistry/key_access_server_registry.go b/service/policy/kasregistry/key_access_server_registry.go index db821d1ac..088996f21 100644 --- a/service/policy/kasregistry/key_access_server_registry.go +++ b/service/policy/kasregistry/key_access_server_registry.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" kasr "github.com/opentdf/platform/protocol/go/policy/kasregistry" + "github.com/opentdf/platform/protocol/go/policy/kasregistry/kasregistryconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,30 +16,31 @@ import ( ) type KeyAccessServerRegistry struct { - kasr.UnimplementedKeyAccessServerRegistryServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[KeyAccessServerRegistry] { - return &serviceregistry.Service[KeyAccessServerRegistry]{ - ServiceOptions: serviceregistry.ServiceOptions[KeyAccessServerRegistry]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &kasr.KeyAccessServerRegistryService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*KeyAccessServerRegistry, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[kasregistryconnect.KeyAccessServerRegistryServiceHandler] { + return &serviceregistry.Service[kasregistryconnect.KeyAccessServerRegistryServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[kasregistryconnect.KeyAccessServerRegistryServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &kasr.KeyAccessServerRegistryService_ServiceDesc, + ConnectRPCFunc: kasregistryconnect.NewKeyAccessServerRegistryServiceHandler, + GRPCGateayFunc: kasr.RegisterKeyAccessServerRegistryServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (kasregistryconnect.KeyAccessServerRegistryServiceHandler, serviceregistry.HandlerServer) { ksr := &KeyAccessServerRegistry{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return ksr, func(ctx context.Context, mux *runtime.ServeMux) error { - return kasr.RegisterKeyAccessServerRegistryServiceHandlerServer(ctx, mux, ksr) - } + return ksr, nil }, }, } } func (s KeyAccessServerRegistry) CreateKeyAccessServer(ctx context.Context, - req *kasr.CreateKeyAccessServerRequest, -) (*kasr.CreateKeyAccessServerResponse, error) { + req *connect.Request[kasr.CreateKeyAccessServerRequest], +) (*connect.Response[kasr.CreateKeyAccessServerResponse], error) { + rsp := &kasr.CreateKeyAccessServerResponse{} + s.logger.Debug("creating key access server") auditParams := audit.PolicyEventParams{ @@ -46,51 +48,57 @@ func (s KeyAccessServerRegistry) CreateKeyAccessServer(ctx context.Context, ObjectType: audit.ObjectTypeKasRegistry, } - ks, err := s.dbClient.CreateKeyAccessServer(ctx, req) + ks, err := s.dbClient.CreateKeyAccessServer(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("keyAccessServer", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("keyAccessServer", req.Msg.String())) } auditParams.ObjectID = ks.GetId() auditParams.Original = ks s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.CreateKeyAccessServerResponse{ - KeyAccessServer: ks, - }, nil + rsp.KeyAccessServer = ks + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) ListKeyAccessServers(ctx context.Context, - _ *kasr.ListKeyAccessServersRequest, -) (*kasr.ListKeyAccessServersResponse, error) { + _ *connect.Request[kasr.ListKeyAccessServersRequest], +) (*connect.Response[kasr.ListKeyAccessServersResponse], error) { + rsp := &kasr.ListKeyAccessServersResponse{} + keyAccessServers, err := s.dbClient.ListKeyAccessServers(ctx) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &kasr.ListKeyAccessServersResponse{ - KeyAccessServers: keyAccessServers, - }, nil + rsp.KeyAccessServers = keyAccessServers + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) GetKeyAccessServer(ctx context.Context, - req *kasr.GetKeyAccessServerRequest, -) (*kasr.GetKeyAccessServerResponse, error) { - keyAccessServer, err := s.dbClient.GetKeyAccessServer(ctx, req.GetId()) + req *connect.Request[kasr.GetKeyAccessServerRequest], +) (*connect.Response[kasr.GetKeyAccessServerResponse], error) { + rsp := &kasr.GetKeyAccessServerResponse{} + + keyAccessServer, err := s.dbClient.GetKeyAccessServer(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &kasr.GetKeyAccessServerResponse{ - KeyAccessServer: keyAccessServer, - }, nil + rsp.KeyAccessServer = keyAccessServer + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) UpdateKeyAccessServer(ctx context.Context, - req *kasr.UpdateKeyAccessServerRequest, -) (*kasr.UpdateKeyAccessServerResponse, error) { - kasID := req.GetId() + req *connect.Request[kasr.UpdateKeyAccessServerRequest], +) (*connect.Response[kasr.UpdateKeyAccessServerResponse], error) { + rsp := &kasr.UpdateKeyAccessServerResponse{} + + kasID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -104,56 +112,60 @@ func (s KeyAccessServerRegistry) UpdateKeyAccessServer(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", kasID)) } - updated, err := s.dbClient.UpdateKeyAccessServer(ctx, kasID, req) + updated, err := s.dbClient.UpdateKeyAccessServer(ctx, kasID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", kasID), slog.String("keyAccessServer", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", kasID), slog.String("keyAccessServer", req.Msg.String())) } auditParams.Original = original auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.UpdateKeyAccessServerResponse{ - KeyAccessServer: &policy.KeyAccessServer{ - Id: kasID, - }, - }, nil + rsp.KeyAccessServer = &policy.KeyAccessServer{ + Id: kasID, + } + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) DeleteKeyAccessServer(ctx context.Context, - req *kasr.DeleteKeyAccessServerRequest, -) (*kasr.DeleteKeyAccessServerResponse, error) { - kasID := req.GetId() + req *connect.Request[kasr.DeleteKeyAccessServerRequest], +) (*connect.Response[kasr.DeleteKeyAccessServerResponse], error) { + rsp := &kasr.DeleteKeyAccessServerResponse{} + + kasID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasRegistry, ObjectID: kasID, } - _, err := s.dbClient.DeleteKeyAccessServer(ctx, req.GetId()) + _, err := s.dbClient.DeleteKeyAccessServer(ctx, req.Msg.GetId()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.Msg.GetId())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.DeleteKeyAccessServerResponse{ - KeyAccessServer: &policy.KeyAccessServer{ - Id: kasID, - }, - }, nil + rsp.KeyAccessServer = &policy.KeyAccessServer{ + Id: kasID, + } + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) ListKeyAccessServerGrants(ctx context.Context, - req *kasr.ListKeyAccessServerGrantsRequest, -) (*kasr.ListKeyAccessServerGrantsResponse, error) { - keyAccessServerGrants, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.GetKasId(), req.GetKasUri(), req.GetKasName()) + req *connect.Request[kasr.ListKeyAccessServerGrantsRequest], +) (*connect.Response[kasr.ListKeyAccessServerGrantsResponse], error) { + rsp := &kasr.ListKeyAccessServerGrantsResponse{} + + keyAccessServerGrants, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.Msg.GetKasId(), req.Msg.GetKasUri(), req.Msg.GetKasName()) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &kasr.ListKeyAccessServerGrantsResponse{ - Grants: keyAccessServerGrants, - }, nil + rsp.Grants = keyAccessServerGrants + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/kasregistry/key_access_server_registry.proto b/service/policy/kasregistry/key_access_server_registry.proto index ce0218ab7..109541944 100644 --- a/service/policy/kasregistry/key_access_server_registry.proto +++ b/service/policy/kasregistry/key_access_server_registry.proto @@ -162,10 +162,12 @@ message ListKeyAccessServerGrantsResponse { service KeyAccessServerRegistryService { rpc ListKeyAccessServers(ListKeyAccessServersRequest) returns (ListKeyAccessServersResponse) { option (google.api.http) = {get: "/key-access-servers"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetKeyAccessServer(GetKeyAccessServerRequest) returns (GetKeyAccessServerResponse) { option (google.api.http) = {get: "/key-access-servers/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateKeyAccessServer(CreateKeyAccessServerRequest) returns (CreateKeyAccessServerResponse) { @@ -188,5 +190,6 @@ service KeyAccessServerRegistryService { rpc ListKeyAccessServerGrants(ListKeyAccessServerGrantsRequest) returns (ListKeyAccessServerGrantsResponse) { option (google.api.http) = {get: "/key-access-servers/grants"}; + option idempotency_level = NO_SIDE_EFFECTS; } } diff --git a/service/policy/namespaces/namespaces.go b/service/policy/namespaces/namespaces.go index f9ca32f53..37cb53970 100644 --- a/service/policy/namespaces/namespaces.go +++ b/service/policy/namespaces/namespaces.go @@ -5,9 +5,10 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/namespaces" + "github.com/opentdf/platform/protocol/go/policy/namespaces/namespacesconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -16,27 +17,26 @@ import ( ) type NamespacesService struct { //nolint:revive // NamespacesService is a valid name - namespaces.UnimplementedNamespaceServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[NamespacesService] { - return &serviceregistry.Service[NamespacesService]{ - ServiceOptions: serviceregistry.ServiceOptions[NamespacesService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &namespaces.NamespaceService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*NamespacesService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[namespacesconnect.NamespaceServiceHandler] { + return &serviceregistry.Service[namespacesconnect.NamespaceServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[namespacesconnect.NamespaceServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &namespaces.NamespaceService_ServiceDesc, + ConnectRPCFunc: namespacesconnect.NewNamespaceServiceHandler, + GRPCGateayFunc: namespaces.RegisterNamespaceServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (namespacesconnect.NamespaceServiceHandler, serviceregistry.HandlerServer) { ns := &NamespacesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} if err := srp.RegisterReadinessCheck("policy", ns.IsReady); err != nil { srp.Logger.Error("failed to register policy readiness check", slog.String("error", err.Error())) } - return ns, func(ctx context.Context, mux *runtime.ServeMux) error { - return namespaces.RegisterNamespaceServiceHandlerServer(ctx, mux, ns) - } + return ns, nil }, }, } @@ -53,8 +53,8 @@ func (ns NamespacesService) IsReady(ctx context.Context) error { return nil } -func (ns NamespacesService) ListNamespaces(ctx context.Context, req *namespaces.ListNamespacesRequest) (*namespaces.ListNamespacesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) +func (ns NamespacesService) ListNamespaces(ctx context.Context, req *connect.Request[namespaces.ListNamespacesRequest]) (*connect.Response[namespaces.ListNamespacesResponse], error) { + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) ns.logger.Debug("listing namespaces", slog.String("state", state)) rsp := &namespaces.ListNamespacesResponse{} @@ -66,26 +66,26 @@ func (ns NamespacesService) ListNamespaces(ctx context.Context, req *namespaces. ns.logger.Debug("listed namespaces") rsp.Namespaces = list - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) GetNamespace(ctx context.Context, req *namespaces.GetNamespaceRequest) (*namespaces.GetNamespaceResponse, error) { - ns.logger.Debug("getting namespace", slog.String("id", req.GetId())) +func (ns NamespacesService) GetNamespace(ctx context.Context, req *connect.Request[namespaces.GetNamespaceRequest]) (*connect.Response[namespaces.GetNamespaceResponse], error) { + ns.logger.Debug("getting namespace", slog.String("id", req.Msg.GetId())) rsp := &namespaces.GetNamespaceResponse{} - namespace, err := ns.dbClient.GetNamespace(ctx, req.GetId()) + namespace, err := ns.dbClient.GetNamespace(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, "id", req.GetId()) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, "id", req.Msg.GetId()) } rsp.Namespace = namespace - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) CreateNamespace(ctx context.Context, req *namespaces.CreateNamespaceRequest) (*namespaces.CreateNamespaceResponse, error) { - ns.logger.Debug("creating new namespace", slog.String("name", req.GetName())) +func (ns NamespacesService) CreateNamespace(ctx context.Context, req *connect.Request[namespaces.CreateNamespaceRequest]) (*connect.Response[namespaces.CreateNamespaceResponse], error) { + ns.logger.Debug("creating new namespace", slog.String("name", req.Msg.GetName())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, @@ -93,24 +93,24 @@ func (ns NamespacesService) CreateNamespace(ctx context.Context, req *namespaces } rsp := &namespaces.CreateNamespaceResponse{} - n, err := ns.dbClient.CreateNamespace(ctx, req) + n, err := ns.dbClient.CreateNamespace(ctx, req.Msg) if err != nil { ns.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("name", req.GetName())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("name", req.Msg.GetName())) } auditParams.ObjectID = n.GetId() auditParams.Original = n ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - ns.logger.Debug("created new namespace", slog.String("name", req.GetName())) + ns.logger.Debug("created new namespace", slog.String("name", req.Msg.GetName())) rsp.Namespace = n - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces.UpdateNamespaceRequest) (*namespaces.UpdateNamespaceResponse, error) { - namespaceID := req.GetId() +func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *connect.Request[namespaces.UpdateNamespaceRequest]) (*connect.Response[namespaces.UpdateNamespaceResponse], error) { + namespaceID := req.Msg.GetId() ns.logger.Debug("updating namespace", slog.String("name", namespaceID)) rsp := &namespaces.UpdateNamespaceResponse{} @@ -126,7 +126,7 @@ func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", namespaceID)) } - updated, err := ns.dbClient.UpdateNamespace(ctx, namespaceID, req) + updated, err := ns.dbClient.UpdateNamespace(ctx, namespaceID, req.Msg) if err != nil { ns.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", namespaceID)) @@ -141,11 +141,11 @@ func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces rsp.Namespace = &policy.Namespace{ Id: namespaceID, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *namespaces.DeactivateNamespaceRequest) (*namespaces.DeactivateNamespaceResponse, error) { - namespaceID := req.GetId() +func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *connect.Request[namespaces.DeactivateNamespaceRequest]) (*connect.Response[namespaces.DeactivateNamespaceResponse], error) { + namespaceID := req.Msg.GetId() ns.logger.Debug("deactivating namespace", slog.String("id", namespaceID)) rsp := &namespaces.DeactivateNamespaceResponse{} @@ -173,11 +173,13 @@ func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *namesp ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) ns.logger.Debug("soft-deleted namespace", slog.String("id", namespaceID)) - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context, req *namespaces.AssignKeyAccessServerToNamespaceRequest) (*namespaces.AssignKeyAccessServerToNamespaceResponse, error) { - grant := req.GetNamespaceKeyAccessServer() +func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context, req *connect.Request[namespaces.AssignKeyAccessServerToNamespaceRequest]) (*connect.Response[namespaces.AssignKeyAccessServerToNamespaceResponse], error) { + rsp := &namespaces.AssignKeyAccessServerToNamespaceResponse{} + + grant := req.Msg.GetNamespaceKeyAccessServer() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeNamespaceAssignment, @@ -191,13 +193,15 @@ func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context } ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &namespaces.AssignKeyAccessServerToNamespaceResponse{ - NamespaceKeyAccessServer: namespaceKas, - }, nil + rsp.NamespaceKeyAccessServer = namespaceKas + + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Context, req *namespaces.RemoveKeyAccessServerFromNamespaceRequest) (*namespaces.RemoveKeyAccessServerFromNamespaceResponse, error) { - grant := req.GetNamespaceKeyAccessServer() +func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Context, req *connect.Request[namespaces.RemoveKeyAccessServerFromNamespaceRequest]) (*connect.Response[namespaces.RemoveKeyAccessServerFromNamespaceResponse], error) { + rsp := &namespaces.RemoveKeyAccessServerFromNamespaceResponse{} + + grant := req.Msg.GetNamespaceKeyAccessServer() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeNamespaceAssignment, @@ -211,7 +215,7 @@ func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Conte } ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &namespaces.RemoveKeyAccessServerFromNamespaceResponse{ - NamespaceKeyAccessServer: namespaceKas, - }, nil + rsp.NamespaceKeyAccessServer = namespaceKas + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/namespaces/namespaces.proto b/service/policy/namespaces/namespaces.proto index 984824e5e..bb1e3730e 100644 --- a/service/policy/namespaces/namespaces.proto +++ b/service/policy/namespaces/namespaces.proto @@ -119,10 +119,12 @@ message RemoveKeyAccessServerFromNamespaceResponse { service NamespaceService { rpc GetNamespace(GetNamespaceRequest) returns (GetNamespaceResponse) { option (google.api.http) = {get: "/attributes/namespaces/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) { option (google.api.http) = {get: "/attributes/namespaces"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateNamespace(CreateNamespaceRequest) returns (CreateNamespaceResponse) { diff --git a/service/policy/resourcemapping/resource_mapping.go b/service/policy/resourcemapping/resource_mapping.go index 54e732172..ba41489ce 100644 --- a/service/policy/resourcemapping/resource_mapping.go +++ b/service/policy/resourcemapping/resource_mapping.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/resourcemapping" + "github.com/opentdf/platform/protocol/go/policy/resourcemapping/resourcemappingconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,21 @@ import ( ) type ResourceMappingService struct { //nolint:revive // ResourceMappingService is a valid name for this struct - resourcemapping.UnimplementedResourceMappingServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[ResourceMappingService] { - return &serviceregistry.Service[ResourceMappingService]{ - ServiceOptions: serviceregistry.ServiceOptions[ResourceMappingService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &resourcemapping.ResourceMappingService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*ResourceMappingService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[resourcemappingconnect.ResourceMappingServiceHandler] { + return &serviceregistry.Service[resourcemappingconnect.ResourceMappingServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[resourcemappingconnect.ResourceMappingServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &resourcemapping.ResourceMappingService_ServiceDesc, + ConnectRPCFunc: resourcemappingconnect.NewResourceMappingServiceHandler, + GRPCGateayFunc: resourcemapping.RegisterResourceMappingServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (resourcemappingconnect.ResourceMappingServiceHandler, serviceregistry.HandlerServer) { rm := &ResourceMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return rm, func(ctx context.Context, mux *runtime.ServeMux) error { - return resourcemapping.RegisterResourceMappingServiceHandlerServer(ctx, mux, rm) - } + return rm, nil }, }, } @@ -40,51 +40,59 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer Resource Mapping Groups */ -func (s ResourceMappingService) ListResourceMappingGroups(ctx context.Context, req *resourcemapping.ListResourceMappingGroupsRequest) (*resourcemapping.ListResourceMappingGroupsResponse, error) { - rmGroups, err := s.dbClient.ListResourceMappingGroups(ctx, req) +func (s ResourceMappingService) ListResourceMappingGroups(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingGroupsRequest]) (*connect.Response[resourcemapping.ListResourceMappingGroupsResponse], error) { + rsp := &resourcemapping.ListResourceMappingGroupsResponse{} + + rmGroups, err := s.dbClient.ListResourceMappingGroups(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &resourcemapping.ListResourceMappingGroupsResponse{ - ResourceMappingGroups: rmGroups, - }, nil + rsp.ResourceMappingGroups = rmGroups + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) GetResourceMappingGroup(ctx context.Context, req *resourcemapping.GetResourceMappingGroupRequest) (*resourcemapping.GetResourceMappingGroupResponse, error) { - rmGroup, err := s.dbClient.GetResourceMappingGroup(ctx, req.GetId()) +func (s ResourceMappingService) GetResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.GetResourceMappingGroupRequest]) (*connect.Response[resourcemapping.GetResourceMappingGroupResponse], error) { + rsp := &resourcemapping.GetResourceMappingGroupResponse{} + + rmGroup, err := s.dbClient.GetResourceMappingGroup(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &resourcemapping.GetResourceMappingGroupResponse{ - ResourceMappingGroup: rmGroup, - }, nil + rsp.ResourceMappingGroup = rmGroup + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) CreateResourceMappingGroup(ctx context.Context, req *resourcemapping.CreateResourceMappingGroupRequest) (*resourcemapping.CreateResourceMappingGroupResponse, error) { +func (s ResourceMappingService) CreateResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.CreateResourceMappingGroupRequest]) (*connect.Response[resourcemapping.CreateResourceMappingGroupResponse], error) { + rsp := &resourcemapping.CreateResourceMappingGroupResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeResourceMappingGroup, } - rmGroup, err := s.dbClient.CreateResourceMappingGroup(ctx, req) + rmGroup, err := s.dbClient.CreateResourceMappingGroup(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMappingGroup", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMappingGroup", req.Msg.String())) } auditParams.ObjectID = rmGroup.GetId() auditParams.Original = rmGroup s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.CreateResourceMappingGroupResponse{ - ResourceMappingGroup: rmGroup, - }, nil + rsp.ResourceMappingGroup = rmGroup + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, req *resourcemapping.UpdateResourceMappingGroupRequest) (*resourcemapping.UpdateResourceMappingGroupResponse, error) { - id := req.GetId() +func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.UpdateResourceMappingGroupRequest]) (*connect.Response[resourcemapping.UpdateResourceMappingGroupResponse], error) { + rsp := &resourcemapping.UpdateResourceMappingGroupResponse{} + + id := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -98,7 +106,7 @@ func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updatedRmGroup, err := s.dbClient.UpdateResourceMappingGroup(ctx, id, req) + updatedRmGroup, err := s.dbClient.UpdateResourceMappingGroup(ctx, id, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id)) @@ -109,15 +117,17 @@ func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.UpdateResourceMappingGroupResponse{ - ResourceMappingGroup: &policy.ResourceMappingGroup{ - Id: id, - }, - }, nil + rsp.ResourceMappingGroup = &policy.ResourceMappingGroup{ + Id: id, + } + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, req *resourcemapping.DeleteResourceMappingGroupRequest) (*resourcemapping.DeleteResourceMappingGroupResponse, error) { - id := req.GetId() +func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.DeleteResourceMappingGroupRequest]) (*connect.Response[resourcemapping.DeleteResourceMappingGroupResponse], error) { + rsp := &resourcemapping.DeleteResourceMappingGroupResponse{} + + id := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, @@ -133,11 +143,11 @@ func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.DeleteResourceMappingGroupResponse{ - ResourceMappingGroup: &policy.ResourceMappingGroup{ - Id: id, - }, - }, nil + rsp.ResourceMappingGroup = &policy.ResourceMappingGroup{ + Id: id, + } + + return connect.NewResponse(rsp), nil } /* @@ -145,47 +155,55 @@ func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, */ func (s ResourceMappingService) ListResourceMappings(ctx context.Context, - req *resourcemapping.ListResourceMappingsRequest, -) (*resourcemapping.ListResourceMappingsResponse, error) { - resourceMappings, err := s.dbClient.ListResourceMappings(ctx, req) + req *connect.Request[resourcemapping.ListResourceMappingsRequest], +) (*connect.Response[resourcemapping.ListResourceMappingsResponse], error) { + rsp := &resourcemapping.ListResourceMappingsResponse{} + + resourceMappings, err := s.dbClient.ListResourceMappings(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &resourcemapping.ListResourceMappingsResponse{ - ResourceMappings: resourceMappings, - }, nil + rsp.ResourceMappings = resourceMappings + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) ListResourceMappingsByGroupFqns(ctx context.Context, req *resourcemapping.ListResourceMappingsByGroupFqnsRequest) (*resourcemapping.ListResourceMappingsByGroupFqnsResponse, error) { - fqns := req.GetFqns() +func (s ResourceMappingService) ListResourceMappingsByGroupFqns(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingsByGroupFqnsRequest]) (*connect.Response[resourcemapping.ListResourceMappingsByGroupFqnsResponse], error) { + rsp := &resourcemapping.ListResourceMappingsByGroupFqnsResponse{} + + fqns := req.Msg.GetFqns() fqnRmGroupMap, err := s.dbClient.ListResourceMappingsByGroupFqns(ctx, fqns) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.Any("fqns", fqns)) } - return &resourcemapping.ListResourceMappingsByGroupFqnsResponse{ - FqnResourceMappingGroups: fqnRmGroupMap, - }, nil + rsp.FqnResourceMappingGroups = fqnRmGroupMap + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) GetResourceMapping(ctx context.Context, - req *resourcemapping.GetResourceMappingRequest, -) (*resourcemapping.GetResourceMappingResponse, error) { - rm, err := s.dbClient.GetResourceMapping(ctx, req.GetId()) + req *connect.Request[resourcemapping.GetResourceMappingRequest], +) (*connect.Response[resourcemapping.GetResourceMappingResponse], error) { + rsp := &resourcemapping.GetResourceMappingResponse{} + + rm, err := s.dbClient.GetResourceMapping(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &resourcemapping.GetResourceMappingResponse{ - ResourceMapping: rm, - }, nil + rsp.ResourceMapping = rm + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) CreateResourceMapping(ctx context.Context, - req *resourcemapping.CreateResourceMappingRequest, -) (*resourcemapping.CreateResourceMappingResponse, error) { + req *connect.Request[resourcemapping.CreateResourceMappingRequest], +) (*connect.Response[resourcemapping.CreateResourceMappingResponse], error) { + rsp := &resourcemapping.CreateResourceMappingResponse{} + s.logger.Debug("creating resource mapping") auditParams := audit.PolicyEventParams{ @@ -193,25 +211,27 @@ func (s ResourceMappingService) CreateResourceMapping(ctx context.Context, ObjectType: audit.ObjectTypeResourceMapping, } - rm, err := s.dbClient.CreateResourceMapping(ctx, req) + rm, err := s.dbClient.CreateResourceMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMapping", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMapping", req.Msg.String())) } auditParams.ObjectID = rm.GetId() auditParams.Original = rm s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.CreateResourceMappingResponse{ - ResourceMapping: rm, - }, nil + rsp.ResourceMapping = rm + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, - req *resourcemapping.UpdateResourceMappingRequest, -) (*resourcemapping.UpdateResourceMappingResponse, error) { - resourceMappingID := req.GetId() + req *connect.Request[resourcemapping.UpdateResourceMappingRequest], +) (*connect.Response[resourcemapping.UpdateResourceMappingResponse], error) { + rsp := &resourcemapping.UpdateResourceMappingResponse{} + + resourceMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -225,12 +245,12 @@ func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - updatedRM, err := s.dbClient.UpdateResourceMapping(ctx, resourceMappingID, req) + updatedRM, err := s.dbClient.UpdateResourceMapping(ctx, resourceMappingID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, - slog.String("id", req.GetId()), - slog.String("resourceMapping", req.String()), + slog.String("id", req.Msg.GetId()), + slog.String("resourceMapping", req.Msg.String()), ) } @@ -238,17 +258,19 @@ func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, auditParams.Updated = updatedRM s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.UpdateResourceMappingResponse{ - ResourceMapping: &policy.ResourceMapping{ - Id: resourceMappingID, - }, - }, nil + rsp.ResourceMapping = &policy.ResourceMapping{ + Id: resourceMappingID, + } + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) DeleteResourceMapping(ctx context.Context, - req *resourcemapping.DeleteResourceMappingRequest, -) (*resourcemapping.DeleteResourceMappingResponse, error) { - resourceMappingID := req.GetId() + req *connect.Request[resourcemapping.DeleteResourceMappingRequest], +) (*connect.Response[resourcemapping.DeleteResourceMappingResponse], error) { + rsp := &resourcemapping.DeleteResourceMappingResponse{} + + resourceMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, @@ -264,9 +286,9 @@ func (s ResourceMappingService) DeleteResourceMapping(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.DeleteResourceMappingResponse{ - ResourceMapping: &policy.ResourceMapping{ - Id: resourceMappingID, - }, - }, nil + rsp.ResourceMapping = &policy.ResourceMapping{ + Id: resourceMappingID, + } + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/resourcemapping/resource_mapping.proto b/service/policy/resourcemapping/resource_mapping.proto index cd9524351..e925fe441 100644 --- a/service/policy/resourcemapping/resource_mapping.proto +++ b/service/policy/resourcemapping/resource_mapping.proto @@ -241,10 +241,12 @@ service ResourceMappingService { rpc ListResourceMappingGroups(ListResourceMappingGroupsRequest) returns (ListResourceMappingGroupsResponse) { option (google.api.http) = {get: "/resource-mapping-groups"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetResourceMappingGroup(GetResourceMappingGroupRequest) returns (GetResourceMappingGroupResponse) { option (google.api.http) = {get: "/resource-mapping-groups/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateResourceMappingGroup(CreateResourceMappingGroupRequest) returns (CreateResourceMappingGroupResponse) { @@ -271,14 +273,17 @@ service ResourceMappingService { rpc ListResourceMappings(ListResourceMappingsRequest) returns (ListResourceMappingsResponse) { option (google.api.http) = {get: "/resource-mappings"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListResourceMappingsByGroupFqns(ListResourceMappingsByGroupFqnsRequest) returns (ListResourceMappingsByGroupFqnsResponse) { option (google.api.http) = {get: "/resource-mappings/group-fqns"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetResourceMapping(GetResourceMappingRequest) returns (GetResourceMappingResponse) { option (google.api.http) = {get: "/resource-mappings/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateResourceMapping(CreateResourceMappingRequest) returns (CreateResourceMappingResponse) { diff --git a/service/policy/subjectmapping/subject_mapping.go b/service/policy/subjectmapping/subject_mapping.go index 31197fa2d..d089fe290 100644 --- a/service/policy/subjectmapping/subject_mapping.go +++ b/service/policy/subjectmapping/subject_mapping.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" sm "github.com/opentdf/platform/protocol/go/policy/subjectmapping" + "github.com/opentdf/platform/protocol/go/policy/subjectmapping/subjectmappingconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,21 @@ import ( ) type SubjectMappingService struct { //nolint:revive // SubjectMappingService is a valid name for this struct - sm.UnimplementedSubjectMappingServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[SubjectMappingService] { - return &serviceregistry.Service[SubjectMappingService]{ - ServiceOptions: serviceregistry.ServiceOptions[SubjectMappingService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &sm.SubjectMappingService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*SubjectMappingService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[subjectmappingconnect.SubjectMappingServiceHandler] { + return &serviceregistry.Service[subjectmappingconnect.SubjectMappingServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[subjectmappingconnect.SubjectMappingServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &sm.SubjectMappingService_ServiceDesc, + ConnectRPCFunc: subjectmappingconnect.NewSubjectMappingServiceHandler, + GRPCGateayFunc: sm.RegisterSubjectMappingServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (subjectmappingconnect.SubjectMappingServiceHandler, serviceregistry.HandlerServer) { smSvc := &SubjectMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return smSvc, func(ctx context.Context, mux *runtime.ServeMux) error { - return sm.RegisterSubjectMappingServiceHandlerServer(ctx, mux, smSvc) - } + return smSvc, nil }, }, } @@ -41,8 +41,8 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer * --------------------------------------------------*/ func (s SubjectMappingService) CreateSubjectMapping(ctx context.Context, - req *sm.CreateSubjectMappingRequest, -) (*sm.CreateSubjectMappingResponse, error) { + req *connect.Request[sm.CreateSubjectMappingRequest], +) (*connect.Response[sm.CreateSubjectMappingResponse], error) { rsp := &sm.CreateSubjectMappingResponse{} s.logger.Debug("creating subject mapping") @@ -51,23 +51,23 @@ func (s SubjectMappingService) CreateSubjectMapping(ctx context.Context, ObjectType: audit.ObjectTypeSubjectMapping, } - sm, err := s.dbClient.CreateSubjectMapping(ctx, req) + subjectMapping, err := s.dbClient.CreateSubjectMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectMapping", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectMapping", req.Msg.String())) } - auditParams.ObjectID = sm.GetId() - auditParams.Original = sm + auditParams.ObjectID = subjectMapping.GetId() + auditParams.Original = subjectMapping s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - rsp.SubjectMapping = sm - return rsp, nil + rsp.SubjectMapping = subjectMapping + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) ListSubjectMappings(ctx context.Context, - _ *sm.ListSubjectMappingsRequest, -) (*sm.ListSubjectMappingsResponse, error) { + _ *connect.Request[sm.ListSubjectMappingsRequest], +) (*connect.Response[sm.ListSubjectMappingsResponse], error) { rsp := &sm.ListSubjectMappingsResponse{} s.logger.Debug("listing subject mappings") @@ -77,31 +77,31 @@ func (s SubjectMappingService) ListSubjectMappings(ctx context.Context, } rsp.SubjectMappings = mappings - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) GetSubjectMapping(ctx context.Context, - req *sm.GetSubjectMappingRequest, -) (*sm.GetSubjectMappingResponse, error) { + req *connect.Request[sm.GetSubjectMappingRequest], +) (*connect.Response[sm.GetSubjectMappingResponse], error) { rsp := &sm.GetSubjectMappingResponse{} - s.logger.Debug("getting subject mapping", slog.String("id", req.GetId())) + s.logger.Debug("getting subject mapping", slog.String("id", req.Msg.GetId())) - mapping, err := s.dbClient.GetSubjectMapping(ctx, req.GetId()) + mapping, err := s.dbClient.GetSubjectMapping(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.SubjectMapping = mapping - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, - req *sm.UpdateSubjectMappingRequest, -) (*sm.UpdateSubjectMappingResponse, error) { + req *connect.Request[sm.UpdateSubjectMappingRequest], +) (*connect.Response[sm.UpdateSubjectMappingResponse], error) { rsp := &sm.UpdateSubjectMappingResponse{} - subjectMappingID := req.GetId() + subjectMappingID := req.Msg.GetId() - s.logger.Debug("updating subject mapping", slog.String("subjectMapping", req.String())) + s.logger.Debug("updating subject mapping", slog.String("subjectMapping", req.Msg.String())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -115,10 +115,10 @@ func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", subjectMappingID)) } - updated, err := s.dbClient.UpdateSubjectMapping(ctx, req) + updated, err := s.dbClient.UpdateSubjectMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("subjectMapping fields", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("subjectMapping fields", req.Msg.String())) } auditParams.Original = original @@ -128,16 +128,16 @@ func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, rsp.SubjectMapping = &policy.SubjectMapping{ Id: subjectMappingID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteSubjectMapping(ctx context.Context, - req *sm.DeleteSubjectMappingRequest, -) (*sm.DeleteSubjectMappingResponse, error) { + req *connect.Request[sm.DeleteSubjectMappingRequest], +) (*connect.Response[sm.DeleteSubjectMappingResponse], error) { rsp := &sm.DeleteSubjectMappingResponse{} - s.logger.Debug("deleting subject mapping", slog.String("id", req.GetId())) + s.logger.Debug("deleting subject mapping", slog.String("id", req.Msg.GetId())) - subjectMappingID := req.GetId() + subjectMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeSubjectMapping, @@ -155,22 +155,22 @@ func (s SubjectMappingService) DeleteSubjectMapping(ctx context.Context, rsp.SubjectMapping = &policy.SubjectMapping{ Id: subjectMappingID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) MatchSubjectMappings(ctx context.Context, - req *sm.MatchSubjectMappingsRequest, -) (*sm.MatchSubjectMappingsResponse, error) { + req *connect.Request[sm.MatchSubjectMappingsRequest], +) (*connect.Response[sm.MatchSubjectMappingsResponse], error) { rsp := &sm.MatchSubjectMappingsResponse{} - s.logger.Debug("matching subject mappings", slog.Any("subjectProperties", req.GetSubjectProperties())) + s.logger.Debug("matching subject mappings", slog.Any("subjectProperties", req.Msg.GetSubjectProperties())) - smList, err := s.dbClient.GetMatchedSubjectMappings(ctx, req.GetSubjectProperties()) + smList, err := s.dbClient.GetMatchedSubjectMappings(ctx, req.Msg.GetSubjectProperties()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.Any("subjectProperties", req.GetSubjectProperties())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.Any("subjectProperties", req.Msg.GetSubjectProperties())) } rsp.SubjectMappings = smList - return rsp, nil + return connect.NewResponse(rsp), nil } /* -------------------------------------------------------- @@ -178,23 +178,23 @@ func (s SubjectMappingService) MatchSubjectMappings(ctx context.Context, * -------------------------------------------------------*/ func (s SubjectMappingService) GetSubjectConditionSet(ctx context.Context, - req *sm.GetSubjectConditionSetRequest, -) (*sm.GetSubjectConditionSetResponse, error) { + req *connect.Request[sm.GetSubjectConditionSetRequest], +) (*connect.Response[sm.GetSubjectConditionSetResponse], error) { rsp := &sm.GetSubjectConditionSetResponse{} - s.logger.Debug("getting subject condition set", slog.String("id", req.GetId())) + s.logger.Debug("getting subject condition set", slog.String("id", req.Msg.GetId())) - conditionSet, err := s.dbClient.GetSubjectConditionSet(ctx, req.GetId()) + conditionSet, err := s.dbClient.GetSubjectConditionSet(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.SubjectConditionSet = conditionSet - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) ListSubjectConditionSets(ctx context.Context, - _ *sm.ListSubjectConditionSetsRequest, -) (*sm.ListSubjectConditionSetsResponse, error) { + _ *connect.Request[sm.ListSubjectConditionSetsRequest], +) (*connect.Response[sm.ListSubjectConditionSetsResponse], error) { rsp := &sm.ListSubjectConditionSetsResponse{} s.logger.Debug("listing subject condition sets") @@ -204,24 +204,24 @@ func (s SubjectMappingService) ListSubjectConditionSets(ctx context.Context, } rsp.SubjectConditionSets = conditionSets - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) CreateSubjectConditionSet(ctx context.Context, - req *sm.CreateSubjectConditionSetRequest, -) (*sm.CreateSubjectConditionSetResponse, error) { + req *connect.Request[sm.CreateSubjectConditionSetRequest], +) (*connect.Response[sm.CreateSubjectConditionSetResponse], error) { rsp := &sm.CreateSubjectConditionSetResponse{} - s.logger.Debug("creating subject condition set", slog.String("subjectConditionSet", req.String())) + s.logger.Debug("creating subject condition set", slog.String("subjectConditionSet", req.Msg.String())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeConditionSet, } - conditionSet, err := s.dbClient.CreateSubjectConditionSet(ctx, req.GetSubjectConditionSet()) + conditionSet, err := s.dbClient.CreateSubjectConditionSet(ctx, req.Msg.GetSubjectConditionSet()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectConditionSet", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectConditionSet", req.Msg.String())) } auditParams.ObjectID = conditionSet.GetId() @@ -229,16 +229,16 @@ func (s SubjectMappingService) CreateSubjectConditionSet(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) rsp.SubjectConditionSet = conditionSet - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, - req *sm.UpdateSubjectConditionSetRequest, -) (*sm.UpdateSubjectConditionSetResponse, error) { + req *connect.Request[sm.UpdateSubjectConditionSetRequest], +) (*connect.Response[sm.UpdateSubjectConditionSetResponse], error) { rsp := &sm.UpdateSubjectConditionSetResponse{} - s.logger.Debug("updating subject condition set", slog.String("subjectConditionSet", req.String())) + s.logger.Debug("updating subject condition set", slog.String("subjectConditionSet", req.Msg.String())) - subjectConditionSetID := req.GetId() + subjectConditionSetID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeConditionSet, @@ -251,10 +251,10 @@ func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", subjectConditionSetID)) } - updated, err := s.dbClient.UpdateSubjectConditionSet(ctx, req) + updated, err := s.dbClient.UpdateSubjectConditionSet(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("subjectConditionSet fields", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("subjectConditionSet fields", req.Msg.String())) } auditParams.Original = original @@ -264,16 +264,16 @@ func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, rsp.SubjectConditionSet = &policy.SubjectConditionSet{ Id: subjectConditionSetID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteSubjectConditionSet(ctx context.Context, - req *sm.DeleteSubjectConditionSetRequest, -) (*sm.DeleteSubjectConditionSetResponse, error) { + req *connect.Request[sm.DeleteSubjectConditionSetRequest], +) (*connect.Response[sm.DeleteSubjectConditionSetResponse], error) { rsp := &sm.DeleteSubjectConditionSetResponse{} - s.logger.Debug("deleting subject condition set", slog.String("id", req.GetId())) + s.logger.Debug("deleting subject condition set", slog.String("id", req.Msg.GetId())) - conditionSetID := req.GetId() + conditionSetID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeConditionSet, @@ -291,12 +291,12 @@ func (s SubjectMappingService) DeleteSubjectConditionSet(ctx context.Context, rsp.SubjectConditionSet = &policy.SubjectConditionSet{ Id: conditionSetID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteAllUnmappedSubjectConditionSets(ctx context.Context, - _ *sm.DeleteAllUnmappedSubjectConditionSetsRequest, -) (*sm.DeleteAllUnmappedSubjectConditionSetsResponse, error) { + _ *connect.Request[sm.DeleteAllUnmappedSubjectConditionSetsRequest], +) (*connect.Response[sm.DeleteAllUnmappedSubjectConditionSetsResponse], error) { rsp := &sm.DeleteAllUnmappedSubjectConditionSetsResponse{} s.logger.Debug("deleting all unmapped subject condition sets") @@ -318,5 +318,5 @@ func (s SubjectMappingService) DeleteAllUnmappedSubjectConditionSets(ctx context } rsp.SubjectConditionSets = deleted - return rsp, nil + return connect.NewResponse(rsp), nil } diff --git a/service/policy/subjectmapping/subject_mapping.proto b/service/policy/subjectmapping/subject_mapping.proto index 6eb7521a7..b858e3287 100644 --- a/service/policy/subjectmapping/subject_mapping.proto +++ b/service/policy/subjectmapping/subject_mapping.proto @@ -197,9 +197,11 @@ service SubjectMappingService { rpc ListSubjectMappings(ListSubjectMappingsRequest) returns (ListSubjectMappingsResponse) { option (google.api.http) = {get: "/subject-mappings"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetSubjectMapping(GetSubjectMappingRequest) returns (GetSubjectMappingResponse) { option (google.api.http) = {get: "/subject-mappings/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateSubjectMapping(CreateSubjectMappingRequest) returns (CreateSubjectMappingResponse) { @@ -222,10 +224,12 @@ service SubjectMappingService { rpc ListSubjectConditionSets(ListSubjectConditionSetsRequest) returns (ListSubjectConditionSetsResponse) { option (google.api.http) = {get: "/subject-condition-sets"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetSubjectConditionSet(GetSubjectConditionSetRequest) returns (GetSubjectConditionSetResponse) { option (google.api.http) = {get: "/subject-condition-sets/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateSubjectConditionSet(CreateSubjectConditionSetRequest) returns (CreateSubjectConditionSetResponse) { diff --git a/service/policy/unsafe/unsafe.go b/service/policy/unsafe/unsafe.go index ed1f2700e..065866b0b 100644 --- a/service/policy/unsafe/unsafe.go +++ b/service/policy/unsafe/unsafe.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/unsafe" + "github.com/opentdf/platform/protocol/go/policy/unsafe/unsafeconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,20 @@ import ( ) type UnsafeService struct { //nolint:revive // UnsafeService is a valid name for this struct - unsafe.UnimplementedUnsafeServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[UnsafeService] { - return &serviceregistry.Service[UnsafeService]{ - ServiceOptions: serviceregistry.ServiceOptions[UnsafeService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &unsafe.UnsafeService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*UnsafeService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[unsafeconnect.UnsafeServiceHandler] { + return &serviceregistry.Service[unsafeconnect.UnsafeServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[unsafeconnect.UnsafeServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &unsafe.UnsafeService_ServiceDesc, + ConnectRPCFunc: unsafeconnect.NewUnsafeServiceHandler, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (unsafeconnect.UnsafeServiceHandler, serviceregistry.HandlerServer) { unsafeSvc := &UnsafeService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return unsafeSvc, func(ctx context.Context, mux *runtime.ServeMux) error { - return unsafe.RegisterUnsafeServiceHandlerServer(ctx, mux, unsafeSvc) - } + return unsafeSvc, nil }, }, } @@ -40,9 +39,9 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer // Unsafe Namespace RPCs // -func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *unsafe.UnsafeUpdateNamespaceRequest) (*unsafe.UnsafeUpdateNamespaceResponse, error) { - id := req.GetId() - name := req.GetName() +func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateNamespaceRequest]) (*connect.Response[unsafe.UnsafeUpdateNamespaceResponse], error) { + id := req.Msg.GetId() + name := req.Msg.GetName() rsp := &unsafe.UnsafeUpdateNamespaceResponse{} @@ -73,11 +72,11 @@ func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *unsafe.UnsafeReactivateNamespaceRequest) (*unsafe.UnsafeReactivateNamespaceResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateNamespaceRequest]) (*connect.Response[unsafe.UnsafeReactivateNamespaceResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateNamespaceResponse{} @@ -108,11 +107,11 @@ func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *unsa Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.UnsafeDeleteNamespaceRequest) (*unsafe.UnsafeDeleteNamespaceResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteNamespaceRequest]) (*connect.Response[unsafe.UnsafeDeleteNamespaceResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteNamespaceResponse{} @@ -128,7 +127,7 @@ func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteNamespace(ctx, existing, req.GetFqn()) + _, err = s.dbClient.UnsafeDeleteNamespace(ctx, existing, req.Msg.GetFqn()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -140,15 +139,15 @@ func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } // // Unsafe Attribute Definition RPCs // -func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.UnsafeUpdateAttributeRequest) (*unsafe.UnsafeUpdateAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateAttributeRequest]) (*connect.Response[unsafe.UnsafeUpdateAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeUpdateAttributeResponse{} @@ -164,10 +163,10 @@ func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updated, err := s.dbClient.UnsafeUpdateAttribute(ctx, req) + updated, err := s.dbClient.UnsafeUpdateAttribute(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute", req.Msg.String())) } auditParams.Original = original @@ -179,11 +178,11 @@ func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *unsafe.UnsafeReactivateAttributeRequest) (*unsafe.UnsafeReactivateAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateAttributeRequest]) (*connect.Response[unsafe.UnsafeReactivateAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateAttributeResponse{} @@ -214,11 +213,11 @@ func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *unsa Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.UnsafeDeleteAttributeRequest) (*unsafe.UnsafeDeleteAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteAttributeRequest]) (*connect.Response[unsafe.UnsafeDeleteAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteAttributeResponse{} @@ -234,7 +233,7 @@ func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteAttribute(ctx, existing, req.GetFqn()) + _, err = s.dbClient.UnsafeDeleteAttribute(ctx, existing, req.Msg.GetFqn()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -246,15 +245,15 @@ func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } // // Unsafe Attribute Value RPCs // -func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *unsafe.UnsafeUpdateAttributeValueRequest) (*unsafe.UnsafeUpdateAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateAttributeValueRequest]) (*connect.Response[unsafe.UnsafeUpdateAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeUpdateAttributeValueResponse{} @@ -270,10 +269,10 @@ func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *uns return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updated, err := s.dbClient.UnsafeUpdateAttributeValue(ctx, req) + updated, err := s.dbClient.UnsafeUpdateAttributeValue(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute_value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute_value", req.Msg.String())) } auditParams.Original = original @@ -284,11 +283,11 @@ func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *uns rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req *unsafe.UnsafeReactivateAttributeValueRequest) (*unsafe.UnsafeReactivateAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateAttributeValueRequest]) (*connect.Response[unsafe.UnsafeReactivateAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateAttributeValueResponse{} @@ -318,11 +317,11 @@ func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *unsafe.UnsafeDeleteAttributeValueRequest) (*unsafe.UnsafeDeleteAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteAttributeValueRequest]) (*connect.Response[unsafe.UnsafeDeleteAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteAttributeValueResponse{} @@ -338,7 +337,7 @@ func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *uns return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteAttributeValue(ctx, existing, req) + _, err = s.dbClient.UnsafeDeleteAttributeValue(ctx, existing, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -349,5 +348,5 @@ func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *uns rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } diff --git a/service/wellknownconfiguration/wellknown_configuration.go b/service/wellknownconfiguration/wellknown_configuration.go index bbfb34e3a..88a096688 100644 --- a/service/wellknownconfiguration/wellknown_configuration.go +++ b/service/wellknownconfiguration/wellknown_configuration.go @@ -6,8 +6,9 @@ import ( "log/slog" "sync" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" wellknown "github.com/opentdf/platform/protocol/go/wellknownconfiguration" + "github.com/opentdf/platform/protocol/go/wellknownconfiguration/wellknownconfigurationconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" @@ -16,7 +17,6 @@ import ( ) type WellKnownService struct { - wellknown.UnimplementedWellKnownServiceServer logger *logger.Logger } @@ -35,22 +35,22 @@ func RegisterConfiguration(namespace string, config any) error { return nil } -func NewRegistration() *serviceregistry.Service[WellKnownService] { - return &serviceregistry.Service[WellKnownService]{ - ServiceOptions: serviceregistry.ServiceOptions[WellKnownService]{ - Namespace: "wellknown", - ServiceDesc: &wellknown.WellKnownService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*WellKnownService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[wellknownconfigurationconnect.WellKnownServiceHandler] { + return &serviceregistry.Service[wellknownconfigurationconnect.WellKnownServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[wellknownconfigurationconnect.WellKnownServiceHandler]{ + Namespace: "wellknown", + ServiceDesc: &wellknown.WellKnownService_ServiceDesc, + ConnectRPCFunc: wellknownconfigurationconnect.NewWellKnownServiceHandler, + GRPCGateayFunc: wellknown.RegisterWellKnownServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (wellknownconfigurationconnect.WellKnownServiceHandler, serviceregistry.HandlerServer) { wk := &WellKnownService{logger: srp.Logger} - return wk, func(ctx context.Context, mux *runtime.ServeMux) error { - return wellknown.RegisterWellKnownServiceHandlerServer(ctx, mux, wk) - } + return wk, nil }, }, } } -func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *wellknown.GetWellKnownConfigurationRequest) (*wellknown.GetWellKnownConfigurationResponse, error) { +func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *connect.Request[wellknown.GetWellKnownConfigurationRequest]) (*connect.Response[wellknown.GetWellKnownConfigurationResponse], error) { rwMutex.RLock() cfg, err := structpb.NewStruct(wellKnownConfiguration) rwMutex.RUnlock() @@ -59,7 +59,8 @@ func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *wellkn return nil, status.Error(codes.Internal, "failed to create struct for wellknown configuration") } - return &wellknown.GetWellKnownConfigurationResponse{ + rsp := &wellknown.GetWellKnownConfigurationResponse{ Configuration: cfg, - }, nil + } + return connect.NewResponse(rsp), nil } diff --git a/service/wellknownconfiguration/wellknown_configuration.proto b/service/wellknownconfiguration/wellknown_configuration.proto index 43606adeb..b6d2c2256 100644 --- a/service/wellknownconfiguration/wellknown_configuration.proto +++ b/service/wellknownconfiguration/wellknown_configuration.proto @@ -18,5 +18,6 @@ message GetWellKnownConfigurationResponse { service WellKnownService { rpc GetWellKnownConfiguration(GetWellKnownConfigurationRequest) returns (GetWellKnownConfigurationResponse) { option (google.api.http) = {get: "/.well-known/opentdf-configuration"}; + option idempotency_level = NO_SIDE_EFFECTS; } } From 46662a791aa5c26ff6b363e773d74c1e7a89614c Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:43:39 -0500 Subject: [PATCH 05/32] fix(core): Autobump service (#1739) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- service/go.mod | 2 +- service/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/service/go.mod b/service/go.mod index 4d865f955..2d40f174f 100644 --- a/service/go.mod +++ b/service/go.mod @@ -24,7 +24,7 @@ require ( github.com/opentdf/platform/lib/flattening v0.1.1 github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 - github.com/opentdf/platform/sdk v0.3.16 + github.com/opentdf/platform/sdk v0.3.19 github.com/pressly/goose/v3 v3.19.1 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.18.2 diff --git a/service/go.sum b/service/go.sum index 582e2af09..90c89d2ac 100644 --- a/service/go.sum +++ b/service/go.sum @@ -280,8 +280,8 @@ github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+ github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= -github.com/opentdf/platform/sdk v0.3.16 h1:goF6Krn14+Y2H1wa3h2iYk1kOBrrze6t392szLb9ryE= -github.com/opentdf/platform/sdk v0.3.16/go.mod h1:c2+nrsRLvLf2OOryXnNy0iGZN/TScc21Pul7uqKVXIs= +github.com/opentdf/platform/sdk v0.3.19 h1:4Ign6HPrxOH6ZllLO/cI6joSuqz8CqPlpxpTKunpMQs= +github.com/opentdf/platform/sdk v0.3.19/go.mod h1:u+XZhVRsMq5blukCFCHcjk6HLCp4Y5mmIQu7GhtKQ3E= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= From 0a60afe54369b504b685e9c5dc268823376047d6 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:45:05 -0500 Subject: [PATCH 06/32] fix(core): Autobump examples (#1738) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- examples/go.mod | 2 +- examples/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index 50b7e1911..86f7874c8 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 - github.com/opentdf/platform/sdk v0.3.16 + github.com/opentdf/platform/sdk v0.3.19 github.com/spf13/cobra v1.8.0 google.golang.org/protobuf v1.34.2 ) diff --git a/examples/go.sum b/examples/go.sum index 6570f7dd7..432e075d7 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -108,8 +108,8 @@ github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+ github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= -github.com/opentdf/platform/sdk v0.3.16 h1:goF6Krn14+Y2H1wa3h2iYk1kOBrrze6t392szLb9ryE= -github.com/opentdf/platform/sdk v0.3.16/go.mod h1:c2+nrsRLvLf2OOryXnNy0iGZN/TScc21Pul7uqKVXIs= +github.com/opentdf/platform/sdk v0.3.19 h1:4Ign6HPrxOH6ZllLO/cI6joSuqz8CqPlpxpTKunpMQs= +github.com/opentdf/platform/sdk v0.3.19/go.mod h1:u+XZhVRsMq5blukCFCHcjk6HLCp4Y5mmIQu7GhtKQ3E= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 471f5f102e7a4e01abaff6fa2750ad784880274b Mon Sep 17 00:00:00 2001 From: Elizabeth Healy <35498075+elizabethhealy@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:46:27 -0500 Subject: [PATCH 07/32] fix(kas): Only hit authorization if data attributes not empty (#1741) ### Proposed Changes * only make authorization call when necessary go sdk creates a policy object with null in the attributes field if none provided but js fills it with "[]" which still triggered an authorization call -- this change should stop that ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- service/kas/access/accessPdp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/kas/access/accessPdp.go b/service/kas/access/accessPdp.go index 4b4b72713..04e7553cf 100644 --- a/service/kas/access/accessPdp.go +++ b/service/kas/access/accessPdp.go @@ -19,7 +19,7 @@ func (p *Provider) canAccess(ctx context.Context, token *authorization.Token, po // TODO: Move dissems check to the getdecisions endpoint p.Logger.Error("Dissems check is not enabled in v2 platform kas") } - if policy.Body.DataAttributes != nil { + if len(policy.Body.DataAttributes) > 0 { attrAccess, err := p.checkAttributes(ctx, policy.Body.DataAttributes, token) if err != nil { return false, err From 1153b09733e03b4e278c5491caadf4b26625b706 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 19:56:13 +0000 Subject: [PATCH 08/32] chore(main): release protocol/go 0.2.21 (#1732) :robot: I have created a release *beep* *boop* --- ## [0.2.21](https://github.com/opentdf/platform/compare/protocol/go/v0.2.20...protocol/go/v0.2.21) (2024-11-13) ### Features * backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) * **policy:** subject condition sets prune service/db ([#1688](https://github.com/opentdf/platform/issues/1688)) ([3cdd1b2](https://github.com/opentdf/platform/commit/3cdd1b26e81cb004b02af44e914baef3422cdcde)), closes [#1178](https://github.com/opentdf/platform/issues/1178) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- protocol/go/CHANGELOG.md | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 54ab6d67b..2749648ef 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -2,7 +2,7 @@ "lib/fixtures": "0.2.7", "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", - "protocol/go": "0.2.20", + "protocol/go": "0.2.21", "sdk": "0.3.19", "service": "0.4.26" } diff --git a/protocol/go/CHANGELOG.md b/protocol/go/CHANGELOG.md index be777dd86..1823dc882 100644 --- a/protocol/go/CHANGELOG.md +++ b/protocol/go/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.2.21](https://github.com/opentdf/platform/compare/protocol/go/v0.2.20...protocol/go/v0.2.21) (2024-11-13) + + +### Features + +* backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) +* **policy:** subject condition sets prune service/db ([#1688](https://github.com/opentdf/platform/issues/1688)) ([3cdd1b2](https://github.com/opentdf/platform/commit/3cdd1b26e81cb004b02af44e914baef3422cdcde)), closes [#1178](https://github.com/opentdf/platform/issues/1178) + ## [0.2.20](https://github.com/opentdf/platform/compare/protocol/go/v0.2.19...protocol/go/v0.2.20) (2024-11-05) From 4c36b1775a1edc0cfb1801c5d8dbbe204d4665f1 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:17:46 -0500 Subject: [PATCH 09/32] chore(main): release lib/fixtures 0.2.8 (#1742) :robot: I have created a release *beep* *boop* --- ## [0.2.8](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.7...lib/fixtures/v0.2.8) (2024-11-13) ### Features * **authz:** Remove org-admin role, move privileges to admin role ([#1740](https://github.com/opentdf/platform/issues/1740)) ([ae931d0](https://github.com/opentdf/platform/commit/ae931d02f347edea468d4c5d48ab3e07ce7d3abe)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- lib/fixtures/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2749648ef..833c2d3aa 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,5 @@ { - "lib/fixtures": "0.2.7", + "lib/fixtures": "0.2.8", "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", "protocol/go": "0.2.21", diff --git a/lib/fixtures/CHANGELOG.md b/lib/fixtures/CHANGELOG.md index ef86fb4a1..651114023 100644 --- a/lib/fixtures/CHANGELOG.md +++ b/lib/fixtures/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.8](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.7...lib/fixtures/v0.2.8) (2024-11-13) + + +### Features + +* **authz:** Remove org-admin role, move privileges to admin role ([#1740](https://github.com/opentdf/platform/issues/1740)) ([ae931d0](https://github.com/opentdf/platform/commit/ae931d02f347edea468d4c5d48ab3e07ce7d3abe)) + ## [0.2.7](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.6...lib/fixtures/v0.2.7) (2024-06-20) From fb50a431cde8691c670c2bf457c0545c89f278f9 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 20:39:41 +0000 Subject: [PATCH 10/32] fix(core): Autobump sdk (#1747) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- sdk/go.mod | 2 +- sdk/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/go.mod b/sdk/go.mod index e1b58e218..d585865c1 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -7,7 +7,7 @@ require ( github.com/gowebpki/jcs v1.0.1 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/lestrrat-go/jwx/v2 v2.0.21 - github.com/opentdf/platform/lib/fixtures v0.2.7 + github.com/opentdf/platform/lib/fixtures v0.2.8 github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 github.com/stretchr/testify v1.9.0 diff --git a/sdk/go.sum b/sdk/go.sum index d798e5c6a..a30c7e1b6 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -109,8 +109,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opentdf/platform/lib/fixtures v0.2.7 h1:2LxWmLBBISONVJnVDH8yMsV72VHQyirua0DwDBBoq+g= -github.com/opentdf/platform/lib/fixtures v0.2.7/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= +github.com/opentdf/platform/lib/fixtures v0.2.8 h1:lGYrMnbORtU62lxsJi8qPsxjFuNIkc4Dop8rVkH6pD0= +github.com/opentdf/platform/lib/fixtures v0.2.8/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+jbJXRRk4LcxII= github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= From a88fb67219c572cc383b6c0239e5b6a1442bb53b Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:01:42 +0000 Subject: [PATCH 11/32] chore(main): release sdk 0.3.20 (#1743) :robot: I have created a release *beep* *boop* --- ## [0.3.20](https://github.com/opentdf/platform/compare/sdk/v0.3.19...sdk/v0.3.20) (2024-11-13) ### Features * backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) ### Bug Fixes * **core:** Autobump sdk ([#1747](https://github.com/opentdf/platform/issues/1747)) ([fb50a43](https://github.com/opentdf/platform/commit/fb50a431cde8691c670c2bf457c0545c89f278f9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- sdk/CHANGELOG.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 833c2d3aa..f56d481af 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -3,6 +3,6 @@ "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", "protocol/go": "0.2.21", - "sdk": "0.3.19", + "sdk": "0.3.20", "service": "0.4.26" } diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 1ada8b556..4a13ce040 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.3.20](https://github.com/opentdf/platform/compare/sdk/v0.3.19...sdk/v0.3.20) (2024-11-13) + + +### Features + +* backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) + + +### Bug Fixes + +* **core:** Autobump sdk ([#1747](https://github.com/opentdf/platform/issues/1747)) ([fb50a43](https://github.com/opentdf/platform/commit/fb50a431cde8691c670c2bf457c0545c89f278f9)) + ## [0.3.19](https://github.com/opentdf/platform/compare/sdk/v0.3.18...sdk/v0.3.19) (2024-11-12) From 4b239b1f288121ec224038aff7534d4b5329c22d Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:29:15 -0500 Subject: [PATCH 12/32] fix(core): Autobump service (#1750) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- service/go.mod | 4 ++-- service/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/service/go.mod b/service/go.mod index 2d40f174f..fbecf5275 100644 --- a/service/go.mod +++ b/service/go.mod @@ -20,11 +20,11 @@ require ( github.com/jackc/pgx/v5 v5.5.5 github.com/lestrrat-go/jwx/v2 v2.0.21 github.com/open-policy-agent/opa v0.68.0 - github.com/opentdf/platform/lib/fixtures v0.2.7 + github.com/opentdf/platform/lib/fixtures v0.2.8 github.com/opentdf/platform/lib/flattening v0.1.1 github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 - github.com/opentdf/platform/sdk v0.3.19 + github.com/opentdf/platform/sdk v0.3.20 github.com/pressly/goose/v3 v3.19.1 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.18.2 diff --git a/service/go.sum b/service/go.sum index 90c89d2ac..d024bf739 100644 --- a/service/go.sum +++ b/service/go.sum @@ -272,16 +272,16 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= -github.com/opentdf/platform/lib/fixtures v0.2.7 h1:2LxWmLBBISONVJnVDH8yMsV72VHQyirua0DwDBBoq+g= -github.com/opentdf/platform/lib/fixtures v0.2.7/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= +github.com/opentdf/platform/lib/fixtures v0.2.8 h1:lGYrMnbORtU62lxsJi8qPsxjFuNIkc4Dop8rVkH6pD0= +github.com/opentdf/platform/lib/fixtures v0.2.8/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= github.com/opentdf/platform/lib/flattening v0.1.1 h1:la1f6PcRsc+yLH8+9UEr0ux6IRKu+6+oMaMVt05+8HU= github.com/opentdf/platform/lib/flattening v0.1.1/go.mod h1:eyG7pe5UZlV+GI5/CymQD3xTAJxNhnP9M4QnBzaad1M= github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+jbJXRRk4LcxII= github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= -github.com/opentdf/platform/sdk v0.3.19 h1:4Ign6HPrxOH6ZllLO/cI6joSuqz8CqPlpxpTKunpMQs= -github.com/opentdf/platform/sdk v0.3.19/go.mod h1:u+XZhVRsMq5blukCFCHcjk6HLCp4Y5mmIQu7GhtKQ3E= +github.com/opentdf/platform/sdk v0.3.20 h1:zyBAZLhQaIv4X2twyPbmbdBd9Vc1vsTwxr1BIuESJWg= +github.com/opentdf/platform/sdk v0.3.20/go.mod h1:O4tyqjK9sJwp+6jUeiJjECe9TQfqaD1kTr6wgsRxkWc= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= From acea8d1dbbc037458e6974376a609e064a238931 Mon Sep 17 00:00:00 2001 From: Sean Trantalis Date: Thu, 14 Nov 2024 09:06:54 -0500 Subject: [PATCH 13/32] fix: cleanup left over status.Error in favor of connect.NewError (#1751) ### Proposed Changes * ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- service/health/health.go | 8 ++++---- service/internal/auth/authn.go | 11 +++++------ service/internal/auth/authn_test.go | 5 ++++- service/kas/access/publicKey.go | 4 +--- .../wellknownconfiguration/wellknown_configuration.go | 5 ++--- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/service/health/health.go b/service/health/health.go index 01489f3a7..d8123bdc5 100644 --- a/service/health/health.go +++ b/service/health/health.go @@ -2,14 +2,14 @@ package health import ( "context" + "errors" "log/slog" + "connectrpc.com/connect" "connectrpc.com/grpchealth" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" - "google.golang.org/grpc/codes" healthpb "google.golang.org/grpc/health/grpc_health_v1" - "google.golang.org/grpc/status" ) var serviceHealthChecks = make(map[string]func(context.Context) error) @@ -75,12 +75,12 @@ func (s HealthService) Check(ctx context.Context, req *grpchealth.CheckRequest) } func (s HealthService) Watch(_ *healthpb.HealthCheckRequest, _ healthpb.Health_WatchServer) error { - return status.Error(codes.Unimplemented, "unimplemented") + return connect.NewError(connect.CodeUnimplemented, errors.New("unimplemented")) } func RegisterReadinessCheck(namespace string, service func(context.Context) error) error { if _, ok := serviceHealthChecks[namespace]; ok { - return status.Error(codes.AlreadyExists, "readiness check already registered") + return errors.New("readiness check already registered") } serviceHealthChecks[namespace] = service diff --git a/service/internal/auth/authn.go b/service/internal/auth/authn.go index 556ecdaa8..31f9991b3 100644 --- a/service/internal/auth/authn.go +++ b/service/internal/auth/authn.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" + "errors" "fmt" "log/slog" "net/http" @@ -23,8 +24,6 @@ import ( sdkAudit "github.com/opentdf/platform/sdk/audit" "github.com/opentdf/platform/service/logger" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) const ( @@ -279,7 +278,7 @@ func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptor header := req.Header()["Authorization"] if len(header) < 1 { - return nil, status.Error(codes.Unauthenticated, "missing authorization header") + return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("missing authorization header")) } // parse the rpc method @@ -297,19 +296,19 @@ func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptor req.Header()["Dpop"], ) if err != nil { - return nil, status.Errorf(codes.Unauthenticated, "unauthenticated") + return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated")) } // Check if the token is allowed to access the resource if allowed, err := a.enforcer.Enforce(token, resource, action); err != nil { if err.Error() == "permission denied" { a.logger.Warn("permission denied", slog.String("azp", token.Subject()), slog.String("error", err.Error())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") + return nil, connect.NewError(connect.CodePermissionDenied, errors.New("permission denied")) } return nil, err } else if !allowed { a.logger.Warn("permission denied", slog.String("azp", token.Subject())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") + return nil, connect.NewError(connect.CodePermissionDenied, errors.New("permission denied")) } return next(newCtx, req) diff --git a/service/internal/auth/authn_test.go b/service/internal/auth/authn_test.go index a7d5ed86a..841458cf7 100644 --- a/service/internal/auth/authn_test.go +++ b/service/internal/auth/authn_test.go @@ -243,7 +243,10 @@ func (s *AuthSuite) Test_UnaryServerInterceptor_When_Authorization_Header_Missin })(context.Background(), req) s.Require().Error(err) - s.Require().ErrorIs(err, status.Error(codes.Unauthenticated, "missing authorization header")) + + connectErr := connect.NewError(connect.CodeUnauthenticated, errors.New("missing authorization header")) + + s.Require().ErrorAs(err, &connectErr) } func (s *AuthSuite) Test_CheckToken_When_Authorization_Header_Invalid_Expect_Error() { diff --git a/service/kas/access/publicKey.go b/service/kas/access/publicKey.go index ca810c53c..080d12de5 100644 --- a/service/kas/access/publicKey.go +++ b/service/kas/access/publicKey.go @@ -11,8 +11,6 @@ import ( "connectrpc.com/connect" kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/service/internal/security" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -116,7 +114,7 @@ func (p Provider) PublicKey(ctx context.Context, req *connect.Request[kaspb.Publ return r(rsaPublicKeyPem, kid, err) } } - return nil, status.Error(codes.NotFound, "invalid algorithm or format") + return nil, connect.NewError(connect.CodeNotFound, errors.New("invalid algorithm or format")) } func exportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) { diff --git a/service/wellknownconfiguration/wellknown_configuration.go b/service/wellknownconfiguration/wellknown_configuration.go index 88a096688..3aae42846 100644 --- a/service/wellknownconfiguration/wellknown_configuration.go +++ b/service/wellknownconfiguration/wellknown_configuration.go @@ -2,6 +2,7 @@ package wellknownconfiguration import ( "context" + "errors" "fmt" "log/slog" "sync" @@ -11,8 +12,6 @@ import ( "github.com/opentdf/platform/protocol/go/wellknownconfiguration/wellknownconfigurationconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/structpb" ) @@ -56,7 +55,7 @@ func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *connec rwMutex.RUnlock() if err != nil { s.logger.Error("failed to create struct for wellknown configuration", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to create struct for wellknown configuration") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to create struct for wellknown configuration")) } rsp := &wellknown.GetWellKnownConfigurationResponse{ From 94a38fbd7e06d31fbcfddb0e9c65ae5652872c1a Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:05:49 -0500 Subject: [PATCH 14/32] chore(main): release service 0.4.27 (#1670) :robot: I have created a release *beep* *boop* --- ## [0.4.27](https://github.com/opentdf/platform/compare/service/v0.4.26...service/v0.4.27) (2024-11-14) ### Features * **authz:** JWT ERS that just returns claims ([#1630](https://github.com/opentdf/platform/issues/1630)) ([316b5be](https://github.com/opentdf/platform/commit/316b5be042d9723b19ad5fdbc02f3ffdbc3764c2)) * **authz:** Remove org-admin role, move privileges to admin role ([#1740](https://github.com/opentdf/platform/issues/1740)) ([ae931d0](https://github.com/opentdf/platform/commit/ae931d02f347edea468d4c5d48ab3e07ce7d3abe)) * backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) * connectrpc realip interceptor ([#1728](https://github.com/opentdf/platform/issues/1728)) ([292fca0](https://github.com/opentdf/platform/commit/292fca06441b1587edb9c64f324eb87dc0b88c5f)) * **docs:** add policy ADR for LIST limit and pagination ([#1557](https://github.com/opentdf/platform/issues/1557)) ([069f939](https://github.com/opentdf/platform/commit/069f939923cb3570c1e62453f68022a0b9c3e544)) * move from fasthttp in-memory listener to memhttp implementation ([#1709](https://github.com/opentdf/platform/issues/1709)) ([70518ff](https://github.com/opentdf/platform/commit/70518ff6da81fda1c61452968ed4c0615e4702b9)) * **policy:** 1603 policy improve upsertattrfqn ([#1679](https://github.com/opentdf/platform/issues/1679)) ([cd17a44](https://github.com/opentdf/platform/commit/cd17a44c3fdb7d510cb9e1fb744a1b12fe1e346e)) * **policy:** 1651 move GetAttributesByValueFqns RPC request validation to protovalidate ([#1657](https://github.com/opentdf/platform/issues/1657)) ([c7d6b15](https://github.com/opentdf/platform/commit/c7d6b1542c10d3e2a35fa00efaf7d415f63c7dca)) * **policy:** 1659 spike on transactions support ([#1678](https://github.com/opentdf/platform/issues/1678)) ([a6fea11](https://github.com/opentdf/platform/commit/a6fea11070f18b7136f47fe87d4fe2020189efb8)) * **policy:** add optional name field to registered KASes in policy ([#1636](https://github.com/opentdf/platform/issues/1636)) ([f1382c1](https://github.com/opentdf/platform/commit/f1382c16893cefd40e930f4112ac7a61c9b05898)) * **policy:** add optional name field to registered KASes in policy ([#1641](https://github.com/opentdf/platform/issues/1641)) ([b277ab4](https://github.com/opentdf/platform/commit/b277ab4cb4fa9aca343fa14d1751f4dff3ea3e23)) * **policy:** limit/offset throughout LIST protos/gencode ([#1668](https://github.com/opentdf/platform/issues/1668)) ([7de6cce](https://github.com/opentdf/platform/commit/7de6cce5c9603228bc0ef5566b5b2d10c4a12ee4)) * **policy:** SPIKE transactions support ([#1663](https://github.com/opentdf/platform/issues/1663)) ([866f4f3](https://github.com/opentdf/platform/commit/866f4f364991c55cad75be79c55adab013a25ead)) * **policy:** subject condition sets prune protos/gencode ([#1687](https://github.com/opentdf/platform/issues/1687)) ([a627e02](https://github.com/opentdf/platform/commit/a627e021e9df2c06e1c86acfc0a4ee83c4bce932)) * **policy:** subject condition sets prune service/db ([#1688](https://github.com/opentdf/platform/issues/1688)) ([3cdd1b2](https://github.com/opentdf/platform/commit/3cdd1b26e81cb004b02af44e914baef3422cdcde)), closes [#1178](https://github.com/opentdf/platform/issues/1178) * update service registry in preperation for connectrpc migration ([#1715](https://github.com/opentdf/platform/issues/1715)) ([ce289a4](https://github.com/opentdf/platform/commit/ce289a44505e5e3be995e5049f5cbbfb1839f41b)) ### Bug Fixes * cleanup left over status.Error in favor of connect.NewError ([#1751](https://github.com/opentdf/platform/issues/1751)) ([acea8d1](https://github.com/opentdf/platform/commit/acea8d1dbbc037458e6974376a609e064a238931)) * **core:** Autobump service ([#1726](https://github.com/opentdf/platform/issues/1726)) ([39a898d](https://github.com/opentdf/platform/commit/39a898d3d7c45c48187ed54e67519d953d5e3d0c)) * **core:** Autobump service ([#1739](https://github.com/opentdf/platform/issues/1739)) ([46662a7](https://github.com/opentdf/platform/commit/46662a791aa5c26ff6b363e773d74c1e7a89614c)) * **core:** Autobump service ([#1750](https://github.com/opentdf/platform/issues/1750)) ([4b239b1](https://github.com/opentdf/platform/commit/4b239b1f288121ec224038aff7534d4b5329c22d)) * Fixtures CodeQL alert for potentially unsafe quoting ([#1703](https://github.com/opentdf/platform/issues/1703)) ([6f2fa9b](https://github.com/opentdf/platform/commit/6f2fa9b49ae59ca22eedd4b41df02a2bc5fe687d)) * **kas:** Only hit authorization if data attributes not empty ([#1741](https://github.com/opentdf/platform/issues/1741)) ([471f5f1](https://github.com/opentdf/platform/commit/471f5f102e7a4e01abaff6fa2750ad784880274b)) * **policy:** enhance proto validation across policy requests ([#1656](https://github.com/opentdf/platform/issues/1656)) ([df534c4](https://github.com/opentdf/platform/commit/df534c40f3f500190b200923e5157701b438431b)) * **policy:** make MatchSubjectMappings operator agnostic ([#1658](https://github.com/opentdf/platform/issues/1658)) ([cb63819](https://github.com/opentdf/platform/commit/cb63819d107ed65cb5d467a956d713bd55214cdb)) * **policy:** REVERT PR [#1663](https://github.com/opentdf/platform/issues/1663) - SPIKE transactions support ([#1719](https://github.com/opentdf/platform/issues/1719)) ([184a733](https://github.com/opentdf/platform/commit/184a733154943abab7fd2a3715dc25b63dfa622e)) * **policy:** schema markdown links should work ([#1672](https://github.com/opentdf/platform/issues/1672)) ([4122262](https://github.com/opentdf/platform/commit/412226296d579f1d9cb52f149a5e4b629a7f7908)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- service/CHANGELOG.md | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f56d481af..d56bee437 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,5 +4,5 @@ "lib/flattening": "0.1.1", "protocol/go": "0.2.21", "sdk": "0.3.20", - "service": "0.4.26" + "service": "0.4.27" } diff --git a/service/CHANGELOG.md b/service/CHANGELOG.md index b7613a009..1c55a721b 100644 --- a/service/CHANGELOG.md +++ b/service/CHANGELOG.md @@ -1,5 +1,41 @@ # Changelog +## [0.4.27](https://github.com/opentdf/platform/compare/service/v0.4.26...service/v0.4.27) (2024-11-14) + + +### Features + +* **authz:** JWT ERS that just returns claims ([#1630](https://github.com/opentdf/platform/issues/1630)) ([316b5be](https://github.com/opentdf/platform/commit/316b5be042d9723b19ad5fdbc02f3ffdbc3764c2)) +* **authz:** Remove org-admin role, move privileges to admin role ([#1740](https://github.com/opentdf/platform/issues/1740)) ([ae931d0](https://github.com/opentdf/platform/commit/ae931d02f347edea468d4c5d48ab3e07ce7d3abe)) +* backend migration to connect-rpc ([#1733](https://github.com/opentdf/platform/issues/1733)) ([d10ba3c](https://github.com/opentdf/platform/commit/d10ba3cb22175a000ba5d156987c9f201749ae88)) +* connectrpc realip interceptor ([#1728](https://github.com/opentdf/platform/issues/1728)) ([292fca0](https://github.com/opentdf/platform/commit/292fca06441b1587edb9c64f324eb87dc0b88c5f)) +* **docs:** add policy ADR for LIST limit and pagination ([#1557](https://github.com/opentdf/platform/issues/1557)) ([069f939](https://github.com/opentdf/platform/commit/069f939923cb3570c1e62453f68022a0b9c3e544)) +* move from fasthttp in-memory listener to memhttp implementation ([#1709](https://github.com/opentdf/platform/issues/1709)) ([70518ff](https://github.com/opentdf/platform/commit/70518ff6da81fda1c61452968ed4c0615e4702b9)) +* **policy:** 1603 policy improve upsertattrfqn ([#1679](https://github.com/opentdf/platform/issues/1679)) ([cd17a44](https://github.com/opentdf/platform/commit/cd17a44c3fdb7d510cb9e1fb744a1b12fe1e346e)) +* **policy:** 1651 move GetAttributesByValueFqns RPC request validation to protovalidate ([#1657](https://github.com/opentdf/platform/issues/1657)) ([c7d6b15](https://github.com/opentdf/platform/commit/c7d6b1542c10d3e2a35fa00efaf7d415f63c7dca)) +* **policy:** 1659 spike on transactions support ([#1678](https://github.com/opentdf/platform/issues/1678)) ([a6fea11](https://github.com/opentdf/platform/commit/a6fea11070f18b7136f47fe87d4fe2020189efb8)) +* **policy:** add optional name field to registered KASes in policy ([#1636](https://github.com/opentdf/platform/issues/1636)) ([f1382c1](https://github.com/opentdf/platform/commit/f1382c16893cefd40e930f4112ac7a61c9b05898)) +* **policy:** add optional name field to registered KASes in policy ([#1641](https://github.com/opentdf/platform/issues/1641)) ([b277ab4](https://github.com/opentdf/platform/commit/b277ab4cb4fa9aca343fa14d1751f4dff3ea3e23)) +* **policy:** limit/offset throughout LIST protos/gencode ([#1668](https://github.com/opentdf/platform/issues/1668)) ([7de6cce](https://github.com/opentdf/platform/commit/7de6cce5c9603228bc0ef5566b5b2d10c4a12ee4)) +* **policy:** SPIKE transactions support ([#1663](https://github.com/opentdf/platform/issues/1663)) ([866f4f3](https://github.com/opentdf/platform/commit/866f4f364991c55cad75be79c55adab013a25ead)) +* **policy:** subject condition sets prune protos/gencode ([#1687](https://github.com/opentdf/platform/issues/1687)) ([a627e02](https://github.com/opentdf/platform/commit/a627e021e9df2c06e1c86acfc0a4ee83c4bce932)) +* **policy:** subject condition sets prune service/db ([#1688](https://github.com/opentdf/platform/issues/1688)) ([3cdd1b2](https://github.com/opentdf/platform/commit/3cdd1b26e81cb004b02af44e914baef3422cdcde)), closes [#1178](https://github.com/opentdf/platform/issues/1178) +* update service registry in preperation for connectrpc migration ([#1715](https://github.com/opentdf/platform/issues/1715)) ([ce289a4](https://github.com/opentdf/platform/commit/ce289a44505e5e3be995e5049f5cbbfb1839f41b)) + + +### Bug Fixes + +* cleanup left over status.Error in favor of connect.NewError ([#1751](https://github.com/opentdf/platform/issues/1751)) ([acea8d1](https://github.com/opentdf/platform/commit/acea8d1dbbc037458e6974376a609e064a238931)) +* **core:** Autobump service ([#1726](https://github.com/opentdf/platform/issues/1726)) ([39a898d](https://github.com/opentdf/platform/commit/39a898d3d7c45c48187ed54e67519d953d5e3d0c)) +* **core:** Autobump service ([#1739](https://github.com/opentdf/platform/issues/1739)) ([46662a7](https://github.com/opentdf/platform/commit/46662a791aa5c26ff6b363e773d74c1e7a89614c)) +* **core:** Autobump service ([#1750](https://github.com/opentdf/platform/issues/1750)) ([4b239b1](https://github.com/opentdf/platform/commit/4b239b1f288121ec224038aff7534d4b5329c22d)) +* Fixtures CodeQL alert for potentially unsafe quoting ([#1703](https://github.com/opentdf/platform/issues/1703)) ([6f2fa9b](https://github.com/opentdf/platform/commit/6f2fa9b49ae59ca22eedd4b41df02a2bc5fe687d)) +* **kas:** Only hit authorization if data attributes not empty ([#1741](https://github.com/opentdf/platform/issues/1741)) ([471f5f1](https://github.com/opentdf/platform/commit/471f5f102e7a4e01abaff6fa2750ad784880274b)) +* **policy:** enhance proto validation across policy requests ([#1656](https://github.com/opentdf/platform/issues/1656)) ([df534c4](https://github.com/opentdf/platform/commit/df534c40f3f500190b200923e5157701b438431b)) +* **policy:** make MatchSubjectMappings operator agnostic ([#1658](https://github.com/opentdf/platform/issues/1658)) ([cb63819](https://github.com/opentdf/platform/commit/cb63819d107ed65cb5d467a956d713bd55214cdb)) +* **policy:** REVERT PR [#1663](https://github.com/opentdf/platform/issues/1663) - SPIKE transactions support ([#1719](https://github.com/opentdf/platform/issues/1719)) ([184a733](https://github.com/opentdf/platform/commit/184a733154943abab7fd2a3715dc25b63dfa622e)) +* **policy:** schema markdown links should work ([#1672](https://github.com/opentdf/platform/issues/1672)) ([4122262](https://github.com/opentdf/platform/commit/412226296d579f1d9cb52f149a5e4b629a7f7908)) + ## [0.4.26](https://github.com/opentdf/platform/compare/service/v0.4.25...service/v0.4.26) (2024-10-17) From 6497bf3a7cee9b6900569bc6cc2c39b2f647fb52 Mon Sep 17 00:00:00 2001 From: dominic reed Date: Thu, 14 Nov 2024 09:37:59 -0800 Subject: [PATCH 15/32] feat(sdk): add collections for nanotdf (#1695) Adds in Datasets for NanoTDF. If dataset store is enabled in SDK, nanoTDF headers will be saved with their unwrapped key, so future nanoTDFs can be decrypted without extra rewrap calls. NanoTDFs will be able to be written in a dataset in the NanoTDFConfig, allowing for flexible usage of datasets. #### Example Local Run To run a quick example collection locally. This will write two collections with 50 nTDFs with the plaintext being changed to `: `. Decrypt will decrypt the two collections and will only do two unwrap calls rather than 100 for each nTDF. ``` mkdir collection go run ./examples encrypt "Collection A" --nano -c 50 -o collection/collection_a.ntdf go run ./examples encrypt "Collection B" --nano -c 50 -o collection/collection_b.ntdf go run ./examples decrypt collection ``` --- examples/cmd/decrypt.go | 28 ++++- examples/cmd/encrypt.go | 56 +++++++--- examples/cmd/examples.go | 4 +- examples/go.mod | 37 ++++--- examples/go.sum | 121 ++++++---------------- go.work.sum | 29 +++++- lib/fixtures/go.mod | 10 +- lib/fixtures/go.sum | 23 ++--- lib/flattening/go.mod | 7 +- lib/flattening/go.sum | 11 +- lib/ocrypto/go.mod | 9 +- lib/ocrypto/go.sum | 14 +-- protocol/go/go.mod | 17 ++- protocol/go/go.sum | 27 ++--- sdk/go.mod | 63 +++++------ sdk/go.sum | 110 +++++++------------- sdk/nanotdf.go | 218 +++++++++++++++++++++++++++++++-------- sdk/nanotdf_config.go | 28 +++-- sdk/nanotdf_test.go | 69 +++++++++++++ sdk/options.go | 8 ++ sdk/sdk.go | 6 ++ service/go.mod | 2 + service/go.sum | 5 +- 23 files changed, 554 insertions(+), 348 deletions(-) diff --git a/examples/cmd/decrypt.go b/examples/cmd/decrypt.go index 7b425207b..84f9de378 100644 --- a/examples/cmd/decrypt.go +++ b/examples/cmd/decrypt.go @@ -3,10 +3,11 @@ package cmd import ( "bytes" "errors" + "fmt" + "github.com/spf13/cobra" "io" "os" - - "github.com/spf13/cobra" + "path/filepath" ) func init() { @@ -31,6 +32,29 @@ func decrypt(cmd *cobra.Command, args []string) error { if err != nil { return err } + // Collection + if stat, err := os.Stat(tdfFile); err == nil && stat.IsDir() { + entries, err := os.ReadDir(tdfFile) + if err != nil { + return err + } + for _, entry := range entries { + if !entry.IsDir() { + f, err := os.Open(filepath.Join(tdfFile, entry.Name())) + if err != nil { + return err + } + _, err = client.ReadNanoTDF(os.Stdout, f) + fmt.Println() + if err != nil { + return err + } + } + } + client.Close() + return nil + } + file, err := os.Open(tdfFile) if err != nil { return err diff --git a/examples/cmd/encrypt.go b/examples/cmd/encrypt.go index f57841acb..fdf242792 100644 --- a/examples/cmd/encrypt.go +++ b/examples/cmd/encrypt.go @@ -4,7 +4,9 @@ import ( "bytes" "encoding/json" "fmt" + "io" "os" + "path/filepath" "strings" "github.com/opentdf/platform/lib/ocrypto" @@ -20,6 +22,7 @@ var ( noKIDInNano bool outputName string dataAttributes []string + collection int ) func init() { @@ -35,6 +38,7 @@ func init() { encryptCmd.Flags().BoolVar(&noKIDInKAO, "no-kid-in-kao", false, "[deprecated] Disable storing key identifiers in TDF KAOs") encryptCmd.Flags().BoolVar(&noKIDInNano, "no-kid-in-nano", true, "Disable storing key identifiers in nanoTDF KAS ResourceLocator") encryptCmd.Flags().StringVarP(&outputName, "output", "o", "sensitive.txt.tdf", "name or path of output file; - for stdout") + encryptCmd.Flags().IntVarP(&collection, "collection", "c", 0, "number of nano's to create for collection. If collection >0 (default) then output will be <iteration>_<output>") ExamplesCmd.AddCommand(&encryptCmd) } @@ -50,7 +54,6 @@ func encrypt(cmd *cobra.Command, args []string) error { opts := []sdk.Option{ sdk.WithInsecurePlaintextConn(), sdk.WithClientCredentials("opentdf-sdk", "secret", nil), - sdk.WithTokenEndpoint("http://localhost:8888/auth/realms/opentdf/protocol/openid-connect/token"), } if noKIDInKAO { @@ -68,17 +71,32 @@ func encrypt(cmd *cobra.Command, args []string) error { } out := os.Stdout - if outputName != "-" { - out, err = os.Create(outputName) - if err != nil { - return err - } + if outputName == "-" && collection > 0 { + return fmt.Errorf("cannot use stdout for collection") } - defer func() { - if outputName != "-" { - out.Close() + + var writer []io.Writer + if outputName == "-" { + writer = append(writer, out) + } else { + dir, file := filepath.Split(outputName) + for i := 0; i < collection; i++ { + out, err = os.Create(filepath.Join(dir, fmt.Sprintf("%d_%s", i, file))) + if err != nil { + return err + } + writer = append(writer, out) + defer out.Close() + } + if collection == 0 { + out, err = os.Create(outputName) + writer = append(writer, out) + defer out.Close() + if err != nil { + return err + } } - }() + } if !nanoFormat { opts := []sdk.TDFOption{sdk.WithDataAttributes(dataAttributes...)} @@ -108,17 +126,27 @@ func encrypt(cmd *cobra.Command, args []string) error { } nanoTDFConfig.SetAttributes(dataAttributes) nanoTDFConfig.EnableECDSAPolicyBinding() + if collection > 0 { + nanoTDFConfig.EnableCollection() + } err = nanoTDFConfig.SetKasURL(fmt.Sprintf("http://%s/kas", platformEndpoint)) if err != nil { return err } + for i, writer := range writer { + input := plainText + if collection > 0 { + input = fmt.Sprintf("%d: %s", i, plainText) + } + in = strings.NewReader(input) + _, err = client.CreateNanoTDF(writer, in, *nanoTDFConfig) + if err != nil { + return err - _, err = client.CreateNanoTDF(out, in, *nanoTDFConfig) - if err != nil { - return err + } } - if outputName != "-" { + if outputName != "-" && collection == 0 { err = cat(cmd, outputName) if err != nil { return err diff --git a/examples/cmd/examples.go b/examples/cmd/examples.go index e9b3523bc..94c0c885b 100644 --- a/examples/cmd/examples.go +++ b/examples/cmd/examples.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "google.golang.org/grpc/resolver" "log" "os" "strings" @@ -28,7 +29,8 @@ func init() { } func newSDK() (*sdk.SDK, error) { - opts := []sdk.Option{sdk.WithInsecurePlaintextConn()} + resolver.SetDefaultScheme("passthrough") + opts := []sdk.Option{sdk.WithStoreCollectionHeaders(), sdk.WithInsecurePlaintextConn()} if clientCredentials != "" { i := strings.Index(clientCredentials, ":") if i < 0 { diff --git a/examples/go.mod b/examples/go.mod index 86f7874c8..a72d964ea 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -6,21 +6,25 @@ require ( github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 github.com/opentdf/platform/sdk v0.3.19 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 + google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/containerd/containerd v1.7.21 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/goccy/go-json v0.10.3 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gowebpki/jcs v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.5 // indirect @@ -31,17 +35,18 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/testcontainers/testcontainers-go v0.32.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect - google.golang.org/grpc v1.62.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/go.sum b/examples/go.sum index 432e075d7..cf903079f 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,58 +1,46 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 h1:0nWhrRcnkgw1kwJ7xibIO8bqfOA7pBzBjGCDBxIHch8= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 h1:LEXWFH/xZ5oOWrC3oOtHbUyBdzRWMCPpAQmKC9v05mA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 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/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= -github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= 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= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= -github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= 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/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.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 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-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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= 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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -62,12 +50,10 @@ 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.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= 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= @@ -88,12 +74,13 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= 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/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= 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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -133,8 +120,7 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -144,8 +130,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= -github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= 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/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -157,70 +142,24 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo 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= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -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.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -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/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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 h1:oqta3O3AnlWbmIE3bFnWbu4bRxZjfbWCp0cKSuZh01E= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 h1:8EeVk1VKMD+GD/neyEHGmz7pFblqPjHoi+PGQIlLx2s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.work.sum b/go.work.sum index 3b76f7b56..56b8c8a32 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,7 +1,9 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 h1:SRsZGA7aFnCZETmov57jwPrWuTmaZK6+4R4v5FUe1/c= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= +buf.build/gen/go/bufbuild/protovalidate-testing/protocolbuffers/go v1.31.0-20230824200732-8bc04916caea.1 h1:wWsaA01KC5hgoW4oHFiGzEqMmgcE7UyU43F8AJrex1U= buf.build/gen/go/bufbuild/protovalidate-testing/protocolbuffers/go v1.31.0-20230824200732-8bc04916caea.1/go.mod h1:cJ4gQkiW4uPTUTI3+O2862OzMSTnzrFNwMauHLwPDPg= +cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -29,6 +31,7 @@ cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go/accessapproval v1.7.4/go.mod h1:/aTEh45LzplQgFYdQdwPMR9YdX0UlhBmvB84uAmQKUc= cloud.google.com/go/accessapproval v1.7.5 h1:uzmAMSgYcnlHa9X9YSQZ4Q1wlfl4NNkZyQgho1Z6p04= @@ -112,9 +115,11 @@ cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdi cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= @@ -348,6 +353,7 @@ cloud.google.com/go/shell v1.7.4/go.mod h1:yLeXB8eKLxw0dpEmXQ/FjriYrBijNsONpwnWs cloud.google.com/go/shell v1.7.5 h1:3Fq2hzO0ZSyaqBboJrFkwwf/qMufDtqwwA6ep8EZxEI= cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE= cloud.google.com/go/spanner v1.55.0/go.mod h1:HXEznMUVhC+PC+HDyo9YFG2Ajj5BQDkcbqB9Z2Ffxi0= +cloud.google.com/go/spanner v1.56.0 h1:o/Cv7/zZ1WgRXVCd5g3Nc23ZI39p/1pWFqFwvg6Wcu8= cloud.google.com/go/spanner v1.56.0/go.mod h1:DndqtUKQAt3VLuV2Le+9Y3WTnq5cNKrnLb/Piqcj+h0= cloud.google.com/go/spanner v1.57.0 h1:fJq+ZfQUDHE+cy1li0bJA8+sy2oiSGhuGqN5nqVaZdU= cloud.google.com/go/spanner v1.57.0/go.mod h1:aXQ5QDdhPRIqVhYmnkAdwPYvj/DRN0FguclhEWw+jOo= @@ -365,6 +371,7 @@ cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYE cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storage v1.37.0 h1:WI8CsaFO8Q9KjPVtsZ5Cmi0dXV25zMoX0FklT7c3Jm4= cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k= +cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= cloud.google.com/go/storagetransfer v1.10.3/go.mod h1:Up8LY2p6X68SZ+WToswpQbQHnJpOty/ACcMafuey8gc= cloud.google.com/go/storagetransfer v1.10.4 h1:dy4fL3wO0VABvzM05ycMUPFHxTPbJz9Em8ikAJVqSbI= @@ -521,9 +528,11 @@ github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwc github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/apache/arrow/go/v12 v12.0.1 h1:JsR2+hzYYjgSUkBSaahpqCetqZMr76djX80fF/DiJbg= github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWMLpY67QwZ/WWw= github.com/apache/arrow/go/v14 v14.0.2 h1:N8OkaJEOfI3mEZt07BIkvo4sC6XDbL+48MBPWO5IONw= github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= +github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -623,6 +632,7 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= @@ -687,6 +697,7 @@ github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2 github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc= github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -753,6 +764,7 @@ github.com/containerd/ttrpc v1.2.3 h1:4jlhbXIGvijRtNC8F/5CpuJZ7yKOBFGFOOXg1bkISz github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM= github.com/containerd/ttrpc v1.2.4 h1:eQCQK4h9dxDmpOb9QOOMh2NHTfzroH1IkmHiKZi05Oo= github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc= +github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= @@ -825,7 +837,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= @@ -912,6 +923,7 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= @@ -1039,7 +1051,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1065,7 +1076,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= @@ -1129,6 +1139,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= @@ -1264,6 +1275,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -1346,7 +1358,9 @@ github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0 github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= @@ -1518,6 +1532,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -1748,6 +1763,7 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= @@ -1789,10 +1805,12 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.2 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= @@ -2295,6 +2313,7 @@ google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2303,6 +2322,8 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8 h1:Cpp2P6TPjujNoC5M2KHY6g7wfyLYfIWRZaSdIKfDasA= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2364,6 +2385,7 @@ google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= @@ -2391,6 +2413,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go. google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240125205218-1f4bbc51befe h1:weYsP+dNijSQVoLAb5bpUos3ciBpNU/NEVlHFKrk8pg= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:SCz6T5xjNXM4QFPRwxHcfChp7V+9DcXR3ay2TkHR8Tg= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78 h1:YqFWYZXim8bG9v68xU8WjTZmYKb5M5dMeSOWIp6jogI= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8= google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= diff --git a/lib/fixtures/go.mod b/lib/fixtures/go.mod index f2c8041e7..e63e1cae0 100644 --- a/lib/fixtures/go.mod +++ b/lib/fixtures/go.mod @@ -5,10 +5,14 @@ go 1.21 require github.com/Nerzal/gocloak/v13 v13.9.0 require ( - github.com/go-resty/resty/v2 v2.7.0 // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/go-resty/resty/v2 v2.12.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.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/segmentio/ksuid v1.0.4 // indirect - golang.org/x/net v0.23.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/time v0.6.0 // indirect ) diff --git a/lib/fixtures/go.sum b/lib/fixtures/go.sum index 9d91c4058..51f299e5b 100644 --- a/lib/fixtures/go.sum +++ b/lib/fixtures/go.sum @@ -1,33 +1,26 @@ github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/flattening/go.mod b/lib/flattening/go.mod index e210ba1be..329cdddec 100644 --- a/lib/flattening/go.mod +++ b/lib/flattening/go.mod @@ -5,7 +5,10 @@ go 1.21 require github.com/stretchr/testify v1.9.0 require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/lib/flattening/go.sum b/lib/flattening/go.sum index 60ce688a0..8c9f00ba7 100644 --- a/lib/flattening/go.sum +++ b/lib/flattening/go.sum @@ -1,10 +1,11 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/ocrypto/go.mod b/lib/ocrypto/go.mod index 38d05702a..5cfb21f8b 100644 --- a/lib/ocrypto/go.mod +++ b/lib/ocrypto/go.mod @@ -4,11 +4,14 @@ go 1.21 require ( github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.23.0 + golang.org/x/crypto v0.26.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/lib/ocrypto/go.sum b/lib/ocrypto/go.sum index d8e634402..08b24dfc2 100644 --- a/lib/ocrypto/go.sum +++ b/lib/ocrypto/go.sum @@ -1,12 +1,12 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/protocol/go/go.mod b/protocol/go/go.mod index 095c29e6f..2101297de 100644 --- a/protocol/go/go.mod +++ b/protocol/go/go.mod @@ -3,18 +3,17 @@ module github.com/opentdf/platform/protocol/go go 1.21 require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 connectrpc.com/connect v1.17.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 - google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 - google.golang.org/grpc v1.62.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 + google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 ) require ( - github.com/golang/protobuf v1.5.4 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect ) diff --git a/protocol/go/go.sum b/protocol/go/go.sum index 12d5c4bb5..a0137368d 100644 --- a/protocol/go/go.sum +++ b/protocol/go/go.sum @@ -1,29 +1,18 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 h1:0nWhrRcnkgw1kwJ7xibIO8bqfOA7pBzBjGCDBxIHch8= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 h1:LEXWFH/xZ5oOWrC3oOtHbUyBdzRWMCPpAQmKC9v05mA= connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 h1:oqta3O3AnlWbmIE3bFnWbu4bRxZjfbWCp0cKSuZh01E= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 h1:8EeVk1VKMD+GD/neyEHGmz7pFblqPjHoi+PGQIlLx2s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/sdk/go.mod b/sdk/go.mod index d585865c1..6ba6ea407 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -11,42 +11,42 @@ require ( github.com/opentdf/platform/lib/ocrypto v0.1.6 github.com/opentdf/platform/protocol/go v0.2.20 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.28.0 + github.com/testcontainers/testcontainers-go v0.32.0 github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 - golang.org/x/oauth2 v0.16.0 - google.golang.org/grpc v1.62.1 + golang.org/x/oauth2 v0.21.0 + google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.0 // indirect github.com/Nerzal/gocloak/v13 v13.9.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/containerd/containerd v1.7.14 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/containerd/containerd v1.7.21 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/distribution/reference v0.5.0 // indirect - github.com/docker/docker v25.0.6+incompatible // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // 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.2 // indirect + github.com/goccy/go-json v0.10.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/kr/text v0.2.0 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect @@ -55,9 +55,11 @@ require ( github.com/lestrrat-go/option v1.0.1 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -66,6 +68,7 @@ require ( 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/rogpeppe/go-internal v1.12.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect @@ -76,19 +79,19 @@ require ( 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.3 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/time v0.6.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/go.sum b/sdk/go.sum index a30c7e1b6..5bb4943b6 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,23 +1,20 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 h1:0nWhrRcnkgw1kwJ7xibIO8bqfOA7pBzBjGCDBxIHch8= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 h1:LEXWFH/xZ5oOWrC3oOtHbUyBdzRWMCPpAQmKC9v05mA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/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/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= -github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= 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= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -27,12 +24,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= -github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= 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= @@ -40,24 +34,19 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD 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.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 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-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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= 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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -69,12 +58,10 @@ 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.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= 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.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= 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= @@ -95,12 +82,13 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= 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/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= 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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -124,8 +112,7 @@ 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/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 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= @@ -149,8 +136,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= -github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= 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/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -167,38 +153,28 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= 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.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= @@ -209,17 +185,13 @@ 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.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= 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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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= @@ -237,48 +209,37 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= 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.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= 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/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.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 h1:oqta3O3AnlWbmIE3bFnWbu4bRxZjfbWCp0cKSuZh01E= -google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 h1:8EeVk1VKMD+GD/neyEHGmz7pFblqPjHoi+PGQIlLx2s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -287,5 +248,4 @@ 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.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index 37ce09db4..6e68f648b 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -11,6 +11,8 @@ import ( "fmt" "io" "log/slog" + "sync" + "time" "github.com/opentdf/platform/lib/ocrypto" ) @@ -37,6 +39,7 @@ const ( kNanoTDFIvSize = 3 kNanoTDFGMACLength = 8 kNanoTDFMagicStringAndVersion = "L1L" + kMaxIters = 1<<24 - 1 ) /******************************** Header************************** @@ -176,6 +179,14 @@ type signatureConfig struct { cipher CipherMode } +type collectionConfig struct { + iterations uint32 + header []byte + useCollection bool + symKey []byte + mux sync.Mutex +} + type policyInfo struct { body PolicyBody // binding *eccSignature @@ -350,17 +361,113 @@ func SizeOfAuthTagForCipher(cipherType CipherMode) (int, error) { return numberOfBytes, nil } +// ============================================================================================================ +// NanoTDF Collection Header Store +// ============================================================================================================ + +const kDefaultExpirationTime = 5 * time.Minute +const kDefaultCleaningInterval = 10 * time.Minute + +type collectionStore struct { + cache sync.Map + expireDuration time.Duration + closeChan chan struct{} +} + +type collectionStoreEntry struct { + key []byte + encryptedHeader []byte + expire time.Time +} + +func newCollectionStore(expireDuration, cleaningInterval time.Duration) *collectionStore { + store := &collectionStore{expireDuration: expireDuration, cache: sync.Map{}, closeChan: make(chan struct{})} + store.startJanitor(cleaningInterval) + return store +} + +func (c *collectionStore) startJanitor(cleaningInterval time.Duration) { + go func() { + ticker := time.NewTicker(cleaningInterval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + now := time.Now() + c.cache.Range(func(key, value any) bool { + entry, _ := value.(*collectionStoreEntry) + if now.Compare(entry.expire) >= 0 { + c.cache.Delete(key) + } + return true + }) + case <-c.closeChan: + return + } + } + }() +} + +func (c *collectionStore) store(header, key []byte) { + hash := ocrypto.SHA256AsHex(header) + expire := time.Now().Add(c.expireDuration) + c.cache.Store(string(hash), &collectionStoreEntry{key: key, encryptedHeader: header, expire: expire}) +} + +func (c *collectionStore) get(header []byte) ([]byte, bool) { + hash := ocrypto.SHA256AsHex(header) + itemIntf, ok := c.cache.Load(string(hash)) + if !ok { + return nil, false + } + item, _ := itemIntf.(*collectionStoreEntry) + // check for hash collision + if bytes.Equal(item.encryptedHeader, header) { + return item.key, true + } + return nil, false +} + +func (c *collectionStore) close() { + c.closeChan <- struct{}{} +} + // ============================================================================================================ // NanoTDF Header read/write // ============================================================================================================ -func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, error) { +func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, uint32, error) { + if config.collectionCfg.useCollection { + // If concurrently writing, we must know what iteration we are on in a threadsafe way + // also when we need to safely read the header to ensure not rewritten in next max iteration + config.collectionCfg.mux.Lock() + defer config.collectionCfg.mux.Unlock() + + // Store iteration and header and increment iteration + iteration := config.collectionCfg.iterations + config.collectionCfg.iterations++ + header := config.collectionCfg.header + // Reset iteration if reached max iters + if iteration == kMaxIters { + config.collectionCfg.iterations = 0 + } + // Return saved header + if iteration != 0 { + n, err := writer.Write(header) + return config.collectionCfg.symKey, uint32(n), iteration, err + } + // First Iteration: header has not been calculated, will write to header and save for later use. + buf := &bytes.Buffer{} + writer = io.MultiWriter(writer, buf) + defer func() { config.collectionCfg.header = buf.Bytes() }() + } + var totalBytes uint32 // Write the magic number l, err := writer.Write([]byte(kNanoTDFMagicStringAndVersion)) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) @@ -369,7 +476,7 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, // Write the kas url err = config.kasURL.writeResourceLocator(writer) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(config.kasURL.getLength()) slog.Debug("writeNanoTDFHeader", slog.Uint64("resource locator number", uint64(config.kasURL.getLength()))) @@ -377,14 +484,14 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, // Write ECC And Binding Mode l, err = writer.Write([]byte{serializeBindingCfg(config.bindCfg)}) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) // Write Payload and Sig Mode l, err = writer.Write([]byte{serializeSignatureCfg(config.sigCfg)}) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) @@ -392,45 +499,45 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, config.policy.body.mode = policyTypeEmbeddedPolicyEncrypted l, err = writer.Write([]byte{byte(config.policy.body.mode)}) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) policyObj, err := createPolicyObject(config.attributes) if err != nil { - return nil, 0, fmt.Errorf("fail to create policy object:%w", err) + return nil, 0, 0, fmt.Errorf("fail to create policy object:%w", err) } policyObjectAsStr, err := json.Marshal(policyObj) if err != nil { - return nil, 0, fmt.Errorf("json.Marshal failed:%w", err) + return nil, 0, 0, fmt.Errorf("json.Marshal failed:%w", err) } ecdhKey, err := ocrypto.ConvertToECDHPrivateKey(config.keyPair.PrivateKey) if err != nil { - return nil, 0, fmt.Errorf("ocrypto.ConvertToECDHPrivateKey failed:%w", err) + return nil, 0, 0, fmt.Errorf("ocrypto.ConvertToECDHPrivateKey failed:%w", err) } symKey, err := ocrypto.ComputeECDHKeyFromECDHKeys(config.kasPublicKey, ecdhKey) if err != nil { - return nil, 0, fmt.Errorf("ocrypto.ComputeECDHKeyFromEC failed:%w", err) + return nil, 0, 0, fmt.Errorf("ocrypto.ComputeECDHKeyFromEC failed:%w", err) } salt := versionSalt() symmetricKey, err := ocrypto.CalculateHKDF(salt, symKey) if err != nil { - return nil, 0, fmt.Errorf("ocrypto.CalculateHKDF failed:%w", err) + return nil, 0, 0, fmt.Errorf("ocrypto.CalculateHKDF failed:%w", err) } aesGcm, err := ocrypto.NewAESGcm(symmetricKey) if err != nil { - return nil, 0, fmt.Errorf("ocrypto.NewAESGcm failed:%w", err) + return nil, 0, 0, fmt.Errorf("ocrypto.NewAESGcm failed:%w", err) } tagSize, err := SizeOfAuthTagForCipher(config.sigCfg.cipher) if err != nil { - return nil, 0, fmt.Errorf("SizeOfAuthTagForCipher failed:%w", err) + return nil, 0, 0, fmt.Errorf("SizeOfAuthTagForCipher failed:%w", err) } const ( @@ -439,7 +546,7 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, iv := make([]byte, kIvLength) cipherText, err := aesGcm.EncryptWithIVAndTagSize(iv, policyObjectAsStr, tagSize) if err != nil { - return nil, 0, fmt.Errorf("AesGcm.EncryptWithIVAndTagSize failed:%w", err) + return nil, 0, 0, fmt.Errorf("AesGcm.EncryptWithIVAndTagSize failed:%w", err) } embeddedP := embeddedPolicy{ @@ -448,7 +555,7 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, } err = embeddedP.writeEmbeddedPolicy(writer) if err != nil { - return nil, 0, fmt.Errorf("writeEmbeddedPolicy failed:%w", err) + return nil, 0, 0, fmt.Errorf("writeEmbeddedPolicy failed:%w", err) } // size of uint16 @@ -461,39 +568,39 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, if config.bindCfg.useEcdsaBinding { //nolint:nestif // todo: subfunction rBytes, sBytes, err := ocrypto.ComputeECDSASig(digest, config.keyPair.PrivateKey) if err != nil { - return nil, 0, fmt.Errorf("ComputeECDSASig failed:%w", err) + return nil, 0, 0, fmt.Errorf("ComputeECDSASig failed:%w", err) } // write rBytes len and rBytes contents l, err = writer.Write([]byte{uint8(len(rBytes))}) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) l, err = writer.Write(rBytes) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) // write sBytes len and sBytes contents l, err = writer.Write([]byte{uint8(len(sBytes))}) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) l, err = writer.Write(sBytes) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) } else { binding := digest[len(digest)-kNanoTDFGMACLength:] l, err = writer.Write(binding) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) } @@ -502,11 +609,15 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32, l, err = writer.Write(ephemeralPublicKeyKey) if err != nil { - return nil, 0, err + return nil, 0, 0, err } totalBytes += uint32(l) - return symmetricKey, totalBytes, nil + if config.collectionCfg.useCollection { + config.collectionCfg.symKey = symmetricKey + } + + return symmetricKey, totalBytes, 0, nil } func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error) { @@ -725,7 +836,7 @@ func (s SDK) CreateNanoTDF(writer io.Writer, reader io.Reader, config NanoTDFCon } // Create nano tdf header - key, totalSize, err := writeNanoTDFHeader(writer, config) + key, totalSize, iteration, err := writeNanoTDFHeader(writer, config) if err != nil { return 0, fmt.Errorf("writeNanoTDFHeader failed:%w", err) } @@ -736,10 +847,17 @@ func (s SDK) CreateNanoTDF(writer io.Writer, reader io.Reader, config NanoTDFCon if err != nil { return 0, fmt.Errorf("ocrypto.NewAESGcm failed:%w", err) } - - ivPadded, err := nonZeroRandomPaddedIV() - if err != nil { - return 0, err + var ivPadded []byte + if config.collectionCfg.useCollection { + ivPadded = make([]byte, gcmIvSize) + iv := make([]byte, binary.MaxVarintLen32) + binary.LittleEndian.PutUint32(iv, iteration) + copy(ivPadded[kIvPadding:], iv[:kNanoTDFIvSize]) + } else { + ivPadded, err = nonZeroRandomPaddedIV() + if err != nil { + return 0, err + } } tagSize, err := SizeOfAuthTagForCipher(config.sigCfg.cipher) @@ -809,21 +927,9 @@ func (s SDK) ReadNanoTDFContext(ctx context.Context, writer io.Writer, reader io return 0, fmt.Errorf("readSeeker.Seek failed: %w", err) } - encodedHeader := ocrypto.Base64Encode(headerBuf) - - rsaKeyPair, err := ocrypto.NewRSAKeyPair(tdf3KeySize) - if err != nil { - return 0, fmt.Errorf("ocrypto.NewRSAKeyPair failed: %w", err) - } - - client, err := newKASClient(s.dialOptions, s.tokenSource, rsaKeyPair) - if err != nil { - return 0, fmt.Errorf("newKASClient failed: %w", err) - } - - symmetricKey, err := client.unwrapNanoTDF(ctx, string(encodedHeader), kasURL) + symmetricKey, err := s.getNanoRewrapKey(ctx, headerBuf, kasURL) if err != nil { - return 0, fmt.Errorf("readSeeker.Seek failed: %w", err) + return 0, err } const ( @@ -874,6 +980,34 @@ func (s SDK) ReadNanoTDFContext(ctx context.Context, writer io.Writer, reader io return uint32(writeLen), nil } +func (s SDK) getNanoRewrapKey(ctx context.Context, header []byte, kasURL string) ([]byte, error) { + if s.collectionStore != nil { + if key, found := s.collectionStore.get(header); found { + return key, nil + } + } + encodedHeader := ocrypto.Base64Encode(header) + + rsaKeyPair, err := ocrypto.NewRSAKeyPair(tdf3KeySize) + if err != nil { + return nil, fmt.Errorf("ocrypto.NewRSAKeyPair failed: %w", err) + } + + client, err := newKASClient(s.dialOptions, s.tokenSource, rsaKeyPair) + if err != nil { + return nil, fmt.Errorf("newKASClient failed: %w", err) + } + + symmetricKey, err := client.unwrapNanoTDF(ctx, string(encodedHeader), kasURL) + if err != nil { + return nil, fmt.Errorf("readSeeker.Seek failed: %w", err) + } + if s.collectionStore != nil { + s.collectionStore.store(header, symmetricKey) + } + return symmetricKey, nil +} + type requestBody struct { Algorithm string `json:"algorithm,omitempty"` KeyAccess keyAccess `json:"keyAccess"` diff --git a/sdk/nanotdf_config.go b/sdk/nanotdf_config.go index d0ddac1cf..6549816b2 100644 --- a/sdk/nanotdf_config.go +++ b/sdk/nanotdf_config.go @@ -17,14 +17,15 @@ import ( // ============================================================================================================ type NanoTDFConfig struct { - keyPair ocrypto.ECKeyPair - kasPublicKey *ecdh.PublicKey - attributes []AttributeValueFQN - cipher CipherMode - kasURL ResourceLocator - sigCfg signatureConfig - policy policyInfo - bindCfg bindingConfig + keyPair ocrypto.ECKeyPair + kasPublicKey *ecdh.PublicKey + attributes []AttributeValueFQN + cipher CipherMode + kasURL ResourceLocator + sigCfg signatureConfig + policy policyInfo + bindCfg bindingConfig + collectionCfg *collectionConfig } type NanoTDFOption func(*NanoTDFConfig) error @@ -49,6 +50,11 @@ func (s SDK) NewNanoTDFConfig() (*NanoTDFConfig, error) { signatureMode: ocrypto.ECCModeSecp256r1, cipher: cipherModeAes256gcm96Bit, }, + collectionCfg: &collectionConfig{ + iterations: 0, + useCollection: false, + header: []byte{}, + }, } return c, nil @@ -77,6 +83,12 @@ func (config *NanoTDFConfig) EnableECDSAPolicyBinding() { config.bindCfg.useEcdsaBinding = true } +// EnableCollection Experimental: Enables Collection in NanoTDFConfig. +// Reuse NanoTDFConfig to add nTDFs to a Collection. +func (config *NanoTDFConfig) EnableCollection() { + config.collectionCfg.useCollection = 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 b7b0807e5..b6cbf249f 100644 --- a/sdk/nanotdf_test.go +++ b/sdk/nanotdf_test.go @@ -2,6 +2,8 @@ package sdk import ( "bytes" + "crypto/ecdh" + "crypto/rand" "encoding/gob" "io" "os" @@ -315,3 +317,70 @@ func TestCreateNanoTDF(t *testing.T) { }) } } + +func TestDataSet(t *testing.T) { + const ( + kasURL = "https://test.virtru.com" + ) + + var s SDK + conf, err := s.NewNanoTDFConfig() + if err != nil { + t.Fatal(err) + } + err = conf.SetKasURL(kasURL) + if err != nil { + t.Fatal(err) + } + + err = conf.SetAttributes([]string{"https://examples.com/attr/attr1/value/value1"}) + if err != nil { + t.Fatal(err) + } + + key, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + conf.kasPublicKey = key.PublicKey() + + getHeaderAndSymKey := func(cfg *NanoTDFConfig) ([]byte, []byte) { + out := &bytes.Buffer{} + symKey, _, _, err := writeNanoTDFHeader(out, *cfg) + if err != nil { + t.Fatal() + } + + return out.Bytes(), symKey + } + + header1, _ := getHeaderAndSymKey(conf) + header2, _ := getHeaderAndSymKey(conf) + + if bytes.Equal(header1, header2) { + t.Fatal("headers should not match") + } + + conf.EnableCollection() + header1, symKey1 := getHeaderAndSymKey(conf) + header2, symKey2 := getHeaderAndSymKey(conf) + + if !bytes.Equal(symKey1, symKey2) { + t.Fatal("keys should match") + } + if !bytes.Equal(header1, header2) { + t.Fatal("headers should match") + } + + for i := 2; i <= kMaxIters; i++ { + header, _ := getHeaderAndSymKey(conf) + if !bytes.Equal(header, header1) { + t.Fatal("max iteration reset occurred too early, headers differ") + } + } + + header, _ := getHeaderAndSymKey(conf) + if bytes.Equal(header, header1) { + t.Fatal("header did not reset") + } +} diff --git a/sdk/options.go b/sdk/options.go index cd1cba416..a59a50c56 100644 --- a/sdk/options.go +++ b/sdk/options.go @@ -35,6 +35,7 @@ type config struct { customAccessTokenSource auth.AccessTokenSource oauthAccessTokenSource oauth2.TokenSource coreConn *grpc.ClientConn + collectionStore *collectionStore } // Options specific to TDF protocol features @@ -68,6 +69,13 @@ func WithInsecureSkipVerifyConn() Option { } } +// WithStoreCollectionHeaders Experimental: returns an Option that sets up storing dataset keys for nTDFs +func WithStoreCollectionHeaders() Option { + return func(c *config) { + c.collectionStore = newCollectionStore(kDefaultExpirationTime, kDefaultCleaningInterval) + } +} + // WithInsecurePlaintextConn returns an Option that sets up HTTP connection sent in the clear. func WithInsecurePlaintextConn() Option { return func(c *config) { diff --git a/sdk/sdk.go b/sdk/sdk.go index 1fce360d5..7202bea27 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -56,6 +56,7 @@ func (c Error) Error() string { type SDK struct { config *kasKeyCache + *collectionStore conn *grpc.ClientConn dialOptions []grpc.DialOption tokenSource auth.AccessTokenSource @@ -170,6 +171,7 @@ func New(platformEndpoint string, opts ...Option) (*SDK, error) { return &SDK{ config: *cfg, + collectionStore: cfg.collectionStore, kasKeyCache: newKasKeyCache(), conn: platformConn, dialOptions: dialOptions, @@ -265,6 +267,10 @@ func buildIDPTokenSource(c *config) (auth.AccessTokenSource, error) { // Close closes the underlying grpc.ClientConn. func (s SDK) Close() error { + if s.collectionStore != nil { + s.collectionStore.close() + } + if s.conn == nil { return nil } diff --git a/service/go.mod b/service/go.mod index fbecf5275..ec02b1115 100644 --- a/service/go.mod +++ b/service/go.mod @@ -60,6 +60,8 @@ require ( github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/flatbuffers v23.5.26+incompatible // indirect github.com/gowebpki/jcs v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect diff --git a/service/go.sum b/service/go.sum index d024bf739..b0bcbcd80 100644 --- a/service/go.sum +++ b/service/go.sum @@ -156,8 +156,8 @@ github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= @@ -165,8 +165,7 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= -github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= From 312035008dfd42c94d3e8135d05deb4cc5bfe21f Mon Sep 17 00:00:00 2001 From: Sean Trantalis <strantalis@virtru.com> Date: Thu, 14 Nov 2024 16:24:15 -0500 Subject: [PATCH 16/32] fix: grpc-gateway connection with tls enabled (#1758) ### Proposed Changes Fixes grpc-gateway from endpoint to support tls. This was a miss on the initial pr https://github.com/opentdf/platform/pull/1733 because we don't have any tests where we enable tls. So this pull request updates the integration tests to run with tls enabled as well. ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- .github/workflows/checks.yaml | 11 +++ examples/cmd/examples.go | 5 +- opentdf-dev.yaml | 4 + service/pkg/server/services.go | 7 ++ service/rttests/rt_test.go | 121 ++++++++++++++--------------- test/policy-service.bats | 2 +- test/rego/custom-entity.bats | 4 +- test/rego/static-entitlements.bats | 4 +- test/service-start.bats | 12 +-- test/tdf-roundtrips.bats | 18 +++-- 10 files changed, 106 insertions(+), 82 deletions(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 26f592678..63f37612b 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -90,6 +90,8 @@ jobs: integration: name: integration tests runs-on: ubuntu-22.04 + env: + TLS_ENABLED: "true" steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 @@ -105,9 +107,18 @@ jobs: run: ./.github/scripts/work-init.sh - run: go mod download - run: go mod verify + - name: Install mkcert + run: | + sudo apt-get install -y libnss3-tools + curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" + chmod +x mkcert-v*-linux-amd64 + sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert - run: | .github/scripts/init-temp-keys.sh + mkcert -install + mkcert -cert-file ./keys/platform.crt -key-file ./keys/platform-key.pem localhost cp opentdf-dev.yaml opentdf.yaml + yq eval '.server.tls.enabled = true' -i opentdf.yaml - name: Added Trusted Certs run: | sudo chmod -R 777 ./keys diff --git a/examples/cmd/examples.go b/examples/cmd/examples.go index 94c0c885b..6eea627dc 100644 --- a/examples/cmd/examples.go +++ b/examples/cmd/examples.go @@ -2,11 +2,12 @@ package cmd import ( "fmt" - "google.golang.org/grpc/resolver" "log" "os" "strings" + "google.golang.org/grpc/resolver" + "github.com/opentdf/platform/sdk" "github.com/spf13/cobra" ) @@ -30,7 +31,7 @@ func init() { func newSDK() (*sdk.SDK, error) { resolver.SetDefaultScheme("passthrough") - opts := []sdk.Option{sdk.WithStoreCollectionHeaders(), sdk.WithInsecurePlaintextConn()} + opts := []sdk.Option{sdk.WithStoreCollectionHeaders()} if clientCredentials != "" { i := strings.Index(clientCredentials, ":") if i < 0 { diff --git a/opentdf-dev.yaml b/opentdf-dev.yaml index 4a8509647..7c1f5d2b9 100644 --- a/opentdf-dev.yaml +++ b/opentdf-dev.yaml @@ -33,6 +33,10 @@ services: email: true username: true server: + tls: + enabled: false + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false diff --git a/service/pkg/server/services.go b/service/pkg/server/services.go index 8760a5fbd..637f96c1d 100644 --- a/service/pkg/server/services.go +++ b/service/pkg/server/services.go @@ -22,6 +22,7 @@ import ( "github.com/opentdf/platform/service/policy" wellknown "github.com/opentdf/platform/service/wellknownconfiguration" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" ) @@ -180,6 +181,12 @@ func startServices(ctx context.Context, cfg config.Config, otdf *server.OpenTDFS grpcGatewayDialOptions := make([]grpc.DialOption, 0) if !cfg.Server.TLS.Enabled { grpcGatewayDialOptions = append(grpcGatewayDialOptions, grpc.WithTransportCredentials(insecure.NewCredentials())) + } else { + creds, err := credentials.NewClientTLSFromFile(cfg.Server.TLS.Cert, "") + if err != nil { + return fmt.Errorf("failed to create grpc-gateway client TLS credentials: %w", err) + } + grpcGatewayDialOptions = append(grpcGatewayDialOptions, grpc.WithTransportCredentials(creds)) } if err := svc.RegisterGRPCGatewayHandler(ctx, otdf.GRPCGatewayMux, fmt.Sprintf("localhost:%d", cfg.Server.Port), grpcGatewayDialOptions); err != nil { logger.Info("service did not register a grpc gateway handler", slog.String("namespace", ns)) diff --git a/service/rttests/rt_test.go b/service/rttests/rt_test.go index d8973e6c4..49a43737b 100644 --- a/service/rttests/rt_test.go +++ b/service/rttests/rt_test.go @@ -36,7 +36,8 @@ type TestConfig struct { var attributesToMap = []string{ "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", - "https://example.com/attr/cards/value/queen"} + "https://example.com/attr/cards/value/queen", +} var successAttributeSets = [][]string{ {}, @@ -45,11 +46,13 @@ var successAttributeSets = [][]string{ {"https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green"}, {"https://example.com/attr/cards/value/jack"}, {"https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", "https://example.com/attr/cards/value/jack", - "https://example.com/attr/cards/value/queen"}, + "https://example.com/attr/cards/value/queen", + }, } var failureAttributeSets = [][]string{ @@ -57,19 +60,25 @@ var failureAttributeSets = [][]string{ {"https://example.com/attr/color/value/blue"}, {"https://example.com/attr/color/value/blue", "https://example.com/attr/color/value/green"}, {"https://example.com/attr/cards/value/king"}, - {"https://example.com/attr/language/value/english", + { + "https://example.com/attr/language/value/english", "https://example.com/attr/language/value/french", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + "https://example.com/attr/cards/value/queen", + }, + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/blue", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + "https://example.com/attr/cards/value/queen", + }, + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/king"}, + "https://example.com/attr/cards/value/king", + }, } func newTestConfig() TestConfig { @@ -91,13 +100,25 @@ func Test_RoundTrips(t *testing.T) { type RoundtripSuite struct { suite.Suite TestConfig + client *sdk.SDK } func (s *RoundtripSuite) SetupSuite() { s.TestConfig = newTestConfig() slog.Info("Test config", "", s.TestConfig) - err := s.CreateTestData() + opts := []sdk.Option{} + if os.Getenv("TLS_ENABLED") == "" { + opts = append(opts, sdk.WithInsecurePlaintextConn()) + } + + opts = append(opts, sdk.WithClientCredentials(s.TestConfig.ClientID, s.TestConfig.ClientSecret, nil)) + + sdk, err := sdk.New(s.TestConfig.PlatformEndpoint, opts...) + s.Require().NoError(err) + s.client = sdk + + err = s.CreateTestData() s.Require().NoError(err) } @@ -108,9 +129,9 @@ func (s *RoundtripSuite) Tests() { s.Run(n, func() { filename := fmt.Sprintf("test-success-%d.tdf", i) plaintext := "Running a roundtrip test!" - err := encrypt(&s.TestConfig, plaintext, attributes, filename) + err := encrypt(s.client, s.TestConfig, plaintext, attributes, filename) s.Require().NoError(err) - err = decrypt(&s.TestConfig, filename, plaintext) + err = decrypt(s.client, filename, plaintext) s.NoError(err) }) } @@ -121,30 +142,21 @@ func (s *RoundtripSuite) Tests() { s.Run(n, func() { filename := fmt.Sprintf("test-failure-%d.tdf", i) plaintext := "Running a roundtrip test!" - err := encrypt(&s.TestConfig, plaintext, attributes, filename) + err := encrypt(s.client, s.TestConfig, plaintext, attributes, filename) s.Require().NoError(err) - err = decrypt(&s.TestConfig, filename, plaintext) + err = decrypt(s.client, filename, plaintext) s.ErrorContains(err, "PermissionDenied") }) } } func (s *RoundtripSuite) CreateTestData() error { - sdk, err := sdk.New(s.TestConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(s.TestConfig.ClientID, - s.TestConfig.ClientSecret, nil), - ) - if err != nil { - slog.Error("could not connect", slog.String("error", err.Error())) - return err - } - defer sdk.Close() + client := s.client // create namespace example.com var exampleNamespace *policy.Namespace slog.Info("listing namespaces") - listResp, err := sdk.Namespaces.ListNamespaces(context.Background(), &namespaces.ListNamespacesRequest{}) + listResp, err := client.Namespaces.ListNamespaces(context.Background(), &namespaces.ListNamespacesRequest{}) if err != nil { return err } @@ -158,7 +170,7 @@ func (s *RoundtripSuite) CreateTestData() error { if exampleNamespace == nil { slog.Info("creating new namespace") - resp, err := sdk.Namespaces.CreateNamespace(context.Background(), &namespaces.CreateNamespaceRequest{ + resp, err := client.Namespaces.CreateNamespace(context.Background(), &namespaces.CreateNamespaceRequest{ Name: "example.com", }) if err != nil { @@ -171,7 +183,7 @@ func (s *RoundtripSuite) CreateTestData() error { // Create the attributes slog.Info("creating attribute language with allOf rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "language", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF.Enum(), @@ -193,7 +205,7 @@ func (s *RoundtripSuite) CreateTestData() error { } slog.Info("creating attribute color with anyOf rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "color", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF.Enum(), @@ -215,7 +227,7 @@ func (s *RoundtripSuite) CreateTestData() error { } slog.Info("creating attribute cards with hierarchy rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "cards", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY.Enum(), @@ -238,7 +250,7 @@ func (s *RoundtripSuite) CreateTestData() error { slog.Info("##################################\n#######################################") - allAttr, err := sdk.Attributes.ListAttributes(context.Background(), &attributes.ListAttributesRequest{}) + allAttr, err := client.Attributes.ListAttributes(context.Background(), &attributes.ListAttributesRequest{}) if err != nil { slog.Error("could not list attributes", slog.String("error", err.Error())) return err @@ -249,7 +261,7 @@ func (s *RoundtripSuite) CreateTestData() error { // get the attribute ids for the values were mapping to the client var attributeValueIDs []string - fqnResp, err := sdk.Attributes.GetAttributeValuesByFqns(context.Background(), &attributes.GetAttributeValuesByFqnsRequest{ + fqnResp, err := client.Attributes.GetAttributeValuesByFqns(context.Background(), &attributes.GetAttributeValuesByFqnsRequest{ Fqns: attributesToMap, WithValue: &policy.AttributeValueSelector{}, }) @@ -264,11 +276,12 @@ func (s *RoundtripSuite) CreateTestData() error { // create subject mappings slog.Info("creating subject mappings for client " + s.TestConfig.ClientID) for _, attributeID := range attributeValueIDs { - _, err = sdk.SubjectMapping.CreateSubjectMapping(context.Background(), &subjectmapping.CreateSubjectMappingRequest{ + _, err = client.SubjectMapping.CreateSubjectMapping(context.Background(), &subjectmapping.CreateSubjectMappingRequest{ AttributeValueId: attributeID, - Actions: []*policy.Action{{Value: &policy.Action_Standard{ - Standard: policy.Action_STANDARD_ACTION_DECRYPT, - }}, + Actions: []*policy.Action{ + {Value: &policy.Action_Standard{ + Standard: policy.Action_STANDARD_ACTION_DECRYPT, + }}, {Value: &policy.Action_Standard{ Standard: policy.Action_STANDARD_ACTION_TRANSMIT, }}, @@ -276,11 +289,12 @@ func (s *RoundtripSuite) CreateTestData() error { NewSubjectConditionSet: &subjectmapping.SubjectConditionSetCreate{ SubjectSets: []*policy.SubjectSet{ {ConditionGroups: []*policy.ConditionGroup{ - {Conditions: []*policy.Condition{{ - SubjectExternalSelectorValue: ".clientId", - Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, - SubjectExternalValues: []string{s.TestConfig.ClientID}, - }}, + { + Conditions: []*policy.Condition{{ + SubjectExternalSelectorValue: ".clientId", + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{s.TestConfig.ClientID}, + }}, BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, }, }}, @@ -299,7 +313,7 @@ func (s *RoundtripSuite) CreateTestData() error { } } - allSubMaps, err := sdk.SubjectMapping.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{}) + allSubMaps, err := client.SubjectMapping.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{}) if err != nil { slog.Error("could not list subject mappings", slog.String("error", err.Error())) return err @@ -309,20 +323,9 @@ func (s *RoundtripSuite) CreateTestData() error { return nil } -func encrypt(testConfig *TestConfig, plaintext string, attributes []string, filename string) error { +func encrypt(client *sdk.SDK, testConfig TestConfig, plaintext string, attributes []string, filename string) error { strReader := strings.NewReader(plaintext) - // Create new offline client - client, err := sdk.New(testConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(testConfig.ClientID, - testConfig.ClientSecret, nil), - sdk.WithTokenEndpoint(testConfig.TokenEndpoint), - ) - if err != nil { - return err - } - tdfFile, err := os.Create(filename) if err != nil { return err @@ -344,17 +347,7 @@ func encrypt(testConfig *TestConfig, plaintext string, attributes []string, file return nil } -func decrypt(testConfig *TestConfig, tdfFile string, plaintext string) error { - // Create new client - client, err := sdk.New(testConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(testConfig.ClientID, - testConfig.ClientSecret, nil), - sdk.WithTokenEndpoint(testConfig.TokenEndpoint), - ) - if err != nil { - return err - } +func decrypt(client *sdk.SDK, tdfFile string, plaintext string) error { file, err := os.Open(tdfFile) if err != nil { return err diff --git a/test/policy-service.bats b/test/policy-service.bats index f08c042f1..47908d0c1 100755 --- a/test/policy-service.bats +++ b/test/policy-service.bats @@ -3,7 +3,7 @@ # Tests for policy service administration @test "gRPC: lists attributes" { - run grpcurl -plaintext "localhost:8080" list + run grpcurl "localhost:8080" list echo "$output" [ $status = 0 ] [[ $output = *grpc.health.v1.Health* ]] diff --git a/test/rego/custom-entity.bats b/test/rego/custom-entity.bats index 4a3506151..0b16ab700 100755 --- a/test/rego/custom-entity.bats +++ b/test/rego/custom-entity.bats @@ -46,9 +46,9 @@ EOF echo "Using Access Token: $ACCESS_TOKEN" # Print the grpcurl command for debugging - echo grpcurl -plaintext -H \"Authorization: Bearer $ACCESS_TOKEN\" -d \"$JSON_BODY\" $BASE_URL authorization.AuthorizationService/GetEntitlements + echo grpcurl -H \"Authorization: Bearer $ACCESS_TOKEN\" -d \"$JSON_BODY\" $BASE_URL authorization.AuthorizationService/GetEntitlements - run grpcurl -plaintext -H "Authorization: Bearer $ACCESS_TOKEN" \ + run grpcurl -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "$JSON_BODY" \ $BASE_URL authorization.AuthorizationService/GetEntitlements diff --git a/test/rego/static-entitlements.bats b/test/rego/static-entitlements.bats index 96042d000..cbb80a028 100755 --- a/test/rego/static-entitlements.bats +++ b/test/rego/static-entitlements.bats @@ -46,9 +46,9 @@ EOF echo "Using Access Token: $ACCESS_TOKEN" # Print the grpcurl command for debugging - echo grpcurl -plaintext -H \"Authorization: Bearer $ACCESS_TOKEN\" -d \"$JSON_BODY\" $BASE_URL authorization.AuthorizationService/GetEntitlements + echo grpcurl -H \"Authorization: Bearer $ACCESS_TOKEN\" -d \"$JSON_BODY\" $BASE_URL authorization.AuthorizationService/GetEntitlements - run grpcurl -plaintext -H "Authorization: Bearer $ACCESS_TOKEN" \ + run grpcurl -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "$JSON_BODY" \ $BASE_URL authorization.AuthorizationService/GetEntitlements diff --git a/test/service-start.bats b/test/service-start.bats index 44febc431..7cc470e37 100755 --- a/test/service-start.bats +++ b/test/service-start.bats @@ -3,14 +3,14 @@ # Tests for validating that the system is nominally running @test "gRPC: health check is healthy" { - run grpcurl -plaintext "localhost:8080" "grpc.health.v1.Health.Check" + run grpcurl "localhost:8080" "grpc.health.v1.Health.Check" echo "$output" [ $status = 0 ] [ $(jq -r .status <<<"${output}") = SERVING ] } @test "gRPC: reports a public key" { - run grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" + run grpcurl "localhost:8080" "kas.AccessService/PublicKey" echo "$output" # Is public key @@ -25,7 +25,7 @@ } @test "REST: new public key endpoint (no algorithm)" { - run curl -s --show-error --fail-with-body --insecure "localhost:8080/kas/v2/kas_public_key" + run curl -s --show-error --fail-with-body "https://localhost:8080/kas/v2/kas_public_key" echo "output=$output" p=$(jq -r .publicKey <<<"${output}") @@ -40,7 +40,7 @@ } @test "REST: new public key endpoint (ec)" { - run curl -s --show-error --fail-with-body --insecure "localhost:8080/kas/v2/kas_public_key?algorithm=ec:secp256r1" + run curl -s --show-error --fail-with-body "https://localhost:8080/kas/v2/kas_public_key?algorithm=ec:secp256r1" echo "$output" # Is public key @@ -55,13 +55,13 @@ } @test "REST: public key endpoint (unknown algorithm)" { - run curl -o /dev/null -s -w "%{http_code}" "localhost:8080/kas/v2/kas_public_key?algorithm=invalid" + run curl -o /dev/null -s -w "%{http_code}" "https://localhost:8080/kas/v2/kas_public_key?algorithm=invalid" echo "$output" [ $output = 404 ] } @test "gRPC: public key endpoint (unknown algorithm)" { - run grpcurl -d '{"algorithm":"invalid"}' -plaintext "localhost:8080" "kas.AccessService/PublicKey" + run grpcurl -d '{"algorithm":"invalid"}' "localhost:8080" "kas.AccessService/PublicKey" echo "$output" [[ $output = *NotFound* ]] } diff --git a/test/tdf-roundtrips.bats b/test/tdf-roundtrips.bats index af28f751f..d9f9ef12b 100755 --- a/test/tdf-roundtrips.bats +++ b/test/tdf-roundtrips.bats @@ -70,7 +70,7 @@ @test "examples: legacy key support Z-TDF" { echo "[INFO] validating default key is r1" - [ $(grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] + [ $(grpcurl "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] echo "[INFO] encrypting samples" go run ./examples encrypt --autoconfigure=false -o sensitive-with-no-kid.txt.tdf --no-kid-in-kao "Hello Legacy" @@ -86,7 +86,7 @@ wait_for_green echo "[INFO] validating default key is r2" - [ $(grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r2 ] + [ $(grpcurl "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r2 ] echo "[INFO] decrypting after key rotation" go run ./examples decrypt sensitive-with-no-kid.txt.tdf | grep "Hello Legacy" @@ -95,7 +95,7 @@ @test "examples: legacy kas and service config format support" { echo "[INFO] validating default key is r1" - [ $(grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] + [ $(grpcurl "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] echo "[INFO] encrypting samples" go run ./examples encrypt --autoconfigure=false -o sensitive-with-no-kid.txt.tdf --no-kid-in-kao "Hello Legacy" @@ -111,7 +111,7 @@ wait_for_green echo "[INFO] validating default key is r1" - [ $(grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] + [ $(grpcurl "localhost:8080" "kas.AccessService/PublicKey" | jq -e -r .kid) = r1 ] echo "[INFO] decrypting after key rotation" go run ./examples decrypt sensitive-with-no-kid.txt.tdf | grep "Hello Legacy" @@ -122,7 +122,7 @@ wait_for_green() { limit=5 for i in $(seq 1 $limit); do - if [ $(grpcurl -plaintext "localhost:8080" "grpc.health.v1.Health.Check" | jq -e -r .status) = SERVING ]; then + if [ $(grpcurl "localhost:8080" "grpc.health.v1.Health.Check" | jq -e -r .status) = SERVING ]; then return 0 fi sleep 4 @@ -158,6 +158,10 @@ services: realm: "opentdf" legacykeycloak: true server: + tls: + enabled: true + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false @@ -229,6 +233,10 @@ services: realm: "opentdf" legacykeycloak: true server: + tls: + enabled: true + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false From 213da5629a7d0523489d75867e1c2506c72cbf42 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:43:48 -0500 Subject: [PATCH 17/32] chore(main): release lib/fixtures 0.2.9 (#1752) :robot: I have created a release *beep* *boop* --- ## [0.2.9](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.8...lib/fixtures/v0.2.9) (2024-11-14) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- lib/fixtures/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d56bee437..3f67aafa6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,5 @@ { - "lib/fixtures": "0.2.8", + "lib/fixtures": "0.2.9", "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", "protocol/go": "0.2.21", diff --git a/lib/fixtures/CHANGELOG.md b/lib/fixtures/CHANGELOG.md index 651114023..089cf8837 100644 --- a/lib/fixtures/CHANGELOG.md +++ b/lib/fixtures/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.9](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.8...lib/fixtures/v0.2.9) (2024-11-14) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + ## [0.2.8](https://github.com/opentdf/platform/compare/lib/fixtures/v0.2.7...lib/fixtures/v0.2.8) (2024-11-13) From 896f69dd87db6b1a3a46ad97f67fc395295b7c5e Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:45:18 -0500 Subject: [PATCH 18/32] chore(main): release protocol/go 0.2.22 (#1753) :robot: I have created a release *beep* *boop* --- ## [0.2.22](https://github.com/opentdf/platform/compare/protocol/go/v0.2.21...protocol/go/v0.2.22) (2024-11-14) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- protocol/go/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3f67aafa6..3369f4b28 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -2,7 +2,7 @@ "lib/fixtures": "0.2.9", "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", - "protocol/go": "0.2.21", + "protocol/go": "0.2.22", "sdk": "0.3.20", "service": "0.4.27" } diff --git a/protocol/go/CHANGELOG.md b/protocol/go/CHANGELOG.md index 1823dc882..9cf361446 100644 --- a/protocol/go/CHANGELOG.md +++ b/protocol/go/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.22](https://github.com/opentdf/platform/compare/protocol/go/v0.2.21...protocol/go/v0.2.22) (2024-11-14) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + ## [0.2.21](https://github.com/opentdf/platform/compare/protocol/go/v0.2.20...protocol/go/v0.2.21) (2024-11-13) From 6d7f24a32222a9eff73c769ac9ec3af91058c7ea Mon Sep 17 00:00:00 2001 From: Dave Mihalcik <dmihalcik@virtru.com> Date: Fri, 15 Nov 2024 08:13:19 -0500 Subject: [PATCH 19/32] fix(core): Updates dpop check for connect (#1760) ### Proposed Changes - Threads through Dpop token and REST service path from gRPC gateway - This is needed when DPoP is enabled (required) OR when the IdP requests it ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- service/internal/auth/authn.go | 64 ++++++++++++++++++++++------- service/internal/auth/authn_test.go | 4 +- service/internal/server/server.go | 26 +++++++++++- 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/service/internal/auth/authn.go b/service/internal/auth/authn.go index 31f9991b3..1b922df47 100644 --- a/service/internal/auth/authn.go +++ b/service/internal/auth/authn.go @@ -181,10 +181,10 @@ func NewAuthenticator(ctx context.Context, cfg Config, logger *logger.Logger, we } type receiverInfo struct { - // The URI of the request - u string - // The HTTP method of the request - m string + // Acceptable URIs of the request + u []string + // Allowed HTTP methods of the request + m []string } func normalizeURL(o string, u *url.URL) string { @@ -209,6 +209,8 @@ func (a Authentication) MuxHandler(handler http.Handler) http.Handler { return } + dp := r.Header.Values("Dpop") + // Verify the token header := r.Header["Authorization"] if len(header) < 1 { @@ -225,10 +227,11 @@ func (a Authentication) MuxHandler(handler http.Handler) http.Handler { } } accessTok, ctxWithJWK, err := a.checkToken(r.Context(), header, receiverInfo{ - u: normalizeURL(origin, r.URL), - m: r.Method, - }, r.Header["Dpop"]) + u: []string{normalizeURL(origin, r.URL)}, + m: []string{r.Method}, + }, dp) if err != nil { + slog.WarnContext(r.Context(), "unauthenticated", "error", err, "dpop", dp, "authorization", header) http.Error(w, "unauthenticated", http.StatusUnauthorized) return } @@ -270,6 +273,32 @@ func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptor ctx context.Context, req connect.AnyRequest, ) (connect.AnyResponse, error) { + ri := receiverInfo{ + u: []string{req.Spec().Procedure}, + m: []string{http.MethodPost}, + } + + paths := req.Header()["Pattern"] + if len(paths) == 0 { + paths = allowedPublicEndpoints[:] + } + for _, m := range []string{"Origin", "Grpcgateway-Origin", "Grpcgateway-Referer"} { + origins := req.Header().Values(m) + if len(origins) == 0 { + continue + } + for _, o := range origins { + if strings.HasSuffix(o, ":443") { + o = "https://" + strings.TrimPrefix(strings.TrimSuffix(o, ":443"), "https://") + } else { + o = strings.TrimSuffix(o, ":80") + } + for _, u := range paths { + ri.u = append(ri.u, normalizeURL(o, &url.URL{Path: u})) + } + } + } + // Interceptor Logic // Allow health checks and other public routes to pass through if slices.ContainsFunc(a.publicRoutes, a.isPublicRoute(req.Spec().Procedure)) { //nolint:contextcheck // There is no way to pass a context here @@ -289,10 +318,7 @@ func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptor token, newCtx, err := a.checkToken( ctx, header, - receiverInfo{ - u: req.Spec().Procedure, - m: http.MethodPost, - }, + ri, req.Header()["Dpop"], ) if err != nil { @@ -510,21 +536,29 @@ func (a Authentication) validateDPoP(accessToken jwt.Token, acessTokenRaw string return nil, fmt.Errorf("the DPoP JWT has expired") } - htm, ok := dpopToken.Get("htm") + htma, ok := dpopToken.Get("htm") if !ok { return nil, fmt.Errorf("`htm` claim missing in DPoP JWT") } + htm, ok := htma.(string) + if !ok { + return nil, fmt.Errorf("`htm` claim invalid format in DPoP JWT") + } - if htm != dpopInfo.m { + if !slices.Contains(dpopInfo.m, htm) { return nil, fmt.Errorf("incorrect `htm` claim in DPoP JWT; received [%v], but should match [%v]", htm, dpopInfo.m) } - htu, ok := dpopToken.Get("htu") + htua, ok := dpopToken.Get("htu") if !ok { return nil, fmt.Errorf("`htu` claim missing in DPoP JWT") } + htu, ok := htua.(string) + if !ok { + return nil, fmt.Errorf("`htu` claim invalid format in DPoP JWT") + } - if htu != dpopInfo.u { + if !slices.Contains(dpopInfo.u, htu) { return nil, fmt.Errorf("incorrect `htu` claim in DPoP JWT; received [%v], but should match [%v]", htu, dpopInfo.u) } diff --git a/service/internal/auth/authn_test.go b/service/internal/auth/authn_test.go index 841458cf7..99d572c60 100644 --- a/service/internal/auth/authn_test.go +++ b/service/internal/auth/authn_test.go @@ -408,8 +408,8 @@ func (s *AuthSuite) TestInvalid_DPoP_Cases() { context.Background(), []string{fmt.Sprintf("DPoP %s", string(testCase.accessToken))}, receiverInfo{ - u: "/a/path", - m: http.MethodPost, + u: []string{"/a/path"}, + m: []string{http.MethodPost}, }, []string{dpopToken}, ) diff --git a/service/internal/server/server.go b/service/internal/server/server.go index b1aa79032..e2f8ef62d 100644 --- a/service/internal/server/server.go +++ b/service/internal/server/server.go @@ -9,6 +9,7 @@ import ( "net" "net/http" "net/http/pprof" + "net/textproto" "regexp" "strings" "time" @@ -28,6 +29,7 @@ import ( "golang.org/x/net/http2/h2c" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/metadata" ) const ( @@ -165,7 +167,29 @@ func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, err } // GRPC Gateway Mux - grpcGatewayMux := runtime.NewServeMux() + grpcGatewayMux := runtime.NewServeMux( + runtime.WithIncomingHeaderMatcher( + func(key string) (string, bool) { + if k, ok := runtime.DefaultHeaderMatcher(key); ok { + return k, true + } + if textproto.CanonicalMIMEHeaderKey(key) == "Dpop" { + return "Dpop", true + } + return "", false + }, + ), + runtime.WithMetadata(func(ctx context.Context, _ *http.Request) metadata.MD { + md := make(map[string]string) + if method, ok := runtime.RPCMethod(ctx); ok { + md["method"] = method // /grpc.gateway.examples.internal.proto.examplepb.LoginService/Login + } + if pattern, ok := runtime.HTTPPathPattern(ctx); ok { + md["pattern"] = pattern // /v1/example/login + } + return metadata.New(md) + }), + ) // Create http server httpServer, err := newHTTPServer(config, connectRPC.Mux, grpcGatewayMux, authN, logger) From cd0fd64388c802a0ce3f2c3ca7146fd687e64972 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:16:58 +0000 Subject: [PATCH 20/32] chore(main): release lib/flattening 0.1.2 (#1755) :robot: I have created a release *beep* *boop* --- ## [0.1.2](https://github.com/opentdf/platform/compare/lib/flattening/v0.1.1...lib/flattening/v0.1.2) (2024-11-15) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- lib/flattening/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3369f4b28..d26edac57 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { "lib/fixtures": "0.2.9", "lib/ocrypto": "0.1.6", - "lib/flattening": "0.1.1", + "lib/flattening": "0.1.2", "protocol/go": "0.2.22", "sdk": "0.3.20", "service": "0.4.27" diff --git a/lib/flattening/CHANGELOG.md b/lib/flattening/CHANGELOG.md index 640e0ac24..5309cf2c1 100644 --- a/lib/flattening/CHANGELOG.md +++ b/lib/flattening/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.1.2](https://github.com/opentdf/platform/compare/lib/flattening/v0.1.1...lib/flattening/v0.1.2) (2024-11-15) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + ## [0.1.1](https://github.com/opentdf/platform/compare/lib/flattening-v0.1.0...lib/flattening/v0.1.1) (2024-06-18) From 738ef0e1fdf0c61b7eb6802e719597f56ae02f73 Mon Sep 17 00:00:00 2001 From: Sean Trantalis <strantalis@virtru.com> Date: Fri, 15 Nov 2024 12:49:24 -0500 Subject: [PATCH 21/32] chore(ci): swap out kc chainguard image to dockerhub image (#1764) ### Proposed Changes I think the chainguard keycloak image is now private so our tests are breaking. https://github.com/opentdf/platform/actions/runs/11859704681/job/33053273929 ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions --- docker-compose.yaml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index a1a15f9b8..01d1bed3c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -8,7 +8,7 @@ services: - ./keys/localhost.key:/etc/x509/tls/localhost.key - ./keys/ca.jks:/truststore/truststore.jks # This is kc 24.0.1 with opentdf protocol mapper on board - image: cgr.dev/chainguard/keycloak@sha256:37895558d2e0e93ffff75da5900f9ae7e79ec6d1c390b18b2ecea6cee45ec26f + image: keycloak/keycloak:25.0 restart: always command: - "start-dev" @@ -32,6 +32,7 @@ services: KC_HTTP_ENABLED: "true" KC_HTTP_PORT: "8888" KC_HTTPS_PORT: "8443" + KC_HTTP_MANAGEMENT_PORT: "9001" KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: changeme #KC_HOSTNAME_URL: http://localhost:8888/auth @@ -43,11 +44,29 @@ services: KC_HTTPS_CERTIFICATE_KEY_FILE: "/etc/x509/tls/localhost.key" KC_HTTPS_CLIENT_AUTH: "request" ports: + - "9001:9001" - "8888:8888" - "8443:8443" healthcheck: - test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:8888/auth/health/live'] - interval: 5s + test: + - CMD-SHELL + - | + [ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { + public static void main(String[] args) throws java.lang.Throwable { + javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); + javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance(\"SSL\"); + sc.init(null, new javax.net.ssl.TrustManager[]{ + new javax.net.ssl.X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {} + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {} + } + }, new java.security.SecureRandom()); + javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + java.net.HttpURLConnection conn = (java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection(); + System.exit(java.net.HttpURLConnection.HTTP_OK == conn.getResponseCode() ? 0 : 1); + } + }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java https://localhost:9001/auth/health/live timeout: 10s retries: 3 start_period: 2m From 0ab8c24e1227a3b264235414657be93b3a3c8d38 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:10:05 +0000 Subject: [PATCH 22/32] chore(main): release lib/ocrypto 0.1.7 (#1754) :robot: I have created a release *beep* *boop* --- ## [0.1.7](https://github.com/opentdf/platform/compare/lib/ocrypto/v0.1.6...lib/ocrypto/v0.1.7) (2024-11-15) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> Co-authored-by: Sean Trantalis <strantalis@virtru.com> --- .release-please-manifest.json | 2 +- lib/ocrypto/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d26edac57..699e96373 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,6 +1,6 @@ { "lib/fixtures": "0.2.9", - "lib/ocrypto": "0.1.6", + "lib/ocrypto": "0.1.7", "lib/flattening": "0.1.2", "protocol/go": "0.2.22", "sdk": "0.3.20", diff --git a/lib/ocrypto/CHANGELOG.md b/lib/ocrypto/CHANGELOG.md index 47325000c..d9dfca584 100644 --- a/lib/ocrypto/CHANGELOG.md +++ b/lib/ocrypto/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.1.7](https://github.com/opentdf/platform/compare/lib/ocrypto/v0.1.6...lib/ocrypto/v0.1.7) (2024-11-15) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + ## [0.1.6](https://github.com/opentdf/platform/compare/lib/ocrypto/v0.1.5...lib/ocrypto/v0.1.6) (2024-10-03) From 04b6006746b1439ad757d54ea9e0428b4cc5cbf3 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:30:18 +0000 Subject: [PATCH 23/32] fix(core): Autobump examples (#1765) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- examples/go.mod | 3 +-- examples/go.sum | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index a72d964ea..cf486bc1f 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -3,7 +3,7 @@ module github.com/opentdf/platform/examples go 1.21 require ( - github.com/opentdf/platform/lib/ocrypto v0.1.6 + github.com/opentdf/platform/lib/ocrypto v0.1.7 github.com/opentdf/platform/protocol/go v0.2.20 github.com/opentdf/platform/sdk v0.3.19 github.com/spf13/cobra v1.8.1 @@ -31,7 +31,6 @@ require ( github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/jwx/v2 v2.0.21 // indirect github.com/lestrrat-go/option v1.0.1 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect diff --git a/examples/go.sum b/examples/go.sum index cf903079f..f20e49bfe 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,27 +1,36 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 h1:LEXWFH/xZ5oOWrC3oOtHbUyBdzRWMCPpAQmKC9v05mA= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1/go.mod h1:XF+P8+RmfdufmIYpGUC+6bF7S+IlmHDEnCrO3OXaUAQ= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= 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/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= +github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= 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= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= 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 v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+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= @@ -29,6 +38,7 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD 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.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/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= @@ -36,6 +46,7 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU 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/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -51,9 +62,11 @@ github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 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= @@ -75,12 +88,15 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/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/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/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/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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -91,8 +107,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentdf/platform/lib/fixtures v0.2.7 h1:2LxWmLBBISONVJnVDH8yMsV72VHQyirua0DwDBBoq+g= github.com/opentdf/platform/lib/fixtures v0.2.7/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= -github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+jbJXRRk4LcxII= -github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= +github.com/opentdf/platform/lib/ocrypto v0.1.7 h1:IcCYRrwmMqntqUE8frmUDg5EZ0WMdldpGeGhbv9+/A8= +github.com/opentdf/platform/lib/ocrypto v0.1.7/go.mod h1:4bhKPbRFzURMerH5Vr/LlszHvcoXQbfJXa0bpY7/7yg= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= github.com/opentdf/platform/sdk v0.3.19 h1:4Ign6HPrxOH6ZllLO/cI6joSuqz8CqPlpxpTKunpMQs= @@ -121,6 +137,7 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -131,6 +148,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= +github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E= 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/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -145,21 +163,34 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 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/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 949087e5e28e2ef082989d0b9622820f6ec57f69 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:32:15 +0000 Subject: [PATCH 24/32] fix(core): Autobump service (#1767) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- service/go.mod | 2 +- service/go.sum | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/service/go.mod b/service/go.mod index ec02b1115..fc6b6931d 100644 --- a/service/go.mod +++ b/service/go.mod @@ -22,7 +22,7 @@ require ( github.com/open-policy-agent/opa v0.68.0 github.com/opentdf/platform/lib/fixtures v0.2.8 github.com/opentdf/platform/lib/flattening v0.1.1 - github.com/opentdf/platform/lib/ocrypto v0.1.6 + github.com/opentdf/platform/lib/ocrypto v0.1.7 github.com/opentdf/platform/protocol/go v0.2.20 github.com/opentdf/platform/sdk v0.3.20 github.com/pressly/goose/v3 v3.19.1 diff --git a/service/go.sum b/service/go.sum index b0bcbcd80..84da2b7b4 100644 --- a/service/go.sum +++ b/service/go.sum @@ -158,6 +158,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= @@ -166,6 +167,7 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -275,8 +277,8 @@ github.com/opentdf/platform/lib/fixtures v0.2.8 h1:lGYrMnbORtU62lxsJi8qPsxjFuNIk github.com/opentdf/platform/lib/fixtures v0.2.8/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= github.com/opentdf/platform/lib/flattening v0.1.1 h1:la1f6PcRsc+yLH8+9UEr0ux6IRKu+6+oMaMVt05+8HU= github.com/opentdf/platform/lib/flattening v0.1.1/go.mod h1:eyG7pe5UZlV+GI5/CymQD3xTAJxNhnP9M4QnBzaad1M= -github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+jbJXRRk4LcxII= -github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= +github.com/opentdf/platform/lib/ocrypto v0.1.7 h1:IcCYRrwmMqntqUE8frmUDg5EZ0WMdldpGeGhbv9+/A8= +github.com/opentdf/platform/lib/ocrypto v0.1.7/go.mod h1:4bhKPbRFzURMerH5Vr/LlszHvcoXQbfJXa0bpY7/7yg= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= github.com/opentdf/platform/sdk v0.3.20 h1:zyBAZLhQaIv4X2twyPbmbdBd9Vc1vsTwxr1BIuESJWg= @@ -391,6 +393,7 @@ github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1 h1:Ebo6J5AMXgJ3A438ECYotA0aK7ETqjQ github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1/go.mod h1:udNPW8eupyH/EZocecFmaSNJacKKYjzQa7cVgX5U2nc= 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.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -428,6 +431,7 @@ golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUF golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= 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.4.2/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.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= @@ -438,6 +442,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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= @@ -450,6 +455,7 @@ golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbht 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-20210220032951-036812b2e83c/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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= @@ -460,6 +466,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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= @@ -497,6 +505,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn 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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= From 9ff9f615ff167c165e3150bf1b571d59e1924720 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:20:07 -0500 Subject: [PATCH 25/32] fix(core): Autobump sdk (#1766) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- sdk/go.mod | 3 +-- sdk/go.sum | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/sdk/go.mod b/sdk/go.mod index 6ba6ea407..54f753522 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -8,7 +8,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/lestrrat-go/jwx/v2 v2.0.21 github.com/opentdf/platform/lib/fixtures v0.2.8 - github.com/opentdf/platform/lib/ocrypto v0.1.6 + github.com/opentdf/platform/lib/ocrypto v0.1.7 github.com/opentdf/platform/protocol/go v0.2.20 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 @@ -68,7 +68,6 @@ require ( 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/rogpeppe/go-internal v1.12.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect diff --git a/sdk/go.sum b/sdk/go.sum index 5bb4943b6..93e9acadc 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,4 +1,5 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 h1:LEXWFH/xZ5oOWrC3oOtHbUyBdzRWMCPpAQmKC9v05mA= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1/go.mod h1:XF+P8+RmfdufmIYpGUC+6bF7S+IlmHDEnCrO3OXaUAQ= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= @@ -6,15 +7,19 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h 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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= 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/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= +github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= 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= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -25,8 +30,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= 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 v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+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= @@ -35,6 +43,7 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 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/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= @@ -42,6 +51,7 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU 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/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -59,9 +69,11 @@ github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= 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/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= @@ -83,12 +95,15 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/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/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/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/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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -99,8 +114,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentdf/platform/lib/fixtures v0.2.8 h1:lGYrMnbORtU62lxsJi8qPsxjFuNIkc4Dop8rVkH6pD0= github.com/opentdf/platform/lib/fixtures v0.2.8/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= -github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+jbJXRRk4LcxII= -github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM= +github.com/opentdf/platform/lib/ocrypto v0.1.7 h1:IcCYRrwmMqntqUE8frmUDg5EZ0WMdldpGeGhbv9+/A8= +github.com/opentdf/platform/lib/ocrypto v0.1.7/go.mod h1:4bhKPbRFzURMerH5Vr/LlszHvcoXQbfJXa0bpY7/7yg= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= @@ -113,6 +128,7 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH 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/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 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= @@ -137,6 +153,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= +github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E= 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/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -154,14 +171,21 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 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/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= 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= @@ -169,6 +193,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y 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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -186,7 +211,9 @@ 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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -210,6 +237,7 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= @@ -217,6 +245,7 @@ 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.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= 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= @@ -224,8 +253,10 @@ 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.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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= @@ -237,9 +268,13 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T 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-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -249,3 +284,4 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C 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= From c60c3219562be566407cc600bbac22213a0b9973 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:42:28 -0500 Subject: [PATCH 26/32] chore(main): release sdk 0.3.21 (#1756) :robot: I have created a release *beep* *boop* --- ## [0.3.21](https://github.com/opentdf/platform/compare/sdk/v0.3.20...sdk/v0.3.21) (2024-11-15) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) ### Bug Fixes * **core:** Autobump sdk ([#1766](https://github.com/opentdf/platform/issues/1766)) ([9ff9f61](https://github.com/opentdf/platform/commit/9ff9f615ff167c165e3150bf1b571d59e1924720)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- sdk/CHANGELOG.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 699e96373..f5622db4d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -3,6 +3,6 @@ "lib/ocrypto": "0.1.7", "lib/flattening": "0.1.2", "protocol/go": "0.2.22", - "sdk": "0.3.20", + "sdk": "0.3.21", "service": "0.4.27" } diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 4a13ce040..2bf3bca88 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.3.21](https://github.com/opentdf/platform/compare/sdk/v0.3.20...sdk/v0.3.21) (2024-11-15) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + + +### Bug Fixes + +* **core:** Autobump sdk ([#1766](https://github.com/opentdf/platform/issues/1766)) ([9ff9f61](https://github.com/opentdf/platform/commit/9ff9f615ff167c165e3150bf1b571d59e1924720)) + ## [0.3.20](https://github.com/opentdf/platform/compare/sdk/v0.3.19...sdk/v0.3.20) (2024-11-13) From 8c7051ce5475f7aa45d6395dd3cbc681e3a387e8 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:01:50 +0000 Subject: [PATCH 27/32] fix(core): Autobump examples (#1770) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- examples/go.mod | 9 +-------- examples/go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index cf486bc1f..7e7a277a1 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/opentdf/platform/lib/ocrypto v0.1.7 github.com/opentdf/platform/protocol/go v0.2.20 - github.com/opentdf/platform/sdk v0.3.19 + github.com/opentdf/platform/sdk v0.3.21 github.com/spf13/cobra v1.8.1 google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 @@ -13,18 +13,14 @@ require ( require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/containerd/containerd v1.7.21 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect - github.com/docker/docker v27.1.1+incompatible // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gowebpki/jcs v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.5 // indirect @@ -34,12 +30,9 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/testcontainers/testcontainers-go v0.32.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index f20e49bfe..6ff65b456 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -105,14 +105,14 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opentdf/platform/lib/fixtures v0.2.7 h1:2LxWmLBBISONVJnVDH8yMsV72VHQyirua0DwDBBoq+g= -github.com/opentdf/platform/lib/fixtures v0.2.7/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= +github.com/opentdf/platform/lib/fixtures v0.2.8 h1:lGYrMnbORtU62lxsJi8qPsxjFuNIkc4Dop8rVkH6pD0= +github.com/opentdf/platform/lib/fixtures v0.2.8/go.mod h1:8yCSe+oUzW9jbM573r9qgE68rjwDMNzktObiGVsO/W8= github.com/opentdf/platform/lib/ocrypto v0.1.7 h1:IcCYRrwmMqntqUE8frmUDg5EZ0WMdldpGeGhbv9+/A8= github.com/opentdf/platform/lib/ocrypto v0.1.7/go.mod h1:4bhKPbRFzURMerH5Vr/LlszHvcoXQbfJXa0bpY7/7yg= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= -github.com/opentdf/platform/sdk v0.3.19 h1:4Ign6HPrxOH6ZllLO/cI6joSuqz8CqPlpxpTKunpMQs= -github.com/opentdf/platform/sdk v0.3.19/go.mod h1:u+XZhVRsMq5blukCFCHcjk6HLCp4Y5mmIQu7GhtKQ3E= +github.com/opentdf/platform/sdk v0.3.21 h1:18oZk8t32luXBL2lhRa3qvjTY17Y3PmA0Wp1F8tdkqc= +github.com/opentdf/platform/sdk v0.3.21/go.mod h1:KpT/m5zXQ19WqhGePKfIC39Ly8LOipKdKGbJ1B/59a8= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 7a2e709acbe0e01df74b0691a93fe54b03754f0c Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:03:19 +0000 Subject: [PATCH 28/32] fix(core): Autobump service (#1771) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- service/go.mod | 2 +- service/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/service/go.mod b/service/go.mod index fc6b6931d..1b64da071 100644 --- a/service/go.mod +++ b/service/go.mod @@ -24,7 +24,7 @@ require ( github.com/opentdf/platform/lib/flattening v0.1.1 github.com/opentdf/platform/lib/ocrypto v0.1.7 github.com/opentdf/platform/protocol/go v0.2.20 - github.com/opentdf/platform/sdk v0.3.20 + github.com/opentdf/platform/sdk v0.3.21 github.com/pressly/goose/v3 v3.19.1 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.18.2 diff --git a/service/go.sum b/service/go.sum index 84da2b7b4..bb87ba553 100644 --- a/service/go.sum +++ b/service/go.sum @@ -281,8 +281,8 @@ github.com/opentdf/platform/lib/ocrypto v0.1.7 h1:IcCYRrwmMqntqUE8frmUDg5EZ0WMdl github.com/opentdf/platform/lib/ocrypto v0.1.7/go.mod h1:4bhKPbRFzURMerH5Vr/LlszHvcoXQbfJXa0bpY7/7yg= github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws= github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto= -github.com/opentdf/platform/sdk v0.3.20 h1:zyBAZLhQaIv4X2twyPbmbdBd9Vc1vsTwxr1BIuESJWg= -github.com/opentdf/platform/sdk v0.3.20/go.mod h1:O4tyqjK9sJwp+6jUeiJjECe9TQfqaD1kTr6wgsRxkWc= +github.com/opentdf/platform/sdk v0.3.21 h1:18oZk8t32luXBL2lhRa3qvjTY17Y3PmA0Wp1F8tdkqc= +github.com/opentdf/platform/sdk v0.3.21/go.mod h1:KpT/m5zXQ19WqhGePKfIC39Ly8LOipKdKGbJ1B/59a8= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= From cd354d7ea3e9037ad180abe1d9edbdf43f7fc1e6 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:26:49 -0500 Subject: [PATCH 29/32] chore(main): release service 0.4.28 (#1757) :robot: I have created a release *beep* *boop* --- ## [0.4.28](https://github.com/opentdf/platform/compare/service/v0.4.27...service/v0.4.28) (2024-11-15) ### Features * **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) ### Bug Fixes * **core:** Autobump service ([#1767](https://github.com/opentdf/platform/issues/1767)) ([949087e](https://github.com/opentdf/platform/commit/949087e5e28e2ef082989d0b9622820f6ec57f69)) * **core:** Autobump service ([#1771](https://github.com/opentdf/platform/issues/1771)) ([7a2e709](https://github.com/opentdf/platform/commit/7a2e709acbe0e01df74b0691a93fe54b03754f0c)) * **core:** Updates dpop check for connect ([#1760](https://github.com/opentdf/platform/issues/1760)) ([6d7f24a](https://github.com/opentdf/platform/commit/6d7f24a32222a9eff73c769ac9ec3af91058c7ea)) * grpc-gateway connection with tls enabled ([#1758](https://github.com/opentdf/platform/issues/1758)) ([3120350](https://github.com/opentdf/platform/commit/312035008dfd42c94d3e8135d05deb4cc5bfe21f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- service/CHANGELOG.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f5622db4d..4d04dbdbc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,5 +4,5 @@ "lib/flattening": "0.1.2", "protocol/go": "0.2.22", "sdk": "0.3.21", - "service": "0.4.27" + "service": "0.4.28" } diff --git a/service/CHANGELOG.md b/service/CHANGELOG.md index 1c55a721b..f55276fa0 100644 --- a/service/CHANGELOG.md +++ b/service/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [0.4.28](https://github.com/opentdf/platform/compare/service/v0.4.27...service/v0.4.28) (2024-11-15) + + +### Features + +* **sdk:** add collections for nanotdf ([#1695](https://github.com/opentdf/platform/issues/1695)) ([6497bf3](https://github.com/opentdf/platform/commit/6497bf3a7cee9b6900569bc6cc2c39b2f647fb52)) + + +### Bug Fixes + +* **core:** Autobump service ([#1767](https://github.com/opentdf/platform/issues/1767)) ([949087e](https://github.com/opentdf/platform/commit/949087e5e28e2ef082989d0b9622820f6ec57f69)) +* **core:** Autobump service ([#1771](https://github.com/opentdf/platform/issues/1771)) ([7a2e709](https://github.com/opentdf/platform/commit/7a2e709acbe0e01df74b0691a93fe54b03754f0c)) +* **core:** Updates dpop check for connect ([#1760](https://github.com/opentdf/platform/issues/1760)) ([6d7f24a](https://github.com/opentdf/platform/commit/6d7f24a32222a9eff73c769ac9ec3af91058c7ea)) +* grpc-gateway connection with tls enabled ([#1758](https://github.com/opentdf/platform/issues/1758)) ([3120350](https://github.com/opentdf/platform/commit/312035008dfd42c94d3e8135d05deb4cc5bfe21f)) + ## [0.4.27](https://github.com/opentdf/platform/compare/service/v0.4.26...service/v0.4.27) (2024-11-14) From dff34ffabf190f21d2f866de23bf9ef955ab7c12 Mon Sep 17 00:00:00 2001 From: Ryan Schumacher <jschumacher@virtru.com> Date: Mon, 18 Nov 2024 09:45:35 -0600 Subject: [PATCH 30/32] feat(core): programmatic setting of authz policy (#1769) Closes #1768 ### Proposed Changes * Enables programmatic setting of authz policy ### Checklist - [x] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [x] I have added or updated documentation ### Testing Instructions --------- Co-authored-by: Jake Van Vorhis <83739412+jakedoublev@users.noreply.github.com> Co-authored-by: Sean Trantalis <strantalis@virtru.com> Co-authored-by: jakedoublev <jake.vanvorhis@virtru.com> --- service/internal/auth/authn.go | 6 +++ service/internal/auth/casbin.go | 12 ++++++ service/internal/auth/casbin_test.go | 59 ++++++++++++++++++++++++++++ service/pkg/server/options.go | 17 ++++++++ service/pkg/server/start.go | 14 +++++++ 5 files changed, 108 insertions(+) diff --git a/service/internal/auth/authn.go b/service/internal/auth/authn.go index 1b922df47..ef9d5310f 100644 --- a/service/internal/auth/authn.go +++ b/service/internal/auth/authn.go @@ -197,10 +197,16 @@ func normalizeURL(o string, u *url.URL) string { return ou.String() } +// deprecated func (a *Authentication) ExtendAuthzDefaultPolicy(policies [][]string) error { return a.enforcer.ExtendDefaultPolicy(policies) } +// SetAuthzPolicy sets the policy for the casbin enforcer +func (a *Authentication) SetAuthzPolicy(policy string) error { + return a.enforcer.SetPolicy(policy) +} + // verifyTokenHandler is a http handler that verifies the token func (a Authentication) MuxHandler(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/service/internal/auth/casbin.go b/service/internal/auth/casbin.go index 8bc392b49..cb4c0851e 100644 --- a/service/internal/auth/casbin.go +++ b/service/internal/auth/casbin.go @@ -179,6 +179,7 @@ func NewCasbinEnforcer(c CasbinConfig, logger *logger.Logger) (*Enforcer, error) }, nil } +// deprecated // Extend the default policy func (e *Enforcer) ExtendDefaultPolicy(policies [][]string) error { if !e.isDefaultPolicy { @@ -215,6 +216,17 @@ func (e *Enforcer) ExtendDefaultPolicy(policies [][]string) error { return nil } +// SetPolicy sets the policy for the enforcer +func (e *Enforcer) SetPolicy(policy string) error { + a := stringadapter.NewAdapter(policy) + e.SetAdapter(a) + if err := e.LoadPolicy(); err != nil { + return fmt.Errorf("failed to load extended default policy: %w", err) + } + e.isDefaultPolicy = false + return nil +} + // casbinEnforce is a helper function to enforce the policy with casbin // TODO implement a common type so this can be used for both http and grpc func (e *Enforcer) Enforce(token jwt.Token, resource, action string) (bool, error) { diff --git a/service/internal/auth/casbin_test.go b/service/internal/auth/casbin_test.go index 8a013f0d0..c4d480a17 100644 --- a/service/internal/auth/casbin_test.go +++ b/service/internal/auth/casbin_test.go @@ -3,6 +3,7 @@ package auth import ( "fmt" "log/slog" + "strings" "testing" "github.com/casbin/casbin/v2/model" @@ -455,3 +456,61 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MalformedErrors() { s.Require().Error(err) s.Require().ErrorIs(err, ErrPolicyMalformed) } + +func (s *AuthnCasbinSuite) Test_SetPolicy() { + enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) + s.Require().NoError(err) + + // Org-admin role + err = enforcer.SetPolicy(strings.Join([]string{ + "p, role:admin, new.hello.*, *, allow", + "p, role:standard, new.hello.*, read, allow", + "p, role:standard, new.hello.*, write, deny", + }, "\n")) + s.Require().NoError(err) + + // unauthorized role + tok := s.newTokWithDefaultClaim(false, false) + allowed, err := enforcer.Enforce(tok, "new.hello.World", "read") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.hello.World", "write") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") + s.Require().Error(err) + s.False(allowed) + + // other roles denied new policy: admin + tok = s.newTokWithDefaultClaim(true, false) + allowed, err = enforcer.Enforce(tok, "new.hello.World", "read") + s.Require().NoError(err) + s.True(allowed) + allowed, err = enforcer.Enforce(tok, "new.hello.World", "write") + s.Require().NoError(err) + s.True(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") + s.Require().Error(err) + s.False(allowed) + + // other roles denied new policy: standard + tok = s.newTokWithDefaultClaim(false, true) + allowed, err = enforcer.Enforce(tok, "new.hello.World", "read") + s.Require().NoError(err) + s.True(allowed) + allowed, err = enforcer.Enforce(tok, "new.hello.World", "write") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read") + s.Require().Error(err) + s.False(allowed) + allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write") + s.Require().Error(err) + s.False(allowed) +} diff --git a/service/pkg/server/options.go b/service/pkg/server/options.go index a570f957d..e80b84b8a 100644 --- a/service/pkg/server/options.go +++ b/service/pkg/server/options.go @@ -12,11 +12,13 @@ type StartConfig struct { WaitForShutdownSignal bool PublicRoutes []string authzDefaultPolicyExtension [][]string + authzPolicy string extraCoreServices []serviceregistry.IService extraServices []serviceregistry.IService } // Deprecated: Use WithConfigKey +// WithConfigName option sets the configuration name. func WithConfigName(name string) StartOptions { return func(c StartConfig) StartConfig { c.ConfigKey = name @@ -58,6 +60,7 @@ func WithPublicRoutes(routes []string) StartOptions { } } +// Deprecated: Use WithAuthZPolicy // WithAuthZDefaultPolicyExtension option allows for extending the default casbin poliy // Example: // @@ -71,6 +74,20 @@ func WithAuthZDefaultPolicyExtension(policies [][]string) StartOptions { } } +// WithAuthZPolicy option sets the casbin policy to be used. +// Example: +// +// opentdf.WithAuthZPolicy(strings.Join([]string{ +// "p, role:admin, pep*, *, allow", +// "p, role:standard, pep*, read, allow", +// }, "\n")), +func WithAuthZPolicy(policy string) StartOptions { + return func(c StartConfig) StartConfig { + c.authzPolicy = policy + return c + } +} + // WithCoreServices option adds additional core services to the platform // It takes a variadic parameter of type serviceregistry.Registration, which represents the core services to be added. func WithCoreServices(services ...serviceregistry.IService) StartOptions { diff --git a/service/pkg/server/start.go b/service/pkg/server/start.go index dbbdf190b..1e86a91f8 100644 --- a/service/pkg/server/start.go +++ b/service/pkg/server/start.go @@ -88,6 +88,20 @@ func Start(f ...StartOptions) error { } } + // Set the authz policy + if startConfig.authzPolicy != "" { + if otdf.AuthN == nil { + err := errors.New("authn not enabled") + logger.Error("issue setting authz policy", slog.String("error", err.Error())) + return fmt.Errorf("issue setting authz policy: %w", err) + } + err := otdf.AuthN.SetAuthzPolicy(startConfig.authzPolicy) + if err != nil { + logger.Error("issue setting authz policy", slog.String("error", err.Error())) + return fmt.Errorf("issue setting authz policy: %w", err) + } + } + // Initialize the service registry logger.Debug("initializing service registry") svcRegistry := serviceregistry.NewServiceRegistry() From 0b16ae92a57561e1d3217d813481c93d785bd3e1 Mon Sep 17 00:00:00 2001 From: "opentdf-automation[bot]" <149537512+opentdf-automation[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:37:20 -0500 Subject: [PATCH 31/32] chore(main): release service 0.4.29 (#1772) :robot: I have created a release *beep* *boop* --- ## [0.4.29](https://github.com/opentdf/platform/compare/service/v0.4.28...service/v0.4.29) (2024-11-18) ### Features * **core:** programmatic setting of authz policy ([#1769](https://github.com/opentdf/platform/issues/1769)) ([dff34ff](https://github.com/opentdf/platform/commit/dff34ffabf190f21d2f866de23bf9ef955ab7c12)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- service/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4d04dbdbc..668d34873 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,5 +4,5 @@ "lib/flattening": "0.1.2", "protocol/go": "0.2.22", "sdk": "0.3.21", - "service": "0.4.28" + "service": "0.4.29" } diff --git a/service/CHANGELOG.md b/service/CHANGELOG.md index f55276fa0..03dee033b 100644 --- a/service/CHANGELOG.md +++ b/service/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.4.29](https://github.com/opentdf/platform/compare/service/v0.4.28...service/v0.4.29) (2024-11-18) + + +### Features + +* **core:** programmatic setting of authz policy ([#1769](https://github.com/opentdf/platform/issues/1769)) ([dff34ff](https://github.com/opentdf/platform/commit/dff34ffabf190f21d2f866de23bf9ef955ab7c12)) + ## [0.4.28](https://github.com/opentdf/platform/compare/service/v0.4.27...service/v0.4.28) (2024-11-15) From ec46a3a4375d6fe1c948c6f25146bb572717c651 Mon Sep 17 00:00:00 2001 From: Jake Van Vorhis <83739412+jakedoublev@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:26:47 -0800 Subject: [PATCH 32/32] feat(policy): limit/offset throughout LIST service RPCs/db (#1669) Closes #55 --- docs/configuration.md | 18 + opentdf-dev.yaml | 5 + opentdf-example.yaml | 5 + opentdf-with-hsm.yaml | 2 + service/cmd/policy.go | 8 +- service/integration/attribute_values_test.go | 191 +++++- service/integration/attributes_test.go | 203 ++++-- service/integration/config.go | 4 - service/integration/kas_registry_test.go | 242 ++++++-- service/integration/namespaces_test.go | 169 +++-- service/integration/resource_mappings_test.go | 197 ++++-- service/integration/subject_mappings_test.go | 167 ++++- service/internal/fixtures/db.go | 12 +- service/internal/fixtures/fixtures.go | 6 - service/pkg/db/errors.go | 6 + service/policy/attributes/attributes.go | 25 +- service/policy/config/config.go | 38 ++ service/policy/db/attribute_fqn.go | 8 +- service/policy/db/attribute_values.go | 60 +- service/policy/db/attributes.go | 63 +- .../policy/db/key_access_server_registry.go | 63 +- service/policy/db/namespaces.go | 69 +- service/policy/db/policy.go | 32 +- service/policy/db/query.sql | 235 ++++--- service/policy/db/query.sql.go | 587 +++++++++++++----- service/policy/db/resource_mapping.go | 62 +- service/policy/db/subject_mappings.go | 60 +- service/policy/db/utils.go | 21 + service/policy/db/utils_test.go | 92 +++ .../kasregistry/key_access_server_registry.go | 25 +- service/policy/namespaces/namespaces.go | 15 +- .../resourcemapping/resource_mapping.go | 22 +- .../policy/subjectmapping/subject_mapping.go | 22 +- service/policy/unsafe/unsafe.go | 10 +- 34 files changed, 2178 insertions(+), 566 deletions(-) create mode 100644 service/policy/config/config.go create mode 100644 service/policy/db/utils_test.go diff --git a/docs/configuration.md b/docs/configuration.md index b9ffd50e6..9997a71a5 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -219,6 +219,24 @@ services: query: data.opentdf.entitlements.attributes ``` +### Policy + +Root level key `policy` + +| Field | Description | Default | Environment Variables | +| ---------------------------- | ------------------------------------------------------ | ------- | -------------------------------------------------- | +| `list_request_limit_default` | Policy List request limit default when not provided | 1000 | OPENTDF_SERVICES_POLICY_LIST_REQUEST_LIMIT_DEFAULT | +| `list_request_limit_max` | Policy List request limit maximum enforced by services | 2500 | OPENTDF_SERVICES_POLICY_LIST_REQUEST_LIMIT_MAX | + +Example: + +```yaml +services: + policy: + list_request_limit_default: 1000 + list_request_limit_max: 2500 +``` + ### Casbin Endpoint Authorization OpenTDF uses Casbin to manage authorization policies. This document provides an overview of how to configure and manage the default authorization policy in OpenTDF. diff --git a/opentdf-dev.yaml b/opentdf-dev.yaml index 7c1f5d2b9..5ea3bf2fe 100644 --- a/opentdf-dev.yaml +++ b/opentdf-dev.yaml @@ -32,6 +32,11 @@ services: from: email: true username: true + # policy is enabled by default in mode 'all' + # policy: + # enabled: true + # list_request_limit_default: 1000 + # list_request_limit_max: 2500 server: tls: enabled: false diff --git a/opentdf-example.yaml b/opentdf-example.yaml index 6fd6549ae..1033c066c 100644 --- a/opentdf-example.yaml +++ b/opentdf-example.yaml @@ -23,6 +23,11 @@ services: from: email: true username: true + # policy is enabled by default in mode 'all' + # policy: + # enabled: true + # list_request_limit_default: 1000 + # list_request_limit_max: 2500 server: auth: enabled: true diff --git a/opentdf-with-hsm.yaml b/opentdf-with-hsm.yaml index 476a45922..92871daae 100644 --- a/opentdf-with-hsm.yaml +++ b/opentdf-with-hsm.yaml @@ -15,6 +15,8 @@ services: rsacertid: r1 policy: enabled: true + # list_request_limit_default: 1000 + # list_request_limit_max: 2500 entityresolution: enabled: true url: http://localhost:8888/auth diff --git a/service/cmd/policy.go b/service/cmd/policy.go index cadcf4ecc..eea0bca5f 100644 --- a/service/cmd/policy.go +++ b/service/cmd/policy.go @@ -83,7 +83,13 @@ func policyDBClient(conf *config.Config) (policydb.PolicyDBClient, error) { return policydb.PolicyDBClient{}, err } - return policydb.NewClient(dbClient, logger), nil + // This command connects directly to the database so runtime policy config list limit settings can be ignored + var ( + limitDefault int32 = 1000 + limitMax int32 = 2500 + ) + + return policydb.NewClient(dbClient, logger, limitMax, limitDefault), nil } func init() { diff --git a/service/integration/attribute_values_test.go b/service/integration/attribute_values_test.go index 882daa7a3..60a1b5a1f 100644 --- a/service/integration/attribute_values_test.go +++ b/service/integration/attribute_values_test.go @@ -13,8 +13,8 @@ import ( "github.com/opentdf/platform/protocol/go/policy/unsafe" "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" - policydb "github.com/opentdf/platform/service/policy/db" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/proto" ) var absentAttributeValueUUID = "78909865-8888-9999-9999-000000000000" @@ -44,30 +44,143 @@ func (s *AttributeValuesSuite) TearDownSuite() { s.f.TearDown() } -func (s *AttributeValuesSuite) Test_ListAttributeValues() { +func (s *AttributeValuesSuite) Test_ListAttributeValues_WithAttributeID_Succeeds() { attrID := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1").AttributeDefinitionID - list, err := s.db.PolicyClient.ListAttributeValues(s.ctx, attrID, policydb.StateActive) + listRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + AttributeId: attrID, + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, + }) s.Require().NoError(err) - s.NotNil(list) + s.NotNil(listRsp) + listed := listRsp.GetValues() // ensure list contains the two test fixtures and that response matches expected data f1 := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1") f2 := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value2") - for _, item := range list { - if item.GetId() == f1.ID { - s.Equal(f1.ID, item.GetId()) - s.Equal(f1.Value, item.GetValue()) - // s.Equal(f1.AttributeDefinitionId, item.AttributeId) - } else if item.GetId() == f2.ID { - s.Equal(f2.ID, item.GetId()) - s.Equal(f2.Value, item.GetValue()) - // s.Equal(f2.AttributeDefinitionId, item.AttributeId) + for _, val := range listed { + if val.GetId() == f1.ID { + s.Equal(f1.ID, val.GetId()) + s.Equal(f1.Value, val.GetValue()) + s.Equal(f1.AttributeDefinitionID, val.GetAttribute().GetId()) + } else if val.GetId() == f2.ID { + s.Equal(f2.ID, val.GetId()) + s.Equal(f2.Value, val.GetValue()) + s.Equal(f2.AttributeDefinitionID, val.GetAttribute().GetId()) } } } +func (s *AttributeValuesSuite) Test_ListAttributeValues_NoPagination_Succeeds() { + allFixtureValueFqns := map[string]bool{ + "https://example.com/attr/attr1/value/value1": false, + "https://example.com/attr/attr1/value/value2": false, + "https://example.com/attr/attr2/value/value1": false, + "https://example.com/attr/attr2/value/value2": false, + "https://example.net/attr/attr1/value/value1": false, + "https://example.net/attr/attr1/value/value2": false, + "https://scenario.com/attr/working_group/value/blue": false, + "https://deactivated.io/attr/deactivated_attr/value/deactivated_value": false, + } + listRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + // mark every listed value true + for _, val := range listRsp.GetValues() { + allFixtureValueFqns[val.GetFqn()] = true + } + // ensure all fixtures were found by unbounded list + for fqn, found := range allFixtureValueFqns { + if !found { + s.Failf("failed to list fixture", fqn) + } + } +} + +func (s *AttributeValuesSuite) Test_ListAttributeValues_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetValues() + s.Equal(len(listed), int(limit)) + + for _, val := range listed { + s.NotEmpty(val.GetFqn()) + s.NotEmpty(val.GetId()) + s.NotEmpty(val.GetValue()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + // request with exactly maximum + listRsp, err = s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListAttributeValues_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *AttributeValuesSuite) Test_ListAttributeValues_Offset_Succeeds() { + req := &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + } + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetValues() + + // set the offset pagination + offset := 5 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetValues() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, val := range offsetListed { + s.True(proto.Equal(val, listed[i+offset])) + } +} + func (s *AttributeValuesSuite) Test_GetAttributeValue() { f := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1") v, err := s.db.PolicyClient.GetAttributeValue(s.ctx, f.ID) @@ -133,7 +246,7 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_SetsActiveStateTrueByDe attrDef := s.f.GetAttributeKey("example.net/attr/attr1") req := &attributes.CreateAttributeValueRequest{ - Value: "testing create gives active true by default", + Value: "testing-create-gives-active-true-by-default", } createdValue, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.ID, req) s.Require().NoError(err) @@ -495,15 +608,18 @@ func setupDeactivateAttributeValue(s *AttributeValuesSuite) (string, string, str func (s *AttributeValuesSuite) Test_DeactivateAttribute_Cascades_List() { type test struct { name string - testFunc func(state string) bool - state string + testFunc func(state common.ActiveStateEnum) bool + state common.ActiveStateEnum isFound bool } - listNamespaces := func(state string) bool { - listedNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, state) + listNamespaces := func(state common.ActiveStateEnum) bool { + listedNamespacesRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedNamespaces) + s.NotNil(listedNamespacesRsp) + listedNamespaces := listedNamespacesRsp.GetNamespaces() for _, ns := range listedNamespaces { if stillActiveNsID == ns.GetId() { return true @@ -512,10 +628,13 @@ func (s *AttributeValuesSuite) Test_DeactivateAttribute_Cascades_List() { return false } - listAttributes := func(state string) bool { - listedAttrs, err := s.db.PolicyClient.ListAttributes(s.ctx, state, "") + listAttributes := func(state common.ActiveStateEnum) bool { + listedAttrsRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedAttrs) + s.NotNil(listedAttrsRsp) + listedAttrs := listedAttrsRsp.GetAttributes() for _, a := range listedAttrs { if stillActiveAttributeID == a.GetId() { return true @@ -524,10 +643,14 @@ func (s *AttributeValuesSuite) Test_DeactivateAttribute_Cascades_List() { return false } - listValues := func(state string) bool { - listedVals, err := s.db.PolicyClient.ListAttributeValues(s.ctx, stillActiveAttributeID, state) + listValues := func(state common.ActiveStateEnum) bool { + listedValsRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + State: state, + AttributeId: stillActiveAttributeID, + }) s.Require().NoError(err) - s.NotNil(listedVals) + s.NotNil(listedValsRsp) + listedVals := listedValsRsp.GetValues() for _, v := range listedVals { if deactivatedAttrValueID == v.GetId() { return true @@ -540,55 +663,55 @@ func (s *AttributeValuesSuite) Test_DeactivateAttribute_Cascades_List() { { name: "namespace is NOT found in LIST of INACTIVE", testFunc: listNamespaces, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: false, }, { name: "namespace is found when filtering for ACTIVE state", testFunc: listNamespaces, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: true, }, { name: "namespace is found when filtering for ANY state", testFunc: listNamespaces, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is NOT found when filtering for INACTIVE state", testFunc: listAttributes, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: false, }, { name: "attribute is found when filtering for ANY state", testFunc: listAttributes, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is found when filtering for ACTIVE state", testFunc: listAttributes, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: true, }, { name: "value is NOT found in LIST of ACTIVE", testFunc: listValues, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "value is found when filtering for INACTIVE state", testFunc: listValues, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "value is found when filtering for ANY state", testFunc: listValues, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, } diff --git a/service/integration/attributes_test.go b/service/integration/attributes_test.go index af98d819f..e99d0ddcf 100644 --- a/service/integration/attributes_test.go +++ b/service/integration/attributes_test.go @@ -18,6 +18,7 @@ import ( "github.com/opentdf/platform/service/pkg/db" policydb "github.com/opentdf/platform/service/policy/db" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/proto" ) type AttributesSuite struct { @@ -369,17 +370,20 @@ func (s *AttributesSuite) Test_GetAttribute_ContainsKASGrants() { s.Equal(kas.GetName(), gotGrants[0].GetName()) } -func (s *AttributesSuite) Test_ListAttributes() { +func (s *AttributesSuite) Test_ListAttributes_NoPagination_Succeeds() { fixtures := s.getAttributeFixtures() - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateActive, "") + r := &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + } + listRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, r) s.Require().NoError(err) - s.NotNil(list) + s.NotNil(listRsp) // all fixtures are listed for _, f := range fixtures { var found bool - for _, l := range list { + for _, l := range listRsp.GetAttributes() { if f.ID == l.GetId() { found = true break @@ -389,6 +393,87 @@ func (s *AttributesSuite) Test_ListAttributes() { } } +func (s *AttributesSuite) Test_ListAttributes_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetAttributes() + s.Equal(len(listed), int(limit)) + + for _, definition := range listed { + s.NotEmpty(definition.GetFqn()) + s.NotEmpty(definition.GetId()) + s.NotEmpty(definition.GetName()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + // exactly maximum + listRsp, err = s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListAttributes_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *AttributesSuite) Test_ListAttributes_Offset_Succeeds() { + req := &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + } + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetAttributes() + + // set the offset pagination + offset := 2 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetAttributes() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, attr := range offsetListed { + s.True(proto.Equal(attr, listed[i+offset])) + } +} + func (s *AttributesSuite) Test_ListAttributes_FqnsIncluded() { // create an attribute attr := &attributes.CreateAttributeRequest{ @@ -401,11 +486,15 @@ func (s *AttributesSuite) Test_ListAttributes_FqnsIncluded() { s.Require().NoError(err) s.NotNil(createdAttr) - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateActive, fixtureNamespaceID) + r := &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, + Namespace: fixtureNamespaceID, + } + list, err := s.db.PolicyClient.ListAttributes(s.ctx, r) s.Require().NoError(err) s.NotNil(list) - for _, a := range list { + for _, a := range list.GetAttributes() { // attr fqn s.NotEqual("", a.GetFqn()) s.Equal(fmt.Sprintf("https://%s/attr/%s", a.GetNamespace().GetName(), a.GetName()), a.GetFqn()) @@ -428,37 +517,45 @@ func (s *AttributesSuite) Test_ListAttributes_ByNamespaceIdOrName() { for _, f := range s.getAttributeFixtures() { namespaces[f.NamespaceID] = "" } + r := &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + } // list attributes by namespace id for nsID := range namespaces { - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateAny, nsID) + r.Namespace = nsID + rsp, err := s.db.PolicyClient.ListAttributes(s.ctx, r) s.Require().NoError(err) - s.NotNil(list) - s.NotEmpty(list) - for _, l := range list { + s.NotNil(rsp) + listed := rsp.GetAttributes() + s.NotEmpty(listed) + for _, l := range listed { s.Equal(nsID, l.GetNamespace().GetId()) } - namespaces[nsID] = list[0].GetNamespace().GetName() + namespaces[nsID] = listed[0].GetNamespace().GetName() } // list attributes by namespace name for _, nsName := range namespaces { - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateAny, nsName) + r.Namespace = nsName + rsp, err := s.db.PolicyClient.ListAttributes(s.ctx, r) s.Require().NoError(err) - s.NotNil(list) - s.NotEmpty(list) - for _, l := range list { + s.NotNil(rsp) + listed := rsp.GetAttributes() + s.NotEmpty(listed) + for _, l := range listed { s.Equal(nsName, l.GetNamespace().GetName()) } } // list attributes by namespace name with case insensitivity for _, nsName := range namespaces { - upperNsName := strings.ToUpper(nsName) - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateAny, upperNsName) + r.Namespace = strings.ToUpper(nsName) + rsp, err := s.db.PolicyClient.ListAttributes(s.ctx, r) s.Require().NoError(err) - s.NotNil(list) - s.NotEmpty(list) - for _, l := range list { + s.NotNil(rsp) + listed := rsp.GetAttributes() + s.NotEmpty(listed) + for _, l := range listed { s.Equal(nsName, l.GetNamespace().GetName()) } } @@ -812,10 +909,14 @@ func (s *AttributesSuite) Test_UnsafeDeleteAttribute() { s.NotEqual("", ns.GetId()) // attribute should not be listed anymore - list, err := s.db.PolicyClient.ListAttributes(s.ctx, policydb.StateAny, fixtureNamespaceID) + rsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Namespace: fixtureNamespaceID, + }) s.Require().NoError(err) - s.NotNil(list) - for _, l := range list { + s.NotNil(rsp) + listed := rsp.GetAttributes() + for _, l := range listed { s.NotEqual(createdAttr.GetId(), l.GetId()) } @@ -908,16 +1009,19 @@ func setupCascadeDeactivateAttribute(s *AttributesSuite) (string, string, string func (s *AttributesSuite) Test_DeactivateAttribute_Cascades_List() { type test struct { name string - testFunc func(state string) bool - state string + testFunc func(state common.ActiveStateEnum) bool + state common.ActiveStateEnum isFound bool } - listNamespaces := func(state string) bool { - listedNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, state) + listNamespaces := func(state common.ActiveStateEnum) bool { + nsListRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedNamespaces) - for _, ns := range listedNamespaces { + s.NotNil(nsListRsp) + listed := nsListRsp.GetNamespaces() + for _, ns := range listed { if stillActiveNsID == ns.GetId() { return true } @@ -925,11 +1029,14 @@ func (s *AttributesSuite) Test_DeactivateAttribute_Cascades_List() { return false } - listAttributes := func(state string) bool { - listedAttrs, err := s.db.PolicyClient.ListAttributes(s.ctx, state, "") + listAttributes := func(state common.ActiveStateEnum) bool { + listAttrsRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedAttrs) - for _, a := range listedAttrs { + s.NotNil(listAttrsRsp) + listed := listAttrsRsp.GetAttributes() + for _, a := range listed { if deactivatedAttrID == a.GetId() { return true } @@ -937,11 +1044,15 @@ func (s *AttributesSuite) Test_DeactivateAttribute_Cascades_List() { return false } - listValues := func(state string) bool { - listedVals, err := s.db.PolicyClient.ListAttributeValues(s.ctx, deactivatedAttrID, state) + listValues := func(state common.ActiveStateEnum) bool { + valsListRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + AttributeId: deactivatedAttrID, + State: state, + }) s.Require().NoError(err) - s.NotNil(listedVals) - for _, v := range listedVals { + s.NotNil(valsListRsp) + listed := valsListRsp.GetValues() + for _, v := range listed { if deactivatedAttrValueID == v.GetId() { return true } @@ -953,55 +1064,55 @@ func (s *AttributesSuite) Test_DeactivateAttribute_Cascades_List() { { name: "namespace is NOT found in LIST of INACTIVE", testFunc: listNamespaces, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: false, }, { name: "namespace is found when filtering for ACTIVE state", testFunc: listNamespaces, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: true, }, { name: "namespace is found when filtering for ANY state", testFunc: listNamespaces, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is found when filtering for INACTIVE state", testFunc: listAttributes, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "attribute is found when filtering for ANY state", testFunc: listAttributes, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is NOT found when filtering for ACTIVE state", testFunc: listAttributes, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "value is NOT found in LIST of ACTIVE", testFunc: listValues, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "value is found when filtering for INACTIVE state", testFunc: listValues, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "value is found when filtering for ANY state", testFunc: listValues, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, } diff --git a/service/integration/config.go b/service/integration/config.go index 1956f8b2f..64ad2b2b7 100644 --- a/service/integration/config.go +++ b/service/integration/config.go @@ -2,10 +2,6 @@ package integration import "github.com/opentdf/platform/service/internal/config" -const ( - nonExistentAttributeValueUUID = "78909865-8888-9999-9999-000000000000" -) - var Config *config.Config func init() { diff --git a/service/integration/kas_registry_test.go b/service/integration/kas_registry_test.go index 87e472363..993660f25 100644 --- a/service/integration/kas_registry_test.go +++ b/service/integration/kas_registry_test.go @@ -14,6 +14,7 @@ import ( "github.com/opentdf/platform/protocol/go/policy/namespaces" "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" + "google.golang.org/protobuf/proto" "github.com/stretchr/testify/suite" ) @@ -49,23 +50,91 @@ func (s *KasRegistrySuite) getKasRegistryFixtures() []fixtures.FixtureDataKasReg } } -func (s *KasRegistrySuite) Test_ListKeyAccessServers() { +func (s *KasRegistrySuite) Test_ListKeyAccessServers_NoPagination_Succeeds() { fixtures := s.getKasRegistryFixtures() - list, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx) - s.Require().NoError(err) - s.NotNil(list) - for _, fixture := range fixtures { - for _, kas := range list { - if kas.GetId() == fixture.ID { - if kas.GetPublicKey().GetRemote() != "" { - s.Equal(fixture.PubKey.Remote, kas.GetPublicKey().GetRemote()) - } else { - s.Equal(fixture.PubKey.Cached, kas.GetPublicKey().GetCached()) - } - s.Equal(fixture.URI, kas.GetUri()) - s.Equal(fixture.Name, kas.GetName()) + listRsp, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx, &kasregistry.ListKeyAccessServersRequest{}) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetKeyAccessServers() + s.NotEmpty(listed) + + // ensure we find each fixture in the list response + for _, f := range fixtures { + found := false + for _, kasr := range listed { + if kasr.GetId() == f.ID { + found = true } } + s.True(found) + } +} + +func (s *KasRegistrySuite) Test_ListKeyAccessServers_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx, &kasregistry.ListKeyAccessServersRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetKeyAccessServers() + s.Equal(len(listed), int(limit)) + + for _, kas := range listed { + s.NotEmpty(kas.GetId()) + s.NotEmpty(kas.GetUri()) + s.NotNil(kas.GetPublicKey()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListKeyAccessServers(s.ctx, &kasregistry.ListKeyAccessServersRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListKeyAccessServers_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx, &kasregistry.ListKeyAccessServersRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *KasRegistrySuite) Test_ListKeyAccessServers_Offset_Succeeds() { + req := &kasregistry.ListKeyAccessServersRequest{} + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetKeyAccessServers() + + // set the offset pagination + offset := 1 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListKeyAccessServers(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetKeyAccessServers() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, val := range offsetListed { + s.True(proto.Equal(val, listed[i+offset])) } } @@ -591,9 +660,13 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasId() { s.NotNil(valGrant) // list grants by KAS ID - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, firstKAS.GetId(), "", "") + listRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasId: firstKAS.GetId(), + }) s.Require().NoError(err) - s.NotNil(listedGrants) + s.NotNil(listRsp) + + listedGrants := listRsp.GetGrants() s.Len(listedGrants, 1) g := listedGrants[0] s.Equal(firstKAS.GetId(), g.GetKeyAccessServer().GetId()) @@ -604,9 +677,13 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasId() { s.Empty(g.GetNamespaceGrants()) // list grants by the other KAS ID - listedGrants, err = s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, otherKAS.GetId(), "", "") + listRsp, err = s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasId: otherKAS.GetId(), + }) s.Require().NoError(err) - s.NotNil(listedGrants) + s.NotNil(listRsp) + + listedGrants = listRsp.GetGrants() s.Len(listedGrants, 1) g = listedGrants[0] s.Equal(otherKAS.GetId(), g.GetKeyAccessServer().GetId()) @@ -619,9 +696,11 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasId() { func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasId_NoResultsIfNotFound() { // list grants by KAS ID - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, nonExistentKasRegistryID, "", "") + listRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasId: nonExistentKasRegistryID, + }) s.Require().NoError(err) - s.Empty(listedGrants) + s.Empty(listRsp.GetGrants()) } func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasUri() { @@ -647,10 +726,12 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasUri() { s.NotNil(createdGrant) // list grants by KAS URI - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, "", fixtureKAS.URI, "") - + listGrantsRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasUri: fixtureKAS.URI, + }) s.Require().NoError(err) - s.NotNil(listedGrants) + s.NotNil(listGrantsRsp) + listedGrants := listGrantsRsp.GetGrants() s.GreaterOrEqual(len(listedGrants), 1) for _, g := range listedGrants { s.Equal(fixtureKAS.ID, g.GetKeyAccessServer().GetId()) @@ -661,9 +742,11 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasUri() { func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasUri_NoResultsIfNotFound() { // list grants by KAS ID - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, "", "https://notfound.com/kas/uri", "") + listGrantsRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasUri: "https://notfound.com/kas/uri", + }) s.Require().NoError(err) - s.Empty(listedGrants) + s.Empty(listGrantsRsp.GetGrants()) } func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasName() { @@ -689,23 +772,38 @@ func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasName() { s.NotNil(createdGrant) // list grants by KAS URI - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, "", "", fixtureKAS.Name) + listedGrantsRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, + &kasregistry.ListKeyAccessServerGrantsRequest{ + KasName: fixtureKAS.Name, + }) s.Require().NoError(err) - s.NotNil(listedGrants) + s.NotNil(listedGrantsRsp) + listedGrants := listedGrantsRsp.GetGrants() s.GreaterOrEqual(len(listedGrants), 1) + found := false for _, g := range listedGrants { - s.Equal(fixtureKAS.ID, g.GetKeyAccessServer().GetId()) - s.Equal(fixtureKAS.URI, g.GetKeyAccessServer().GetUri()) - s.Equal(fixtureKAS.Name, g.GetKeyAccessServer().GetName()) + if g.GetKeyAccessServer().GetId() == fixtureKAS.ID { + s.Equal(fixtureKAS.URI, g.GetKeyAccessServer().GetUri()) + s.Equal(fixtureKAS.Name, g.GetKeyAccessServer().GetName()) + for _, attrGrant := range g.GetAttributeGrants() { + if attrGrant.GetId() == createdAttr.GetId() { + found = true + s.Equal(attrGrant.GetFqn(), createdAttr.GetFqn()) + } + } + } } + s.True(found) } func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_KasName_NoResultsIfNotFound() { // list grants by KAS ID - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, "", "", "unknown_kas") + listGrantsRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + KasName: "unknown-name", + }) s.Require().NoError(err) - s.Empty(listedGrants) + s.Empty(listGrantsRsp.GetGrants()) } func (s *KasRegistrySuite) Test_ListAllKeyAccessServerGrants() { @@ -812,11 +910,14 @@ func (s *KasRegistrySuite) Test_ListAllKeyAccessServerGrants() { s.NotNil(nsAnotherGrant) // list all grants - listedGrants, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, "", "", "") + listGrantsRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{}) s.Require().NoError(err) - s.NotNil(listedGrants) - s.GreaterOrEqual(len(listedGrants), 2) + s.NotNil(listGrantsRsp) + listedGrants := listGrantsRsp.GetGrants() + s.GreaterOrEqual(len(listedGrants), 1) + s.GreaterOrEqual(len(listedGrants), 2) + foundCount := 0 for _, g := range listedGrants { switch g.GetKeyAccessServer().GetId() { case firstKAS.GetId(): @@ -828,6 +929,9 @@ func (s *KasRegistrySuite) Test_ListAllKeyAccessServerGrants() { s.Len(g.GetNamespaceGrants(), 1) s.Equal(createdNs.GetId(), g.GetNamespaceGrants()[0].GetId()) s.Equal(nsFQN, g.GetNamespaceGrants()[0].GetFqn()) + + foundCount++ + case secondKAS.GetId(): // should have expected value grant s.Len(g.GetValueGrants(), 1) @@ -837,8 +941,76 @@ func (s *KasRegistrySuite) Test_ListAllKeyAccessServerGrants() { s.Len(g.GetNamespaceGrants(), 1) s.Equal(createdNs.GetId(), g.GetNamespaceGrants()[0].GetId()) s.Equal(nsFQN, g.GetNamespaceGrants()[0].GetFqn()) + + foundCount++ } } + s.Equal(2, foundCount) +} + +func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetGrants() + s.Equal(len(listed), int(limit)) + + for _, grant := range listed { + s.NotNil(grant.GetKeyAccessServer()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListKeyAccessServerGrants_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, &kasregistry.ListKeyAccessServerGrantsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *KasRegistrySuite) Test_ListKeyAccessServerGrants_Offset_Succeeds() { + req := &kasregistry.ListKeyAccessServerGrantsRequest{} + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetGrants() + + // set the offset pagination + offset := 1 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListKeyAccessServerGrants(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetGrants() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, val := range offsetListed { + s.True(proto.Equal(val, listed[i+offset])) + } } func TestKasRegistrySuite(t *testing.T) { diff --git a/service/integration/namespaces_test.go b/service/integration/namespaces_test.go index bd36a4ec9..249b33f87 100644 --- a/service/integration/namespaces_test.go +++ b/service/integration/namespaces_test.go @@ -13,8 +13,8 @@ import ( "github.com/opentdf/platform/protocol/go/policy/namespaces" "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" - policydb "github.com/opentdf/platform/service/policy/db" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/proto" ) type NamespacesSuite struct { @@ -129,13 +129,87 @@ func (s *NamespacesSuite) Test_GetNamespace_DoesNotExist_ShouldFail() { s.Nil(ns) } -func (s *NamespacesSuite) Test_ListNamespaces() { +func (s *NamespacesSuite) Test_ListNamespaces_NoPagination_Succeeds() { testData := s.getActiveNamespaceFixtures() - gotNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, policydb.StateActive) + listNamespacesRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, + }) + s.Require().NoError(err) + s.NotNil(listNamespacesRsp) + listed := listNamespacesRsp.GetNamespaces() + s.GreaterOrEqual(len(listed), len(testData)) + + for _, f := range testData { + found := false + for _, ns := range listed { + if ns.GetId() == f.ID { + found = true + } + } + s.True(found) + } +} + +func (s *NamespacesSuite) Test_ListNamespaces_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) s.Require().NoError(err) - s.NotNil(gotNamespaces) - s.GreaterOrEqual(len(gotNamespaces), len(testData)) + s.NotNil(listRsp) + listed := listRsp.GetNamespaces() + s.Equal(len(listed), int(limit)) + + for _, ns := range listed { + s.NotEmpty(ns.GetFqn()) + s.NotEmpty(ns.GetId()) + s.NotEmpty(ns.GetName()) + } +} + +func (s *NamespacesSuite) Test_ListNamespaces_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *NamespacesSuite) Test_ListNamespaces_Offset_Succeeds() { + req := &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + } + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetNamespaces() + + // set the offset pagination + offset := 4 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetNamespaces() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, ns := range offsetListed { + s.True(proto.Equal(ns, listed[i+offset])) + } } func (s *NamespacesSuite) Test_UpdateNamespace() { @@ -218,10 +292,13 @@ func (s *NamespacesSuite) Test_DeactivateNamespace() { s.False(inactive.GetActive().GetValue()) // Deactivated namespace should not be found on List - gotNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, policydb.StateActive) + listNamespacesRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, + }) s.Require().NoError(err) - s.NotNil(gotNamespaces) - for _, ns := range gotNamespaces { + s.NotNil(listNamespacesRsp) + listed := listNamespacesRsp.GetNamespaces() + for _, ns := range listed { s.NotEqual(n.GetId(), ns.GetId()) } @@ -269,16 +346,20 @@ func setupCascadeDeactivateNamespace(s *NamespacesSuite) (string, string, string func (s *NamespacesSuite) Test_DeactivateNamespace_Cascades_List() { type test struct { name string - testFunc func(state string) bool - state string + testFunc func(state common.ActiveStateEnum) bool + state common.ActiveStateEnum isFound bool } - listNamespaces := func(state string) bool { - listedNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, state) + listNamespaces := func(state common.ActiveStateEnum) bool { + listNamespacesRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedNamespaces) - for _, ns := range listedNamespaces { + s.NotNil(listNamespacesRsp) + + listed := listNamespacesRsp.GetNamespaces() + for _, ns := range listed { if deactivatedNsID == ns.GetId() { return true } @@ -286,11 +367,15 @@ func (s *NamespacesSuite) Test_DeactivateNamespace_Cascades_List() { return false } - listAttributes := func(state string) bool { - listedAttrs, err := s.db.PolicyClient.ListAttributes(s.ctx, state, "") + listAttributes := func(state common.ActiveStateEnum) bool { + listAttrsRsp, err := s.db.PolicyClient.ListAttributes(s.ctx, &attributes.ListAttributesRequest{ + State: state, + }) s.Require().NoError(err) - s.NotNil(listedAttrs) - for _, a := range listedAttrs { + s.NotNil(listAttrsRsp) + + listed := listAttrsRsp.GetAttributes() + for _, a := range listed { if deactivatedAttrID == a.GetId() { return true } @@ -298,11 +383,15 @@ func (s *NamespacesSuite) Test_DeactivateNamespace_Cascades_List() { return false } - listValues := func(state string) bool { - listedVals, err := s.db.PolicyClient.ListAttributeValues(s.ctx, deactivatedAttrID, state) + listValues := func(state common.ActiveStateEnum) bool { + listedValsRsp, err := s.db.PolicyClient.ListAttributeValues(s.ctx, &attributes.ListAttributeValuesRequest{ + AttributeId: deactivatedAttrID, + State: state, + }) s.Require().NoError(err) - s.NotNil(listedVals) - for _, v := range listedVals { + s.NotNil(listedValsRsp) + listed := listedValsRsp.GetValues() + for _, v := range listed { if deactivatedAttrValueID == v.GetId() { return true } @@ -314,55 +403,55 @@ func (s *NamespacesSuite) Test_DeactivateNamespace_Cascades_List() { { name: "namespace is NOT found in LIST of ACTIVE", testFunc: listNamespaces, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "namespace is found when filtering for INACTIVE state", testFunc: listNamespaces, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "namespace is found when filtering for ANY state", testFunc: listNamespaces, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is found when filtering for INACTIVE state", testFunc: listAttributes, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "attribute is found when filtering for ANY state", testFunc: listAttributes, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, { name: "attribute is NOT found when filtering for ACTIVE state", testFunc: listAttributes, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "value is NOT found in LIST of ACTIVE", testFunc: listValues, - state: policydb.StateActive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, isFound: false, }, { name: "value is found when filtering for INACTIVE state", testFunc: listValues, - state: policydb.StateInactive, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, isFound: true, }, { name: "value is found when filtering for ANY state", testFunc: listValues, - state: policydb.StateAny, + state: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, isFound: true, }, } @@ -554,11 +643,14 @@ func (s *NamespacesSuite) Test_UnsafeReactivateNamespace_SetsActiveStatusOfNames s.True(active.GetActive().GetValue()) // test that the namespace is found in the list of active namespaces - gotNamespaces, err := s.db.PolicyClient.ListNamespaces(s.ctx, policydb.StateActive) + listNamespacesRsp, err := s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE, + }) s.Require().NoError(err) - s.NotNil(gotNamespaces) + s.NotNil(listNamespacesRsp) + listed := listNamespacesRsp.GetNamespaces() found := false - for _, ns := range gotNamespaces { + for _, ns := range listed { if n.GetId() == ns.GetId() { found = true break @@ -567,11 +659,14 @@ func (s *NamespacesSuite) Test_UnsafeReactivateNamespace_SetsActiveStatusOfNames s.True(found) // test that the namespace is not found in the list of inactive namespaces - gotNamespaces, err = s.db.PolicyClient.ListNamespaces(s.ctx, policydb.StateInactive) + listNamespacesRsp, err = s.db.PolicyClient.ListNamespaces(s.ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE, + }) s.Require().NoError(err) - s.NotNil(gotNamespaces) + s.NotNil(listNamespacesRsp) + listed = listNamespacesRsp.GetNamespaces() found = false - for _, ns := range gotNamespaces { + for _, ns := range listed { if n.GetId() == ns.GetId() { found = true break diff --git a/service/integration/resource_mappings_test.go b/service/integration/resource_mappings_test.go index e8d7d704f..93e5bfb10 100644 --- a/service/integration/resource_mappings_test.go +++ b/service/integration/resource_mappings_test.go @@ -7,15 +7,19 @@ import ( "testing" "github.com/opentdf/platform/protocol/go/common" + "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/resourcemapping" "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/proto" ) -var unknownNamespaceID = "64257d69-c007-4893-931a-434f1819a4f7" -var unknownResourceMappingGroupID = "c70cad07-21b4-4cb1-9095-bce54615536a" -var unknownResourceMappingID = "45674556-8888-9999-9999-000001230000" +const ( + unknownNamespaceID = "64257d69-c007-4893-931a-434f1819a4f7" + unknownResourceMappingGroupID = "c70cad07-21b4-4cb1-9095-bce54615536a" + unknownResourceMappingID = "45674556-8888-9999-9999-000001230000" +) type ResourceMappingsSuite struct { suite.Suite @@ -76,14 +80,15 @@ func (s *ResourceMappingsSuite) getResourceMappingAttributeValueFixtures() []fix Resource Mapping Groups */ -func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups() { +func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups_NoPagination_Succeeds() { testData := s.getResourceMappingGroupFixtures() - rmGroups, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{}) + listRmGroupsRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{}) s.Require().NoError(err) - s.NotNil(rmGroups) + s.NotNil(listRmGroupsRsp) + listed := listRmGroupsRsp.GetResourceMappingGroups() for _, testRmGroup := range testData { found := false - for _, rmGroup := range rmGroups { + for _, rmGroup := range listed { if testRmGroup.ID == rmGroup.GetId() { found = true break @@ -93,17 +98,75 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups() { } } -func (s *ResourceMappingsSuite) Test_ListResourceMappingGroupsWithNamespaceIdSucceeds() { +func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups_Limit_Succeeds() { + var limit int32 = 2 + listRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetResourceMappingGroups() + s.Equal(len(listed), int(limit)) + + for _, rmg := range listed { + s.NotEmpty(rmg.GetNamespaceId()) + s.NotEmpty(rmg.GetId()) + s.NotEmpty(rmg.GetName()) + } +} + +func (s *NamespacesSuite) Test_ListResourceMappingGroups_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups_Offset_Succeeds() { + req := &resourcemapping.ListResourceMappingGroupsRequest{} + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetResourceMappingGroups() + + // set the offset pagination + offset := 2 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetResourceMappingGroups() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, val := range offsetListed { + s.True(proto.Equal(val, listed[i+offset])) + } +} + +func (s *ResourceMappingsSuite) Test_ListResourceMappingGroups_WithNamespaceId_Succeeds() { scenarioDotComRmGroup := s.f.GetResourceMappingGroupKey("scenario.com_ns_group_1") - rmGroups, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{ + rmGroupsRsp, err := s.db.PolicyClient.ListResourceMappingGroups(s.ctx, &resourcemapping.ListResourceMappingGroupsRequest{ NamespaceId: scenarioDotComRmGroup.NamespaceID, }) s.Require().NoError(err) - s.NotNil(rmGroups) - s.Len(rmGroups, 1) - s.Equal(scenarioDotComRmGroup.ID, rmGroups[0].GetId()) - s.Equal(scenarioDotComRmGroup.NamespaceID, rmGroups[0].GetNamespaceId()) - s.Equal(scenarioDotComRmGroup.Name, rmGroups[0].GetName()) + s.NotNil(rmGroupsRsp) + list := rmGroupsRsp.GetResourceMappingGroups() + s.Len(list, 1) + s.Equal(scenarioDotComRmGroup.ID, list[0].GetId()) + s.Equal(scenarioDotComRmGroup.NamespaceID, list[0].GetNamespaceId()) + s.Equal(scenarioDotComRmGroup.Name, list[0].GetName()) } func (s *ResourceMappingsSuite) Test_GetResourceMappingGroup() { @@ -368,22 +431,6 @@ func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithUnknownAttributeVa s.Require().ErrorIs(err, db.ErrForeignKeyViolation) } -func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithEmptyTermsSucceeds() { - metadata := &common.MetadataMutable{} - - attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2") - mapping := &resourcemapping.CreateResourceMappingRequest{ - AttributeValueId: attrValue.ID, - Metadata: metadata, - Terms: []string{}, - } - createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) - s.Require().NoError(err) - s.NotNil(createdMapping) - s.NotNil(createdMapping.GetTerms()) - s.Empty(createdMapping.GetTerms()) -} - func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithGroupIdSucceeds() { metadata := &common.MetadataMutable{} @@ -416,7 +463,7 @@ func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithUnknownGroupIdFail s.Nil(createdMapping) } -func (s *ResourceMappingsSuite) Test_ListResourceMappings() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_NoPagination_Succeeds() { testMappings := make(map[string]fixtures.FixtureDataResourceMapping) for _, testMapping := range s.getResourceMappingFixtures() { testMappings[testMapping.ID] = testMapping @@ -427,18 +474,20 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappings() { testValues[testValue.ID] = testValue } - req := &resourcemapping.ListResourceMappingsRequest{} - mappings, err := s.db.PolicyClient.ListResourceMappings(s.ctx, req) + listRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, &resourcemapping.ListResourceMappingsRequest{}) s.Require().NoError(err) - s.NotNil(mappings) + s.NotNil(listRsp) + + list := listRsp.GetResourceMappings() + s.NotEmpty(list) testMappingCount := len(testMappings) foundCount := 0 - for _, mapping := range mappings { + for _, mapping := range list { testMapping, ok := testMappings[mapping.GetId()] if !ok { - // todo: DB is not cleaned up between tests, so ignore any unexpected mappings + // only validating presence of all fixtures within the list response continue } foundCount++ @@ -462,13 +511,71 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappings() { s.Equal(testMappingCount, foundCount) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupId() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_Limit_Succeeds() { + var limit int32 = 4 + listRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, &resourcemapping.ListResourceMappingsRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetResourceMappings() + s.Equal(len(listed), int(limit)) + + for _, rm := range listed { + s.NotEmpty(rm.GetId()) + s.NotEmpty(rm.GetAttributeValue()) + } +} + +func (s *NamespacesSuite) Test_ListResourceMappings_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, &resourcemapping.ListResourceMappingsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *ResourceMappingsSuite) Test_ListResourceMappings_Offset_Succeeds() { + req := &resourcemapping.ListResourceMappingsRequest{} + // make initial list request to compare against + listRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, req) + s.Require().NoError(err) + s.NotNil(listRsp) + listed := listRsp.GetResourceMappings() + + // set the offset pagination + offset := 2 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + offsetListRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, req) + s.Require().NoError(err) + s.NotNil(offsetListRsp) + offsetListed := offsetListRsp.GetResourceMappings() + + // length is reduced by the offset amount + s.Equal(len(offsetListed), len(listed)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, rm := range offsetListed { + s.True(proto.Equal(rm, listed[i+offset])) + } +} + +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupId_Succeeds() { req := &resourcemapping.ListResourceMappingsRequest{ GroupId: s.getResourceMappingGroupFixtures()[0].ID, } - mappings, err := s.db.PolicyClient.ListResourceMappings(s.ctx, req) + listRsp, err := s.db.PolicyClient.ListResourceMappings(s.ctx, req) s.Require().NoError(err) - s.NotNil(mappings) + s.NotNil(listRsp) + mappings := listRsp.GetResourceMappings() for _, mapping := range mappings { expectedGroupID := req.GetGroupId() actualGroupID := mapping.GetGroup().GetId() @@ -477,7 +584,7 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupId() { } } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqns() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupFqns_Succeeds() { scenarioDotComNs := s.getScenarioDotComNamespace() scenarioDotComGroup := s.f.GetResourceMappingGroupKey("scenario.com_ns_group_1") scenarioDotComGroupMapping := s.f.GetResourceMappingKey("resource_mapping_to_attribute_value3") @@ -519,7 +626,7 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqns() { s.Equal("https://scenario.com/attr/working_group/value/blue", value.GetFqn()) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithEmptyOrNilFqnsFails() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupFqns_WithEmptyOrNilFqns_Fails() { fqnRmGroupMap, err := s.db.PolicyClient.ListResourceMappingsByGroupFqns(s.ctx, nil) s.Require().Error(err) s.Nil(fqnRmGroupMap) @@ -529,20 +636,20 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithEmptyOrN s.Nil(fqnRmGroupMap) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithInvalidFqnsFails() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupFqns_WithInvalidFqns_Fails() { fqnRmGroupMap, err := s.db.PolicyClient.ListResourceMappingsByGroupFqns(s.ctx, []string{"invalid_fqn"}) s.Require().Error(err) s.Nil(fqnRmGroupMap) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithUnknownFqnsFails() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupFqns_WithUnknownFqns_Fails() { unknownFqn := "https://unknown.com/resm/unknown_group" fqnRmGroupMap, err := s.db.PolicyClient.ListResourceMappingsByGroupFqns(s.ctx, []string{unknownFqn}) s.Require().Error(err) s.Nil(fqnRmGroupMap) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithKnownAndUnknownFqnsSucceeds() { +func (s *ResourceMappingsSuite) Test_ListResourceMappings_ByGroupFqns_WithKnownAndUnknownFqns_Succeeds() { exampleDotComNs := s.getExampleDotComNamespace() exampleDotComRmGroup1 := s.f.GetResourceMappingGroupKey("example.com_ns_group_1") @@ -562,7 +669,7 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithKnownAnd s.Nil(unknownResp) } -func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqnsWithKnownAndInvalidFqnsSucceeds() { +func (s *ResourceMappingsSuite) Test_ListResourceMappingsByGroupFqns_WithKnownAndInvalidFqns_Succeeds() { exampleDotComNs := s.getExampleDotComNamespace() exampleDotComRmGroup1 := s.f.GetResourceMappingGroupKey("example.com_ns_group_1") diff --git a/service/integration/subject_mappings_test.go b/service/integration/subject_mappings_test.go index 6d28e5f1f..a70ff0fc4 100644 --- a/service/integration/subject_mappings_test.go +++ b/service/integration/subject_mappings_test.go @@ -11,8 +11,11 @@ import ( "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/proto" ) +const nonExistentAttributeValueUUID = "78909865-8888-9999-9999-000000000000" + type SubjectMappingsSuite struct { suite.Suite f fixtures.Fixtures @@ -377,10 +380,12 @@ func (s *SubjectMappingsSuite) TestGetSubjectMapping_NonExistentId_Fails() { s.Require().ErrorIs(err, db.ErrNotFound) } -func (s *SubjectMappingsSuite) TestListSubjectMappings() { - list, err := s.db.PolicyClient.ListSubjectMappings(s.ctx) +func (s *SubjectMappingsSuite) Test_ListSubjectMappings_NoPagination_Succeeds() { + listRsp, err := s.db.PolicyClient.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{}) s.Require().NoError(err) - s.NotNil(list) + s.NotNil(listRsp) + listed := listRsp.GetSubjectMappings() + s.NotEmpty(listed) fixture1 := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute1") found1 := false @@ -388,7 +393,7 @@ func (s *SubjectMappingsSuite) TestListSubjectMappings() { found2 := false fixture3 := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute3") found3 := false - s.GreaterOrEqual(len(list), 3) + s.GreaterOrEqual(len(listed), 3) assertEqual := func(sm *policy.SubjectMapping, fixture fixtures.FixtureDataSubjectMapping) { s.Equal(fixture.AttributeValueID, sm.GetAttributeValue().GetId()) @@ -396,7 +401,7 @@ func (s *SubjectMappingsSuite) TestListSubjectMappings() { s.Equal(fixture.SubjectConditionSetID, sm.GetSubjectConditionSet().GetId()) s.Equal(len(fixture.Actions), len(sm.GetActions())) } - for _, sm := range list { + for _, sm := range listed { if sm.GetId() == fixture1.ID { assertEqual(sm, fixture1) found1 = true @@ -415,6 +420,77 @@ func (s *SubjectMappingsSuite) TestListSubjectMappings() { s.True(found3) } +func (s *SubjectMappingsSuite) Test_ListSubjectMappings_Limit_Succeeds() { + var limit int32 = 3 + listRsp, err := s.db.PolicyClient.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetSubjectMappings() + s.NotEmpty(listed) + + for _, sm := range listed { + s.NotEmpty(sm.GetId()) + s.NotEmpty(sm.GetAttributeValue()) + s.NotNil(sm.GetSubjectConditionSet()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListSubjectMappings_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *SubjectMappingsSuite) Test_ListSubjectMappings_Offset_Succeeds() { + req := &subjectmapping.ListSubjectMappingsRequest{} + totalListRsp, err := s.db.PolicyClient.ListSubjectMappings(context.Background(), req) + s.Require().NoError(err) + s.NotNil(totalListRsp) + + totalList := totalListRsp.GetSubjectMappings() + s.NotEmpty(totalList) + + // set the offset pagination + offset := 2 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + + offetListRsp, err := s.db.PolicyClient.ListSubjectMappings(context.Background(), req) + s.Require().NoError(err) + s.NotNil(offetListRsp) + + offsetList := offetListRsp.GetSubjectMappings() + s.NotEmpty(offsetList) + + // length is reduced by the offset amount + s.Equal(len(offsetList), len(totalList)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, sm := range offsetList { + s.True(proto.Equal(sm, totalList[i+offset])) + } +} + func (s *SubjectMappingsSuite) TestDeleteSubjectMapping() { // create a new subject mapping, delete it, and verify get fails with not found fixtureAttrValID := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value1").ID @@ -577,10 +653,11 @@ func (s *SubjectMappingsSuite) TestGetSubjectConditionSet_NonExistentId_Fails() s.Require().ErrorIs(err, db.ErrNotFound) } -func (s *SubjectMappingsSuite) TestListSubjectConditionSet() { - list, err := s.db.PolicyClient.ListSubjectConditionSets(s.ctx) +func (s *SubjectMappingsSuite) Test_ListSubjectConditionSet_NoPagination_Succeeds() { + listRsp, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background(), &subjectmapping.ListSubjectConditionSetsRequest{}) s.Require().NoError(err) - s.NotNil(list) + s.NotNil(listRsp) + listed := listRsp.GetSubjectConditionSets() fixture1 := s.f.GetSubjectConditionSetKey("subject_condition_set1") found1 := false @@ -591,8 +668,8 @@ func (s *SubjectMappingsSuite) TestListSubjectConditionSet() { fixture4 := s.f.GetSubjectConditionSetKey("subject_condition_simple_in") found4 := false - s.GreaterOrEqual(len(list), 3) - for _, scs := range list { + s.GreaterOrEqual(len(listed), 3) + for _, scs := range listed { switch scs.GetId() { case fixture1.ID: found1 = true @@ -610,6 +687,76 @@ func (s *SubjectMappingsSuite) TestListSubjectConditionSet() { s.True(found4) } +func (s *SubjectMappingsSuite) Test_ListSubjectConditionSet_Limit_Succeeds() { + var limit int32 = 3 + listRsp, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background(), &subjectmapping.ListSubjectConditionSetsRequest{ + Pagination: &policy.PageRequest{ + Limit: limit, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) + + listed := listRsp.GetSubjectConditionSets() + s.NotEmpty(listed) + + for _, sm := range listed { + s.NotEmpty(sm.GetId()) + s.NotEmpty(sm.GetSubjectSets()) + } + + // request with one below maximum + listRsp, err = s.db.PolicyClient.ListSubjectConditionSets(context.Background(), &subjectmapping.ListSubjectConditionSetsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax - 1, + }, + }) + s.Require().NoError(err) + s.NotNil(listRsp) +} + +func (s *NamespacesSuite) Test_ListSubjectConditionSets_Limit_TooLarge_Fails() { + listRsp, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background(), &subjectmapping.ListSubjectConditionSetsRequest{ + Pagination: &policy.PageRequest{ + Limit: s.db.LimitMax + 1, + }, + }) + s.Require().Error(err) + s.Require().ErrorIs(err, db.ErrListLimitTooLarge) + s.Nil(listRsp) +} + +func (s *SubjectMappingsSuite) Test_ListSubjectConditionSet_Offset_Succeeds() { + req := &subjectmapping.ListSubjectConditionSetsRequest{} + totalListRsp, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background(), req) + s.Require().NoError(err) + s.NotNil(totalListRsp) + + totalList := totalListRsp.GetSubjectConditionSets() + s.NotEmpty(totalList) + + // set the offset pagination + offset := 5 + req.Pagination = &policy.PageRequest{ + Offset: int32(offset), + } + + offetListRsp, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background(), req) + s.Require().NoError(err) + s.NotNil(offetListRsp) + + offsetList := offetListRsp.GetSubjectConditionSets() + s.NotEmpty(offsetList) + + // length is reduced by the offset amount + s.Equal(len(offsetList), len(totalList)-offset) + + // objects are equal between offset and original list beginning at offset index + for i, scs := range offsetList { + s.True(proto.Equal(scs, totalList[i+offset])) + } +} + func (s *SubjectMappingsSuite) TestDeleteSubjectConditionSet() { // create a new subject condition set, delete it, and verify get fails with not found newConditionSet := &subjectmapping.SubjectConditionSetCreate{ diff --git a/service/internal/fixtures/db.go b/service/internal/fixtures/db.go index 5fc628cf6..dc70ce6c2 100644 --- a/service/internal/fixtures/db.go +++ b/service/internal/fixtures/db.go @@ -13,10 +13,18 @@ import ( policydb "github.com/opentdf/platform/service/policy/db" ) +var ( + // Configured default LIST Limit when working with fixtures + fixtureLimitDefault int32 = 1000 + fixtureLimitMax int32 = 5000 +) + type DBInterface struct { Client *db.Client PolicyClient policydb.PolicyDBClient Schema string + LimitDefault int32 + LimitMax int32 } func NewDBInterface(cfg config.Config) DBInterface { @@ -42,7 +50,9 @@ func NewDBInterface(cfg config.Config) DBInterface { return DBInterface{ Client: c, Schema: config.Schema, - PolicyClient: policydb.NewClient(c, logger), + PolicyClient: policydb.NewClient(c, logger, fixtureLimitMax, fixtureLimitDefault), + LimitDefault: fixtureLimitDefault, + LimitMax: fixtureLimitMax, } } diff --git a/service/internal/fixtures/fixtures.go b/service/internal/fixtures/fixtures.go index ed4ebbdcb..5c00892aa 100644 --- a/service/internal/fixtures/fixtures.go +++ b/service/internal/fixtures/fixtures.go @@ -47,12 +47,6 @@ type FixtureDataAttributeValue struct { Active bool `yaml:"active"` } -type FixtureDataValueMember struct { - ID string `yaml:"id"` - ValueID string `yaml:"value_id"` - MemberID string `yaml:"member_id"` -} - type FixtureDataAttributeValueKeyAccessServer struct { ValueID string `yaml:"value_id"` KeyAccessServerID string `yaml:"key_access_server_id"` diff --git a/service/pkg/db/errors.go b/service/pkg/db/errors.go index 49188f14d..74a159dd4 100644 --- a/service/pkg/db/errors.go +++ b/service/pkg/db/errors.go @@ -21,6 +21,7 @@ var ( ErrEnumValueInvalid = errors.New("ErrEnumValueInvalid: not a valid enum value") ErrUUIDInvalid = errors.New("ErrUUIDInvalid: value not a valid UUID") ErrMissingValue = errors.New("ErrMissingValue: value must be included") + ErrListLimitTooLarge = errors.New("ErrListLimitTooLarge: requested limit greater than configured maximum") ) // Get helpful error message for PostgreSQL violation @@ -97,6 +98,7 @@ const ( ErrTextUUIDInvalid = "invalid input syntax for type uuid" ErrTextRestrictViolation = "intended action would violate a restriction" ErrTextFqnMissingValue = "FQN must specify a valid value and be of format 'https://<namespace>/attr/<attribute name>/value/<value>'" + ErrTextListLimitTooLarge = "requested pagination limit must be less than or equal to configured limit" ) func StatusifyError(err error, fallbackErr string, log ...any) error { @@ -125,6 +127,10 @@ func StatusifyError(err error, fallbackErr string, log ...any) error { slog.Error(ErrTextRestrictViolation, l...) return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextRestrictViolation)) } + if errors.Is(err, ErrListLimitTooLarge) { + slog.Error(ErrTextListLimitTooLarge, l...) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextListLimitTooLarge)) + } slog.Error(err.Error(), l...) return connect.NewError(connect.CodeInternal, errors.New(fallbackErr)) } diff --git a/service/policy/attributes/attributes.go b/service/policy/attributes/attributes.go index 8ca210ac0..da59557ff 100644 --- a/service/policy/attributes/attributes.go +++ b/service/policy/attributes/attributes.go @@ -13,12 +13,14 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" policydb "github.com/opentdf/platform/service/policy/db" ) type AttributesService struct { //nolint:revive // AttributesService is a valid name for this struct dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[attributesconnect.AttributesServiceHandler] { @@ -30,8 +32,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ConnectRPCFunc: attributesconnect.NewAttributesServiceHandler, GRPCGateayFunc: attributes.RegisterAttributesServiceHandlerFromEndpoint, RegisterFunc: func(srp serviceregistry.RegistrationParams) (attributesconnect.AttributesServiceHandler, serviceregistry.HandlerServer) { - as := &AttributesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return as, nil + cfg := policyconfig.GetSharedPolicyConfig(srp) + return &AttributesService{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + }, nil }, }, } @@ -67,16 +73,13 @@ func (s AttributesService) CreateAttribute(ctx context.Context, func (s *AttributesService) ListAttributes(ctx context.Context, req *connect.Request[attributes.ListAttributesRequest], ) (*connect.Response[attributes.ListAttributesResponse], error) { - state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) - namespace := req.Msg.GetNamespace() + state := req.Msg.GetState().String() s.logger.Debug("listing attribute definitions", slog.String("state", state)) - rsp := &attributes.ListAttributesResponse{} - list, err := s.dbClient.ListAttributes(ctx, state, namespace) + rsp, err := s.dbClient.ListAttributes(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.Attributes = list return connect.NewResponse(rsp), nil } @@ -205,17 +208,13 @@ func (s *AttributesService) CreateAttributeValue(ctx context.Context, req *conne } func (s *AttributesService) ListAttributeValues(ctx context.Context, req *connect.Request[attributes.ListAttributeValuesRequest]) (*connect.Response[attributes.ListAttributeValuesResponse], error) { - rsp := &attributes.ListAttributeValuesResponse{} - - state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + state := req.Msg.GetState().String() s.logger.Debug("listing attribute values", slog.String("attributeId", req.Msg.GetAttributeId()), slog.String("state", state)) - list, err := s.dbClient.ListAttributeValues(ctx, req.Msg.GetAttributeId(), state) + rsp, err := s.dbClient.ListAttributeValues(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.String("attributeId", req.Msg.GetAttributeId())) } - rsp.Values = list - return connect.NewResponse(rsp), nil } diff --git a/service/policy/config/config.go b/service/policy/config/config.go new file mode 100644 index 000000000..2c2c5ec3d --- /dev/null +++ b/service/policy/config/config.go @@ -0,0 +1,38 @@ +package config + +import ( + "fmt" + + "github.com/creasty/defaults" + "github.com/mitchellh/mapstructure" + "github.com/opentdf/platform/service/pkg/serviceregistry" +) + +// Global policy config to share among policy services +type Config struct { + // Default pagination list limit when not provided in request + ListRequestLimitDefault int `mapstructure:"list_request_limit_default" default:"1000"` + // Maximum pagination list limit allowed by policy services + ListRequestLimitMax int `mapstructure:"list_request_limit_max" default:"2500"` +} + +func GetSharedPolicyConfig(srp serviceregistry.RegistrationParams) *Config { + policyCfg := new(Config) + + if err := defaults.Set(policyCfg); err != nil { + panic(fmt.Errorf("failed to set defaults for policy service config: %w", err)) + } + + // Only decode config if it exists + if srp.Config != nil { + if err := mapstructure.Decode(srp.Config, &policyCfg); err != nil { + panic(fmt.Errorf("invalid policy svc cfg [%v] %w", srp.Config, err)) + } + } + + if policyCfg.ListRequestLimitMax <= policyCfg.ListRequestLimitDefault { + panic(fmt.Errorf("policy svc config request limit maximum [%d] must be greater than request limit default [%d]", policyCfg.ListRequestLimitMax, policyCfg.ListRequestLimitDefault)) + } + + return policyCfg +} diff --git a/service/policy/db/attribute_fqn.go b/service/policy/db/attribute_fqn.go index 30a5eeb8a..3374817fa 100644 --- a/service/policy/db/attribute_fqn.go +++ b/service/policy/db/attribute_fqn.go @@ -5,7 +5,9 @@ import ( "fmt" "strings" + "github.com/opentdf/platform/protocol/go/common" "github.com/opentdf/platform/protocol/go/policy/attributes" + "github.com/opentdf/platform/protocol/go/policy/namespaces" "github.com/opentdf/platform/service/pkg/db" ) @@ -26,14 +28,16 @@ func (c *PolicyDBClient) AttrFqnReindex(ctx context.Context) (res struct { //nol }, ) { // Get all namespaces - ns, err := c.ListNamespaces(ctx, StateAny) + ns, err := c.ListNamespaces(ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + }) if err != nil { panic(fmt.Errorf("could not get namespaces: %w", err)) } // Reindex all namespaces reindexedRecords := []UpsertAttributeNamespaceFqnRow{} - for _, n := range ns { + for _, n := range ns.GetNamespaces() { rows, err := c.Queries.UpsertAttributeNamespaceFqn(ctx, n.GetId()) if err != nil { panic(fmt.Errorf("could not update namespace [%s] FQN: %w", n.GetId(), err)) diff --git a/service/policy/db/attribute_values.go b/service/policy/db/attribute_values.go index 5cddd269d..952b39073 100644 --- a/service/policy/db/attribute_values.go +++ b/service/policy/db/attribute_values.go @@ -74,18 +74,28 @@ func (c PolicyDBClient) GetAttributeValue(ctx context.Context, id string) (*poli }, nil } -func (c PolicyDBClient) ListAttributeValues(ctx context.Context, attributeID string, state string) ([]*policy.Value, error) { +func (c PolicyDBClient) ListAttributeValues(ctx context.Context, r *attributes.ListAttributeValuesRequest) (*attributes.ListAttributeValuesResponse, error) { + state := getDBStateTypeTransformedEnum(r.GetState()) + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + active := pgtype.Bool{ Valid: false, } - if state != "" && state != StateAny { - active = pgtypeBool(state == StateActive) + if state != stateAny { + active = pgtypeBool(state == stateActive) } list, err := c.Queries.ListAttributeValues(ctx, ListAttributeValuesParams{ - AttributeDefinitionID: attributeID, + AttributeDefinitionID: r.GetAttributeId(), Active: active, + Limit: limit, + Offset: offset, }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) @@ -110,13 +120,49 @@ func (c PolicyDBClient) ListAttributeValues(ctx context.Context, attributeID str Fqn: av.Fqn.String, } } + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } - return attributeValues, nil + return &attributes.ListAttributeValuesResponse{ + Values: attributeValues, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } +// Loads all attribute values into memory by making iterative db roundtrip requests of defaultObjectListAllLimit size func (c PolicyDBClient) ListAllAttributeValues(ctx context.Context) ([]*policy.Value, error) { - // call ListAttributeValues method with "empty" param values to make the query return all rows - return c.ListAttributeValues(ctx, "", StateAny) + var nextOffset int32 + valsList := make([]*policy.Value, 0) + + for { + listed, err := c.ListAttributeValues(ctx, &attributes.ListAttributeValuesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: c.listCfg.limitMax, + Offset: nextOffset, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to list all attributes: %w", err) + } + + nextOffset = listed.GetPagination().GetNextOffset() + valsList = append(valsList, listed.GetValues()...) + + // offset becomes zero when list is exhausted + if nextOffset <= 0 { + break + } + } + return valsList, nil } func (c PolicyDBClient) UpdateAttributeValue(ctx context.Context, r *attributes.UpdateAttributeValueRequest) (*policy.Value, error) { diff --git a/service/policy/db/attributes.go b/service/policy/db/attributes.go index acf3f2e59..86c8a93d2 100644 --- a/service/policy/db/attributes.go +++ b/service/policy/db/attributes.go @@ -114,7 +114,10 @@ func hydrateAttribute(row *attributeQueryRow) (*policy.Attribute, error) { // CRUD operations /// -func (c PolicyDBClient) ListAttributes(ctx context.Context, state string, namespace string) ([]*policy.Attribute, error) { +func (c PolicyDBClient) ListAttributes(ctx context.Context, r *attributes.ListAttributesRequest) (*attributes.ListAttributesResponse, error) { + namespace := r.GetNamespace() + state := getDBStateTypeTransformedEnum(r.GetState()) + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) var ( active = pgtype.Bool{ Valid: false, @@ -123,8 +126,13 @@ func (c PolicyDBClient) ListAttributes(ctx context.Context, state string, namesp namespaceName = "" ) - if state != "" && state != StateAny { - active = pgtypeBool(state == StateActive) + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + if state != stateAny { + active = pgtypeBool(state == stateActive) } if namespace != "" { @@ -139,6 +147,8 @@ func (c PolicyDBClient) ListAttributes(ctx context.Context, state string, namesp Active: active, NamespaceID: namespaceID, NamespaceName: namespaceName, + Limit: limit, + Offset: offset, }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) @@ -163,12 +173,49 @@ func (c PolicyDBClient) ListAttributes(ctx context.Context, state string, namesp } } - return policyAttributes, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &attributes.ListAttributesResponse{ + Attributes: policyAttributes, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } +// Loads all attributes into memory by making iterative db roundtrip requests of defaultObjectListAllLimit size func (c PolicyDBClient) ListAllAttributes(ctx context.Context) ([]*policy.Attribute, error) { - // call general List method with empty params to get all attributes - return c.ListAttributes(ctx, "", "") + var nextOffset int32 + attrsList := make([]*policy.Attribute, 0) + + for { + listed, err := c.ListAttributes(ctx, &attributes.ListAttributesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: c.listCfg.limitMax, + Offset: nextOffset, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to list all attributes: %w", err) + } + + nextOffset = listed.GetPagination().GetNextOffset() + attrsList = append(attrsList, listed.GetAttributes()...) + + // offset becomes zero when list is exhausted + if nextOffset <= 0 { + break + } + } + return attrsList, nil } func (c PolicyDBClient) GetAttribute(ctx context.Context, id string) (*policy.Attribute, error) { @@ -253,7 +300,9 @@ func (c PolicyDBClient) GetAttributeByFqn(ctx context.Context, fqn string) (*pol } func (c PolicyDBClient) GetAttributesByNamespace(ctx context.Context, namespaceID string) ([]*policy.Attribute, error) { - list, err := c.Queries.ListAttributesSummary(ctx, namespaceID) + list, err := c.Queries.ListAttributesSummary(ctx, ListAttributesSummaryParams{ + NamespaceID: namespaceID, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } diff --git a/service/policy/db/key_access_server_registry.go b/service/policy/db/key_access_server_registry.go index 45cf9d11b..1ae09e63f 100644 --- a/service/policy/db/key_access_server_registry.go +++ b/service/policy/db/key_access_server_registry.go @@ -12,8 +12,18 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) -func (c PolicyDBClient) ListKeyAccessServers(ctx context.Context) ([]*policy.KeyAccessServer, error) { - list, err := c.Queries.ListKeyAccessServers(ctx) +func (c PolicyDBClient) ListKeyAccessServers(ctx context.Context, r *kasregistry.ListKeyAccessServersRequest) (*kasregistry.ListKeyAccessServersResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + list, err := c.Queries.ListKeyAccessServers(ctx, ListKeyAccessServersParams{ + Offset: offset, + Limit: limit, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } @@ -37,13 +47,26 @@ func (c PolicyDBClient) ListKeyAccessServers(ctx context.Context) ([]*policy.Key keyAccessServer.Id = kas.ID keyAccessServer.Uri = kas.Uri keyAccessServer.PublicKey = publicKey - keyAccessServer.Name = kas.Name.String + keyAccessServer.Name = kas.KasName.String keyAccessServer.Metadata = metadata keyAccessServers[i] = keyAccessServer } + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } - return keyAccessServers, nil + return &kasregistry.ListKeyAccessServersResponse{ + KeyAccessServers: keyAccessServers, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } func (c PolicyDBClient) GetKeyAccessServer(ctx context.Context, id string) (*policy.KeyAccessServer, error) { @@ -171,11 +194,19 @@ func (c PolicyDBClient) DeleteKeyAccessServer(ctx context.Context, id string) (* }, nil } -func (c PolicyDBClient) ListKeyAccessServerGrants(ctx context.Context, kasID, kasURI, kasName string) ([]*kasregistry.KeyAccessServerGrants, error) { +func (c PolicyDBClient) ListKeyAccessServerGrants(ctx context.Context, r *kasregistry.ListKeyAccessServerGrantsRequest) (*kasregistry.ListKeyAccessServerGrantsResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + params := ListKeyAccessServerGrantsParams{ - KasID: kasID, - KasUri: kasURI, - KasName: kasName, + KasID: r.GetKasId(), + KasUri: r.GetKasUri(), + KasName: r.GetKasName(), + Offset: offset, + Limit: limit, } listRows, err := c.Queries.ListKeyAccessServerGrants(ctx, params) if err != nil { @@ -213,6 +244,18 @@ func (c PolicyDBClient) ListKeyAccessServerGrants(ctx context.Context, kasID, ka NamespaceGrants: namespaceGrants, } } - - return grants, nil + var total int32 + var nextOffset int32 + if len(listRows) > 0 { + total = int32(listRows[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + return &kasregistry.ListKeyAccessServerGrantsResponse{ + Grants: grants, + Pagination: &policy.PageResponse{ + CurrentOffset: params.Offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } diff --git a/service/policy/db/namespaces.go b/service/policy/db/namespaces.go index d1fd0a0c2..d4a19467c 100644 --- a/service/policy/db/namespaces.go +++ b/service/policy/db/namespaces.go @@ -44,21 +44,32 @@ func (c PolicyDBClient) GetNamespace(ctx context.Context, id string) (*policy.Na }, nil } -func (c PolicyDBClient) ListNamespaces(ctx context.Context, state string) ([]*policy.Namespace, error) { +func (c PolicyDBClient) ListNamespaces(ctx context.Context, r *namespaces.ListNamespacesRequest) (*namespaces.ListNamespacesResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + active := pgtype.Bool{ Valid: false, } - - if state != "" && state != StateAny { - active = pgtypeBool(state == StateActive) + state := getDBStateTypeTransformedEnum(r.GetState()) + if state != stateAny { + active = pgtypeBool(state == stateActive) } - list, err := c.Queries.ListNamespaces(ctx, active) + list, err := c.Queries.ListNamespaces(ctx, ListNamespacesParams{ + Active: active, + Limit: limit, + Offset: offset, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } - namespaces := make([]*policy.Namespace, len(list)) + nsList := make([]*policy.Namespace, len(list)) for i, ns := range list { metadata := &common.Metadata{} @@ -66,7 +77,7 @@ func (c PolicyDBClient) ListNamespaces(ctx context.Context, state string) ([]*po return nil, err } - namespaces[i] = &policy.Namespace{ + nsList[i] = &policy.Namespace{ Id: ns.ID, Name: ns.Name, Active: &wrapperspb.BoolValue{Value: ns.Active}, @@ -75,7 +86,49 @@ func (c PolicyDBClient) ListNamespaces(ctx context.Context, state string) ([]*po } } - return namespaces, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &namespaces.ListNamespacesResponse{ + Namespaces: nsList, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil +} + +// Loads all namespaces into memory by making iterative db roundtrip requests of defaultObjectListAllLimit size +func (c PolicyDBClient) ListAllNamespaces(ctx context.Context) ([]*policy.Namespace, error) { + var nextOffset int32 + nsList := make([]*policy.Namespace, 0) + + for { + listed, err := c.ListNamespaces(ctx, &namespaces.ListNamespacesRequest{ + State: common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY, + Pagination: &policy.PageRequest{ + Limit: c.listCfg.limitMax, + Offset: nextOffset, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to list all namespaces: %w", err) + } + + nextOffset = listed.GetPagination().GetNextOffset() + nsList = append(nsList, listed.GetNamespaces()...) + + // offset becomes zero when list is exhausted + if nextOffset <= 0 { + break + } + } + return nsList, nil } func (c PolicyDBClient) CreateNamespace(ctx context.Context, r *namespaces.CreateNamespaceRequest) (*policy.Namespace, error) { diff --git a/service/policy/db/policy.go b/service/policy/db/policy.go index cb2304500..390362b3d 100644 --- a/service/policy/db/policy.go +++ b/service/policy/db/policy.go @@ -7,33 +7,41 @@ import ( ) const ( - StateInactive = "INACTIVE" - StateActive = "ACTIVE" - StateAny = "ANY" - StateUnspecified = "UNSPECIFIED" + stateInactive transformedState = "INACTIVE" + stateActive transformedState = "ACTIVE" + stateAny transformedState = "ANY" + stateUnspecified transformedState = "UNSPECIFIED" ) +type transformedState string + +type ListConfig struct { + limitDefault int32 + limitMax int32 +} + type PolicyDBClient struct { *db.Client logger *logger.Logger *Queries + listCfg ListConfig } -func NewClient(c *db.Client, logger *logger.Logger) PolicyDBClient { - return PolicyDBClient{c, logger, New(c.Pgx)} +func NewClient(c *db.Client, logger *logger.Logger, configuredListLimitMax, configuredListLimitDefault int32) PolicyDBClient { + return PolicyDBClient{c, logger, New(c.Pgx), ListConfig{limitDefault: configuredListLimitDefault, limitMax: configuredListLimitMax}} } -func GetDBStateTypeTransformedEnum(state common.ActiveStateEnum) string { +func getDBStateTypeTransformedEnum(state common.ActiveStateEnum) transformedState { switch state.String() { case common.ActiveStateEnum_ACTIVE_STATE_ENUM_ACTIVE.String(): - return StateActive + return stateActive case common.ActiveStateEnum_ACTIVE_STATE_ENUM_INACTIVE.String(): - return StateInactive + return stateInactive case common.ActiveStateEnum_ACTIVE_STATE_ENUM_ANY.String(): - return StateAny + return stateAny case common.ActiveStateEnum_ACTIVE_STATE_ENUM_UNSPECIFIED.String(): - return StateActive + return stateActive default: - return StateActive + return stateActive } } diff --git a/service/policy/db/query.sql b/service/policy/db/query.sql index fdb7c2956..dc36dd37a 100644 --- a/service/policy/db/query.sql +++ b/service/policy/db/query.sql @@ -3,60 +3,87 @@ ---------------------------------------------------------------- -- name: ListKeyAccessServerGrants :many +WITH listed AS ( + SELECT + COUNT(*) OVER() AS total, + kas.id AS kas_id, + kas.uri AS kas_uri, + kas.name AS kas_name, + kas.public_key AS kas_public_key, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT( + 'labels', kas.metadata -> 'labels', + 'created_at', kas.created_at, + 'updated_at', kas.updated_at + )) AS kas_metadata, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', attrkag.attribute_definition_id, + 'fqn', fqns_on_attr.fqn + )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', valkag.attribute_value_id, + 'fqn', fqns_on_vals.fqn + )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', nskag.namespace_id, + 'fqn', fqns_on_ns.fqn + )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants + FROM + key_access_servers kas + LEFT JOIN + attribute_definition_key_access_grants attrkag + ON kas.id = attrkag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_attr + ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id + AND fqns_on_attr.value_id IS NULL + LEFT JOIN + attribute_value_key_access_grants valkag + ON kas.id = valkag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_vals + ON valkag.attribute_value_id = fqns_on_vals.value_id + LEFT JOIN + attribute_namespace_key_access_grants nskag + ON kas.id = nskag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_ns + ON nskag.namespace_id = fqns_on_ns.namespace_id + AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL + WHERE (NULLIF(@kas_id, '') IS NULL OR kas.id = @kas_id::uuid) + AND (NULLIF(@kas_uri, '') IS NULL OR kas.uri = @kas_uri::varchar) + AND (NULLIF(@kas_name, '') IS NULL OR kas.name = @kas_name::varchar) + GROUP BY + kas.id +) SELECT - kas.id AS kas_id, - kas.uri AS kas_uri, - kas.name AS kas_name, - kas.public_key AS kas_public_key, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT( - 'labels', kas.metadata -> 'labels', - 'created_at', kas.created_at, - 'updated_at', kas.updated_at - )) AS kas_metadata, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', attrkag.attribute_definition_id, - 'fqn', fqns_on_attr.fqn - )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', valkag.attribute_value_id, - 'fqn', fqns_on_vals.fqn - )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', nskag.namespace_id, - 'fqn', fqns_on_ns.fqn - )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants -FROM - key_access_servers kas -LEFT JOIN - attribute_definition_key_access_grants attrkag - ON kas.id = attrkag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_attr - ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id - AND fqns_on_attr.value_id IS NULL -LEFT JOIN - attribute_value_key_access_grants valkag - ON kas.id = valkag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_vals - ON valkag.attribute_value_id = fqns_on_vals.value_id -LEFT JOIN - attribute_namespace_key_access_grants nskag - ON kas.id = nskag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_ns - ON nskag.namespace_id = fqns_on_ns.namespace_id - AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL -WHERE (NULLIF(@kas_id, '') IS NULL OR kas.id = @kas_id::uuid) - AND (NULLIF(@kas_uri, '') IS NULL OR kas.uri = @kas_uri::varchar) - AND (NULLIF(@kas_name, '') IS NULL OR kas.name = @kas_name::varchar) -GROUP BY - kas.id; + listed.kas_id, + listed.kas_uri, + listed.kas_name, + listed.kas_public_key, + listed.kas_metadata, + listed.attributes_grants, + listed.values_grants, + listed.namespace_grants, + listed.total +FROM listed +LIMIT @limit_ +OFFSET @offset_; -- name: ListKeyAccessServers :many -SELECT id, uri, public_key, name, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM key_access_servers; +WITH counted AS ( + SELECT COUNT(kas.id) AS total + FROM key_access_servers kas +) +SELECT kas.id, + kas.uri, + kas.public_key, + kas.name AS kas_name, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', kas.metadata -> 'labels', 'created_at', kas.created_at, 'updated_at', kas.updated_at)) as metadata, + counted.total +FROM key_access_servers kas +CROSS JOIN counted +LIMIT @limit_ +OFFSET @offset_; -- name: GetKeyAccessServer :one SELECT id, uri, public_key, name, @@ -206,6 +233,10 @@ RETURNING ---------------------------------------------------------------- -- name: ListAttributesDetail :many +WITH counted AS ( + SELECT COUNT(ad.id) AS total + FROM attribute_definitions ad +) SELECT ad.id, ad.name as attribute_name, @@ -222,8 +253,10 @@ SELECT 'fqn', CONCAT(fqns.fqn, '/value/', avt.value) ) ORDER BY ARRAY_POSITION(ad.values_order, avt.id) ) AS values, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_definitions ad +CROSS JOIN counted LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id LEFT JOIN ( SELECT @@ -249,9 +282,14 @@ WHERE (sqlc.narg('active')::BOOLEAN IS NULL OR ad.active = sqlc.narg('active')) AND (NULLIF(@namespace_id, '') IS NULL OR ad.namespace_id = @namespace_id::uuid) AND (NULLIF(@namespace_name, '') IS NULL OR n.name = @namespace_name) -GROUP BY ad.id, n.name, fqns.fqn; +GROUP BY ad.id, n.name, fqns.fqn, counted.total +LIMIT @limit_ +OFFSET @offset_; -- name: ListAttributesSummary :many +WITH counted AS ( + SELECT COUNT(ad.id) AS total FROM attribute_definitions ad +) SELECT ad.id, ad.name as attribute_name, @@ -259,11 +297,15 @@ SELECT JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ad.metadata -> 'labels', 'created_at', ad.created_at, 'updated_at', ad.updated_at)) AS metadata, ad.namespace_id, ad.active, - n.name as namespace_name + n.name as namespace_name, + counted.total FROM attribute_definitions ad +CROSS JOIN counted LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id WHERE ad.namespace_id = $1 -GROUP BY ad.id, n.name; +GROUP BY ad.id, n.name, counted.total +LIMIT @limit_ +OFFSET @offset_; -- name: ListAttributesByDefOrValueFqns :many -- get the attribute definition for the provided value or definition fqn @@ -468,21 +510,27 @@ WHERE attribute_definition_id = $1 AND key_access_server_id = $2; ---------------------------------------------------------------- -- name: ListAttributeValues :many - +WITH counted AS ( + SELECT COUNT(av.id) AS total + FROM attribute_values av +) SELECT av.id, av.value, av.active, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', av.metadata -> 'labels', 'created_at', av.created_at, 'updated_at', av.updated_at)) as metadata, av.attribute_definition_id, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_values av +CROSS JOIN counted LEFT JOIN attribute_fqns fqns ON av.id = fqns.value_id WHERE ( (sqlc.narg('active')::BOOLEAN IS NULL OR av.active = sqlc.narg('active')) AND (NULLIF(@attribute_definition_id, '') IS NULL OR av.attribute_definition_id = @attribute_definition_id::UUID) ) -GROUP BY av.id, fqns.fqn; +LIMIT @limit_ +OFFSET @offset_; -- name: GetAttributeValue :one SELECT @@ -537,10 +585,20 @@ WHERE attribute_value_id = $1 AND key_access_server_id = $2; ---------------------------------------------------------------- -- name: ListResourceMappingGroups :many -SELECT id, namespace_id, name, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM resource_mapping_groups -WHERE (NULLIF(@namespace_id, '') IS NULL OR namespace_id = @namespace_id::uuid); +WITH counted AS ( + SELECT COUNT(rmg.id) AS total + FROM resource_mapping_groups rmg +) +SELECT rmg.id, + rmg.namespace_id, + rmg.name, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', rmg.metadata -> 'labels', 'created_at', rmg.created_at, 'updated_at', rmg.updated_at)) as metadata, + counted.total +FROM resource_mapping_groups rmg +CROSS JOIN counted +WHERE (NULLIF(@namespace_id, '') IS NULL OR rmg.namespace_id = @namespace_id::uuid) +LIMIT @limit_ +OFFSET @offset_; -- name: GetResourceMappingGroup :one SELECT id, namespace_id, name, @@ -569,17 +627,25 @@ DELETE FROM resource_mapping_groups WHERE id = $1; ---------------------------------------------------------------- -- name: ListResourceMappings :many +WITH counted AS ( + SELECT COUNT(rm.id) AS total + FROM resource_mappings rm +) SELECT m.id, JSON_BUILD_OBJECT('id', av.id, 'value', av.value, 'fqn', fqns.fqn) as attribute_value, m.terms, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', m.metadata -> 'labels', 'created_at', m.created_at, 'updated_at', m.updated_at)) as metadata, - COALESCE(m.group_id::TEXT, '')::TEXT as group_id + COALESCE(m.group_id::TEXT, '')::TEXT as group_id, + counted.total FROM resource_mappings m +CROSS JOIN counted LEFT JOIN attribute_values av on m.attribute_value_id = av.id LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id WHERE (NULLIF(@group_id, '') IS NULL OR m.group_id = @group_id::UUID) -GROUP BY av.id, m.id, fqns.fqn; +GROUP BY av.id, m.id, fqns.fqn, counted.total +LIMIT @limit_ +OFFSET @offset_; -- name: ListResourceMappingsByFullyQualifiedGroup :many -- CTE to cache the group JSON build since it will be the same for all mappings of the group @@ -646,15 +712,22 @@ DELETE FROM resource_mappings WHERE id = $1; ---------------------------------------------------------------- -- name: ListNamespaces :many +WITH counted AS ( + SELECT COUNT(id) AS total FROM attribute_namespaces +) SELECT ns.id, ns.name, ns.active, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ns.metadata -> 'labels', 'created_at', ns.created_at, 'updated_at', ns.updated_at)) as metadata, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_namespaces ns +CROSS JOIN counted LEFT JOIN attribute_fqns fqns ON ns.id = fqns.namespace_id AND fqns.attribute_id IS NULL -WHERE (sqlc.narg('active')::BOOLEAN IS NULL OR ns.active = sqlc.narg('active')::BOOLEAN); +WHERE (sqlc.narg('active')::BOOLEAN IS NULL OR ns.active = sqlc.narg('active')::BOOLEAN) +LIMIT @limit_ +OFFSET @offset_; -- name: GetNamespace :one SELECT @@ -706,11 +779,19 @@ WHERE namespace_id = $1 AND key_access_server_id = $2; ---------------------------------------------------------------- -- name: ListSubjectConditionSets :many +WITH counted AS ( + SELECT COUNT(scs.id) AS total + FROM subject_condition_set scs +) SELECT - id, - condition, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM subject_condition_set; + scs.id, + scs.condition, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata -> 'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)) as metadata, + counted.total +FROM subject_condition_set scs +CROSS JOIN counted +LIMIT @limit_ +OFFSET @offset_; -- name: GetSubjectConditionSet :one SELECT @@ -745,6 +826,10 @@ RETURNING id; ---------------------------------------------------------------- -- name: ListSubjectMappings :many +WITH counted AS ( + SELECT COUNT(sm.id) AS total + FROM subject_mappings sm +) SELECT sm.id, sm.actions, @@ -754,11 +839,15 @@ SELECT 'metadata', JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata->'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)), 'subject_sets', scs.condition ) AS subject_condition_set, - JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value + JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value, + counted.total FROM subject_mappings sm +CROSS JOIN counted LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id -GROUP BY av.id, sm.id, scs.id; +GROUP BY av.id, sm.id, scs.id, counted.total +LIMIT @limit_ +OFFSET @offset_; -- name: GetSubjectMapping :one SELECT @@ -813,4 +902,4 @@ SET WHERE id = $1; -- name: DeleteSubjectMapping :execrows -DELETE FROM subject_mappings WHERE id = $1; +DELETE FROM subject_mappings WHERE id = $1; \ No newline at end of file diff --git a/service/policy/db/query.sql.go b/service/policy/db/query.sql.go index e79ce3a9a..3e21083c0 100644 --- a/service/policy/db/query.sql.go +++ b/service/policy/db/query.sql.go @@ -904,26 +904,34 @@ func (q *Queries) GetSubjectMapping(ctx context.Context, id string) (GetSubjectM const listAttributeValues = `-- name: ListAttributeValues :many - +WITH counted AS ( + SELECT COUNT(av.id) AS total + FROM attribute_values av +) SELECT av.id, av.value, av.active, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', av.metadata -> 'labels', 'created_at', av.created_at, 'updated_at', av.updated_at)) as metadata, av.attribute_definition_id, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_values av +CROSS JOIN counted LEFT JOIN attribute_fqns fqns ON av.id = fqns.value_id WHERE ( ($1::BOOLEAN IS NULL OR av.active = $1) AND (NULLIF($2, '') IS NULL OR av.attribute_definition_id = $2::UUID) ) -GROUP BY av.id, fqns.fqn +LIMIT $4 +OFFSET $3 ` type ListAttributeValuesParams struct { Active pgtype.Bool `json:"active"` AttributeDefinitionID interface{} `json:"attribute_definition_id"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` } type ListAttributeValuesRow struct { @@ -933,28 +941,41 @@ type ListAttributeValuesRow struct { Metadata []byte `json:"metadata"` AttributeDefinitionID string `json:"attribute_definition_id"` Fqn pgtype.Text `json:"fqn"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // ATTRIBUTE VALUES // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(av.id) AS total +// FROM attribute_values av +// ) // SELECT // av.id, // av.value, // av.active, // JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', av.metadata -> 'labels', 'created_at', av.created_at, 'updated_at', av.updated_at)) as metadata, // av.attribute_definition_id, -// fqns.fqn +// fqns.fqn, +// counted.total // FROM attribute_values av +// CROSS JOIN counted // LEFT JOIN attribute_fqns fqns ON av.id = fqns.value_id // WHERE ( // ($1::BOOLEAN IS NULL OR av.active = $1) AND // (NULLIF($2, '') IS NULL OR av.attribute_definition_id = $2::UUID) // ) -// GROUP BY av.id, fqns.fqn +// LIMIT $4 +// OFFSET $3 func (q *Queries) ListAttributeValues(ctx context.Context, arg ListAttributeValuesParams) ([]ListAttributeValuesRow, error) { - rows, err := q.db.Query(ctx, listAttributeValues, arg.Active, arg.AttributeDefinitionID) + rows, err := q.db.Query(ctx, listAttributeValues, + arg.Active, + arg.AttributeDefinitionID, + arg.Offset, + arg.Limit, + ) if err != nil { return nil, err } @@ -969,6 +990,7 @@ func (q *Queries) ListAttributeValues(ctx context.Context, arg ListAttributeValu &i.Metadata, &i.AttributeDefinitionID, &i.Fqn, + &i.Total, ); err != nil { return nil, err } @@ -1271,6 +1293,10 @@ func (q *Queries) ListAttributesByDefOrValueFqns(ctx context.Context, fqns []str const listAttributesDetail = `-- name: ListAttributesDetail :many +WITH counted AS ( + SELECT COUNT(ad.id) AS total + FROM attribute_definitions ad +) SELECT ad.id, ad.name as attribute_name, @@ -1287,8 +1313,10 @@ SELECT 'fqn', CONCAT(fqns.fqn, '/value/', avt.value) ) ORDER BY ARRAY_POSITION(ad.values_order, avt.id) ) AS values, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_definitions ad +CROSS JOIN counted LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id LEFT JOIN ( SELECT @@ -1314,13 +1342,17 @@ WHERE ($1::BOOLEAN IS NULL OR ad.active = $1) AND (NULLIF($2, '') IS NULL OR ad.namespace_id = $2::uuid) AND (NULLIF($3, '') IS NULL OR n.name = $3) -GROUP BY ad.id, n.name, fqns.fqn +GROUP BY ad.id, n.name, fqns.fqn, counted.total +LIMIT $5 +OFFSET $4 ` type ListAttributesDetailParams struct { Active pgtype.Bool `json:"active"` NamespaceID interface{} `json:"namespace_id"` NamespaceName interface{} `json:"namespace_name"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` } type ListAttributesDetailRow struct { @@ -1333,12 +1365,17 @@ type ListAttributesDetailRow struct { NamespaceName pgtype.Text `json:"namespace_name"` Values []byte `json:"values"` Fqn pgtype.Text `json:"fqn"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // ATTRIBUTES // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(ad.id) AS total +// FROM attribute_definitions ad +// ) // SELECT // ad.id, // ad.name as attribute_name, @@ -1355,8 +1392,10 @@ type ListAttributesDetailRow struct { // 'fqn', CONCAT(fqns.fqn, '/value/', avt.value) // ) ORDER BY ARRAY_POSITION(ad.values_order, avt.id) // ) AS values, -// fqns.fqn +// fqns.fqn, +// counted.total // FROM attribute_definitions ad +// CROSS JOIN counted // LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id // LEFT JOIN ( // SELECT @@ -1382,9 +1421,17 @@ type ListAttributesDetailRow struct { // ($1::BOOLEAN IS NULL OR ad.active = $1) AND // (NULLIF($2, '') IS NULL OR ad.namespace_id = $2::uuid) AND // (NULLIF($3, '') IS NULL OR n.name = $3) -// GROUP BY ad.id, n.name, fqns.fqn +// GROUP BY ad.id, n.name, fqns.fqn, counted.total +// LIMIT $5 +// OFFSET $4 func (q *Queries) ListAttributesDetail(ctx context.Context, arg ListAttributesDetailParams) ([]ListAttributesDetailRow, error) { - rows, err := q.db.Query(ctx, listAttributesDetail, arg.Active, arg.NamespaceID, arg.NamespaceName) + rows, err := q.db.Query(ctx, listAttributesDetail, + arg.Active, + arg.NamespaceID, + arg.NamespaceName, + arg.Offset, + arg.Limit, + ) if err != nil { return nil, err } @@ -1402,6 +1449,7 @@ func (q *Queries) ListAttributesDetail(ctx context.Context, arg ListAttributesDe &i.NamespaceName, &i.Values, &i.Fqn, + &i.Total, ); err != nil { return nil, err } @@ -1414,6 +1462,9 @@ func (q *Queries) ListAttributesDetail(ctx context.Context, arg ListAttributesDe } const listAttributesSummary = `-- name: ListAttributesSummary :many +WITH counted AS ( + SELECT COUNT(ad.id) AS total FROM attribute_definitions ad +) SELECT ad.id, ad.name as attribute_name, @@ -1421,13 +1472,23 @@ SELECT JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ad.metadata -> 'labels', 'created_at', ad.created_at, 'updated_at', ad.updated_at)) AS metadata, ad.namespace_id, ad.active, - n.name as namespace_name + n.name as namespace_name, + counted.total FROM attribute_definitions ad +CROSS JOIN counted LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id WHERE ad.namespace_id = $1 -GROUP BY ad.id, n.name +GROUP BY ad.id, n.name, counted.total +LIMIT $3 +OFFSET $2 ` +type ListAttributesSummaryParams struct { + NamespaceID string `json:"namespace_id"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListAttributesSummaryRow struct { ID string `json:"id"` AttributeName string `json:"attribute_name"` @@ -1436,10 +1497,14 @@ type ListAttributesSummaryRow struct { NamespaceID string `json:"namespace_id"` Active bool `json:"active"` NamespaceName pgtype.Text `json:"namespace_name"` + Total int64 `json:"total"` } // ListAttributesSummary // +// WITH counted AS ( +// SELECT COUNT(ad.id) AS total FROM attribute_definitions ad +// ) // SELECT // ad.id, // ad.name as attribute_name, @@ -1447,13 +1512,17 @@ type ListAttributesSummaryRow struct { // JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ad.metadata -> 'labels', 'created_at', ad.created_at, 'updated_at', ad.updated_at)) AS metadata, // ad.namespace_id, // ad.active, -// n.name as namespace_name +// n.name as namespace_name, +// counted.total // FROM attribute_definitions ad +// CROSS JOIN counted // LEFT JOIN attribute_namespaces n ON n.id = ad.namespace_id // WHERE ad.namespace_id = $1 -// GROUP BY ad.id, n.name -func (q *Queries) ListAttributesSummary(ctx context.Context, namespaceID string) ([]ListAttributesSummaryRow, error) { - rows, err := q.db.Query(ctx, listAttributesSummary, namespaceID) +// GROUP BY ad.id, n.name, counted.total +// LIMIT $3 +// OFFSET $2 +func (q *Queries) ListAttributesSummary(ctx context.Context, arg ListAttributesSummaryParams) ([]ListAttributesSummaryRow, error) { + rows, err := q.db.Query(ctx, listAttributesSummary, arg.NamespaceID, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1469,6 +1538,7 @@ func (q *Queries) ListAttributesSummary(ctx context.Context, namespaceID string) &i.NamespaceID, &i.Active, &i.NamespaceName, + &i.Total, ); err != nil { return nil, err } @@ -1482,58 +1552,76 @@ func (q *Queries) ListAttributesSummary(ctx context.Context, namespaceID string) const listKeyAccessServerGrants = `-- name: ListKeyAccessServerGrants :many +WITH listed AS ( + SELECT + COUNT(*) OVER() AS total, + kas.id AS kas_id, + kas.uri AS kas_uri, + kas.name AS kas_name, + kas.public_key AS kas_public_key, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT( + 'labels', kas.metadata -> 'labels', + 'created_at', kas.created_at, + 'updated_at', kas.updated_at + )) AS kas_metadata, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', attrkag.attribute_definition_id, + 'fqn', fqns_on_attr.fqn + )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', valkag.attribute_value_id, + 'fqn', fqns_on_vals.fqn + )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, + JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( + 'id', nskag.namespace_id, + 'fqn', fqns_on_ns.fqn + )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants + FROM + key_access_servers kas + LEFT JOIN + attribute_definition_key_access_grants attrkag + ON kas.id = attrkag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_attr + ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id + AND fqns_on_attr.value_id IS NULL + LEFT JOIN + attribute_value_key_access_grants valkag + ON kas.id = valkag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_vals + ON valkag.attribute_value_id = fqns_on_vals.value_id + LEFT JOIN + attribute_namespace_key_access_grants nskag + ON kas.id = nskag.key_access_server_id + LEFT JOIN + attribute_fqns fqns_on_ns + ON nskag.namespace_id = fqns_on_ns.namespace_id + AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL + WHERE (NULLIF($3, '') IS NULL OR kas.id = $3::uuid) + AND (NULLIF($4, '') IS NULL OR kas.uri = $4::varchar) + AND (NULLIF($5, '') IS NULL OR kas.name = $5::varchar) + GROUP BY + kas.id +) SELECT - kas.id AS kas_id, - kas.uri AS kas_uri, - kas.name AS kas_name, - kas.public_key AS kas_public_key, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT( - 'labels', kas.metadata -> 'labels', - 'created_at', kas.created_at, - 'updated_at', kas.updated_at - )) AS kas_metadata, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', attrkag.attribute_definition_id, - 'fqn', fqns_on_attr.fqn - )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', valkag.attribute_value_id, - 'fqn', fqns_on_vals.fqn - )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, - JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( - 'id', nskag.namespace_id, - 'fqn', fqns_on_ns.fqn - )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants -FROM - key_access_servers kas -LEFT JOIN - attribute_definition_key_access_grants attrkag - ON kas.id = attrkag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_attr - ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id - AND fqns_on_attr.value_id IS NULL -LEFT JOIN - attribute_value_key_access_grants valkag - ON kas.id = valkag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_vals - ON valkag.attribute_value_id = fqns_on_vals.value_id -LEFT JOIN - attribute_namespace_key_access_grants nskag - ON kas.id = nskag.key_access_server_id -LEFT JOIN - attribute_fqns fqns_on_ns - ON nskag.namespace_id = fqns_on_ns.namespace_id - AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL -WHERE (NULLIF($1, '') IS NULL OR kas.id = $1::uuid) - AND (NULLIF($2, '') IS NULL OR kas.uri = $2::varchar) - AND (NULLIF($3, '') IS NULL OR kas.name = $3::varchar) -GROUP BY - kas.id + listed.kas_id, + listed.kas_uri, + listed.kas_name, + listed.kas_public_key, + listed.kas_metadata, + listed.attributes_grants, + listed.values_grants, + listed.namespace_grants, + listed.total +FROM listed +LIMIT $2 +OFFSET $1 ` type ListKeyAccessServerGrantsParams struct { + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` KasID interface{} `json:"kas_id"` KasUri interface{} `json:"kas_uri"` KasName interface{} `json:"kas_name"` @@ -1548,63 +1636,86 @@ type ListKeyAccessServerGrantsRow struct { AttributesGrants []byte `json:"attributes_grants"` ValuesGrants []byte `json:"values_grants"` NamespaceGrants []byte `json:"namespace_grants"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // KEY ACCESS SERVERS // -------------------------------------------------------------- // +// WITH listed AS ( +// SELECT +// COUNT(*) OVER() AS total, +// kas.id AS kas_id, +// kas.uri AS kas_uri, +// kas.name AS kas_name, +// kas.public_key AS kas_public_key, +// JSON_STRIP_NULLS(JSON_BUILD_OBJECT( +// 'labels', kas.metadata -> 'labels', +// 'created_at', kas.created_at, +// 'updated_at', kas.updated_at +// )) AS kas_metadata, +// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( +// 'id', attrkag.attribute_definition_id, +// 'fqn', fqns_on_attr.fqn +// )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, +// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( +// 'id', valkag.attribute_value_id, +// 'fqn', fqns_on_vals.fqn +// )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, +// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( +// 'id', nskag.namespace_id, +// 'fqn', fqns_on_ns.fqn +// )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants +// FROM +// key_access_servers kas +// LEFT JOIN +// attribute_definition_key_access_grants attrkag +// ON kas.id = attrkag.key_access_server_id +// LEFT JOIN +// attribute_fqns fqns_on_attr +// ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id +// AND fqns_on_attr.value_id IS NULL +// LEFT JOIN +// attribute_value_key_access_grants valkag +// ON kas.id = valkag.key_access_server_id +// LEFT JOIN +// attribute_fqns fqns_on_vals +// ON valkag.attribute_value_id = fqns_on_vals.value_id +// LEFT JOIN +// attribute_namespace_key_access_grants nskag +// ON kas.id = nskag.key_access_server_id +// LEFT JOIN +// attribute_fqns fqns_on_ns +// ON nskag.namespace_id = fqns_on_ns.namespace_id +// AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL +// WHERE (NULLIF($3, '') IS NULL OR kas.id = $3::uuid) +// AND (NULLIF($4, '') IS NULL OR kas.uri = $4::varchar) +// AND (NULLIF($5, '') IS NULL OR kas.name = $5::varchar) +// GROUP BY +// kas.id +// ) // SELECT -// kas.id AS kas_id, -// kas.uri AS kas_uri, -// kas.name AS kas_name, -// kas.public_key AS kas_public_key, -// JSON_STRIP_NULLS(JSON_BUILD_OBJECT( -// 'labels', kas.metadata -> 'labels', -// 'created_at', kas.created_at, -// 'updated_at', kas.updated_at -// )) AS kas_metadata, -// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( -// 'id', attrkag.attribute_definition_id, -// 'fqn', fqns_on_attr.fqn -// )) FILTER (WHERE attrkag.attribute_definition_id IS NOT NULL) AS attributes_grants, -// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( -// 'id', valkag.attribute_value_id, -// 'fqn', fqns_on_vals.fqn -// )) FILTER (WHERE valkag.attribute_value_id IS NOT NULL) AS values_grants, -// JSON_AGG(DISTINCT JSONB_BUILD_OBJECT( -// 'id', nskag.namespace_id, -// 'fqn', fqns_on_ns.fqn -// )) FILTER (WHERE nskag.namespace_id IS NOT NULL) AS namespace_grants -// FROM -// key_access_servers kas -// LEFT JOIN -// attribute_definition_key_access_grants attrkag -// ON kas.id = attrkag.key_access_server_id -// LEFT JOIN -// attribute_fqns fqns_on_attr -// ON attrkag.attribute_definition_id = fqns_on_attr.attribute_id -// AND fqns_on_attr.value_id IS NULL -// LEFT JOIN -// attribute_value_key_access_grants valkag -// ON kas.id = valkag.key_access_server_id -// LEFT JOIN -// attribute_fqns fqns_on_vals -// ON valkag.attribute_value_id = fqns_on_vals.value_id -// LEFT JOIN -// attribute_namespace_key_access_grants nskag -// ON kas.id = nskag.key_access_server_id -// LEFT JOIN -// attribute_fqns fqns_on_ns -// ON nskag.namespace_id = fqns_on_ns.namespace_id -// AND fqns_on_ns.attribute_id IS NULL AND fqns_on_ns.value_id IS NULL -// WHERE (NULLIF($1, '') IS NULL OR kas.id = $1::uuid) -// AND (NULLIF($2, '') IS NULL OR kas.uri = $2::varchar) -// AND (NULLIF($3, '') IS NULL OR kas.name = $3::varchar) -// GROUP BY -// kas.id +// listed.kas_id, +// listed.kas_uri, +// listed.kas_name, +// listed.kas_public_key, +// listed.kas_metadata, +// listed.attributes_grants, +// listed.values_grants, +// listed.namespace_grants, +// listed.total +// FROM listed +// LIMIT $2 +// OFFSET $1 func (q *Queries) ListKeyAccessServerGrants(ctx context.Context, arg ListKeyAccessServerGrantsParams) ([]ListKeyAccessServerGrantsRow, error) { - rows, err := q.db.Query(ctx, listKeyAccessServerGrants, arg.KasID, arg.KasUri, arg.KasName) + rows, err := q.db.Query(ctx, listKeyAccessServerGrants, + arg.Offset, + arg.Limit, + arg.KasID, + arg.KasUri, + arg.KasName, + ) if err != nil { return nil, err } @@ -1621,6 +1732,7 @@ func (q *Queries) ListKeyAccessServerGrants(ctx context.Context, arg ListKeyAcce &i.AttributesGrants, &i.ValuesGrants, &i.NamespaceGrants, + &i.Total, ); err != nil { return nil, err } @@ -1633,26 +1745,54 @@ func (q *Queries) ListKeyAccessServerGrants(ctx context.Context, arg ListKeyAcce } const listKeyAccessServers = `-- name: ListKeyAccessServers :many -SELECT id, uri, public_key, name, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM key_access_servers +WITH counted AS ( + SELECT COUNT(kas.id) AS total + FROM key_access_servers kas +) +SELECT kas.id, + kas.uri, + kas.public_key, + kas.name AS kas_name, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', kas.metadata -> 'labels', 'created_at', kas.created_at, 'updated_at', kas.updated_at)) as metadata, + counted.total +FROM key_access_servers kas +CROSS JOIN counted +LIMIT $2 +OFFSET $1 ` +type ListKeyAccessServersParams struct { + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListKeyAccessServersRow struct { ID string `json:"id"` Uri string `json:"uri"` PublicKey []byte `json:"public_key"` - Name pgtype.Text `json:"name"` + KasName pgtype.Text `json:"kas_name"` Metadata []byte `json:"metadata"` + Total int64 `json:"total"` } // ListKeyAccessServers // -// SELECT id, uri, public_key, name, -// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -// FROM key_access_servers -func (q *Queries) ListKeyAccessServers(ctx context.Context) ([]ListKeyAccessServersRow, error) { - rows, err := q.db.Query(ctx, listKeyAccessServers) +// WITH counted AS ( +// SELECT COUNT(kas.id) AS total +// FROM key_access_servers kas +// ) +// SELECT kas.id, +// kas.uri, +// kas.public_key, +// kas.name AS kas_name, +// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', kas.metadata -> 'labels', 'created_at', kas.created_at, 'updated_at', kas.updated_at)) as metadata, +// counted.total +// FROM key_access_servers kas +// CROSS JOIN counted +// LIMIT $2 +// OFFSET $1 +func (q *Queries) ListKeyAccessServers(ctx context.Context, arg ListKeyAccessServersParams) ([]ListKeyAccessServersRow, error) { + rows, err := q.db.Query(ctx, listKeyAccessServers, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1664,8 +1804,9 @@ func (q *Queries) ListKeyAccessServers(ctx context.Context) ([]ListKeyAccessServ &i.ID, &i.Uri, &i.PublicKey, - &i.Name, + &i.KasName, &i.Metadata, + &i.Total, ); err != nil { return nil, err } @@ -1679,40 +1820,61 @@ func (q *Queries) ListKeyAccessServers(ctx context.Context) ([]ListKeyAccessServ const listNamespaces = `-- name: ListNamespaces :many +WITH counted AS ( + SELECT COUNT(id) AS total FROM attribute_namespaces +) SELECT ns.id, ns.name, ns.active, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ns.metadata -> 'labels', 'created_at', ns.created_at, 'updated_at', ns.updated_at)) as metadata, - fqns.fqn + fqns.fqn, + counted.total FROM attribute_namespaces ns +CROSS JOIN counted LEFT JOIN attribute_fqns fqns ON ns.id = fqns.namespace_id AND fqns.attribute_id IS NULL WHERE ($1::BOOLEAN IS NULL OR ns.active = $1::BOOLEAN) +LIMIT $3 +OFFSET $2 ` +type ListNamespacesParams struct { + Active pgtype.Bool `json:"active"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListNamespacesRow struct { ID string `json:"id"` Name string `json:"name"` Active bool `json:"active"` Metadata []byte `json:"metadata"` Fqn pgtype.Text `json:"fqn"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // NAMESPACES // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(id) AS total FROM attribute_namespaces +// ) // SELECT // ns.id, // ns.name, // ns.active, // JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', ns.metadata -> 'labels', 'created_at', ns.created_at, 'updated_at', ns.updated_at)) as metadata, -// fqns.fqn +// fqns.fqn, +// counted.total // FROM attribute_namespaces ns +// CROSS JOIN counted // LEFT JOIN attribute_fqns fqns ON ns.id = fqns.namespace_id AND fqns.attribute_id IS NULL // WHERE ($1::BOOLEAN IS NULL OR ns.active = $1::BOOLEAN) -func (q *Queries) ListNamespaces(ctx context.Context, active pgtype.Bool) ([]ListNamespacesRow, error) { - rows, err := q.db.Query(ctx, listNamespaces, active) +// LIMIT $3 +// OFFSET $2 +func (q *Queries) ListNamespaces(ctx context.Context, arg ListNamespacesParams) ([]ListNamespacesRow, error) { + rows, err := q.db.Query(ctx, listNamespaces, arg.Active, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1726,6 +1888,7 @@ func (q *Queries) ListNamespaces(ctx context.Context, active pgtype.Bool) ([]Lis &i.Active, &i.Metadata, &i.Fqn, + &i.Total, ); err != nil { return nil, err } @@ -1739,29 +1902,56 @@ func (q *Queries) ListNamespaces(ctx context.Context, active pgtype.Bool) ([]Lis const listResourceMappingGroups = `-- name: ListResourceMappingGroups :many -SELECT id, namespace_id, name, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM resource_mapping_groups -WHERE (NULLIF($1, '') IS NULL OR namespace_id = $1::uuid) +WITH counted AS ( + SELECT COUNT(rmg.id) AS total + FROM resource_mapping_groups rmg +) +SELECT rmg.id, + rmg.namespace_id, + rmg.name, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', rmg.metadata -> 'labels', 'created_at', rmg.created_at, 'updated_at', rmg.updated_at)) as metadata, + counted.total +FROM resource_mapping_groups rmg +CROSS JOIN counted +WHERE (NULLIF($1, '') IS NULL OR rmg.namespace_id = $1::uuid) +LIMIT $3 +OFFSET $2 ` +type ListResourceMappingGroupsParams struct { + NamespaceID interface{} `json:"namespace_id"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListResourceMappingGroupsRow struct { ID string `json:"id"` NamespaceID string `json:"namespace_id"` Name string `json:"name"` Metadata []byte `json:"metadata"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // RESOURCE MAPPING GROUPS // -------------------------------------------------------------- // -// SELECT id, namespace_id, name, -// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -// FROM resource_mapping_groups -// WHERE (NULLIF($1, '') IS NULL OR namespace_id = $1::uuid) -func (q *Queries) ListResourceMappingGroups(ctx context.Context, namespaceID interface{}) ([]ListResourceMappingGroupsRow, error) { - rows, err := q.db.Query(ctx, listResourceMappingGroups, namespaceID) +// WITH counted AS ( +// SELECT COUNT(rmg.id) AS total +// FROM resource_mapping_groups rmg +// ) +// SELECT rmg.id, +// rmg.namespace_id, +// rmg.name, +// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', rmg.metadata -> 'labels', 'created_at', rmg.created_at, 'updated_at', rmg.updated_at)) as metadata, +// counted.total +// FROM resource_mapping_groups rmg +// CROSS JOIN counted +// WHERE (NULLIF($1, '') IS NULL OR rmg.namespace_id = $1::uuid) +// LIMIT $3 +// OFFSET $2 +func (q *Queries) ListResourceMappingGroups(ctx context.Context, arg ListResourceMappingGroupsParams) ([]ListResourceMappingGroupsRow, error) { + rows, err := q.db.Query(ctx, listResourceMappingGroups, arg.NamespaceID, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1774,6 +1964,7 @@ func (q *Queries) ListResourceMappingGroups(ctx context.Context, namespaceID int &i.NamespaceID, &i.Name, &i.Metadata, + &i.Total, ); err != nil { return nil, err } @@ -1787,44 +1978,67 @@ func (q *Queries) ListResourceMappingGroups(ctx context.Context, namespaceID int const listResourceMappings = `-- name: ListResourceMappings :many +WITH counted AS ( + SELECT COUNT(rm.id) AS total + FROM resource_mappings rm +) SELECT m.id, JSON_BUILD_OBJECT('id', av.id, 'value', av.value, 'fqn', fqns.fqn) as attribute_value, m.terms, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', m.metadata -> 'labels', 'created_at', m.created_at, 'updated_at', m.updated_at)) as metadata, - COALESCE(m.group_id::TEXT, '')::TEXT as group_id + COALESCE(m.group_id::TEXT, '')::TEXT as group_id, + counted.total FROM resource_mappings m +CROSS JOIN counted LEFT JOIN attribute_values av on m.attribute_value_id = av.id LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id WHERE (NULLIF($1, '') IS NULL OR m.group_id = $1::UUID) -GROUP BY av.id, m.id, fqns.fqn +GROUP BY av.id, m.id, fqns.fqn, counted.total +LIMIT $3 +OFFSET $2 ` +type ListResourceMappingsParams struct { + GroupID interface{} `json:"group_id"` + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListResourceMappingsRow struct { ID string `json:"id"` AttributeValue []byte `json:"attribute_value"` Terms []string `json:"terms"` Metadata []byte `json:"metadata"` GroupID string `json:"group_id"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // RESOURCE MAPPING // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(rm.id) AS total +// FROM resource_mappings rm +// ) // SELECT // m.id, // JSON_BUILD_OBJECT('id', av.id, 'value', av.value, 'fqn', fqns.fqn) as attribute_value, // m.terms, // JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', m.metadata -> 'labels', 'created_at', m.created_at, 'updated_at', m.updated_at)) as metadata, -// COALESCE(m.group_id::TEXT, '')::TEXT as group_id +// COALESCE(m.group_id::TEXT, '')::TEXT as group_id, +// counted.total // FROM resource_mappings m +// CROSS JOIN counted // LEFT JOIN attribute_values av on m.attribute_value_id = av.id // LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id // WHERE (NULLIF($1, '') IS NULL OR m.group_id = $1::UUID) -// GROUP BY av.id, m.id, fqns.fqn -func (q *Queries) ListResourceMappings(ctx context.Context, groupID interface{}) ([]ListResourceMappingsRow, error) { - rows, err := q.db.Query(ctx, listResourceMappings, groupID) +// GROUP BY av.id, m.id, fqns.fqn, counted.total +// LIMIT $3 +// OFFSET $2 +func (q *Queries) ListResourceMappings(ctx context.Context, arg ListResourceMappingsParams) ([]ListResourceMappingsRow, error) { + rows, err := q.db.Query(ctx, listResourceMappings, arg.GroupID, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1838,6 +2052,7 @@ func (q *Queries) ListResourceMappings(ctx context.Context, groupID interface{}) &i.Terms, &i.Metadata, &i.GroupID, + &i.Total, ); err != nil { return nil, err } @@ -1949,30 +2164,52 @@ func (q *Queries) ListResourceMappingsByFullyQualifiedGroup(ctx context.Context, const listSubjectConditionSets = `-- name: ListSubjectConditionSets :many +WITH counted AS ( + SELECT COUNT(scs.id) AS total + FROM subject_condition_set scs +) SELECT - id, - condition, - JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -FROM subject_condition_set + scs.id, + scs.condition, + JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata -> 'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)) as metadata, + counted.total +FROM subject_condition_set scs +CROSS JOIN counted +LIMIT $2 +OFFSET $1 ` +type ListSubjectConditionSetsParams struct { + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListSubjectConditionSetsRow struct { ID string `json:"id"` Condition []byte `json:"condition"` Metadata []byte `json:"metadata"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // SUBJECT CONDITION SETS // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(scs.id) AS total +// FROM subject_condition_set scs +// ) // SELECT -// id, -// condition, -// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', metadata -> 'labels', 'created_at', created_at, 'updated_at', updated_at)) as metadata -// FROM subject_condition_set -func (q *Queries) ListSubjectConditionSets(ctx context.Context) ([]ListSubjectConditionSetsRow, error) { - rows, err := q.db.Query(ctx, listSubjectConditionSets) +// scs.id, +// scs.condition, +// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata -> 'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)) as metadata, +// counted.total +// FROM subject_condition_set scs +// CROSS JOIN counted +// LIMIT $2 +// OFFSET $1 +func (q *Queries) ListSubjectConditionSets(ctx context.Context, arg ListSubjectConditionSetsParams) ([]ListSubjectConditionSetsRow, error) { + rows, err := q.db.Query(ctx, listSubjectConditionSets, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -1980,7 +2217,12 @@ func (q *Queries) ListSubjectConditionSets(ctx context.Context) ([]ListSubjectCo var items []ListSubjectConditionSetsRow for rows.Next() { var i ListSubjectConditionSetsRow - if err := rows.Scan(&i.ID, &i.Condition, &i.Metadata); err != nil { + if err := rows.Scan( + &i.ID, + &i.Condition, + &i.Metadata, + &i.Total, + ); err != nil { return nil, err } items = append(items, i) @@ -1993,6 +2235,10 @@ func (q *Queries) ListSubjectConditionSets(ctx context.Context) ([]ListSubjectCo const listSubjectMappings = `-- name: ListSubjectMappings :many +WITH counted AS ( + SELECT COUNT(sm.id) AS total + FROM subject_mappings sm +) SELECT sm.id, sm.actions, @@ -2002,25 +2248,39 @@ SELECT 'metadata', JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata->'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)), 'subject_sets', scs.condition ) AS subject_condition_set, - JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value + JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value, + counted.total FROM subject_mappings sm +CROSS JOIN counted LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id -GROUP BY av.id, sm.id, scs.id +GROUP BY av.id, sm.id, scs.id, counted.total +LIMIT $2 +OFFSET $1 ` +type ListSubjectMappingsParams struct { + Offset int32 `json:"offset_"` + Limit int32 `json:"limit_"` +} + type ListSubjectMappingsRow struct { ID string `json:"id"` Actions []byte `json:"actions"` Metadata []byte `json:"metadata"` SubjectConditionSet []byte `json:"subject_condition_set"` AttributeValue []byte `json:"attribute_value"` + Total int64 `json:"total"` } // -------------------------------------------------------------- // SUBJECT MAPPINGS // -------------------------------------------------------------- // +// WITH counted AS ( +// SELECT COUNT(sm.id) AS total +// FROM subject_mappings sm +// ) // SELECT // sm.id, // sm.actions, @@ -2030,13 +2290,17 @@ type ListSubjectMappingsRow struct { // 'metadata', JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', scs.metadata->'labels', 'created_at', scs.created_at, 'updated_at', scs.updated_at)), // 'subject_sets', scs.condition // ) AS subject_condition_set, -// JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value +// JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value, +// counted.total // FROM subject_mappings sm +// CROSS JOIN counted // LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id // LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id -// GROUP BY av.id, sm.id, scs.id -func (q *Queries) ListSubjectMappings(ctx context.Context) ([]ListSubjectMappingsRow, error) { - rows, err := q.db.Query(ctx, listSubjectMappings) +// GROUP BY av.id, sm.id, scs.id, counted.total +// LIMIT $2 +// OFFSET $1 +func (q *Queries) ListSubjectMappings(ctx context.Context, arg ListSubjectMappingsParams) ([]ListSubjectMappingsRow, error) { + rows, err := q.db.Query(ctx, listSubjectMappings, arg.Offset, arg.Limit) if err != nil { return nil, err } @@ -2050,6 +2314,7 @@ func (q *Queries) ListSubjectMappings(ctx context.Context) ([]ListSubjectMapping &i.Metadata, &i.SubjectConditionSet, &i.AttributeValue, + &i.Total, ); err != nil { return nil, err } diff --git a/service/policy/db/resource_mapping.go b/service/policy/db/resource_mapping.go index b8d8c0f7a..210aea57f 100644 --- a/service/policy/db/resource_mapping.go +++ b/service/policy/db/resource_mapping.go @@ -17,8 +17,19 @@ import ( Resource Mapping CRUD */ -func (c PolicyDBClient) ListResourceMappingGroups(ctx context.Context, r *resourcemapping.ListResourceMappingGroupsRequest) ([]*policy.ResourceMappingGroup, error) { - list, err := c.Queries.ListResourceMappingGroups(ctx, r.GetNamespaceId()) +func (c PolicyDBClient) ListResourceMappingGroups(ctx context.Context, r *resourcemapping.ListResourceMappingGroupsRequest) (*resourcemapping.ListResourceMappingGroupsResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + list, err := c.Queries.ListResourceMappingGroups(ctx, ListResourceMappingGroupsParams{ + NamespaceID: r.GetNamespaceId(), + Limit: limit, + Offset: offset, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } @@ -39,7 +50,21 @@ func (c PolicyDBClient) ListResourceMappingGroups(ctx context.Context, r *resour } } - return rmGroups, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &resourcemapping.ListResourceMappingGroupsResponse{ + ResourceMappingGroups: rmGroups, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } func (c PolicyDBClient) GetResourceMappingGroup(ctx context.Context, id string) (*policy.ResourceMappingGroup, error) { @@ -141,8 +166,19 @@ func (c PolicyDBClient) DeleteResourceMappingGroup(ctx context.Context, id strin Resource Mapping CRUD */ -func (c PolicyDBClient) ListResourceMappings(ctx context.Context, r *resourcemapping.ListResourceMappingsRequest) ([]*policy.ResourceMapping, error) { - list, err := c.Queries.ListResourceMappings(ctx, r.GetGroupId()) +func (c PolicyDBClient) ListResourceMappings(ctx context.Context, r *resourcemapping.ListResourceMappingsRequest) (*resourcemapping.ListResourceMappingsResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + list, err := c.Queries.ListResourceMappings(ctx, ListResourceMappingsParams{ + GroupID: r.GetGroupId(), + Limit: limit, + Offset: offset, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } @@ -177,7 +213,21 @@ func (c PolicyDBClient) ListResourceMappings(ctx context.Context, r *resourcemap mappings[i] = mapping } - return mappings, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &resourcemapping.ListResourceMappingsResponse{ + ResourceMappings: mappings, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } func (c PolicyDBClient) ListResourceMappingsByGroupFqns(ctx context.Context, fqns []string) (map[string]*resourcemapping.ResourceMappingsByGroup, error) { diff --git a/service/policy/db/subject_mappings.go b/service/policy/db/subject_mappings.go index 10257e842..15b8f392a 100644 --- a/service/policy/db/subject_mappings.go +++ b/service/policy/db/subject_mappings.go @@ -136,8 +136,18 @@ func (c PolicyDBClient) GetSubjectConditionSet(ctx context.Context, id string) ( }, nil } -func (c PolicyDBClient) ListSubjectConditionSets(ctx context.Context) ([]*policy.SubjectConditionSet, error) { - list, err := c.Queries.ListSubjectConditionSets(ctx) +func (c PolicyDBClient) ListSubjectConditionSets(ctx context.Context, r *subjectmapping.ListSubjectConditionSetsRequest) (*subjectmapping.ListSubjectConditionSetsResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + list, err := c.Queries.ListSubjectConditionSets(ctx, ListSubjectConditionSetsParams{ + Limit: limit, + Offset: offset, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } @@ -161,7 +171,21 @@ func (c PolicyDBClient) ListSubjectConditionSets(ctx context.Context) ([]*policy } } - return setList, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &subjectmapping.ListSubjectConditionSetsResponse{ + SubjectConditionSets: setList, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } // Mutates provided fields and returns the updated subject condition set @@ -339,8 +363,18 @@ func (c PolicyDBClient) GetSubjectMapping(ctx context.Context, id string) (*poli }, nil } -func (c PolicyDBClient) ListSubjectMappings(ctx context.Context) ([]*policy.SubjectMapping, error) { - list, err := c.Queries.ListSubjectMappings(ctx) +func (c PolicyDBClient) ListSubjectMappings(ctx context.Context, r *subjectmapping.ListSubjectMappingsRequest) (*subjectmapping.ListSubjectMappingsResponse, error) { + limit, offset := c.getRequestedLimitOffset(r.GetPagination()) + + maxLimit := c.listCfg.limitMax + if maxLimit > 0 && limit > maxLimit { + return nil, db.ErrListLimitTooLarge + } + + list, err := c.Queries.ListSubjectMappings(ctx, ListSubjectMappingsParams{ + Limit: limit, + Offset: offset, + }) if err != nil { return nil, db.WrapIfKnownInvalidQueryErr(err) } @@ -376,7 +410,21 @@ func (c PolicyDBClient) ListSubjectMappings(ctx context.Context) ([]*policy.Subj } } - return mappings, nil + var total int32 + var nextOffset int32 + if len(list) > 0 { + total = int32(list[0].Total) + nextOffset = getNextOffset(offset, limit, total) + } + + return &subjectmapping.ListSubjectMappingsResponse{ + SubjectMappings: mappings, + Pagination: &policy.PageResponse{ + CurrentOffset: offset, + Total: total, + NextOffset: nextOffset, + }, + }, nil } // Mutates provided fields and returns the updated subject mapping diff --git a/service/policy/db/utils.go b/service/policy/db/utils.go index 30864bb90..c0f4784c1 100644 --- a/service/policy/db/utils.go +++ b/service/policy/db/utils.go @@ -10,6 +10,27 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) +// Gathers request pagination limit/offset or configured default +func (c PolicyDBClient) getRequestedLimitOffset(page *policy.PageRequest) (int32, int32) { + return getListLimit(page.GetLimit(), c.listCfg.limitDefault), page.GetOffset() +} + +func getListLimit(limit int32, fallback int32) int32 { + if limit > 0 { + return limit + } + return fallback +} + +// Returns next page's offset if has not yet reached total, or else returns 0 +func getNextOffset(currentOffset, limit, total int32) int32 { + next := currentOffset + limit + if next < total { + return next + } + return 0 +} + func unmarshalMetadata(metadataJSON []byte, m *common.Metadata) error { if metadataJSON != nil { if err := protojson.Unmarshal(metadataJSON, m); err != nil { diff --git a/service/policy/db/utils_test.go b/service/policy/db/utils_test.go new file mode 100644 index 000000000..8cc720a42 --- /dev/null +++ b/service/policy/db/utils_test.go @@ -0,0 +1,92 @@ +package db + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_GetListLimit(t *testing.T) { + var defaultListLimit int32 = 1000 + cases := []struct { + limit int32 + expected int32 + }{ + { + 0, + 1000, + }, + { + 1, + 1, + }, + { + 10000, + 10000, + }, + } + + for _, test := range cases { + result := getListLimit(test.limit, defaultListLimit) + assert.Equal(t, test.expected, result) + } +} + +func Test_GetNextOffset(t *testing.T) { + var defaultTestListLimit int32 = 250 + cases := []struct { + currOffset int32 + limit int32 + total int32 + expected int32 + scenario string + }{ + { + currOffset: 0, + limit: defaultTestListLimit, + total: 1000, + expected: defaultTestListLimit, + scenario: "defaulted limit with many remaining", + }, + { + currOffset: 100, + limit: 100, + total: 1000, + expected: 200, + scenario: "custom limit with many remaining", + }, + { + currOffset: 100, + limit: 100, + total: 200, + expected: 0, + scenario: "custom limit with none remaining", + }, + { + currOffset: 100, + limit: defaultTestListLimit, + total: 200, + expected: 0, + scenario: "default limit with none remaining", + }, + { + currOffset: 350 - defaultTestListLimit - 1, + limit: defaultTestListLimit, + total: 350, + expected: 349, + scenario: "default limit with exactly one remaining", + }, + { + currOffset: 1000 - 500 - 1, + limit: 500, + total: 1000, + expected: 1000 - 1, + scenario: "custom limit with exactly one remaining", + }, + } + + for _, test := range cases { + result := getNextOffset(test.currOffset, test.limit, test.total) + assert.Equal(t, test.expected, result, test.scenario) + } +} diff --git a/service/policy/kasregistry/key_access_server_registry.go b/service/policy/kasregistry/key_access_server_registry.go index 088996f21..b42922a9f 100644 --- a/service/policy/kasregistry/key_access_server_registry.go +++ b/service/policy/kasregistry/key_access_server_registry.go @@ -12,12 +12,15 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" + policydb "github.com/opentdf/platform/service/policy/db" ) type KeyAccessServerRegistry struct { dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[kasregistryconnect.KeyAccessServerRegistryServiceHandler] { @@ -29,8 +32,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ConnectRPCFunc: kasregistryconnect.NewKeyAccessServerRegistryServiceHandler, GRPCGateayFunc: kasr.RegisterKeyAccessServerRegistryServiceHandlerFromEndpoint, RegisterFunc: func(srp serviceregistry.RegistrationParams) (kasregistryconnect.KeyAccessServerRegistryServiceHandler, serviceregistry.HandlerServer) { - ksr := &KeyAccessServerRegistry{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return ksr, nil + cfg := policyconfig.GetSharedPolicyConfig(srp) + return &KeyAccessServerRegistry{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + }, nil }, }, } @@ -64,17 +71,13 @@ func (s KeyAccessServerRegistry) CreateKeyAccessServer(ctx context.Context, } func (s KeyAccessServerRegistry) ListKeyAccessServers(ctx context.Context, - _ *connect.Request[kasr.ListKeyAccessServersRequest], + req *connect.Request[kasr.ListKeyAccessServersRequest], ) (*connect.Response[kasr.ListKeyAccessServersResponse], error) { - rsp := &kasr.ListKeyAccessServersResponse{} - - keyAccessServers, err := s.dbClient.ListKeyAccessServers(ctx) + rsp, err := s.dbClient.ListKeyAccessServers(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.KeyAccessServers = keyAccessServers - return connect.NewResponse(rsp), nil } @@ -158,14 +161,10 @@ func (s KeyAccessServerRegistry) DeleteKeyAccessServer(ctx context.Context, func (s KeyAccessServerRegistry) ListKeyAccessServerGrants(ctx context.Context, req *connect.Request[kasr.ListKeyAccessServerGrantsRequest], ) (*connect.Response[kasr.ListKeyAccessServerGrantsResponse], error) { - rsp := &kasr.ListKeyAccessServerGrantsResponse{} - - keyAccessServerGrants, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.Msg.GetKasId(), req.Msg.GetKasUri(), req.Msg.GetKasName()) + rsp, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.Grants = keyAccessServerGrants - return connect.NewResponse(rsp), nil } diff --git a/service/policy/namespaces/namespaces.go b/service/policy/namespaces/namespaces.go index 37cb53970..7ae3d7181 100644 --- a/service/policy/namespaces/namespaces.go +++ b/service/policy/namespaces/namespaces.go @@ -13,12 +13,14 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" policydb "github.com/opentdf/platform/service/policy/db" ) type NamespacesService struct { //nolint:revive // NamespacesService is a valid name dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[namespacesconnect.NamespaceServiceHandler] { @@ -30,7 +32,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ConnectRPCFunc: namespacesconnect.NewNamespaceServiceHandler, GRPCGateayFunc: namespaces.RegisterNamespaceServiceHandlerFromEndpoint, RegisterFunc: func(srp serviceregistry.RegistrationParams) (namespacesconnect.NamespaceServiceHandler, serviceregistry.HandlerServer) { - ns := &NamespacesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} + cfg := policyconfig.GetSharedPolicyConfig(srp) + ns := &NamespacesService{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + } if err := srp.RegisterReadinessCheck("policy", ns.IsReady); err != nil { srp.Logger.Error("failed to register policy readiness check", slog.String("error", err.Error())) @@ -54,17 +61,15 @@ func (ns NamespacesService) IsReady(ctx context.Context) error { } func (ns NamespacesService) ListNamespaces(ctx context.Context, req *connect.Request[namespaces.ListNamespacesRequest]) (*connect.Response[namespaces.ListNamespacesResponse], error) { - state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + state := req.Msg.GetState().String() ns.logger.Debug("listing namespaces", slog.String("state", state)) - rsp := &namespaces.ListNamespacesResponse{} - list, err := ns.dbClient.ListNamespaces(ctx, state) + rsp, err := ns.dbClient.ListNamespaces(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } ns.logger.Debug("listed namespaces") - rsp.Namespaces = list return connect.NewResponse(rsp), nil } diff --git a/service/policy/resourcemapping/resource_mapping.go b/service/policy/resourcemapping/resource_mapping.go index ba41489ce..ec385e107 100644 --- a/service/policy/resourcemapping/resource_mapping.go +++ b/service/policy/resourcemapping/resource_mapping.go @@ -12,12 +12,14 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" policydb "github.com/opentdf/platform/service/policy/db" ) type ResourceMappingService struct { //nolint:revive // ResourceMappingService is a valid name for this struct dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[resourcemappingconnect.ResourceMappingServiceHandler] { @@ -29,8 +31,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ConnectRPCFunc: resourcemappingconnect.NewResourceMappingServiceHandler, GRPCGateayFunc: resourcemapping.RegisterResourceMappingServiceHandlerFromEndpoint, RegisterFunc: func(srp serviceregistry.RegistrationParams) (resourcemappingconnect.ResourceMappingServiceHandler, serviceregistry.HandlerServer) { - rm := &ResourceMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return rm, nil + cfg := policyconfig.GetSharedPolicyConfig(srp) + return &ResourceMappingService{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + }, nil }, }, } @@ -41,15 +47,11 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer */ func (s ResourceMappingService) ListResourceMappingGroups(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingGroupsRequest]) (*connect.Response[resourcemapping.ListResourceMappingGroupsResponse], error) { - rsp := &resourcemapping.ListResourceMappingGroupsResponse{} - - rmGroups, err := s.dbClient.ListResourceMappingGroups(ctx, req.Msg) + rsp, err := s.dbClient.ListResourceMappingGroups(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.ResourceMappingGroups = rmGroups - return connect.NewResponse(rsp), nil } @@ -157,15 +159,11 @@ func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, func (s ResourceMappingService) ListResourceMappings(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingsRequest], ) (*connect.Response[resourcemapping.ListResourceMappingsResponse], error) { - rsp := &resourcemapping.ListResourceMappingsResponse{} - - resourceMappings, err := s.dbClient.ListResourceMappings(ctx, req.Msg) + rsp, err := s.dbClient.ListResourceMappings(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.ResourceMappings = resourceMappings - return connect.NewResponse(rsp), nil } diff --git a/service/policy/subjectmapping/subject_mapping.go b/service/policy/subjectmapping/subject_mapping.go index d089fe290..a2cc54090 100644 --- a/service/policy/subjectmapping/subject_mapping.go +++ b/service/policy/subjectmapping/subject_mapping.go @@ -12,12 +12,14 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" policydb "github.com/opentdf/platform/service/policy/db" ) type SubjectMappingService struct { //nolint:revive // SubjectMappingService is a valid name for this struct dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[subjectmappingconnect.SubjectMappingServiceHandler] { @@ -29,8 +31,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ConnectRPCFunc: subjectmappingconnect.NewSubjectMappingServiceHandler, GRPCGateayFunc: sm.RegisterSubjectMappingServiceHandlerFromEndpoint, RegisterFunc: func(srp serviceregistry.RegistrationParams) (subjectmappingconnect.SubjectMappingServiceHandler, serviceregistry.HandlerServer) { - smSvc := &SubjectMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return smSvc, nil + cfg := policyconfig.GetSharedPolicyConfig(srp) + return &SubjectMappingService{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + }, nil }, }, } @@ -66,17 +72,15 @@ func (s SubjectMappingService) CreateSubjectMapping(ctx context.Context, } func (s SubjectMappingService) ListSubjectMappings(ctx context.Context, - _ *connect.Request[sm.ListSubjectMappingsRequest], + req *connect.Request[sm.ListSubjectMappingsRequest], ) (*connect.Response[sm.ListSubjectMappingsResponse], error) { - rsp := &sm.ListSubjectMappingsResponse{} s.logger.Debug("listing subject mappings") - mappings, err := s.dbClient.ListSubjectMappings(ctx) + rsp, err := s.dbClient.ListSubjectMappings(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.SubjectMappings = mappings return connect.NewResponse(rsp), nil } @@ -193,17 +197,15 @@ func (s SubjectMappingService) GetSubjectConditionSet(ctx context.Context, } func (s SubjectMappingService) ListSubjectConditionSets(ctx context.Context, - _ *connect.Request[sm.ListSubjectConditionSetsRequest], + req *connect.Request[sm.ListSubjectConditionSetsRequest], ) (*connect.Response[sm.ListSubjectConditionSetsResponse], error) { - rsp := &sm.ListSubjectConditionSetsResponse{} s.logger.Debug("listing subject condition sets") - conditionSets, err := s.dbClient.ListSubjectConditionSets(ctx) + rsp, err := s.dbClient.ListSubjectConditionSets(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - rsp.SubjectConditionSets = conditionSets return connect.NewResponse(rsp), nil } diff --git a/service/policy/unsafe/unsafe.go b/service/policy/unsafe/unsafe.go index 065866b0b..8c78cfa0c 100644 --- a/service/policy/unsafe/unsafe.go +++ b/service/policy/unsafe/unsafe.go @@ -12,12 +12,14 @@ import ( "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" "github.com/opentdf/platform/service/pkg/serviceregistry" + policyconfig "github.com/opentdf/platform/service/policy/config" policydb "github.com/opentdf/platform/service/policy/db" ) type UnsafeService struct { //nolint:revive // UnsafeService is a valid name for this struct dbClient policydb.PolicyDBClient logger *logger.Logger + config *policyconfig.Config } func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[unsafeconnect.UnsafeServiceHandler] { @@ -28,8 +30,12 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer ServiceDesc: &unsafe.UnsafeService_ServiceDesc, ConnectRPCFunc: unsafeconnect.NewUnsafeServiceHandler, RegisterFunc: func(srp serviceregistry.RegistrationParams) (unsafeconnect.UnsafeServiceHandler, serviceregistry.HandlerServer) { - unsafeSvc := &UnsafeService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return unsafeSvc, nil + cfg := policyconfig.GetSharedPolicyConfig(srp) + return &UnsafeService{ + dbClient: policydb.NewClient(srp.DBClient, srp.Logger, int32(cfg.ListRequestLimitMax), int32(cfg.ListRequestLimitDefault)), + logger: srp.Logger, + config: cfg, + }, nil }, }, }