diff --git a/access/resource_permissions.go b/access/resource_permissions.go index a692fb6e33..24ceedc8cb 100644 --- a/access/resource_permissions.go +++ b/access/resource_permissions.go @@ -14,6 +14,7 @@ import ( "github.com/databrickslabs/terraform-provider-databricks/workspace" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/pkg/errors" ) @@ -211,6 +212,8 @@ func (a PermissionsAPI) Read(objectID string) (objectACL ObjectACL, err error) { type permissionsIDFieldMapping struct { field, objectType, resourceType string + allowedPermissionLevels []string + idRetriever func(client *common.DatabricksClient, id string) (string, error) } @@ -227,20 +230,20 @@ func permissionsResourceIDFields(ctx context.Context) []permissionsIDFieldMappin return strconv.FormatInt(info.ObjectID, 10), nil } return []permissionsIDFieldMapping{ - {"cluster_policy_id", "cluster-policy", "cluster-policies", SIMPLE}, - {"instance_pool_id", "instance-pool", "instance-pools", SIMPLE}, - {"cluster_id", "cluster", "clusters", SIMPLE}, - {"job_id", "job", "jobs", SIMPLE}, - {"notebook_id", "notebook", "notebooks", SIMPLE}, - {"notebook_path", "notebook", "notebooks", PATH}, - {"directory_id", "directory", "directories", SIMPLE}, - {"directory_path", "directory", "directories", PATH}, - {"authorization", "tokens", "authorization", SIMPLE}, - {"authorization", "passwords", "authorization", SIMPLE}, - {"sql_endpoint_id", "endpoints", "sql/endpoints", SIMPLE}, - {"sql_dashboard_id", "dashboard", "sql/dashboards", SIMPLE}, - {"sql_alert_id", "alert", "sql/alerts", SIMPLE}, - {"sql_query_id", "query", "sql/queries", SIMPLE}, + {"cluster_policy_id", "cluster-policy", "cluster-policies", []string{"CAN_USE"}, SIMPLE}, + {"instance_pool_id", "instance-pool", "instance-pools", []string{"CAN_ATTACH_TO", "CAN_MANAGE"}, SIMPLE}, + {"cluster_id", "cluster", "clusters", []string{"CAN_ATTACH_TO", "CAN_RESTART", "CAN_MANAGE"}, SIMPLE}, + {"job_id", "job", "jobs", []string{"CAN_VIEW", "CAN_MANAGE_RUN", "IS_OWNER", "CAN_MANAGE"}, SIMPLE}, + {"notebook_id", "notebook", "notebooks", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, + {"notebook_path", "notebook", "notebooks", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, + {"directory_id", "directory", "directories", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, + {"directory_path", "directory", "directories", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, + {"authorization", "tokens", "authorization", []string{"CAN_USE"}, SIMPLE}, + {"authorization", "passwords", "authorization", []string{"CAN_USE"}, SIMPLE}, + {"sql_endpoint_id", "endpoints", "sql/endpoints", []string{"CAN_USE", "CAN_MANAGE"}, SIMPLE}, + {"sql_dashboard_id", "dashboard", "sql/dashboards", []string{"CAN_USE", "CAN_MANAGE"}, SIMPLE}, + {"sql_alert_id", "alert", "sql/alerts", []string{"CAN_USE", "CAN_MANAGE"}, SIMPLE}, + {"sql_query_id", "query", "sql/queries", []string{"CAN_USE", "CAN_MANAGE"}, SIMPLE}, } } @@ -286,6 +289,15 @@ func (oa *ObjectACL) ToPermissionsEntity(ctx context.Context, d *schema.Resource return entity, fmt.Errorf("unknown object type %s", oa.ObjectType) } +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + // ResourcePermissions definition func ResourcePermissions() *schema.Resource { s := common.StructToSchema(PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { @@ -353,7 +365,30 @@ func ResourcePermissions() *schema.Resource { return nil } return &schema.Resource{ - Schema: s, + Schema: s, + CustomizeDiff: customdiff.Sequence( + func(ctx context.Context, diff *schema.ResourceDiff, v interface{}) error { + // Plan time validation for object permission levels + for _, mapping := range permissionsResourceIDFields(ctx) { + if _, ok := diff.GetOk(mapping.field); !ok { + continue + } + + access_control_list := diff.Get("access_control").(*schema.Set).List() + for _, access_control := range access_control_list { + m := access_control.(map[string]interface{}) + + permission_level := m["permission_level"].(string) + + if !stringInSlice(permission_level, mapping.allowedPermissionLevels) { + return fmt.Errorf(`permission_level %s is not supported with %s objects`, permission_level, mapping.field) + } + } + } + + return nil + }, + ), ReadContext: readContext, CreateContext: func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var entity PermissionsEntity diff --git a/access/resource_permissions_test.go b/access/resource_permissions_test.go index 796342f1e6..a64a0d27d6 100644 --- a/access/resource_permissions_test.go +++ b/access/resource_permissions_test.go @@ -368,7 +368,7 @@ func TestResourcePermissionsCreate(t *testing.T) { AccessControlList: []AccessControlChange{ { UserName: TestingUser, - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_ATTACH_TO", }, }, }, @@ -384,7 +384,7 @@ func TestResourcePermissionsCreate(t *testing.T) { UserName: TestingUser, AllPermissions: []Permission{ { - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_ATTACH_TO", Inherited: false, }, }, @@ -415,7 +415,7 @@ func TestResourcePermissionsCreate(t *testing.T) { "access_control": []interface{}{ map[string]interface{}{ "user_name": TestingUser, - "permission_level": "CAN_READ", + "permission_level": "CAN_ATTACH_TO", }, }, }, @@ -426,7 +426,7 @@ func TestResourcePermissionsCreate(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]interface{}) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_READ", firstElem["permission_level"]) + assert.Equal(t, "CAN_ATTACH_TO", firstElem["permission_level"]) } func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { @@ -439,7 +439,7 @@ func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { AccessControlList: []AccessControlChange{ { UserName: TestingUser, - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_USE", }, { UserName: TestingAdminUser, @@ -457,7 +457,7 @@ func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { AccessControlList: []AccessControl{ { UserName: TestingUser, - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_USE", }, { UserName: TestingAdminUser, @@ -481,7 +481,7 @@ func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { "access_control": []interface{}{ map[string]interface{}{ "user_name": TestingUser, - "permission_level": "CAN_READ", + "permission_level": "CAN_USE", }, }, }, @@ -492,7 +492,7 @@ func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]interface{}) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_READ", firstElem["permission_level"]) + assert.Equal(t, "CAN_USE", firstElem["permission_level"]) } func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { @@ -505,7 +505,7 @@ func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { AccessControlList: []AccessControlChange{ { UserName: TestingUser, - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_USE", }, { UserName: TestingAdminUser, @@ -523,7 +523,7 @@ func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { AccessControlList: []AccessControl{ { UserName: TestingUser, - PermissionLevel: "CAN_READ", + PermissionLevel: "CAN_USE", }, { UserName: TestingAdminUser, @@ -547,7 +547,7 @@ func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { "access_control": []interface{}{ map[string]interface{}{ "user_name": TestingUser, - "permission_level": "CAN_READ", + "permission_level": "CAN_USE", }, }, }, @@ -558,7 +558,7 @@ func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]interface{}) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_READ", firstElem["permission_level"]) + assert.Equal(t, "CAN_USE", firstElem["permission_level"]) } func TestResourcePermissionsCreate_NotebookPath_NotExists(t *testing.T) { @@ -608,7 +608,7 @@ func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { AccessControlList: []AccessControlChange{ { UserName: TestingUser, - PermissionLevel: "CAN_USE", + PermissionLevel: "CAN_READ", }, }, }, @@ -624,7 +624,7 @@ func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { UserName: TestingUser, AllPermissions: []Permission{ { - PermissionLevel: "CAN_USE", + PermissionLevel: "CAN_READ", Inherited: false, }, }, @@ -655,7 +655,7 @@ func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { "access_control": []interface{}{ map[string]interface{}{ "user_name": TestingUser, - "permission_level": "CAN_USE", + "permission_level": "CAN_READ", }, }, }, @@ -667,7 +667,7 @@ func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]interface{}) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_USE", firstElem["permission_level"]) + assert.Equal(t, "CAN_READ", firstElem["permission_level"]) } func TestResourcePermissionsCreate_error(t *testing.T) { @@ -716,7 +716,7 @@ func TestResourcePermissionsUpdate(t *testing.T) { UserName: TestingUser, AllPermissions: []Permission{ { - PermissionLevel: "CAN_RUN", + PermissionLevel: "CAN_VIEW", Inherited: false, }, }, @@ -748,7 +748,7 @@ func TestResourcePermissionsUpdate(t *testing.T) { AccessControlList: []AccessControlChange{ { UserName: TestingUser, - PermissionLevel: "CAN_RUN", + PermissionLevel: "CAN_VIEW", }, { UserName: TestingAdminUser, @@ -763,7 +763,7 @@ func TestResourcePermissionsUpdate(t *testing.T) { access_control { user_name = "ben" - permission_level = "CAN_RUN" + permission_level = "CAN_VIEW" } `, Resource: ResourcePermissions(), @@ -776,7 +776,7 @@ func TestResourcePermissionsUpdate(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]interface{}) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_RUN", firstElem["permission_level"]) + assert.Equal(t, "CAN_VIEW", firstElem["permission_level"]) } func permissionsTestHelper(t *testing.T,