Skip to content

Commit 719e774

Browse files
authored
databricks_secret_scope: make initial_manage_principal empty by default
1 parent c2dc11f commit 719e774

File tree

5 files changed

+110
-33
lines changed

5 files changed

+110
-33
lines changed

access/acceptance/secret_acl_test.go

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
. "github.com/databrickslabs/databricks-terraform/access"
10+
"github.com/databrickslabs/databricks-terraform/identity"
1011

1112
"github.com/databrickslabs/databricks-terraform/common"
1213
"github.com/databrickslabs/databricks-terraform/internal/acceptance"
@@ -26,6 +27,9 @@ func TestAccSecretAclResource(t *testing.T) {
2627
scope := fmt.Sprintf("tf-scope-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
2728
principal := "users"
2829
permission := "READ"
30+
client := common.CommonEnvironmentClient()
31+
me, _ := identity.NewUsersAPI(client).Me()
32+
userName := me.UserName
2933

3034
acceptance.AccTest(t, resource.TestCase{
3135
CheckDestroy: testSecretACLResourceDestroy,
@@ -35,6 +39,8 @@ func TestAccSecretAclResource(t *testing.T) {
3539
Config: testSecretACLResource(scope, principal, permission),
3640
// compose a basic test, checking both remote and local values
3741
Check: resource.ComposeTestCheckFunc(
42+
// test scope permissions - it should be current user
43+
testSecretScopeHasPrincipal(t, scope, userName, "MANAGE"),
3844
// query the API to retrieve the tokenInfo object
3945
testSecretACLResourceExists("databricks_secret_acl.my_secret_acl", &secretACL, t),
4046
// verify remote values
@@ -69,6 +75,45 @@ func TestAccSecretAclResource(t *testing.T) {
6975
})
7076
}
7177

78+
// this test checks that any user has access when initial principal is set to 'users'
79+
func TestAccSecretAclResourceDefaultPrincipal(t *testing.T) {
80+
// TODO: refactor for common instance pool & AZ CLI
81+
if _, ok := os.LookupEnv("CLOUD_ENV"); !ok {
82+
t.Skip("Acceptance tests skipped unless env 'CLOUD_ENV' is set")
83+
}
84+
scope := fmt.Sprintf("tf-scope-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
85+
client := common.CommonEnvironmentClient()
86+
me, _ := identity.NewUsersAPI(client).Me()
87+
userName := me.UserName
88+
userPermission := "READ"
89+
initialPrincipal := "users"
90+
initialPermission := "MANAGE"
91+
var secretACL ACLItem
92+
93+
acceptance.AccTest(t, resource.TestCase{
94+
CheckDestroy: testSecretACLResourceDestroy,
95+
Steps: []resource.TestStep{
96+
{
97+
// use a dynamic configuration with the random name from above
98+
Config: testSecretACLResourceWithDefaultPrincipal(scope, initialPrincipal, userName, userPermission),
99+
// compose a basic test, checking both remote and local values
100+
Check: resource.ComposeTestCheckFunc(
101+
// test scope permissions - it should be users
102+
testSecretScopeHasPrincipal(t, scope, initialPrincipal, initialPermission),
103+
// query the API to retrieve the tokenInfo object
104+
testSecretACLResourceExists("databricks_secret_acl.my_secret_acl", &secretACL, t),
105+
// verify remote values
106+
testSecretACLValues(t, &secretACL, userPermission, userName),
107+
// verify local values
108+
resource.TestCheckResourceAttr("databricks_secret_acl.my_secret_acl", "scope", scope),
109+
resource.TestCheckResourceAttr("databricks_secret_acl.my_secret_acl", "principal", userName),
110+
resource.TestCheckResourceAttr("databricks_secret_acl.my_secret_acl", "permission", userPermission),
111+
),
112+
},
113+
},
114+
})
115+
}
116+
72117
func testSecretACLResourceDestroy(s *terraform.State) error {
73118
client := common.CommonEnvironmentClient()
74119
for _, rs := range s.RootModule().Resources {
@@ -89,12 +134,37 @@ func testSecretACLResourceDestroy(s *terraform.State) error {
89134

90135
func testSecretACLValues(t *testing.T, acl *ACLItem, permission, principal string) resource.TestCheckFunc {
91136
return func(s *terraform.State) error {
92-
assert.True(t, acl.Permission == ACLPermissionRead)
93-
assert.True(t, acl.Principal == principal)
137+
assert.EqualValues(t, permission, acl.Permission)
138+
assert.EqualValues(t, principal, acl.Principal)
94139
return nil
95140
}
96141
}
97142

143+
func testSecretScopeHasPrincipal(t *testing.T, scope, principal, permission string) resource.TestCheckFunc {
144+
return func(s *terraform.State) error {
145+
var acl ACLItem
146+
err := getSecretACLResourceExistsForScopeAndPrincipal(scope, principal, &acl)
147+
if err != nil {
148+
return err
149+
}
150+
assert.EqualValues(t, permission, acl.Permission)
151+
assert.EqualValues(t, principal, acl.Principal)
152+
return nil
153+
}
154+
}
155+
156+
func getSecretACLResourceExistsForScopeAndPrincipal(scope, principal string, aclItem *ACLItem) error {
157+
// retrieve the configured client from the test setup
158+
conn := common.CommonEnvironmentClient()
159+
resp, err := NewSecretAclsAPI(conn).Read(scope, principal)
160+
if err != nil {
161+
return err
162+
}
163+
// If no error, assign the response Widget attribute to the widget pointer
164+
*aclItem = resp
165+
return nil
166+
}
167+
98168
// testAccCheckTokenResourceExists queries the API and retrieves the matching Widget.
99169
func testSecretACLResourceExists(n string, aclItem *ACLItem, t *testing.T) resource.TestCheckFunc {
100170
return func(s *terraform.State) error {
@@ -103,32 +173,36 @@ func testSecretACLResourceExists(n string, aclItem *ACLItem, t *testing.T) resou
103173
if !ok {
104174
return fmt.Errorf("Not found: %s", n)
105175
}
106-
107-
// retrieve the configured client from the test setup
108-
conn := common.CommonEnvironmentClient()
109-
resp, err := NewSecretAclsAPI(conn).Read(rs.Primary.Attributes["scope"], rs.Primary.Attributes["principal"])
110-
//t.Log(resp)
111-
if err != nil {
112-
return err
113-
}
114-
115-
// If no error, assign the response Widget attribute to the widget pointer
116-
*aclItem = resp
117-
return nil
118-
//return fmt.Errorf("Token (%s) not found", rs.Primary.ID)
176+
return getSecretACLResourceExistsForScopeAndPrincipal(rs.Primary.Attributes["scope"],
177+
rs.Primary.Attributes["principal"], aclItem)
119178
}
120179
}
121180

122181
// testAccTokenResource returns an configuration for an Example Widget with the provided name
123182
func testSecretACLResource(scopeName, principal, permission string) string {
124183
return fmt.Sprintf(`
125-
resource "databricks_secret_scope" "my_scope" {
126-
name = "%s"
127-
}
128-
resource "databricks_secret_acl" "my_secret_acl" {
129-
principal = "%s"
130-
permission = "%s"
131-
scope = databricks_secret_scope.my_scope.name
132-
}
133-
`, scopeName, principal, permission)
184+
resource "databricks_secret_scope" "my_scope" {
185+
name = "%s"
186+
}
187+
resource "databricks_secret_acl" "my_secret_acl" {
188+
principal = "%s"
189+
permission = "%s"
190+
scope = databricks_secret_scope.my_scope.name
191+
}
192+
`, scopeName, principal, permission)
193+
}
194+
195+
// testAccTokenResource returns an configuration for an Example Widget with the provided name
196+
func testSecretACLResourceWithDefaultPrincipal(scopeName, defaultPrincipal, principal, permission string) string {
197+
return fmt.Sprintf(`
198+
resource "databricks_secret_scope" "my_scope" {
199+
name = "%s"
200+
initial_manage_principal = "%s"
201+
}
202+
resource "databricks_secret_acl" "my_secret_acl" {
203+
principal = "%s"
204+
permission = "%s"
205+
scope = databricks_secret_scope.my_scope.name
206+
}
207+
`, scopeName, defaultPrincipal, principal, permission)
134208
}

access/resource_secret_scope.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ type SecretScopesAPI struct {
2121

2222
// Create creates a new secret scope
2323
func (a SecretScopesAPI) Create(scope string, initialManagePrincipal string) error {
24-
return a.C.Post("/secrets/scopes/create", map[string]string{
25-
"scope": scope,
26-
"initial_manage_principal": initialManagePrincipal,
27-
}, nil)
24+
paramsMap := map[string]string{
25+
"scope": scope,
26+
}
27+
if len(initialManagePrincipal) > 0 {
28+
paramsMap["initial_manage_principal"] = initialManagePrincipal
29+
}
30+
31+
return a.C.Post("/secrets/scopes/create", paramsMap, nil)
2832
}
2933

3034
// Delete deletes a secret scope
@@ -79,8 +83,6 @@ func ResourceSecretScope() *schema.Resource {
7983
Type: schema.TypeString,
8084
Optional: true,
8185
ForceNew: true,
82-
// or creator...
83-
Default: "users",
8486
},
8587
"backend_type": {
8688
Type: schema.TypeString,

access/resource_secret_scope_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestResourceSecretScopeRead(t *testing.T) {
3535
assert.NoError(t, err, err)
3636
assert.Equal(t, "abc", d.Id())
3737
assert.Equal(t, "DATABRICKS", d.Get("backend_type"))
38-
assert.Equal(t, "users", d.Get("initial_manage_principal"))
38+
assert.Equal(t, "", d.Get("initial_manage_principal"))
3939
assert.Equal(t, "abc", d.Get("name"))
4040
}
4141

docs/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
**Behavior changes**
1616
* State changes to legacy `spark.databricks.delta.preview.enabled` config option are [now ignored](https://github.com/databrickslabs/terraform-provider-databricks/pull/334) by `databricks_job` & `databricks_cluster`
1717
* Libraries, which are installed on all clusters and are not part of cluster resource definition, won't be waited for INSTALLED status
18+
* Fixed "[Secret scope ACL is MANAGE for all users by default](https://github.com/databrickslabs/terraform-provider-databricks/pull/326)" ([issue 322](https://github.com/databrickslabs/terraform-provider-databricks/issues/322)). If you were relying on setting `MANAGE` permission to all users by default, you need to add `initial_manage_principal = "users"` to your `resource "databricks_secret_scope"` declaration.
1819

1920
## 0.2.5
2021

docs/resources/secret_scope.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ resource "databricks_secret_scope" "my-scope" {
2323
The following arguments are supported:
2424

2525
* `name` - (Required) Scope name requested by the user. Scope names are unique. This field is required.
26-
* `initial_manage_principal` - (Optional) The principal that is initially granted `MANAGE` permission to the created scope. Defaults to `users`. Additional principals can be added with [databricks_secret_acl](secret_acl.md)
26+
* `initial_manage_principal` - (Optional) The principal that is initially granted `MANAGE` permission to the created scope. If it's omitted, then the initial ACL with `MANAGE` permission applied to the scope is assigned to the API request issuer's user identity (see [documentation](https://docs.databricks.com/dev-tools/api/latest/secrets.html#create-secret-scope)).
2727

2828
## Attribute Reference
2929

@@ -37,4 +37,4 @@ The resource secret scope can be imported using the scope name:
3737

3838
```bash
3939
$ terraform import databricks_secret_scope.object <scopeName>
40-
```
40+
```

0 commit comments

Comments
 (0)