diff --git a/Makefile b/Makefile index 6c5213d8f..eea8ce25a 100644 --- a/Makefile +++ b/Makefile @@ -165,6 +165,8 @@ protobuild: @protoc-go-inject-tag -input=./internal/gen/controller/api/services/host_catalog_service.pb.go @protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/hostsets/host_set.pb.go @protoc-go-inject-tag -input=./internal/gen/controller/api/services/host_set_service.pb.go + @protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/authtokens/authtoken.pb.go + @protoc-go-inject-tag -input=./internal/gen/controller/api/services/authtokens_service.pb.go # these protos, services and openapi artifacts are purely for testing purposes @protoc-go-inject-tag -input=./internal/gen/testing/event/event.pb.go diff --git a/internal/gen/controller/api/services/authtokens_service.pb.go b/internal/gen/controller/api/services/authtokens_service.pb.go index 21504de96..66f919c8c 100644 --- a/internal/gen/controller/api/services/authtokens_service.pb.go +++ b/internal/gen/controller/api/services/authtokens_service.pb.go @@ -28,7 +28,7 @@ type GetAuthTokenRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *GetAuthTokenRequest) Reset() { @@ -122,9 +122,9 @@ type ListAuthTokensRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ScopeId string `protobuf:"bytes,1,opt,name=scope_id,proto3" json:"scope_id,omitempty"` - Recursive bool `protobuf:"varint,20,opt,name=recursive,proto3" json:"recursive,omitempty"` - Filter string `protobuf:"bytes,30,opt,name=filter,proto3" json:"filter,omitempty"` + ScopeId string `protobuf:"bytes,1,opt,name=scope_id,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"` + Recursive bool `protobuf:"varint,20,opt,name=recursive,proto3" json:"recursive,omitempty" class:"public"` // @gotags: `class:"public"` + Filter string `protobuf:"bytes,30,opt,name=filter,proto3" json:"filter,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ListAuthTokensRequest) Reset() { @@ -232,7 +232,7 @@ type DeleteAuthTokenRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *DeleteAuthTokenRequest) Reset() { diff --git a/internal/proto/controller/api/resources/authtokens/v1/authtoken.proto b/internal/proto/controller/api/resources/authtokens/v1/authtoken.proto index f4b6e75a9..4f31098ac 100644 --- a/internal/proto/controller/api/resources/authtokens/v1/authtoken.proto +++ b/internal/proto/controller/api/resources/authtokens/v1/authtoken.proto @@ -10,38 +10,38 @@ import "controller/api/resources/scopes/v1/scope.proto"; // AuthToken contains all fields related to an Auth Token resource message AuthToken { // Output only. The ID of the Auth Token. - string id = 10; + string id = 10; // @gotags: `class:"public"` // The Scope in which this Auth Token was generated. - string scope_id = 20 [json_name="scope_id"]; + string scope_id = 20 [json_name="scope_id"]; // @gotags: `class:"public"` // Output only. Scope information for this resource. resources.scopes.v1.ScopeInfo scope = 30; // Output only. The token value, which will only be populated after authentication and is only ever visible to the end user whose login request resulted in this Auth Token being created. - string token = 40; + string token = 40; // @gotags: `class:"secret"` // Output only. The ID of the User associated with this Auth Token. - string user_id = 50 [json_name="user_id"]; + string user_id = 50 [json_name="user_id"]; // @gotags: `class:"public"` // Output only. The ID of the Auth Method associated with this Auth Token. - string auth_method_id = 60 [json_name="auth_method_id"]; + string auth_method_id = 60 [json_name="auth_method_id"]; // @gotags: `class:"public"` // Output only. The ID of the Account associated with this Auth Token. - string account_id = 70 [json_name="account_id"]; + string account_id = 70 [json_name="account_id"]; // @gotags: `class:"public"` // Output only. The time this resource was created. - google.protobuf.Timestamp created_time = 80 [json_name="created_time"]; + google.protobuf.Timestamp created_time = 80 [json_name="created_time"]; // @gotags: `class:"public"` // Output only. The time this resource was last updated. - google.protobuf.Timestamp updated_time = 90 [json_name="updated_time"]; + google.protobuf.Timestamp updated_time = 90 [json_name="updated_time"]; // @gotags: `class:"public"` // Output only. The approximate time this Auth Token was last used. - google.protobuf.Timestamp approximate_last_used_time = 100 [json_name = "approximate_last_used_time"]; + google.protobuf.Timestamp approximate_last_used_time = 100 [json_name = "approximate_last_used_time"]; // @gotags: `class:"public"` // Output only. The time this Auth Token expires. - google.protobuf.Timestamp expiration_time = 110 [json_name="expiration_time"]; + google.protobuf.Timestamp expiration_time = 110 [json_name="expiration_time"]; // @gotags: `class:"public"` // Output only. The available actions on this resource for this user. - repeated string authorized_actions = 300 [json_name="authorized_actions"]; + repeated string authorized_actions = 300 [json_name="authorized_actions"]; // @gotags: `class:"public"` } diff --git a/internal/proto/controller/api/services/v1/authtokens_service.proto b/internal/proto/controller/api/services/v1/authtokens_service.proto index a76588cd7..d03626d65 100644 --- a/internal/proto/controller/api/services/v1/authtokens_service.proto +++ b/internal/proto/controller/api/services/v1/authtokens_service.proto @@ -49,7 +49,7 @@ service AuthTokenService { } message GetAuthTokenRequest { - string id = 1; + string id = 1; // @gotags: `class:"public"` } message GetAuthTokenResponse { @@ -57,9 +57,9 @@ message GetAuthTokenResponse { } message ListAuthTokensRequest { - string scope_id = 1 [json_name="scope_id"]; - bool recursive = 20 [json_name="recursive"]; - string filter = 30 [json_name="filter"]; + string scope_id = 1 [json_name="scope_id"]; // @gotags: `class:"public"` + bool recursive = 20 [json_name="recursive"]; // @gotags: `class:"public"` + string filter = 30 [json_name="filter"]; // @gotags: `class:"public"` } message ListAuthTokensResponse { @@ -67,7 +67,7 @@ message ListAuthTokensResponse { } message DeleteAuthTokenRequest { - string id = 1; + string id = 1; // @gotags: `class:"public"` } -message DeleteAuthTokenResponse {} \ No newline at end of file +message DeleteAuthTokenResponse {} diff --git a/internal/tests/api/authmethods/authenticate_test.go b/internal/tests/api/authmethods/authenticate_test.go index 4e84761a8..a75d3efa0 100644 --- a/internal/tests/api/authmethods/authenticate_test.go +++ b/internal/tests/api/authmethods/authenticate_test.go @@ -81,16 +81,13 @@ func TestAuthenticate(t *testing.T) { got := tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) // All attribute fields are classified for now. - // TODO(johanbrandhorst): revert this when classification is done for auth methods reqDetails := tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) - tests_api.AssertRedactedValues(t, reqDetails["Attrs"]) tests_api.AssertRedactedValues(t, reqDetails["Attrs"].(map[string]interface{})["PasswordLoginAttributes"], "password", "login_name") respDetails := tests_api.GetEventDetails(t, got, "response") tests_api.AssertRedactedValues(t, respDetails) - tests_api.AssertRedactedValues(t, respDetails["Attrs"]) - tests_api.AssertRedactedValues(t, respDetails["Attrs"].(map[string]interface{})["AuthTokenResponse"], "token", "token_type", "user_id", "account_id", "auth_method_id", "authorized_actions", "id", "scope_id") + tests_api.AssertRedactedValues(t, respDetails["Attrs"].(map[string]interface{})["AuthTokenResponse"], "token") _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls tok, err = methods.Authenticate(tc.Context(), tc.Server().DevPasswordAuthMethodId, "login", map[string]interface{}{"login_name": "user", "password": "bad-pass"}) @@ -100,6 +97,5 @@ func TestAuthenticate(t *testing.T) { reqDetails = tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) - tests_api.AssertRedactedValues(t, reqDetails["Attrs"]) tests_api.AssertRedactedValues(t, reqDetails["Attrs"].(map[string]interface{})["PasswordLoginAttributes"], "password", "login_name") } diff --git a/internal/tests/api/authmethods/service_classification_test.go b/internal/tests/api/authmethods/service_classification_test.go index dd00a3c6c..f227c562b 100644 --- a/internal/tests/api/authmethods/service_classification_test.go +++ b/internal/tests/api/authmethods/service_classification_test.go @@ -76,16 +76,16 @@ func TestAuthenticate_Tags(t *testing.T) { // TODO(johanbrandhorst): update redaction once typed attributes are available Attrs: &services.AuthenticateResponse_AuthTokenResponse{ AuthTokenResponse: &authtokens.AuthToken{ - AccountId: encrypt.RedactedData, + AccountId: "public-account_id", ApproximateLastUsedTime: timestamppb.New(now), - AuthMethodId: encrypt.RedactedData, + AuthMethodId: "public-auth_method_id", AuthorizedActions: []string{ - encrypt.RedactedData, + "public-authorized_actions", }, CreatedTime: timestamppb.New(now), ExpirationTime: timestamppb.New(now), - Id: encrypt.RedactedData, - ScopeId: encrypt.RedactedData, + Id: "public-id", + ScopeId: "public-scope_id", Scope: &scopes.ScopeInfo{ Id: "public-scope_id", Type: "public-scope_type", @@ -94,7 +94,7 @@ func TestAuthenticate_Tags(t *testing.T) { ParentScopeId: "public-parent_scope_id", }, UpdatedTime: timestamppb.New(now), - UserId: encrypt.RedactedData, + UserId: "public-user_id", Token: encrypt.RedactedData, }, }, diff --git a/internal/tests/api/authtokens/classification_test.go b/internal/tests/api/authtokens/classification_test.go new file mode 100644 index 000000000..39f52a51c --- /dev/null +++ b/internal/tests/api/authtokens/classification_test.go @@ -0,0 +1,102 @@ +package authtokens_test + +import ( + "context" + "encoding/json" + "testing" + "time" + + "github.com/hashicorp/boundary/sdk/pbs/controller/api" + pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authtokens" + "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/types/known/timestamppb" +) + +func TestAuthtokenClassification(t *testing.T) { + ctx := context.Background() + now := time.Now() + wrapper := wrapper.TestWrapper(t) + testEncryptingFilter := api.NewEncryptFilter(t, wrapper) + + tests := []struct { + name string + testEvent *eventlogger.Event + wantEvent *eventlogger.Event + }{ + { + name: "validate-authtoken-filtering", + testEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &pb.AuthToken{ + AccountId: "public-account_id", + ApproximateLastUsedTime: timestamppb.New(now), + AuthMethodId: "public-auth_method_id", + AuthorizedActions: []string{ + "public-authorized_actions", + }, + CreatedTime: timestamppb.New(now), + ExpirationTime: timestamppb.New(now), + Id: "public-id", + ScopeId: "public-scope_id", + Scope: &scopes.ScopeInfo{ + Id: "public-scope_id", + Type: "public-scope_type", + Name: "public-scope_name", + Description: "public-scope_description", + ParentScopeId: "public-parent_scope_id", + }, + UpdatedTime: timestamppb.New(now), + UserId: "public-user_id", + Token: "secret-token", + }, + }, + wantEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &pb.AuthToken{ + AccountId: "public-account_id", + ApproximateLastUsedTime: timestamppb.New(now), + AuthMethodId: "public-auth_method_id", + AuthorizedActions: []string{ + "public-authorized_actions", + }, + CreatedTime: timestamppb.New(now), + ExpirationTime: timestamppb.New(now), + Id: "public-id", + ScopeId: "public-scope_id", + Scope: &scopes.ScopeInfo{ + Id: "public-scope_id", + Type: "public-scope_type", + Name: "public-scope_name", + Description: "public-scope_description", + ParentScopeId: "public-parent_scope_id", + }, + UpdatedTime: timestamppb.New(now), + UserId: "public-user_id", + Token: encrypt.RedactedData, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + got, err := testEncryptingFilter.Process(ctx, tt.testEvent) + require.NoError(err) + require.NotNil(got) + actualJson, err := json.Marshal(got) + require.NoError(err) + t.Log(string(actualJson)) + + wantJson, err := json.Marshal(tt.wantEvent) + require.NoError(err) + assert.JSONEq(string(wantJson), string(actualJson)) + }) + } +} diff --git a/sdk/pbs/controller/api/resources/authtokens/authtoken.pb.go b/sdk/pbs/controller/api/resources/authtokens/authtoken.pb.go index 34a4903ee..e7ccc8aeb 100644 --- a/sdk/pbs/controller/api/resources/authtokens/authtoken.pb.go +++ b/sdk/pbs/controller/api/resources/authtokens/authtoken.pb.go @@ -29,29 +29,29 @@ type AuthToken struct { unknownFields protoimpl.UnknownFields // Output only. The ID of the Auth Token. - Id string `protobuf:"bytes,10,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,10,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"` // The Scope in which this Auth Token was generated. - ScopeId string `protobuf:"bytes,20,opt,name=scope_id,proto3" json:"scope_id,omitempty"` + ScopeId string `protobuf:"bytes,20,opt,name=scope_id,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Scope information for this resource. Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"` // Output only. The token value, which will only be populated after authentication and is only ever visible to the end user whose login request resulted in this Auth Token being created. - Token string `protobuf:"bytes,40,opt,name=token,proto3" json:"token,omitempty"` + Token string `protobuf:"bytes,40,opt,name=token,proto3" json:"token,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The ID of the User associated with this Auth Token. - UserId string `protobuf:"bytes,50,opt,name=user_id,proto3" json:"user_id,omitempty"` + UserId string `protobuf:"bytes,50,opt,name=user_id,proto3" json:"user_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The ID of the Auth Method associated with this Auth Token. - AuthMethodId string `protobuf:"bytes,60,opt,name=auth_method_id,proto3" json:"auth_method_id,omitempty"` + AuthMethodId string `protobuf:"bytes,60,opt,name=auth_method_id,proto3" json:"auth_method_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The ID of the Account associated with this Auth Token. - AccountId string `protobuf:"bytes,70,opt,name=account_id,proto3" json:"account_id,omitempty"` + AccountId string `protobuf:"bytes,70,opt,name=account_id,proto3" json:"account_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The time this resource was created. - CreatedTime *timestamppb.Timestamp `protobuf:"bytes,80,opt,name=created_time,proto3" json:"created_time,omitempty"` + CreatedTime *timestamppb.Timestamp `protobuf:"bytes,80,opt,name=created_time,proto3" json:"created_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The time this resource was last updated. - UpdatedTime *timestamppb.Timestamp `protobuf:"bytes,90,opt,name=updated_time,proto3" json:"updated_time,omitempty"` + UpdatedTime *timestamppb.Timestamp `protobuf:"bytes,90,opt,name=updated_time,proto3" json:"updated_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The approximate time this Auth Token was last used. - ApproximateLastUsedTime *timestamppb.Timestamp `protobuf:"bytes,100,opt,name=approximate_last_used_time,proto3" json:"approximate_last_used_time,omitempty"` + ApproximateLastUsedTime *timestamppb.Timestamp `protobuf:"bytes,100,opt,name=approximate_last_used_time,proto3" json:"approximate_last_used_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The time this Auth Token expires. - ExpirationTime *timestamppb.Timestamp `protobuf:"bytes,110,opt,name=expiration_time,proto3" json:"expiration_time,omitempty"` + ExpirationTime *timestamppb.Timestamp `protobuf:"bytes,110,opt,name=expiration_time,proto3" json:"expiration_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The available actions on this resource for this user. - AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *AuthToken) Reset() {