diff --git a/internal/gen/controller/api/services/auth_method_service.pb.go b/internal/gen/controller/api/services/auth_method_service.pb.go index 5648ba675..cbb116e12 100644 --- a/internal/gen/controller/api/services/auth_method_service.pb.go +++ b/internal/gen/controller/api/services/auth_method_service.pb.go @@ -127,9 +127,9 @@ type ListAuthMethodsRequest 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 *ListAuthMethodsRequest) Reset() { @@ -449,7 +449,7 @@ type DeleteAuthMethodRequest 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 *DeleteAuthMethodRequest) Reset() { @@ -536,11 +536,11 @@ type OidcChangeStateAttributes struct { unknownFields protoimpl.UnknownFields // state must be `inactive`, `active-private`, or `active-public` - State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty" class:"public"` // @gotags: `class:"public"` // This flag is only useful for an oidc auth method. It should not be used // unless the oidc provider's config is incorrectly set and is stopping the // activation of this auth method. - DisableDiscoveredConfigValidation bool `protobuf:"varint,2,opt,name=disable_discovered_config_validation,proto3" json:"disable_discovered_config_validation,omitempty"` + DisableDiscoveredConfigValidation bool `protobuf:"varint,2,opt,name=disable_discovered_config_validation,proto3" json:"disable_discovered_config_validation,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *OidcChangeStateAttributes) Reset() { @@ -597,7 +597,7 @@ type ChangeStateRequest struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"` // Version is used to ensure this resource has not changed. // The mutation will fail if the version does not match the latest known good version. - Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"` // Types that are assignable to Attrs: // *ChangeStateRequest_Attributes // *ChangeStateRequest_OidcChangeStateAttributes @@ -742,8 +742,8 @@ type PasswordLoginAttributes struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LoginName string `protobuf:"bytes,1,opt,name=login_name,proto3" json:"login_name,omitempty"` - Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + LoginName string `protobuf:"bytes,1,opt,name=login_name,proto3" json:"login_name,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty" class:"secret"` // @gotags: `class:"secret"` } func (x *PasswordLoginAttributes) Reset() { @@ -802,7 +802,7 @@ type OidcStartAttributes struct { // An object which will be marshaled as JSON and roundtripped in the token command call. RoundtripPayload *structpb.Struct `protobuf:"bytes,1,opt,name=roundtrip_payload,proto3" json:"roundtrip_payload,omitempty"` // Cached marshaled payload. This is not ingressed from the client; anything found will be thrown out. - CachedRoundtripPayload string `protobuf:"bytes,2,opt,name=cached_roundtrip_payload,json=cachedRoundtripPayload,proto3" json:"cached_roundtrip_payload,omitempty"` + CachedRoundtripPayload string `protobuf:"bytes,2,opt,name=cached_roundtrip_payload,json=cachedRoundtripPayload,proto3" json:"cached_roundtrip_payload,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` } func (x *OidcStartAttributes) Reset() { diff --git a/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto b/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto index 34cab4d76..52759d736 100644 --- a/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto +++ b/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto @@ -22,7 +22,7 @@ message AuthMethod { string scope_id = 20 [json_name = "scope_id"]; // @gotags: `class:"public"` // Output only. Scope information for this Auth method. - resources.scopes.v1.ScopeInfo scope = 30; // @gotags: `class:"public"` + resources.scopes.v1.ScopeInfo scope = 30; // Optional name for identification purposes. google.protobuf.StringValue name = 40 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "name" that: "Name" }]; // @gotags: `class:"public"` @@ -74,77 +74,77 @@ message AuthMethod { message PasswordAuthMethodAttributes { // The minimum length allowed for user names for Accounts in this Auth Method. uint32 min_login_name_length = 10 - [json_name = "min_login_name_length", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.min_login_name_length" that: "MinLoginNameLength" }]; + [json_name = "min_login_name_length", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.min_login_name_length" that: "MinLoginNameLength" }]; // @gotags: `class:"public"` // The minimum length allowed for passwords for Accounts in this Auth Method. uint32 min_password_length = 20 - [json_name = "min_password_length", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.min_password_length" that: "MinPasswordLength" }]; + [json_name = "min_password_length", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.min_password_length" that: "MinPasswordLength" }]; // @gotags: `class:"public"` } // The attributes of an OIDC typed auth method. message OidcAuthMethodAttributes { // Output only. The state of the auth method. Will be "inactive", // "active-private", or "active-public". - string state = 10 [json_name = "state"]; + string state = 10 [json_name = "state"]; // @gotags: `class:"public"` // The issuer URL. Boundary expects only the schema, host, and port and will // strip off ".well-known/openid-configuration" if present. This will be // used for configuration discovery as well as for validation of the "iss" // claim. - google.protobuf.StringValue issuer = 20 [json_name = "issuer", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.issuer" that: "Issuer" }]; + google.protobuf.StringValue issuer = 20 [json_name = "issuer", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.issuer" that: "Issuer" }]; // @gotags: `class:"public"` // An OAuth 2.0 Client Identifier valid at the Authorization Server. google.protobuf.StringValue client_id = 30 - [json_name = "client_id", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.client_id" that: "ClientId" }]; + [json_name = "client_id", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.client_id" that: "ClientId" }]; // @gotags: `class:"public"` // Input only. The client's secret. google.protobuf.StringValue client_secret = 40 - [json_name = "client_secret", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.client_secret" that: "ClientSecret" }]; + [json_name = "client_secret", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.client_secret" that: "ClientSecret" }]; // @gotags: `class:"secret"` // Output only. The HMAC'd value of the clients secret to indicate whether // the client secret has changed. - string client_secret_hmac = 50 [json_name = "client_secret_hmac"]; + string client_secret_hmac = 50 [json_name = "client_secret_hmac"]; // @gotags: `class:"public"` // The OIDC "max_age" parameter sent to the Authorization Server indicating // a maximum acceptable time in seconds since the user's last authentication // before requiring the user to reauthenticate. 0 indicates an immediate // need to reauthenticate. - google.protobuf.UInt32Value max_age = 60 [json_name = "max_age", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.max_age" that: "MaxAge" }]; + google.protobuf.UInt32Value max_age = 60 [json_name = "max_age", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.max_age" that: "MaxAge" }]; // @gotags: `class:"public"` // The signing algorithms allowed for the auth method. repeated string signing_algorithms = 70 - [json_name = "signing_algorithms", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.signing_algorithms" that: "SigningAlgs" }]; + [json_name = "signing_algorithms", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.signing_algorithms" that: "SigningAlgs" }]; // @gotags: `class:"public"` // The prefix that should be used for any URLs needed during the // authentication flow. This includes the callback URL, the token retrieval // URL, and the redirection URL used by the OIDC Authorization Server. google.protobuf.StringValue api_url_prefix = 80 - [json_name = "api_url_prefix", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.api_url_prefix" that: "ApiUrl" }]; + [json_name = "api_url_prefix", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.api_url_prefix" that: "ApiUrl" }]; // @gotags: `class:"public"` // Output only. The callback URL that should be configured on the // Authorization Server to use during the authentication flow. - string callback_url = 90 [json_name = "callback_url"]; + string callback_url = 90 [json_name = "callback_url"]; // @gotags: `class:"public"` // Optional PEM-encoded X.509 CA certificates that can be used as trust anchors // when connecting to an OIDC provider. repeated string idp_ca_certs = 100 - [json_name = "idp_ca_certs", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.idp_ca_certs" that: "Certificates" }]; + [json_name = "idp_ca_certs", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.idp_ca_certs" that: "Certificates" }]; // @gotags: `class:"public"` // Allowed audience claims for this auth method. repeated string allowed_audiences = 110 - [json_name = "allowed_audiences", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.allowed_audiences" that: "AudClaims" }]; + [json_name = "allowed_audiences", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.allowed_audiences" that: "AudClaims" }]; // @gotags: `class:"public"` // Optional claims scopes that will be requested during authentication. // see: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims repeated string claims_scopes = 112 - [json_name = "claims_scopes", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.claims_scopes" that: "ClaimsScopes" }]; + [json_name = "claims_scopes", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.claims_scopes" that: "ClaimsScopes" }]; // @gotags: `class:"public"` // account_claim_maps are optional claim maps from custom claims to the // standard claims of sub, name and email. These maps are represented as // key=value where the key equals the from_claim and the value equals the // to_claim. For example "oid=sub". repeated string account_claim_maps = 113 - [json_name = "account_claim_maps", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.account_claim_maps" that: "AccountClaimMaps" }]; + [json_name = "account_claim_maps", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.account_claim_maps" that: "AccountClaimMaps" }]; // @gotags: `class:"public"` // If the Authorization Server's discovered configuration contains values // that do not match the configuration set on this auth method, this can be @@ -154,7 +154,7 @@ message OidcAuthMethodAttributes { // will be treated the same as "false"; that is, every time the method is // updated or the state is changed, this value must be set to "true" or it // will be disabled. - bool disable_discovered_config_validation = 120 [json_name = "disable_discovered_config_validation", (custom_options.v1.generate_sdk_option) = true]; + bool disable_discovered_config_validation = 120 [json_name = "disable_discovered_config_validation", (custom_options.v1.generate_sdk_option) = true]; // @gotags: `class:"public"` // dry_run, when set on an update request, indicates that the changes should // not be persisted. Boundary will still perform the normal checks to confirm @@ -162,7 +162,7 @@ message OidcAuthMethodAttributes { // This value will also be set on the returned resource when set in the request // along with the updated fields applied to the resource (but not persisted) as // a result of the update request. - bool dry_run = 130 [json_name = "dry_run", (custom_options.v1.generate_sdk_option) = true]; + bool dry_run = 130 [json_name = "dry_run", (custom_options.v1.generate_sdk_option) = true]; // @gotags: `class:"public"` } // The structure of the OIDC authenticate start response, in the JSON object @@ -197,7 +197,7 @@ message OidcAuthMethodAuthenticateCallbackResponse { // The structure of OIDC token request parameters message OidcAuthMethodAuthenticateTokenRequest { // The ID of the pending token - string token_id = 10 [json_name = "token_id"]; // @gotags: `class:"private"` + string token_id = 10 [json_name = "token_id"]; // @gotags: `class:"secret"` } // Internal only: the structure of a token response if it _does not_ contain a diff --git a/internal/proto/controller/api/services/v1/auth_method_service.proto b/internal/proto/controller/api/services/v1/auth_method_service.proto index 9be8afb27..286bc13e3 100644 --- a/internal/proto/controller/api/services/v1/auth_method_service.proto +++ b/internal/proto/controller/api/services/v1/auth_method_service.proto @@ -120,9 +120,9 @@ message GetAuthMethodResponse { } message ListAuthMethodsRequest { - 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 ListAuthMethodsResponse { @@ -149,7 +149,7 @@ message UpdateAuthMethodResponse { } message DeleteAuthMethodRequest { - string id = 1; + string id = 1; // @gotags: `class:"public"` } message DeleteAuthMethodResponse {} @@ -157,18 +157,18 @@ message DeleteAuthMethodResponse {} // Attributes specific to changing the state of an oidc auth method. message OidcChangeStateAttributes { // state must be `inactive`, `active-private`, or `active-public` - string state = 1; + string state = 1; // @gotags: `class:"public"` // This flag is only useful for an oidc auth method. It should not be used // unless the oidc provider's config is incorrectly set and is stopping the // activation of this auth method. - bool disable_discovered_config_validation = 2 [json_name = "disable_discovered_config_validation"]; + bool disable_discovered_config_validation = 2 [json_name = "disable_discovered_config_validation"]; // @gotags: `class:"public"` } message ChangeStateRequest { string id = 1; // @gotags: `class:"public"` // Version is used to ensure this resource has not changed. // The mutation will fail if the version does not match the latest known good version. - uint32 version = 2; + uint32 version = 2; // @gotags: `class:"public"` oneof attrs { // The attributes specific to this auth method's state. @@ -184,8 +184,8 @@ message ChangeStateResponse { // The layout of the struct for "attributes" field in AuthenticateRequest for a password type. This message isn't directly referenced anywhere but is used here to define the expected field names and // types. message PasswordLoginAttributes { - string login_name = 1 [json_name = "login_name"]; - string password = 2; + string login_name = 1 [json_name = "login_name"]; // @gotags: `class:"sensitive"` + string password = 2; // @gotags: `class:"secret"` } // The layout of the struct for "attributes" field in AuthenticateRequest for a oidc type's start command. This message isn't directly referenced anywhere but is used here to define the expected field @@ -194,7 +194,7 @@ message OidcStartAttributes { // An object which will be marshaled as JSON and roundtripped in the token command call. google.protobuf.Struct roundtrip_payload = 1 [json_name = "roundtrip_payload"]; // Cached marshaled payload. This is not ingressed from the client; anything found will be thrown out. - string cached_roundtrip_payload = 2; + string cached_roundtrip_payload = 2; // @gotags: `class:"sensitive"` } message AuthenticateRequest { diff --git a/internal/tests/api/authmethods/authmethod_test.go b/internal/tests/api/authmethods/authmethod_test.go index e9f654f5c..8097203e2 100644 --- a/internal/tests/api/authmethods/authmethod_test.go +++ b/internal/tests/api/authmethods/authmethod_test.go @@ -69,13 +69,11 @@ func TestCrud(t *testing.T) { reqItem := tests_api.GetEventDetails(t, got, "request")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, reqItem) tests_api.AssertRedactedValues(t, reqItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually tests_api.AssertRedactedValues(t, reqItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) respItem := tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) tests_api.AssertRedactedValues(t, respItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls @@ -89,7 +87,6 @@ func TestCrud(t *testing.T) { respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) tests_api.AssertRedactedValues(t, respItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls @@ -103,7 +100,6 @@ func TestCrud(t *testing.T) { respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) tests_api.AssertRedactedValues(t, respItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) pw, err = amClient.Update(tc.Context(), pw.Item.Id, pw.Item.Version, authmethods.DefaultName()) @@ -129,14 +125,12 @@ func TestCrud(t *testing.T) { reqItem = tests_api.GetEventDetails(t, got, "request")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, reqItem) tests_api.AssertRedactedValues(t, reqItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually - tests_api.AssertRedactedValues(t, reqItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "callback_url", "state", "client_secret_hmac") + tests_api.AssertRedactedValues(t, reqItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"]) respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) tests_api.AssertRedactedValues(t, respItem["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually - tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "state", "client_secret_hmac", "callback_url") + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"]) oidc, err = amClient.Read(tc.Context(), oidc.Item.Id) require.NoError(err) @@ -300,13 +294,11 @@ func TestCustomMethods(t *testing.T) { reqDetails := tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) tests_api.AssertRedactedValues(t, reqDetails["Attrs"]) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually - tests_api.AssertRedactedValues(t, reqDetails["Attrs"].(map[string]interface{})["OidcChangeStateAttributes"], "state") + tests_api.AssertRedactedValues(t, reqDetails["Attrs"].(map[string]interface{})["OidcChangeStateAttributes"]) respItem := tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - // TODO(johanbrandhorst): Not all of these fields will be redacted eventually - tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "signing_algorithms", "callback_url", "idp_ca_certs", "state", "client_secret_hmac") + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"]) _, err = amClient.ChangeState(tc.Context(), u.Item.Id, u.Item.Version, "", authmethods.WithOidcAuthMethodDisableDiscoveredConfigValidation(true)) assert.Error(err) diff --git a/internal/tests/api/authmethods/classification_test.go b/internal/tests/api/authmethods/classification_test.go index bad427d65..ac2b4d966 100644 --- a/internal/tests/api/authmethods/classification_test.go +++ b/internal/tests/api/authmethods/classification_test.go @@ -22,6 +22,10 @@ func TestAuthMethod_Tags(t *testing.T) { now := time.Now() wrapper := wrapper.TestWrapper(t) testEncryptingFilter := api.NewEncryptFilter(t, wrapper) + testEncryptingFilter.FilterOperationOverrides = map[encrypt.DataClassification]encrypt.FilterOperation{ + // Use HMAC for sensitive fields for easy test comparisons + encrypt.SensitiveClassification: encrypt.HmacSha256Operation, + } tests := []struct { name string @@ -78,21 +82,20 @@ func TestAuthMethod_Tags(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "oidc", - // TODO(johanbrandhorst): update redaction once typed attributes are available Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ - State: encrypt.RedactedData, - Issuer: wrapperspb.String(encrypt.RedactedData), - ClientId: wrapperspb.String(encrypt.RedactedData), - ClientSecretHmac: encrypt.RedactedData, + State: "public-state", + Issuer: wrapperspb.String("public-issuer"), + ClientId: wrapperspb.String("public-client_id"), + ClientSecretHmac: "public-client_secret_hmac", MaxAge: wrapperspb.UInt32(100), - SigningAlgorithms: []string{encrypt.RedactedData}, - IdpCaCerts: []string{encrypt.RedactedData}, - ApiUrlPrefix: wrapperspb.String(encrypt.RedactedData), - CallbackUrl: encrypt.RedactedData, - AllowedAudiences: []string{encrypt.RedactedData}, - ClaimsScopes: []string{encrypt.RedactedData}, - AccountClaimMaps: []string{encrypt.RedactedData}, + SigningAlgorithms: []string{"public-signing_algorithms"}, + IdpCaCerts: []string{"public-idp_ca_certs"}, + ApiUrlPrefix: wrapperspb.String("public-api_url_prefix"), + CallbackUrl: "public-callback_url", + AllowedAudiences: []string{"public-allowed_audiences"}, + ClaimsScopes: []string{"public-claims_scopes"}, + AccountClaimMaps: []string{"public-account_claim_maps"}, DisableDiscoveredConfigValidation: false, DryRun: false, ClientSecret: wrapperspb.String(encrypt.RedactedData), @@ -147,7 +150,6 @@ func TestAuthMethod_Tags(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "password", - // TODO(johanbrandhorst): update redaction once typed attributes are available Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ MinLoginNameLength: 100, diff --git a/internal/tests/api/authmethods/service_classification_test.go b/internal/tests/api/authmethods/service_classification_test.go index f227c562b..1a1aab702 100644 --- a/internal/tests/api/authmethods/service_classification_test.go +++ b/internal/tests/api/authmethods/service_classification_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/eventlogger/filters/encrypt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -28,6 +29,10 @@ func TestAuthenticate_Tags(t *testing.T) { now := time.Now() wrapper := wrapper.TestWrapper(t) testEncryptingFilter := api.NewEncryptFilter(t, wrapper) + testEncryptingFilter.FilterOperationOverrides = map[encrypt.DataClassification]encrypt.FilterOperation{ + // Use HMAC for sensitive fields for easy test comparisons + encrypt.SensitiveClassification: encrypt.HmacSha256Operation, + } tests := []struct { name string @@ -35,7 +40,48 @@ func TestAuthenticate_Tags(t *testing.T) { wantEvent *eventlogger.Event }{ { - name: "validate-response-filtering", + name: "validate-authenticate-request-filtering", + testEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateRequest{ + AuthMethodId: "public-auth-method-id", + TokenType: "public-token-type", + Command: "public-command", + Attrs: &services.AuthenticateRequest_OidcStartAttributes{ + OidcStartAttributes: &services.OidcStartAttributes{ + RoundtripPayload: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "key": structpb.NewStringValue("value"), + }, + }, + CachedRoundtripPayload: "public-cached_roundtrip_payload", + }, + }, + }, + }, + wantEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateRequest{ + AuthMethodId: "public-auth-method-id", + TokenType: "public-token-type", + Command: "public-command", + Attrs: &services.AuthenticateRequest_OidcStartAttributes{ + OidcStartAttributes: &services.OidcStartAttributes{ + RoundtripPayload: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "key": structpb.NewStringValue(encrypt.RedactedData), + }, + }, + CachedRoundtripPayload: encrypt.TestHmacSha256(t, []byte("public-cached_roundtrip_payload"), wrapper, nil, nil), + }, + }, + }, + }, + }, + { + name: "validate-authenticate-response-filtering", testEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, @@ -73,7 +119,6 @@ func TestAuthenticate_Tags(t *testing.T) { CreatedAt: now, Payload: &services.AuthenticateResponse{ Command: "public-command", - // TODO(johanbrandhorst): update redaction once typed attributes are available Attrs: &services.AuthenticateResponse_AuthTokenResponse{ AuthTokenResponse: &authtokens.AuthToken{ AccountId: "public-account_id", @@ -103,7 +148,7 @@ func TestAuthenticate_Tags(t *testing.T) { }, }, { - name: "validate-request-filtering", + name: "validate-callback-request-filtering", testEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, @@ -111,9 +156,75 @@ func TestAuthenticate_Tags(t *testing.T) { AuthMethodId: "public-auth-method-id", TokenType: "public-token-type", Command: "public-command", - Attrs: &services.AuthenticateRequest_OidcAuthMethodAuthenticateTokenRequest{ - OidcAuthMethodAuthenticateTokenRequest: &authmethods.OidcAuthMethodAuthenticateTokenRequest{ - TokenId: "public-token-id", + Attrs: &services.AuthenticateRequest_OidcAuthMethodAuthenticateCallbackRequest{ + OidcAuthMethodAuthenticateCallbackRequest: &authmethods.OidcAuthMethodAuthenticateCallbackRequest{ + Code: "secret-code", + State: "public-state", + Error: "public-error", + ErrorDescription: "public-error_description", + ErrorUri: "public-error_uri", + }, + }, + }, + }, + wantEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateRequest{ + AuthMethodId: "public-auth-method-id", + TokenType: "public-token-type", + Command: "public-command", + Attrs: &services.AuthenticateRequest_OidcAuthMethodAuthenticateCallbackRequest{ + OidcAuthMethodAuthenticateCallbackRequest: &authmethods.OidcAuthMethodAuthenticateCallbackRequest{ + Code: encrypt.RedactedData, + State: "public-state", + Error: "public-error", + ErrorDescription: "public-error_description", + ErrorUri: "public-error_uri", + }, + }, + }, + }, + }, + { + name: "validate-callback-response-filtering", + testEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateResponse{ + Command: "public-command", + Attrs: &services.AuthenticateResponse_OidcAuthMethodAuthenticateCallbackResponse{ + OidcAuthMethodAuthenticateCallbackResponse: &authmethods.OidcAuthMethodAuthenticateCallbackResponse{ + FinalRedirectUrl: "public-final_redirect_url", + }, + }, + }, + }, + wantEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateResponse{ + Command: "public-command", + Attrs: &services.AuthenticateResponse_OidcAuthMethodAuthenticateCallbackResponse{ + OidcAuthMethodAuthenticateCallbackResponse: &authmethods.OidcAuthMethodAuthenticateCallbackResponse{ + FinalRedirectUrl: "public-final_redirect_url", + }, + }, + }, + }, + }, + { + name: "validate-token-request-filtering", + testEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateRequest{ + AuthMethodId: "public-auth-method-id", + TokenType: "public-token-type", + Command: "public-command", + Attrs: &services.AuthenticateRequest_OidcAuthMethodAuthenticateTokenRequest{ + OidcAuthMethodAuthenticateTokenRequest: &authmethods.OidcAuthMethodAuthenticateTokenRequest{ + TokenId: "secret-token-id", }, }, }, @@ -125,7 +236,6 @@ func TestAuthenticate_Tags(t *testing.T) { AuthMethodId: "public-auth-method-id", TokenType: "public-token-type", Command: "public-command", - // TODO(johanbrandhorst): update redaction once typed attributes are available Attrs: &services.AuthenticateRequest_OidcAuthMethodAuthenticateTokenRequest{ OidcAuthMethodAuthenticateTokenRequest: &authmethods.OidcAuthMethodAuthenticateTokenRequest{ TokenId: encrypt.RedactedData, @@ -134,6 +244,33 @@ func TestAuthenticate_Tags(t *testing.T) { }, }, }, + { + name: "validate-token-response-filtering", + testEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateResponse{ + Command: "public-command", + Attrs: &services.AuthenticateResponse_OidcAuthMethodAuthenticateTokenResponse{ + OidcAuthMethodAuthenticateTokenResponse: &authmethods.OidcAuthMethodAuthenticateTokenResponse{ + Status: "public-status", + }, + }, + }, + }, + wantEvent: &eventlogger.Event{ + Type: "test", + CreatedAt: now, + Payload: &services.AuthenticateResponse{ + Command: "public-command", + Attrs: &services.AuthenticateResponse_OidcAuthMethodAuthenticateTokenResponse{ + OidcAuthMethodAuthenticateTokenResponse: &authmethods.OidcAuthMethodAuthenticateTokenResponse{ + Status: "public-status", + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go b/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go index 670625e6f..16dbd78ab 100644 --- a/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go +++ b/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go @@ -37,7 +37,7 @@ type AuthMethod struct { // The ID of the Scope of which this Auth Method is a part. 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 Auth method. - Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty" class:"public"` // @gotags: `class:"public"` + Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"` // Optional name for identification purposes. Name *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=name,proto3" json:"name,omitempty" class:"public"` // @gotags: `class:"public"` // Optional user-set description for identification purposes. @@ -239,9 +239,9 @@ type PasswordAuthMethodAttributes struct { unknownFields protoimpl.UnknownFields // The minimum length allowed for user names for Accounts in this Auth Method. - MinLoginNameLength uint32 `protobuf:"varint,10,opt,name=min_login_name_length,proto3" json:"min_login_name_length,omitempty"` + MinLoginNameLength uint32 `protobuf:"varint,10,opt,name=min_login_name_length,proto3" json:"min_login_name_length,omitempty" class:"public"` // @gotags: `class:"public"` // The minimum length allowed for passwords for Accounts in this Auth Method. - MinPasswordLength uint32 `protobuf:"varint,20,opt,name=min_password_length,proto3" json:"min_password_length,omitempty"` + MinPasswordLength uint32 `protobuf:"varint,20,opt,name=min_password_length,proto3" json:"min_password_length,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *PasswordAuthMethodAttributes) Reset() { @@ -298,46 +298,46 @@ type OidcAuthMethodAttributes struct { // Output only. The state of the auth method. Will be "inactive", // "active-private", or "active-public". - State string `protobuf:"bytes,10,opt,name=state,proto3" json:"state,omitempty"` + State string `protobuf:"bytes,10,opt,name=state,proto3" json:"state,omitempty" class:"public"` // @gotags: `class:"public"` // The issuer URL. Boundary expects only the schema, host, and port and will // strip off ".well-known/openid-configuration" if present. This will be // used for configuration discovery as well as for validation of the "iss" // claim. - Issuer *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=issuer,proto3" json:"issuer,omitempty"` + Issuer *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=issuer,proto3" json:"issuer,omitempty" class:"public"` // @gotags: `class:"public"` // An OAuth 2.0 Client Identifier valid at the Authorization Server. - ClientId *wrapperspb.StringValue `protobuf:"bytes,30,opt,name=client_id,proto3" json:"client_id,omitempty"` + ClientId *wrapperspb.StringValue `protobuf:"bytes,30,opt,name=client_id,proto3" json:"client_id,omitempty" class:"public"` // @gotags: `class:"public"` // Input only. The client's secret. - ClientSecret *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=client_secret,proto3" json:"client_secret,omitempty"` + ClientSecret *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=client_secret,proto3" json:"client_secret,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The HMAC'd value of the clients secret to indicate whether // the client secret has changed. - ClientSecretHmac string `protobuf:"bytes,50,opt,name=client_secret_hmac,proto3" json:"client_secret_hmac,omitempty"` + ClientSecretHmac string `protobuf:"bytes,50,opt,name=client_secret_hmac,proto3" json:"client_secret_hmac,omitempty" class:"public"` // @gotags: `class:"public"` // The OIDC "max_age" parameter sent to the Authorization Server indicating // a maximum acceptable time in seconds since the user's last authentication // before requiring the user to reauthenticate. 0 indicates an immediate // need to reauthenticate. - MaxAge *wrapperspb.UInt32Value `protobuf:"bytes,60,opt,name=max_age,proto3" json:"max_age,omitempty"` + MaxAge *wrapperspb.UInt32Value `protobuf:"bytes,60,opt,name=max_age,proto3" json:"max_age,omitempty" class:"public"` // @gotags: `class:"public"` // The signing algorithms allowed for the auth method. - SigningAlgorithms []string `protobuf:"bytes,70,rep,name=signing_algorithms,proto3" json:"signing_algorithms,omitempty"` + SigningAlgorithms []string `protobuf:"bytes,70,rep,name=signing_algorithms,proto3" json:"signing_algorithms,omitempty" class:"public"` // @gotags: `class:"public"` // The prefix that should be used for any URLs needed during the // authentication flow. This includes the callback URL, the token retrieval // URL, and the redirection URL used by the OIDC Authorization Server. - ApiUrlPrefix *wrapperspb.StringValue `protobuf:"bytes,80,opt,name=api_url_prefix,proto3" json:"api_url_prefix,omitempty"` + ApiUrlPrefix *wrapperspb.StringValue `protobuf:"bytes,80,opt,name=api_url_prefix,proto3" json:"api_url_prefix,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The callback URL that should be configured on the // Authorization Server to use during the authentication flow. - CallbackUrl string `protobuf:"bytes,90,opt,name=callback_url,proto3" json:"callback_url,omitempty"` + CallbackUrl string `protobuf:"bytes,90,opt,name=callback_url,proto3" json:"callback_url,omitempty" class:"public"` // @gotags: `class:"public"` // Optional PEM-encoded X.509 CA certificates that can be used as trust anchors // when connecting to an OIDC provider. - IdpCaCerts []string `protobuf:"bytes,100,rep,name=idp_ca_certs,proto3" json:"idp_ca_certs,omitempty"` + IdpCaCerts []string `protobuf:"bytes,100,rep,name=idp_ca_certs,proto3" json:"idp_ca_certs,omitempty" class:"public"` // @gotags: `class:"public"` // Allowed audience claims for this auth method. - AllowedAudiences []string `protobuf:"bytes,110,rep,name=allowed_audiences,proto3" json:"allowed_audiences,omitempty"` + AllowedAudiences []string `protobuf:"bytes,110,rep,name=allowed_audiences,proto3" json:"allowed_audiences,omitempty" class:"public"` // @gotags: `class:"public"` // Optional claims scopes that will be requested during authentication. // see: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims - ClaimsScopes []string `protobuf:"bytes,112,rep,name=claims_scopes,proto3" json:"claims_scopes,omitempty"` + ClaimsScopes []string `protobuf:"bytes,112,rep,name=claims_scopes,proto3" json:"claims_scopes,omitempty" class:"public"` // @gotags: `class:"public"` // account_claim_maps are optional claim maps from custom claims to the // standard claims of sub, name and email. These maps are represented as // key=value where the key equals the from_claim and the value equals the // to_claim. For example "oid=sub". - AccountClaimMaps []string `protobuf:"bytes,113,rep,name=account_claim_maps,proto3" json:"account_claim_maps,omitempty"` + AccountClaimMaps []string `protobuf:"bytes,113,rep,name=account_claim_maps,proto3" json:"account_claim_maps,omitempty" class:"public"` // @gotags: `class:"public"` // If the Authorization Server's discovered configuration contains values // that do not match the configuration set on this auth method, this can be // set to force the local configuration to override the discovered values. @@ -346,14 +346,14 @@ type OidcAuthMethodAttributes struct { // will be treated the same as "false"; that is, every time the method is // updated or the state is changed, this value must be set to "true" or it // will be disabled. - DisableDiscoveredConfigValidation bool `protobuf:"varint,120,opt,name=disable_discovered_config_validation,proto3" json:"disable_discovered_config_validation,omitempty"` + DisableDiscoveredConfigValidation bool `protobuf:"varint,120,opt,name=disable_discovered_config_validation,proto3" json:"disable_discovered_config_validation,omitempty" class:"public"` // @gotags: `class:"public"` // dry_run, when set on an update request, indicates that the changes should // not be persisted. Boundary will still perform the normal checks to confirm // the auth method is complete and validated against the discovered config. // This value will also be set on the returned resource when set in the request // along with the updated fields applied to the resource (but not persisted) as // a result of the update request. - DryRun bool `protobuf:"varint,130,opt,name=dry_run,proto3" json:"dry_run,omitempty"` + DryRun bool `protobuf:"varint,130,opt,name=dry_run,proto3" json:"dry_run,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *OidcAuthMethodAttributes) Reset() { @@ -690,7 +690,7 @@ type OidcAuthMethodAuthenticateTokenRequest struct { unknownFields protoimpl.UnknownFields // The ID of the pending token - TokenId string `protobuf:"bytes,10,opt,name=token_id,proto3" json:"token_id,omitempty" class:"private"` // @gotags: `class:"private"` + TokenId string `protobuf:"bytes,10,opt,name=token_id,proto3" json:"token_id,omitempty" class:"secret"` // @gotags: `class:"secret"` } func (x *OidcAuthMethodAuthenticateTokenRequest) Reset() {