Skip to content

Commit f54d336

Browse files
authored
Fix edge cases for databricks_permissions resource (#2158)
1 parent f2552ba commit f54d336

File tree

2 files changed

+123
-32
lines changed

2 files changed

+123
-32
lines changed

permissions/resource_permissions.go

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import (
1212
"github.com/databricks/databricks-sdk-go/apierr"
1313
"github.com/databricks/terraform-provider-databricks/common"
1414

15-
"github.com/hashicorp/go-cty/cty"
16-
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1715
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1816
)
1917

@@ -170,7 +168,7 @@ func (a PermissionsAPI) put(objectID string, objectACL AccessControlChangeList)
170168

171169
// Update updates object permissions. Technically, it's using method named SetOrDelete, but here we do more
172170
func (a PermissionsAPI) Update(objectID string, objectACL AccessControlChangeList) error {
173-
if objectID == "/authorization/tokens" || objectID == "/registered-models/root" {
171+
if objectID == "/authorization/tokens" || objectID == "/registered-models/root" || objectID == "/directories/0" {
174172
// Prevent "Cannot change permissions for group 'admins' to None."
175173
objectACL.AccessControlList = append(objectACL.AccessControlList, AccessControlChange{
176174
GroupName: "admins",
@@ -372,23 +370,6 @@ func ResourcePermissions() *schema.Resource {
372370
}
373371
}
374372
s["access_control"].MinItems = 1
375-
if groupNameSchema, err := common.SchemaPath(s,
376-
"access_control", "group_name"); err == nil {
377-
groupNameSchema.ValidateDiagFunc = func(i any, p cty.Path) diag.Diagnostics {
378-
if v, ok := i.(string); ok {
379-
if strings.ToLower(v) == "admins" {
380-
return diag.Diagnostics{
381-
{
382-
Summary: "It is not possible to restrict any permissions from `admins`.",
383-
Severity: diag.Error,
384-
AttributePath: p,
385-
},
386-
}
387-
}
388-
}
389-
return nil
390-
}
391-
}
392373
return s
393374
})
394375
return common.Resource{
@@ -447,22 +428,27 @@ func ResourcePermissions() *schema.Resource {
447428
if err != nil {
448429
return err
449430
}
450-
// this logic was moved from CustomizeDiff because of undeterministic auth behavior
451-
// in the corner-case scenarios.
452-
// see https://github.com/databricks/terraform-provider-databricks/issues/2052
453-
for _, v := range entity.AccessControlList {
454-
if v.UserName == me.UserName {
455-
format := "it is not possible to decrease administrative permissions for the current user: %s"
456-
return fmt.Errorf(format, me.UserName)
457-
}
458-
}
459431
for _, mapping := range permissionsResourceIDFields() {
460432
if v, ok := d.GetOk(mapping.field); ok {
461433
id, err := mapping.idRetriever(ctx, w, v.(string))
462434
if err != nil {
463435
return err
464436
}
465437
objectID := fmt.Sprintf("/%s/%s", mapping.resourceType, id)
438+
// this logic was moved from CustomizeDiff because of undeterministic auth behavior
439+
// in the corner-case scenarios.
440+
// see https://github.com/databricks/terraform-provider-databricks/issues/2052
441+
for _, v := range entity.AccessControlList {
442+
if v.UserName == me.UserName {
443+
format := "it is not possible to decrease administrative permissions for the current user: %s"
444+
return fmt.Errorf(format, me.UserName)
445+
}
446+
447+
if v.GroupName == "admins" && mapping.resourceType != "authorization" {
448+
// should allow setting admins permissions for passwords and tokens usage
449+
return fmt.Errorf("it is not possible to restrict any permissions from `admins`")
450+
}
451+
}
466452
err = NewPermissionsAPI(ctx, c).Update(objectID, AccessControlChangeList{
467453
AccessControlList: entity.AccessControlList,
468454
})

permissions/resource_permissions_test.go

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ func TestResourcePermissionsCreate_conflicting_fields(t *testing.T) {
668668

669669
func TestResourcePermissionsCreate_AdminsThrowError(t *testing.T) {
670670
_, err := qa.ResourceFixture{
671-
Fixtures: []qa.HTTPFixture{},
671+
Fixtures: []qa.HTTPFixture{me},
672672
Resource: ResourcePermissions(),
673673
Create: true,
674674
HCL: `
@@ -679,8 +679,7 @@ func TestResourcePermissionsCreate_AdminsThrowError(t *testing.T) {
679679
}
680680
`,
681681
}.Apply(t)
682-
assert.EqualError(t, err, "invalid config supplied. [access_control] "+
683-
"It is not possible to restrict any permissions from `admins`.")
682+
assert.EqualError(t, err, "it is not possible to restrict any permissions from `admins`")
684683
}
685684

686685
func TestResourcePermissionsCreate(t *testing.T) {
@@ -1590,3 +1589,109 @@ func TestResourcePermissionsCreate_DirectoryPath(t *testing.T) {
15901589
assert.Equal(t, TestingUser, firstElem["user_name"])
15911590
assert.Equal(t, "CAN_READ", firstElem["permission_level"])
15921591
}
1592+
1593+
func TestResourcePermissionsPasswordUsage(t *testing.T) {
1594+
d, err := qa.ResourceFixture{
1595+
Fixtures: []qa.HTTPFixture{
1596+
me,
1597+
{
1598+
Method: http.MethodPut,
1599+
Resource: "/api/2.0/permissions/authorization/passwords",
1600+
ExpectedRequest: AccessControlChangeList{
1601+
AccessControlList: []AccessControlChange{
1602+
{
1603+
GroupName: "admins",
1604+
PermissionLevel: "CAN_USE",
1605+
},
1606+
},
1607+
},
1608+
},
1609+
{
1610+
Method: http.MethodGet,
1611+
Resource: "/api/2.0/permissions/authorization/passwords",
1612+
Response: ObjectACL{
1613+
ObjectID: "/authorization/passwords",
1614+
ObjectType: "passwords",
1615+
AccessControlList: []AccessControl{
1616+
{
1617+
GroupName: "admins",
1618+
PermissionLevel: "CAN_USE",
1619+
},
1620+
},
1621+
},
1622+
},
1623+
},
1624+
Resource: ResourcePermissions(),
1625+
HCL: `
1626+
authorization = "passwords"
1627+
access_control {
1628+
group_name = "admins"
1629+
permission_level = "CAN_USE"
1630+
}
1631+
`,
1632+
Create: true,
1633+
}.Apply(t)
1634+
assert.NoError(t, err)
1635+
ac := d.Get("access_control").(*schema.Set)
1636+
require.Equal(t, 1, len(ac.List()))
1637+
firstElem := ac.List()[0].(map[string]any)
1638+
assert.Equal(t, "admins", firstElem["group_name"])
1639+
assert.Equal(t, "CAN_USE", firstElem["permission_level"])
1640+
}
1641+
1642+
func TestResourcePermissionsRootDirectory(t *testing.T) {
1643+
d, err := qa.ResourceFixture{
1644+
Fixtures: []qa.HTTPFixture{
1645+
me,
1646+
{
1647+
Method: http.MethodPut,
1648+
Resource: "/api/2.0/permissions/directories/0",
1649+
ExpectedRequest: AccessControlChangeList{
1650+
AccessControlList: []AccessControlChange{
1651+
{
1652+
UserName: TestingUser,
1653+
PermissionLevel: "CAN_READ",
1654+
},
1655+
{
1656+
GroupName: "admins",
1657+
PermissionLevel: "CAN_MANAGE",
1658+
},
1659+
},
1660+
},
1661+
},
1662+
{
1663+
Method: http.MethodGet,
1664+
Resource: "/api/2.0/permissions/directories/0",
1665+
Response: ObjectACL{
1666+
ObjectID: "/directories/0",
1667+
ObjectType: "directory",
1668+
AccessControlList: []AccessControl{
1669+
{
1670+
UserName: TestingUser,
1671+
PermissionLevel: "CAN_READ",
1672+
},
1673+
{
1674+
GroupName: "admins",
1675+
PermissionLevel: "CAN_MANAGE",
1676+
},
1677+
},
1678+
},
1679+
},
1680+
},
1681+
Resource: ResourcePermissions(),
1682+
HCL: `
1683+
directory_id = "0"
1684+
access_control {
1685+
user_name = "ben"
1686+
permission_level = "CAN_READ"
1687+
}
1688+
`,
1689+
Create: true,
1690+
}.Apply(t)
1691+
assert.NoError(t, err)
1692+
ac := d.Get("access_control").(*schema.Set)
1693+
require.Equal(t, 1, len(ac.List()))
1694+
firstElem := ac.List()[0].(map[string]any)
1695+
assert.Equal(t, TestingUser, firstElem["user_name"])
1696+
assert.Equal(t, "CAN_READ", firstElem["permission_level"])
1697+
}

0 commit comments

Comments
 (0)