From 0111123cac021db2e37dcc5f35863146c9ce480d Mon Sep 17 00:00:00 2001 From: Hugo <10965479+hugoghx@users.noreply.github.com> Date: Mon, 19 May 2025 13:04:11 +0100 Subject: [PATCH] fix(proto): Make UPD domain field public + ensure consistency across API pkgs --- .../resources/credentials/v1/credential.proto | 6 +- .../api/resources/targets/v1/target.proto | 2 +- .../credentials_classification_test.go | 116 +++++++++++++++--- .../resources/credentials/credential.pb.go | 6 +- .../api/resources/targets/target.pb.go | 2 +- 5 files changed, 109 insertions(+), 23 deletions(-) diff --git a/internal/proto/controller/api/resources/credentials/v1/credential.proto b/internal/proto/controller/api/resources/credentials/v1/credential.proto index 2b006398cc..c3bca93290 100644 --- a/internal/proto/controller/api/resources/credentials/v1/credential.proto +++ b/internal/proto/controller/api/resources/credentials/v1/credential.proto @@ -97,7 +97,7 @@ message UsernamePasswordAttributes { this: "attributes.username" that: "Username" } - ]; // @gotags: `class:"public"` + ]; // @gotags: `class:"sensitive"` // Input only. The password associated with the credential. google.protobuf.StringValue password = 20 [ @@ -127,7 +127,7 @@ message UsernamePasswordDomainAttributes { this: "attributes.username" that: "Username" } - ]; // @gotags: `class:"public"` + ]; // @gotags: `class:"sensitive"` // Input only. The password associated with the credential. google.protobuf.StringValue password = 20 [ @@ -166,7 +166,7 @@ message SshPrivateKeyAttributes { this: "attributes.username" that: "Username" } - ]; // @gotags: `class:"public"` + ]; // @gotags: `class:"sensitive"` // Input only. The SSH private key associated with the credential. google.protobuf.StringValue private_key = 20 [ diff --git a/internal/proto/controller/api/resources/targets/v1/target.proto b/internal/proto/controller/api/resources/targets/v1/target.proto index 2d7db8e9d2..f7a180a5c7 100644 --- a/internal/proto/controller/api/resources/targets/v1/target.proto +++ b/internal/proto/controller/api/resources/targets/v1/target.proto @@ -443,7 +443,7 @@ message UsernamePasswordDomainCredential { string password = 2; // @gotags: `class:"secret"` // Domain of the credential - string domain = 3; // @gotags: `class:"sensitive"` + string domain = 3; // @gotags: `class:"public"` } // The layout of the struct for "credential" field in SessionCredential for a ssh_private_key credential type. diff --git a/internal/tests/api/credentials/credentials_classification_test.go b/internal/tests/api/credentials/credentials_classification_test.go index 8aeac7d1a4..4a0dd79a83 100644 --- a/internal/tests/api/credentials/credentials_classification_test.go +++ b/internal/tests/api/credentials/credentials_classification_test.go @@ -5,18 +5,20 @@ package credentials_test import ( "context" - "encoding/json" + "strings" "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/boundary/sdk/pbs/controller/api" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" "github.com/hashicorp/boundary/sdk/wrapper" "github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger/filters/encrypt" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" @@ -35,8 +37,85 @@ func TestCredentialClassification(t *testing.T) { want *eventlogger.Event }{ { - "Usernamepassword", - &eventlogger.Event{ + name: "usernamePasswordDomainCredential", + in: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &pb.Credential{ + Id: "id", + CredentialStoreId: "cred-store-id", + Scope: &scopes.ScopeInfo{ + Id: "scope-id", + Type: "scope-type", + Name: "scope-name", + Description: "scope-descriptione", + ParentScopeId: "scope-parent-scope-id", + }, + Name: &wrapperspb.StringValue{ + Value: "name", + }, + Description: &wrapperspb.StringValue{ + Value: "description", + }, + CreatedTime: pbNow, + UpdatedTime: pbNow, + Version: 1, + Type: "username_password_domain", + Attrs: &pb.Credential_UsernamePasswordDomainAttributes{ + UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{ + Username: &wrapperspb.StringValue{Value: "username"}, + Password: &wrapperspb.StringValue{Value: "password"}, + PasswordHmac: "password-hmac", + Domain: &wrapperspb.StringValue{Value: "domain"}, + }, + }, + AuthorizedActions: []string{ + "action-1", + "action-2", + }, + }, + }, + want: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &pb.Credential{ + Id: "id", + CredentialStoreId: "cred-store-id", + Scope: &scopes.ScopeInfo{ + Id: "scope-id", + Type: "scope-type", + Name: "scope-name", + Description: "scope-descriptione", + ParentScopeId: "scope-parent-scope-id", + }, + Name: &wrapperspb.StringValue{ + Value: "name", + }, + Description: &wrapperspb.StringValue{ + Value: "description", + }, + CreatedTime: pbNow, + UpdatedTime: pbNow, + Version: 1, + Type: "username_password_domain", + Attrs: &pb.Credential_UsernamePasswordDomainAttributes{ + UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{ + Username: &wrapperspb.StringValue{Value: "encrypted:"}, + Password: &wrapperspb.StringValue{Value: "[REDACTED]"}, + PasswordHmac: "password-hmac", + Domain: &wrapperspb.StringValue{Value: "domain"}, + }, + }, + AuthorizedActions: []string{ + "action-1", + "action-2", + }, + }, + }, + }, + { + name: "usernamePasswordCredential", + in: &eventlogger.Event{ Type: "test", CreatedAt: now, Payload: &pb.Credential{ @@ -72,7 +151,7 @@ func TestCredentialClassification(t *testing.T) { }, }, }, - &eventlogger.Event{ + want: &eventlogger.Event{ Type: "test", CreatedAt: now, Payload: &pb.Credential{ @@ -97,7 +176,7 @@ func TestCredentialClassification(t *testing.T) { Type: "username_password", Attrs: &pb.Credential_UsernamePasswordAttributes{ UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{ - Username: &wrapperspb.StringValue{Value: "username"}, + Username: &wrapperspb.StringValue{Value: "encrypted:"}, Password: &wrapperspb.StringValue{Value: "[REDACTED]"}, PasswordHmac: "password-hmac", }, @@ -110,8 +189,8 @@ func TestCredentialClassification(t *testing.T) { }, }, { - "Default", - &eventlogger.Event{ + name: "default", + in: &eventlogger.Event{ Type: "test", CreatedAt: now, Payload: &pb.Credential{ @@ -148,7 +227,7 @@ func TestCredentialClassification(t *testing.T) { }, }, }, - &eventlogger.Event{ + want: &eventlogger.Event{ Type: "test", CreatedAt: now, Payload: &pb.Credential{ @@ -190,15 +269,22 @@ func TestCredentialClassification(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - wantJSON, err := json.Marshal(tc.want) - require.NoError(t, err) - got, err := testEncryptingFilter.Process(ctx, tc.in) require.NoError(t, err) require.NotNil(t, got) - gotJSON, err := json.Marshal(got) - require.NoError(t, err) - assert.JSONEq(t, string(wantJSON), string(gotJSON)) + + at := cmpopts.AcyclicTransformer("removeEncryptedValue", func(s string) string { + // A sensitive field is by default encrypted and set to an + // `encrypted:` value in the event object. + // This function gets called for each string in the object and + // trims off the encrypted value if it exists so we can make a + // full object comparison. + if strings.HasPrefix(s, "encrypted:") { + return "encrypted:" + } + return s + }) + require.Empty(t, cmp.Diff(tc.want.Payload, got.Payload, protocmp.Transform(), at)) }) } } diff --git a/sdk/pbs/controller/api/resources/credentials/credential.pb.go b/sdk/pbs/controller/api/resources/credentials/credential.pb.go index e75be32530..b48885da34 100644 --- a/sdk/pbs/controller/api/resources/credentials/credential.pb.go +++ b/sdk/pbs/controller/api/resources/credentials/credential.pb.go @@ -257,7 +257,7 @@ func (*Credential_UsernamePasswordDomainAttributes) isCredential_Attrs() {} type UsernamePasswordAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` // The username associated with the credential. - Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"public"` // @gotags: `class:"public"` + Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` // Input only. The password associated with the credential. Password *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=password,proto3" json:"password,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The hmac value of the password. @@ -320,7 +320,7 @@ func (x *UsernamePasswordAttributes) GetPasswordHmac() string { type UsernamePasswordDomainAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` // The username associated with the credential. - Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"public"` // @gotags: `class:"public"` + Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` // Input only. The password associated with the credential. Password *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=password,proto3" json:"password,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The hmac value of the password. @@ -392,7 +392,7 @@ func (x *UsernamePasswordDomainAttributes) GetDomain() *wrapperspb.StringValue { type SshPrivateKeyAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` // The username associated with the credential. - Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"public"` // @gotags: `class:"public"` + Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` // Input only. The SSH private key associated with the credential. PrivateKey *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=private_key,proto3" json:"private_key,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The hmac value of the SSH private key. diff --git a/sdk/pbs/controller/api/resources/targets/target.pb.go b/sdk/pbs/controller/api/resources/targets/target.pb.go index 423152778e..51675bda18 100644 --- a/sdk/pbs/controller/api/resources/targets/target.pb.go +++ b/sdk/pbs/controller/api/resources/targets/target.pb.go @@ -1359,7 +1359,7 @@ type UsernamePasswordDomainCredential struct { // Password of the credential Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty" class:"secret"` // @gotags: `class:"secret"` // Domain of the credential - Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` + Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty" class:"public"` // @gotags: `class:"public"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache }