diff --git a/cmd/lint/main.go b/cmd/lint/main.go index 80cf81531a..af8ffeff05 100644 --- a/cmd/lint/main.go +++ b/cmd/lint/main.go @@ -363,6 +363,7 @@ var vocabWords = []string{ "uri", "url", "us", + "usm", "v2", "vertexai", "vnet", diff --git a/internal/iam/command_rbac_role_binding.go b/internal/iam/command_rbac_role_binding.go index 3d9f5fb933..095cdd387c 100644 --- a/internal/iam/command_rbac_role_binding.go +++ b/internal/iam/command_rbac_role_binding.go @@ -24,17 +24,19 @@ import ( ) const ( - httpStatusCodeErrorMsg = "no error but received HTTP status code %d" - httpStatusCodeSuggestions = "Please file a support ticket with details." - invalidResourceTypeErrorMsg = `invalid resource type "%s"` - invalidResourceTypeSuggestions = "The available resource types are %s." - lookUpRoleSuggestions = "To check for valid roles, use `confluent iam rbac role list`." - principalFormatErrorMsg = "incorrect principal format specified" - principalFormatSuggestions = "Principal must be specified in this format: \":\".\nFor example, \"User:u-xxxxxx\" or \"User:sa-xxxxxx\"." - resourceFormatErrorMsg = "incorrect resource format specified" - resourceFormatSuggestions = "Resource must be specified in this format: `:`." - specifyCloudClusterErrorMsg = "must specify `--cloud-cluster` to indicate role binding scope" - specifyEnvironmentErrorMsg = "must specify `--environment` to indicate role binding scope" + httpStatusCodeErrorMsg = "no error but received HTTP status code %d" + httpStatusCodeSuggestions = "Please file a support ticket with details." + invalidResourceTypeErrorMsg = `invalid resource type "%s"` + invalidResourceTypeSuggestions = "The available resource types are %s." + lookUpRoleSuggestions = "To check for valid roles, use `confluent iam rbac role list`." + principalFormatErrorMsg = "incorrect principal format specified" + principalFormatSuggestions = "Principal must be specified in this format: \":\".\nFor example, \"User:u-xxxxxx\" or \"User:sa-xxxxxx\"." + resourceFormatErrorMsg = "incorrect resource format specified" + resourceFormatSuggestions = "Resource must be specified in this format: `:`." + specifyCloudClusterErrorMsg = "must specify `--cloud-cluster` to indicate role binding scope" + specifyEnvironmentErrorMsg = "must specify `--environment` to indicate role binding scope" + specifyUsmKafkaClusterErrorMsg = "must specify `--usm-kafka-cluster` to indicate role binding scope" + specifyUsmConnectClusterErrorMsg = "must specify `--usm-connect-cluster` to indicate role binding scope" ) var ( @@ -53,6 +55,11 @@ var ( clusterScopedRolesV2 = types.NewSet("CloudClusterAdmin") environmentScopedRoles = types.NewSet("EnvironmentAdmin") + // USM cluster-scoped roles bind at the "usm-kafka-cluster" or "usm-connect-cluster" scope, + // as siblings to "cloud-cluster" under "environment". The role name (not display name) is used. + usmKafkaClusterScopedRoles = types.NewSet("UsmKafkaClusterAdmin", "UsmKafkaOperator", "UsmKafkaMetricsViewer") + usmConnectClusterScopedRoles = types.NewSet("UsmConnectClusterAdmin", "UsmConnectOperator", "UsmConnectMetricsViewer") + literalPatternType = "LITERAL" prefixedPatternType = "PREFIXED" ) @@ -186,6 +193,8 @@ func addClusterFlags(cmd *cobra.Command, cfg *config.Config, cliCommand *pcmd.CL cmd.Flags().String("schema-registry-cluster", "", "Schema Registry cluster ID for the role binding.") cmd.Flags().String("ksql-cluster", "", "ksqlDB cluster name for the role binding.") cmd.Flags().String("flink-region", "", `Flink region for the role binding, formatted as "cloud.region".`) + cmd.Flags().String("usm-kafka-cluster", "", "USM Kafka cluster ID for the role binding.") + cmd.Flags().String("usm-connect-cluster", "", "USM Connect cluster ID for the role binding.") } else { cmd.Flags().String("kafka-cluster", "", "Kafka cluster ID for the role binding.") cmd.Flags().String("schema-registry-cluster", "", "Schema Registry cluster ID for the role binding.") @@ -626,6 +635,22 @@ func (c *roleBindingCommand) parseV2BaseCrnPattern(cmd *cobra.Command) (string, crnPattern += "/flink-region=" + flinkRegion } + if cmd.Flags().Changed("usm-kafka-cluster") { + usmKafkaCluster, err := cmd.Flags().GetString("usm-kafka-cluster") + if err != nil { + return "", err + } + crnPattern += "/usm-kafka-cluster=" + usmKafkaCluster + } + + if cmd.Flags().Changed("usm-connect-cluster") { + usmConnectCluster, err := cmd.Flags().GetString("usm-connect-cluster") + if err != nil { + return "", err + } + crnPattern += "/usm-connect-cluster=" + usmConnectCluster + } + if cmd.Flags().Changed("role") { role, err := cmd.Flags().GetString("role") if err != nil { @@ -634,12 +659,18 @@ func (c *roleBindingCommand) parseV2BaseCrnPattern(cmd *cobra.Command) (string, if clusterScopedRolesV2.Contains(role) && !cmd.Flags().Changed("cloud-cluster") { return "", errors.New(specifyCloudClusterErrorMsg) } - if (environmentScopedRoles[role] || clusterScopedRolesV2.Contains(role)) && !cmd.Flags().Changed("current-environment") && !cmd.Flags().Changed("environment") { + if usmKafkaClusterScopedRoles.Contains(role) && !cmd.Flags().Changed("usm-kafka-cluster") { + return "", errors.New(specifyUsmKafkaClusterErrorMsg) + } + if usmConnectClusterScopedRoles.Contains(role) && !cmd.Flags().Changed("usm-connect-cluster") { + return "", errors.New(specifyUsmConnectClusterErrorMsg) + } + if (environmentScopedRoles[role] || clusterScopedRolesV2.Contains(role) || usmKafkaClusterScopedRoles.Contains(role) || usmConnectClusterScopedRoles.Contains(role)) && !cmd.Flags().Changed("current-environment") && !cmd.Flags().Changed("environment") { return "", errors.New(specifyEnvironmentErrorMsg) } } - if cmd.Flags().Changed("cloud-cluster") && !cmd.Flags().Changed("current-environment") && !cmd.Flags().Changed("environment") { + if (cmd.Flags().Changed("cloud-cluster") || cmd.Flags().Changed("usm-kafka-cluster") || cmd.Flags().Changed("usm-connect-cluster")) && !cmd.Flags().Changed("current-environment") && !cmd.Flags().Changed("environment") { return "", errors.New(specifyEnvironmentErrorMsg) } return crnPattern, nil diff --git a/internal/iam/command_rbac_role_binding_create.go b/internal/iam/command_rbac_role_binding_create.go index a817065487..d0cca133b7 100644 --- a/internal/iam/command_rbac_role_binding_create.go +++ b/internal/iam/command_rbac_role_binding_create.go @@ -63,6 +63,14 @@ func (c *roleBindingCommand) newCreateCommand() *cobra.Command { Text: `Grant the "FlinkDeveloper" scoped to Flink compute pool "lfcp-123456" in AWS us-east-1 to principal "User:u-123456":`, Code: "confluent iam rbac role-binding create --principal User:u-123456 --role FlinkDeveloper --environment env-123456 --flink-region aws.us-east-1 --resource ComputePool:lfcp-123456", }, + examples.Example{ + Text: `Grant the role "UsmKafkaClusterAdmin" to the principal "User:u-123456" for the USM Kafka cluster "usmkc-123456" in the environment "env-123456":`, + Code: "confluent iam rbac role-binding create --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456", + }, + examples.Example{ + Text: `Grant the role "UsmConnectClusterAdmin" to the principal "User:u-123456" for the USM Connect cluster "usmcc-123456" in the environment "env-123456":`, + Code: "confluent iam rbac role-binding create --principal User:u-123456 --role UsmConnectClusterAdmin --environment env-123456 --usm-connect-cluster usmcc-123456", + }, ) } else { exs = append(exs, diff --git a/internal/iam/command_rbac_role_binding_delete.go b/internal/iam/command_rbac_role_binding_delete.go index c721942589..67e20665f4 100644 --- a/internal/iam/command_rbac_role_binding_delete.go +++ b/internal/iam/command_rbac_role_binding_delete.go @@ -31,6 +31,10 @@ func (c *roleBindingCommand) newDeleteCommand() *cobra.Command { Text: `Delete the role "ResourceOwner" for the resource "Topic:my-topic" on the Kafka cluster "lkc-123456":`, Code: "confluent iam rbac role-binding delete --principal User:u-123456 --role ResourceOwner --environment env-123456 --kafka-cluster lkc-123456 --resource Topic:my-topic", }, + examples.Example{ + Text: `Delete the role "UsmKafkaClusterAdmin" for the principal "User:u-123456" on the USM Kafka cluster "usmkc-123456" in the environment "env-123456":`, + Code: "confluent iam rbac role-binding delete --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456", + }, ) } else { cmd.Example = examples.BuildExampleString( diff --git a/internal/iam/command_rbac_role_binding_list.go b/internal/iam/command_rbac_role_binding_list.go index be7ff740e0..62929dcd48 100644 --- a/internal/iam/command_rbac_role_binding_list.go +++ b/internal/iam/command_rbac_role_binding_list.go @@ -54,6 +54,10 @@ func (c *roleBindingCommand) newListCommand() *cobra.Command { Text: `List the role bindings for user "u-123456" with role "CloudClusterAdmin":`, Code: "confluent iam rbac role-binding list --principal User:u-123456 --role CloudClusterAdmin --environment env-123456 --cloud-cluster lkc-123456", }, + examples.Example{ + Text: `List the role bindings for user "u-123456" with role "UsmKafkaClusterAdmin" for the USM Kafka cluster "usmkc-123456":`, + Code: "confluent iam rbac role-binding list --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456", + }, examples.Example{ Text: `List the role bindings for user "u-123456" for all scopes:`, Code: "confluent iam rbac role-binding list --principal User:u-123456 --inclusive", @@ -100,6 +104,8 @@ func (c *roleBindingCommand) newListCommand() *cobra.Command { cmd.Flags().String("schema-registry-cluster", "", "Schema Registry cluster ID, which specifies the Schema Registry cluster scope.") cmd.Flags().String("ksql-cluster", "", "ksqlDB cluster name, which specifies the ksqlDB cluster scope.") cmd.Flags().String("flink-region", "", `Flink region for the role binding, formatted as "cloud.region".`) + cmd.Flags().String("usm-kafka-cluster", "", "USM Kafka cluster ID, which specifies the USM Kafka cluster scope.") + cmd.Flags().String("usm-connect-cluster", "", "USM Connect cluster ID, which specifies the USM Connect cluster scope.") } else { cmd.Flags().String("kafka-cluster", "", "Kafka cluster ID, which specifies the Kafka cluster scope.") cmd.Flags().String("schema-registry-cluster", "", "Schema Registry cluster ID, which specifies the Schema Registry cluster scope.") @@ -424,6 +430,12 @@ func (c *roleBindingCommand) listMyRoleBindings(cmd *cobra.Command, listRoleBind envName = content case "cloud-cluster": cloudClusterName = content + case "usm-kafka-cluster": + clusterType = "USM Kafka" + logicalCluster = content + case "usm-connect-cluster": + clusterType = "USM Connect" + logicalCluster = content case "ksql": clusterType = "ksqlDB" logicalCluster = content diff --git a/internal/iam/command_rbac_role_binding_test.go b/internal/iam/command_rbac_role_binding_test.go index d0f3382955..2507cfc2cb 100644 --- a/internal/iam/command_rbac_role_binding_test.go +++ b/internal/iam/command_rbac_role_binding_test.go @@ -3,7 +3,11 @@ package iam import ( "testing" + "github.com/spf13/cobra" "github.com/stretchr/testify/require" + + pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/config" ) func TestParseAndValidateResourcePattern_Prefixed(t *testing.T) { @@ -35,3 +39,90 @@ func TestParseAndValidateResourcePattern_ErrIncorrectResourceFormat(t *testing.T _, err := parseAndValidateResourcePattern("string with no colon", true) require.Error(t, err) } + +// newRoleBindingTestCommand returns a roleBindingCommand with a minimal context that only +// supplies the current organization, which is all parseV2BaseCrnPattern reads from context. +func newRoleBindingTestCommand() *roleBindingCommand { + return &roleBindingCommand{ + AuthenticatedCLICommand: &pcmd.AuthenticatedCLICommand{ + Context: &config.Context{LastOrgId: "abc-123"}, + }, + } +} + +// newCloudRoleBindingFlagSet registers the cloud scope flags that parseV2BaseCrnPattern reads. +func newCloudRoleBindingFlagSet() *cobra.Command { + cmd := &cobra.Command{} + cmd.Flags().String("role", "", "") + cmd.Flags().String("environment", "", "") + cmd.Flags().Bool("current-environment", false, "") + cmd.Flags().String("cloud-cluster", "", "") + cmd.Flags().String("schema-registry-cluster", "", "") + cmd.Flags().String("ksql-cluster", "", "") + cmd.Flags().String("kafka-cluster", "", "") + cmd.Flags().String("flink-region", "", "") + cmd.Flags().String("usm-kafka-cluster", "", "") + cmd.Flags().String("usm-connect-cluster", "", "") + return cmd +} + +func TestParseV2BaseCrnPattern_UsmKafkaCluster(t *testing.T) { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("role", "UsmKafkaClusterAdmin")) + require.NoError(t, cmd.Flags().Set("environment", "env-596")) + require.NoError(t, cmd.Flags().Set("usm-kafka-cluster", "usmkc-123456")) + + crnPattern, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.NoError(t, err) + require.Equal(t, "crn://confluent.cloud/organization=abc-123/environment=env-596/usm-kafka-cluster=usmkc-123456", crnPattern) +} + +func TestParseV2BaseCrnPattern_UsmConnectCluster(t *testing.T) { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("role", "UsmConnectClusterAdmin")) + require.NoError(t, cmd.Flags().Set("environment", "env-596")) + require.NoError(t, cmd.Flags().Set("usm-connect-cluster", "usmcc-123456")) + + crnPattern, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.NoError(t, err) + require.Equal(t, "crn://confluent.cloud/organization=abc-123/environment=env-596/usm-connect-cluster=usmcc-123456", crnPattern) +} + +func TestParseV2BaseCrnPattern_UsmKafkaRolesRequireClusterFlag(t *testing.T) { + for _, role := range []string{"UsmKafkaClusterAdmin", "UsmKafkaOperator", "UsmKafkaMetricsViewer"} { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("role", role)) + require.NoError(t, cmd.Flags().Set("environment", "env-596")) + + _, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.EqualError(t, err, specifyUsmKafkaClusterErrorMsg, "role %q must require --usm-kafka-cluster", role) + } +} + +func TestParseV2BaseCrnPattern_UsmConnectRolesRequireClusterFlag(t *testing.T) { + for _, role := range []string{"UsmConnectClusterAdmin", "UsmConnectOperator", "UsmConnectMetricsViewer"} { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("role", role)) + require.NoError(t, cmd.Flags().Set("environment", "env-596")) + + _, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.EqualError(t, err, specifyUsmConnectClusterErrorMsg, "role %q must require --usm-connect-cluster", role) + } +} + +func TestParseV2BaseCrnPattern_UsmRoleRequiresEnvironment(t *testing.T) { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("role", "UsmKafkaClusterAdmin")) + require.NoError(t, cmd.Flags().Set("usm-kafka-cluster", "usmkc-123456")) + + _, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.EqualError(t, err, specifyEnvironmentErrorMsg) +} + +func TestParseV2BaseCrnPattern_UsmClusterFlagRequiresEnvironment(t *testing.T) { + cmd := newCloudRoleBindingFlagSet() + require.NoError(t, cmd.Flags().Set("usm-connect-cluster", "usmcc-123456")) + + _, err := newRoleBindingTestCommand().parseV2BaseCrnPattern(cmd) + require.EqualError(t, err, specifyEnvironmentErrorMsg) +} diff --git a/test/fixtures/output/iam/rbac/role-binding/create-help.golden b/test/fixtures/output/iam/rbac/role-binding/create-help.golden index 3887f8f740..528b609b55 100644 --- a/test/fixtures/output/iam/rbac/role-binding/create-help.golden +++ b/test/fixtures/output/iam/rbac/role-binding/create-help.golden @@ -44,6 +44,14 @@ Grant the "FlinkDeveloper" scoped to Flink compute pool "lfcp-123456" in AWS us- $ confluent iam rbac role-binding create --principal User:u-123456 --role FlinkDeveloper --environment env-123456 --flink-region aws.us-east-1 --resource ComputePool:lfcp-123456 +Grant the role "UsmKafkaClusterAdmin" to the principal "User:u-123456" for the USM Kafka cluster "usmkc-123456" in the environment "env-123456": + + $ confluent iam rbac role-binding create --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456 + +Grant the role "UsmConnectClusterAdmin" to the principal "User:u-123456" for the USM Connect cluster "usmcc-123456" in the environment "env-123456": + + $ confluent iam rbac role-binding create --principal User:u-123456 --role UsmConnectClusterAdmin --environment env-123456 --usm-connect-cluster usmcc-123456 + Flags: --role string REQUIRED: Role name of the new role binding. --principal string REQUIRED: Principal type and identifier using "Prefix:ID" format. @@ -54,6 +62,8 @@ Flags: --schema-registry-cluster string Schema Registry cluster ID for the role binding. --ksql-cluster string ksqlDB cluster name for the role binding. --flink-region string Flink region for the role binding, formatted as "cloud.region". + --usm-kafka-cluster string USM Kafka cluster ID for the role binding. + --usm-connect-cluster string USM Connect cluster ID for the role binding. --resource string Resource type and identifier using "Prefix:ID" format. --prefix Whether the provided resource name is treated as a prefix pattern. -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") diff --git a/test/fixtures/output/iam/rbac/role-binding/create-usm-connect-cluster-admin-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/create-usm-connect-cluster-admin-cloud.golden new file mode 100644 index 0000000000..bb919df53d --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/create-usm-connect-cluster-admin-cloud.golden @@ -0,0 +1,5 @@ ++-----------+------------------------+ +| Principal | User:u-11aaa | +| Email | u-11aaa@confluent.io | +| Role | UsmConnectClusterAdmin | ++-----------+------------------------+ diff --git a/test/fixtures/output/iam/rbac/role-binding/create-usm-kafka-cluster-admin-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/create-usm-kafka-cluster-admin-cloud.golden new file mode 100644 index 0000000000..8b28870ade --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/create-usm-kafka-cluster-admin-cloud.golden @@ -0,0 +1,5 @@ ++-----------+----------------------+ +| Principal | User:u-11aaa | +| Email | u-11aaa@confluent.io | +| Role | UsmKafkaClusterAdmin | ++-----------+----------------------+ diff --git a/test/fixtures/output/iam/rbac/role-binding/delete-help.golden b/test/fixtures/output/iam/rbac/role-binding/delete-help.golden index cb2e87bdb0..d3168659ee 100644 --- a/test/fixtures/output/iam/rbac/role-binding/delete-help.golden +++ b/test/fixtures/output/iam/rbac/role-binding/delete-help.golden @@ -8,6 +8,10 @@ Delete the role "ResourceOwner" for the resource "Topic:my-topic" on the Kafka c $ confluent iam rbac role-binding delete --principal User:u-123456 --role ResourceOwner --environment env-123456 --kafka-cluster lkc-123456 --resource Topic:my-topic +Delete the role "UsmKafkaClusterAdmin" for the principal "User:u-123456" on the USM Kafka cluster "usmkc-123456" in the environment "env-123456": + + $ confluent iam rbac role-binding delete --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456 + Flags: --role string REQUIRED: Role name of the existing role binding. --principal string REQUIRED: Principal type and identifier using "Prefix:ID" format. @@ -19,6 +23,8 @@ Flags: --schema-registry-cluster string Schema Registry cluster ID for the role binding. --ksql-cluster string ksqlDB cluster name for the role binding. --flink-region string Flink region for the role binding, formatted as "cloud.region". + --usm-kafka-cluster string USM Kafka cluster ID for the role binding. + --usm-connect-cluster string USM Connect cluster ID for the role binding. --resource string Resource type and identifier using "Prefix:ID" format. --prefix Whether the provided resource name is treated as a prefix pattern. -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") diff --git a/test/fixtures/output/iam/rbac/role-binding/delete-missing-role-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/delete-missing-role-cloud.golden index ca55f3598c..7f1e25a4d3 100644 --- a/test/fixtures/output/iam/rbac/role-binding/delete-missing-role-cloud.golden +++ b/test/fixtures/output/iam/rbac/role-binding/delete-missing-role-cloud.golden @@ -7,6 +7,10 @@ Delete the role "ResourceOwner" for the resource "Topic:my-topic" on the Kafka c $ confluent iam rbac role-binding delete --principal User:u-123456 --role ResourceOwner --environment env-123456 --kafka-cluster lkc-123456 --resource Topic:my-topic +Delete the role "UsmKafkaClusterAdmin" for the principal "User:u-123456" on the USM Kafka cluster "usmkc-123456" in the environment "env-123456": + + $ confluent iam rbac role-binding delete --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456 + Flags: --role string REQUIRED: Role name of the existing role binding. --principal string REQUIRED: Principal type and identifier using "Prefix:ID" format. @@ -18,6 +22,8 @@ Flags: --schema-registry-cluster string Schema Registry cluster ID for the role binding. --ksql-cluster string ksqlDB cluster name for the role binding. --flink-region string Flink region for the role binding, formatted as "cloud.region". + --usm-kafka-cluster string USM Kafka cluster ID for the role binding. + --usm-connect-cluster string USM Connect cluster ID for the role binding. --resource string Resource type and identifier using "Prefix:ID" format. --prefix Whether the provided resource name is treated as a prefix pattern. -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") diff --git a/test/fixtures/output/iam/rbac/role-binding/delete-usm-kafka-cluster-admin-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/delete-usm-kafka-cluster-admin-cloud.golden new file mode 100644 index 0000000000..cab9bc7f5f --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/delete-usm-kafka-cluster-admin-cloud.golden @@ -0,0 +1,6 @@ ++-----------+----------------------+ +| ID | rb-88hhh | +| Principal | User:u-11aaa | +| Email | u-11aaa@confluent.io | +| Role | UsmKafkaClusterAdmin | ++-----------+----------------------+ diff --git a/test/fixtures/output/iam/rbac/role-binding/list-failure-help-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/list-failure-help-cloud.golden index b3f8a39e1a..f3348a3843 100644 --- a/test/fixtures/output/iam/rbac/role-binding/list-failure-help-cloud.golden +++ b/test/fixtures/output/iam/rbac/role-binding/list-failure-help-cloud.golden @@ -19,6 +19,10 @@ List the role bindings for user "u-123456" with role "CloudClusterAdmin": $ confluent iam rbac role-binding list --principal User:u-123456 --role CloudClusterAdmin --environment env-123456 --cloud-cluster lkc-123456 +List the role bindings for user "u-123456" with role "UsmKafkaClusterAdmin" for the USM Kafka cluster "usmkc-123456": + + $ confluent iam rbac role-binding list --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456 + List the role bindings for user "u-123456" for all scopes: $ confluent iam rbac role-binding list --principal User:u-123456 --inclusive @@ -38,6 +42,8 @@ Flags: --schema-registry-cluster string Schema Registry cluster ID, which specifies the Schema Registry cluster scope. --ksql-cluster string ksqlDB cluster name, which specifies the ksqlDB cluster scope. --flink-region string Flink region for the role binding, formatted as "cloud.region". + --usm-kafka-cluster string USM Kafka cluster ID, which specifies the USM Kafka cluster scope. + --usm-connect-cluster string USM Connect cluster ID, which specifies the USM Connect cluster scope. --resource string Resource type and identifier using "Prefix:ID" format. If specified with "--role" and no principals, list all principals and role bindings. --inclusive List role bindings for specified scopes and nested scopes. Otherwise, list role bindings for the specified scopes. If scopes are unspecified, list only organization-scoped role bindings. -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") diff --git a/test/fixtures/output/iam/rbac/role-binding/list-help.golden b/test/fixtures/output/iam/rbac/role-binding/list-help.golden index 28a1de56b8..4ca9526130 100644 --- a/test/fixtures/output/iam/rbac/role-binding/list-help.golden +++ b/test/fixtures/output/iam/rbac/role-binding/list-help.golden @@ -20,6 +20,10 @@ List the role bindings for user "u-123456" with role "CloudClusterAdmin": $ confluent iam rbac role-binding list --principal User:u-123456 --role CloudClusterAdmin --environment env-123456 --cloud-cluster lkc-123456 +List the role bindings for user "u-123456" with role "UsmKafkaClusterAdmin" for the USM Kafka cluster "usmkc-123456": + + $ confluent iam rbac role-binding list --principal User:u-123456 --role UsmKafkaClusterAdmin --environment env-123456 --usm-kafka-cluster usmkc-123456 + List the role bindings for user "u-123456" for all scopes: $ confluent iam rbac role-binding list --principal User:u-123456 --inclusive @@ -39,6 +43,8 @@ Flags: --schema-registry-cluster string Schema Registry cluster ID, which specifies the Schema Registry cluster scope. --ksql-cluster string ksqlDB cluster name, which specifies the ksqlDB cluster scope. --flink-region string Flink region for the role binding, formatted as "cloud.region". + --usm-kafka-cluster string USM Kafka cluster ID, which specifies the USM Kafka cluster scope. + --usm-connect-cluster string USM Connect cluster ID, which specifies the USM Connect cluster scope. --resource string Resource type and identifier using "Prefix:ID" format. If specified with "--role" and no principals, list all principals and role bindings. --inclusive List role bindings for specified scopes and nested scopes. Otherwise, list role bindings for the specified scopes. If scopes are unspecified, list only organization-scoped role bindings. -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") diff --git a/test/fixtures/output/iam/rbac/role-binding/list-user-usm-connect-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/list-user-usm-connect-cloud.golden new file mode 100644 index 0000000000..cdcc3d6c2e --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/list-user-usm-connect-cloud.golden @@ -0,0 +1,3 @@ + ID | Principal | Email | Role | Environment | Cloud Cluster | Cluster Type | Logical Cluster | Resource Type | Name | Pattern Type +-----------+--------------+----------------------+------------------------+-------------+---------------+--------------+-----------------+---------------+------+--------------- + rb-99iii | User:u-11aaa | u-11aaa@confluent.io | UsmConnectClusterAdmin | env-596 | | USM Connect | usmcc-123456 | | | diff --git a/test/fixtures/output/iam/rbac/role-binding/list-user-usm-kafka-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/list-user-usm-kafka-cloud.golden new file mode 100644 index 0000000000..591815c01c --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/list-user-usm-kafka-cloud.golden @@ -0,0 +1,3 @@ + ID | Principal | Email | Role | Environment | Cloud Cluster | Cluster Type | Logical Cluster | Resource Type | Name | Pattern Type +-----------+--------------+----------------------+----------------------+-------------+---------------+--------------+-----------------+---------------+------+--------------- + rb-88hhh | User:u-11aaa | u-11aaa@confluent.io | UsmKafkaClusterAdmin | env-596 | | USM Kafka | usmkc-123456 | | | diff --git a/test/fixtures/output/iam/rbac/role-binding/list-usm-kafka-cluster-admin-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/list-usm-kafka-cluster-admin-cloud.golden new file mode 100644 index 0000000000..270e513297 --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/list-usm-kafka-cluster-admin-cloud.golden @@ -0,0 +1,3 @@ + Principal | Name | Email +---------------+--------+----------------------- + User:u-11aaa | 11 Aaa | u-11aaa@confluent.io diff --git a/test/fixtures/output/iam/rbac/role-binding/missing-usm-connect-cluster-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/missing-usm-connect-cluster-cloud.golden new file mode 100644 index 0000000000..b3944d05c0 --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/missing-usm-connect-cluster-cloud.golden @@ -0,0 +1 @@ +Error: must specify `--usm-connect-cluster` to indicate role binding scope diff --git a/test/fixtures/output/iam/rbac/role-binding/missing-usm-kafka-cluster-cloud.golden b/test/fixtures/output/iam/rbac/role-binding/missing-usm-kafka-cluster-cloud.golden new file mode 100644 index 0000000000..c1e638e903 --- /dev/null +++ b/test/fixtures/output/iam/rbac/role-binding/missing-usm-kafka-cluster-cloud.golden @@ -0,0 +1 @@ +Error: must specify `--usm-kafka-cluster` to indicate role binding scope diff --git a/test/iam_test.go b/test/iam_test.go index 964dad4e89..3c25aee4d5 100644 --- a/test/iam_test.go +++ b/test/iam_test.go @@ -51,6 +51,12 @@ func (s *CLITestSuite) TestIamRbacRoleBinding_Cloud() { {args: "iam rbac role-binding delete --principal User:u-11aaa --current-environment --cloud-cluster lkc-1111aaa", fixture: "iam/rbac/role-binding/delete-missing-role-cloud.golden", exitCode: 1}, {args: "iam rbac role-binding create --principal User:u-11aaa@confluent.io --role CloudClusterAdmin --current-environment --cloud-cluster lkc-1111aaa", fixture: "iam/rbac/role-binding/create-with-email-cloud.golden"}, {args: "iam rbac role-binding create --principal User:u-77ggg --role FlinkDeveloper --environment env-596 --flink-region aws.us-east-1 --resource ComputePool:lfcp-1111aaa", fixture: "iam/rbac/role-binding/create-flink-developer-cloud.golden"}, + {args: "iam rbac role-binding create --principal User:u-11aaa --role UsmKafkaClusterAdmin --environment env-596 --usm-kafka-cluster usmkc-123456", fixture: "iam/rbac/role-binding/create-usm-kafka-cluster-admin-cloud.golden"}, + {args: "iam rbac role-binding create --principal User:u-11aaa --role UsmConnectClusterAdmin --environment env-596 --usm-connect-cluster usmcc-123456", fixture: "iam/rbac/role-binding/create-usm-connect-cluster-admin-cloud.golden"}, + {args: "iam rbac role-binding create --principal User:u-11aaa --role UsmKafkaClusterAdmin --environment env-596", fixture: "iam/rbac/role-binding/missing-usm-kafka-cluster-cloud.golden", exitCode: 1}, + {args: "iam rbac role-binding create --principal User:u-11aaa --role UsmConnectClusterAdmin --environment env-596", fixture: "iam/rbac/role-binding/missing-usm-connect-cluster-cloud.golden", exitCode: 1}, + {args: "iam rbac role-binding create --principal User:u-11aaa --role UsmKafkaClusterAdmin --usm-kafka-cluster usmkc-123456", fixture: "iam/rbac/role-binding/missing-environment-cloud.golden", exitCode: 1}, + {args: "iam rbac role-binding delete --principal User:u-11aaa --role UsmKafkaClusterAdmin --environment env-596 --usm-kafka-cluster usmkc-123456 --force", fixture: "iam/rbac/role-binding/delete-usm-kafka-cluster-admin-cloud.golden"}, } for _, test := range tests { @@ -80,6 +86,9 @@ func (s *CLITestSuite) TestIamRbacRoleBindingList_Cloud() { {args: "iam rbac role-binding list --environment env-596 --cloud-cluster lkc-1111aaa --role InvalidOrgAdmin", fixture: "iam/rbac/role-binding/list-invalid-role-error-type-1-cloud.golden", exitCode: 1}, {args: "iam rbac role-binding list --environment env-596 --cloud-cluster lkc-1111aaa --role InvalidMetricsViewer", fixture: "iam/rbac/role-binding/list-invalid-role-error-type-2-cloud.golden", exitCode: 1}, {args: "iam rbac role-binding list --role FlinkDeveloper --environment env-596 --flink-region aws.us-east-1 --resource ComputePool:lfcp-1111aaa", fixture: "iam/rbac/role-binding/list-flink-developer-cloud.golden"}, + {args: "iam rbac role-binding list --environment env-596 --usm-kafka-cluster usmkc-123456 --role UsmKafkaClusterAdmin", fixture: "iam/rbac/role-binding/list-usm-kafka-cluster-admin-cloud.golden"}, + {args: "iam rbac role-binding list --environment env-596 --usm-kafka-cluster usmkc-123456 --principal User:u-11aaa", fixture: "iam/rbac/role-binding/list-user-usm-kafka-cloud.golden"}, + {args: "iam rbac role-binding list --environment env-596 --usm-connect-cluster usmcc-123456 --principal User:u-11aaa", fixture: "iam/rbac/role-binding/list-user-usm-connect-cloud.golden"}, } for _, test := range tests { diff --git a/test/test-server/iam_handlers.go b/test/test-server/iam_handlers.go index 6602de6906..b7085a7bef 100644 --- a/test/test-server/iam_handlers.go +++ b/test/test-server/iam_handlers.go @@ -57,6 +57,10 @@ var ( "crn://confluent.cloud/organization=abc-123/environment=env-596/schema-registry=lsrc-3333ccc/subject=clicks"), buildRoleBinding("rb-777gg", "u-777gg", "FlinkDeveloper", "crn://confluent.cloud/organization=abc-123/environment=env-596/flink-region=aws.us-east-1/compute-pool=lfcp-1111aaa"), + buildRoleBinding("rb-88hhh", "u-11aaa", "UsmKafkaClusterAdmin", + "crn://confluent.cloud/organization=abc-123/environment=env-596/usm-kafka-cluster=usmkc-123456"), + buildRoleBinding("rb-99iii", "u-11aaa", "UsmConnectClusterAdmin", + "crn://confluent.cloud/organization=abc-123/environment=env-596/usm-connect-cluster=usmcc-123456"), } )