mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-07-09 03:28:29 +00:00
Change IAM binding to be authoritative (#2764)
<!-- This change is generated by MagicModules. --> /cc @chrisst
This commit is contained in:
parent
505cb42d01
commit
43d40f4065
|
@ -123,6 +123,25 @@ func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModify
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Takes a single binding and will either overwrite the same role in a list or append it to the end
|
||||||
|
func overwriteBinding(bindings []*cloudresourcemanager.Binding, overwrite *cloudresourcemanager.Binding) []*cloudresourcemanager.Binding {
|
||||||
|
var found bool
|
||||||
|
|
||||||
|
for i, b := range bindings {
|
||||||
|
if b.Role == overwrite.Role {
|
||||||
|
bindings[i] = overwrite
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
bindings = append(bindings, overwrite)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindings
|
||||||
|
}
|
||||||
|
|
||||||
// Merge multiple Bindings such that Bindings with the same Role result in
|
// Merge multiple Bindings such that Bindings with the same Role result in
|
||||||
// a single Binding with combined Members
|
// a single Binding with combined Members
|
||||||
func mergeBindings(bindings []*cloudresourcemanager.Binding) []*cloudresourcemanager.Binding {
|
func mergeBindings(bindings []*cloudresourcemanager.Binding) []*cloudresourcemanager.Binding {
|
||||||
|
|
|
@ -169,6 +169,62 @@ func testAccCheckGoogleProjectIamPolicyExists(projectRes, policyRes, pid string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIamOverwriteBinding(t *testing.T) {
|
||||||
|
table := []struct {
|
||||||
|
input []*cloudresourcemanager.Binding
|
||||||
|
override cloudresourcemanager.Binding
|
||||||
|
expect []cloudresourcemanager.Binding
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []*cloudresourcemanager.Binding{
|
||||||
|
{
|
||||||
|
Role: "role-1",
|
||||||
|
Members: []string{"member-1", "member-2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
override: cloudresourcemanager.Binding{
|
||||||
|
Role: "role-1",
|
||||||
|
Members: []string{"new-member"},
|
||||||
|
},
|
||||||
|
expect: []cloudresourcemanager.Binding{
|
||||||
|
{
|
||||||
|
Role: "role-1",
|
||||||
|
Members: []string{"new-member"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []*cloudresourcemanager.Binding{
|
||||||
|
{
|
||||||
|
Role: "role-1",
|
||||||
|
Members: []string{"member-1", "member-2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
override: cloudresourcemanager.Binding{
|
||||||
|
Role: "role-2",
|
||||||
|
Members: []string{"member-3"},
|
||||||
|
},
|
||||||
|
expect: []cloudresourcemanager.Binding{
|
||||||
|
{
|
||||||
|
Role: "role-1",
|
||||||
|
Members: []string{"member-1", "member-2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Role: "role-2",
|
||||||
|
Members: []string{"member-3"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range table {
|
||||||
|
got := overwriteBinding(test.input, &test.override)
|
||||||
|
if !reflect.DeepEqual(derefBindings(got), test.expect) {
|
||||||
|
t.Errorf("OverwriteIamBinding failed.\nGot %+v\nWant %+v", derefBindings(got), test.expect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIamMergeBindings(t *testing.T) {
|
func TestIamMergeBindings(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input []*cloudresourcemanager.Binding
|
input []*cloudresourcemanager.Binding
|
||||||
|
@ -178,26 +234,17 @@ func TestIamMergeBindings(t *testing.T) {
|
||||||
input: []*cloudresourcemanager.Binding{
|
input: []*cloudresourcemanager.Binding{
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-1", "member-2"},
|
||||||
"member-1",
|
|
||||||
"member-2",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-3"},
|
||||||
"member-3",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expect: []cloudresourcemanager.Binding{
|
expect: []cloudresourcemanager.Binding{
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-1", "member-2", "member-3"},
|
||||||
"member-1",
|
|
||||||
"member-2",
|
|
||||||
"member-3",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -205,67 +252,42 @@ func TestIamMergeBindings(t *testing.T) {
|
||||||
input: []*cloudresourcemanager.Binding{
|
input: []*cloudresourcemanager.Binding{
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-3", "member-4"},
|
||||||
"member-3",
|
|
||||||
"member-4",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-2", "member-1"},
|
||||||
"member-2",
|
|
||||||
"member-1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-2",
|
Role: "role-2",
|
||||||
Members: []string{
|
Members: []string{"member-1"},
|
||||||
"member-1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-5"},
|
||||||
"member-5",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-3",
|
Role: "role-3",
|
||||||
Members: []string{
|
Members: []string{"member-1"},
|
||||||
"member-1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-2",
|
Role: "role-2",
|
||||||
Members: []string{
|
Members: []string{"member-2"},
|
||||||
"member-2",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{Role: "empty-role", Members: []string{}},
|
{Role: "empty-role", Members: []string{}},
|
||||||
},
|
},
|
||||||
expect: []cloudresourcemanager.Binding{
|
expect: []cloudresourcemanager.Binding{
|
||||||
{
|
{
|
||||||
Role: "role-1",
|
Role: "role-1",
|
||||||
Members: []string{
|
Members: []string{"member-1", "member-2", "member-3", "member-4", "member-5"},
|
||||||
"member-1",
|
|
||||||
"member-2",
|
|
||||||
"member-3",
|
|
||||||
"member-4",
|
|
||||||
"member-5",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-2",
|
Role: "role-2",
|
||||||
Members: []string{
|
Members: []string{"member-1", "member-2"},
|
||||||
"member-1",
|
|
||||||
"member-2",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "role-3",
|
Role: "role-3",
|
||||||
Members: []string{
|
Members: []string{"member-1"},
|
||||||
"member-1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,9 +31,9 @@ var iamBindingSchema = map[string]*schema.Schema{
|
||||||
|
|
||||||
func ResourceIamBinding(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc) *schema.Resource {
|
func ResourceIamBinding(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc) *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
Create: resourceIamBindingCreate(newUpdaterFunc),
|
Create: resourceIamBindingCreateUpdate(newUpdaterFunc),
|
||||||
Read: resourceIamBindingRead(newUpdaterFunc),
|
Read: resourceIamBindingRead(newUpdaterFunc),
|
||||||
Update: resourceIamBindingUpdate(newUpdaterFunc),
|
Update: resourceIamBindingCreateUpdate(newUpdaterFunc),
|
||||||
Delete: resourceIamBindingDelete(newUpdaterFunc),
|
Delete: resourceIamBindingDelete(newUpdaterFunc),
|
||||||
Schema: mergeSchemas(iamBindingSchema, parentSpecificSchema),
|
Schema: mergeSchemas(iamBindingSchema, parentSpecificSchema),
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func ResourceIamBindingWithImport(parentSpecificSchema map[string]*schema.Schema
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceIamBindingCreate(newUpdaterFunc newResourceIamUpdaterFunc) schema.CreateFunc {
|
func resourceIamBindingCreateUpdate(newUpdaterFunc newResourceIamUpdaterFunc) func(*schema.ResourceData, interface{}) error {
|
||||||
return func(d *schema.ResourceData, meta interface{}) error {
|
return func(d *schema.ResourceData, meta interface{}) error {
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
updater, err := newUpdaterFunc(d, config)
|
updater, err := newUpdaterFunc(d, config)
|
||||||
|
@ -57,11 +57,7 @@ func resourceIamBindingCreate(newUpdaterFunc newResourceIamUpdaterFunc) schema.C
|
||||||
|
|
||||||
p := getResourceIamBinding(d)
|
p := getResourceIamBinding(d)
|
||||||
err = iamPolicyReadModifyWrite(updater, func(ep *cloudresourcemanager.Policy) error {
|
err = iamPolicyReadModifyWrite(updater, func(ep *cloudresourcemanager.Policy) error {
|
||||||
// Creating a binding does not remove existing members if they are not in the provided members list.
|
ep.Bindings = overwriteBinding(ep.Bindings, p)
|
||||||
// This prevents removing existing permission without the user's knowledge.
|
|
||||||
// Instead, a diff is shown in that case after creation. Subsequent calls to update will remove any
|
|
||||||
// existing members not present in the provided list.
|
|
||||||
ep.Bindings = mergeBindings(append(ep.Bindings, p))
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -151,38 +147,6 @@ func iamBindingImport(resourceIdParser resourceIdParserFunc) schema.StateFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceIamBindingUpdate(newUpdaterFunc newResourceIamUpdaterFunc) schema.UpdateFunc {
|
|
||||||
return func(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
config := meta.(*Config)
|
|
||||||
updater, err := newUpdaterFunc(d, config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
binding := getResourceIamBinding(d)
|
|
||||||
err = iamPolicyReadModifyWrite(updater, func(p *cloudresourcemanager.Policy) error {
|
|
||||||
var found bool
|
|
||||||
for pos, b := range p.Bindings {
|
|
||||||
if b.Role != binding.Role {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = true
|
|
||||||
p.Bindings[pos] = binding
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
p.Bindings = append(p.Bindings, binding)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resourceIamBindingRead(newUpdaterFunc)(d, meta)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceIamBindingDelete(newUpdaterFunc newResourceIamUpdaterFunc) schema.DeleteFunc {
|
func resourceIamBindingDelete(newUpdaterFunc newResourceIamUpdaterFunc) schema.DeleteFunc {
|
||||||
return func(d *schema.ResourceData, meta interface{}) error {
|
return func(d *schema.ResourceData, meta interface{}) error {
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
|
@ -26,7 +26,7 @@ data "google_iam_policy" "admin" {
|
||||||
role = "roles/storage.objectViewer"
|
role = "roles/storage.objectViewer"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"user:jane@example.com",
|
"user:alice@gmail.com",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@ each accept the following arguments:
|
||||||
See the [IAM Roles](https://cloud.google.com/compute/docs/access/iam) documentation for a complete list of roles.
|
See the [IAM Roles](https://cloud.google.com/compute/docs/access/iam) documentation for a complete list of roles.
|
||||||
Note that custom roles must be of the format `[projects|organizations]/{parent-name}/roles/{role-name}`.
|
Note that custom roles must be of the format `[projects|organizations]/{parent-name}/roles/{role-name}`.
|
||||||
|
|
||||||
* `members` (Required) - An array of identites that will be granted the privilege in the `role`.
|
* `members` (Required) - An array of identites that will be granted the privilege in the `role`. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
Each entry can have one of the following values:
|
Each entry can have one of the following values:
|
||||||
* **allUsers**: A special identifier that represents anyone who is on the internet; with or without a Google account. It **can't** be used with the `google_project` resource.
|
* **allUsers**: A special identifier that represents anyone who is on the internet; with or without a Google account. It **can't** be used with the `google_project` resource.
|
||||||
* **allAuthenticatedUsers**: A special identifier that represents anyone who is authenticated with a Google account or a service account. It **can't** be used with the `google_project` resource.
|
* **allAuthenticatedUsers**: A special identifier that represents anyone who is authenticated with a Google account or a service account. It **can't** be used with the `google_project` resource.
|
||||||
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
|
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com.
|
||||||
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
||||||
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
|
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
|
||||||
* **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com.
|
* **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com.
|
||||||
|
|
|
@ -15,6 +15,10 @@ an existing Google Cloud Platform Billing Account.
|
||||||
`google_billing_account_iam_member` for the __same role__ or they will fight over
|
`google_billing_account_iam_member` for the __same role__ or they will fight over
|
||||||
what your policy should be.
|
what your policy should be.
|
||||||
|
|
||||||
|
~> **Note:** On create, this resource will overwrite members of any existing roles.
|
||||||
|
Use `terraform import` and inspect the `terraform plan` output to ensure
|
||||||
|
your existing members are preserved.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
@ -23,7 +27,7 @@ resource "google_billing_account_iam_binding" "binding" {
|
||||||
role = "roles/billing.viewer"
|
role = "roles/billing.viewer"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"user:jane@example.com",
|
"user:alice@gmail.com",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -36,7 +40,7 @@ The following arguments are supported:
|
||||||
|
|
||||||
* `role` - (Required) The role that should be applied.
|
* `role` - (Required) The role that should be applied.
|
||||||
|
|
||||||
* `members` - (Required) A list of users that the role should apply to.
|
* `members` - (Required) A list of users that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ the IAM policy for an existing Google Cloud Platform Billing Account.
|
||||||
resource "google_billing_account_iam_member" "binding" {
|
resource "google_billing_account_iam_member" "binding" {
|
||||||
billing_account_id = "00AA00-000AAA-00AA0A"
|
billing_account_id = "00AA00-000AAA-00AA0A"
|
||||||
role = "roles/billing.viewer"
|
role = "roles/billing.viewer"
|
||||||
member = "user:jane@example.com"
|
member = "user:alice@gmail.com"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ The following arguments are supported:
|
||||||
|
|
||||||
* `role` - (Required) The role that should be applied.
|
* `role` - (Required) The role that should be applied.
|
||||||
|
|
||||||
* `member` - (Required) The user that the role should apply to.
|
* `member` - (Required) The user that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@ an existing Google Cloud Platform folder.
|
||||||
`google_folder_iam_policy` or they will fight over what your policy
|
`google_folder_iam_policy` or they will fight over what your policy
|
||||||
should be.
|
should be.
|
||||||
|
|
||||||
|
~> **Note:** On create, this resource will overwrite members of any existing roles.
|
||||||
|
Use `terraform import` and inspect the `terraform plan` output to ensure
|
||||||
|
your existing members are preserved.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
@ -28,7 +32,7 @@ resource "google_folder_iam_binding" "admin" {
|
||||||
role = "roles/editor"
|
role = "roles/editor"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"user:jane@example.com",
|
"user:alice@gmail.com",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -41,10 +45,11 @@ The following arguments are supported:
|
||||||
|
|
||||||
* `members` (Required) - An array of identites that will be granted the privilege in the `role`.
|
* `members` (Required) - An array of identites that will be granted the privilege in the `role`.
|
||||||
Each entry can have one of the following values:
|
Each entry can have one of the following values:
|
||||||
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
|
* **user:{emailid}**: An email address that is associated with a specific Google account. For example, alice@gmail.com.
|
||||||
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
||||||
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
|
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
|
||||||
* **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com.
|
* **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com.
|
||||||
|
* For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
* `role` - (Required) The role that should be applied. Only one
|
* `role` - (Required) The role that should be applied. Only one
|
||||||
`google_folder_iam_binding` can be used per role. Note that custom roles must be of the format
|
`google_folder_iam_binding` can be used per role. Note that custom roles must be of the format
|
||||||
|
|
|
@ -27,7 +27,7 @@ resource "google_folder" "department1" {
|
||||||
resource "google_folder_iam_member" "admin" {
|
resource "google_folder_iam_member" "admin" {
|
||||||
folder = "${google_folder.department1.name}"
|
folder = "${google_folder.department1.name}"
|
||||||
role = "roles/editor"
|
role = "roles/editor"
|
||||||
member = "user:jane@example.com"
|
member = "user:alice@gmail.com"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ The following arguments are supported:
|
||||||
|
|
||||||
* `folder` - (Required) The resource name of the folder the policy is attached to. Its format is folders/{folder_id}.
|
* `folder` - (Required) The resource name of the folder the policy is attached to. Its format is folders/{folder_id}.
|
||||||
|
|
||||||
* `member` - (Required) The identity that will be granted the privilege in the `role`.
|
* `member` - (Required) The identity that will be granted the privilege in the `role`. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
This field can have one of the following values:
|
This field can have one of the following values:
|
||||||
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
|
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
|
||||||
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
|
||||||
|
|
|
@ -11,6 +11,10 @@ description: |-
|
||||||
Allows creation and management of a single binding within IAM policy for
|
Allows creation and management of a single binding within IAM policy for
|
||||||
an existing Google Cloud KMS crypto key.
|
an existing Google Cloud KMS crypto key.
|
||||||
|
|
||||||
|
~> **Note:** On create, this resource will overwrite members of any existing roles.
|
||||||
|
Use `terraform import` and inspect the `terraform plan` output to ensure
|
||||||
|
your existing members are preserved.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
@ -19,7 +23,7 @@ resource "google_kms_crypto_key_iam_binding" "crypto_key" {
|
||||||
role = "roles/editor"
|
role = "roles/editor"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"user:jane@example.com",
|
"user:alice@gmail.com",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -28,7 +32,7 @@ resource "google_kms_crypto_key_iam_binding" "crypto_key" {
|
||||||
|
|
||||||
The following arguments are supported:
|
The following arguments are supported:
|
||||||
|
|
||||||
* `members` - (Required) A list of users that the role should apply to.
|
* `members` - (Required) A list of users that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
* `role` - (Required) The role that should be applied. Only one
|
* `role` - (Required) The role that should be applied. Only one
|
||||||
`google_kms_crypto_key_iam_binding` can be used per role. Note that custom roles must be of the format
|
`google_kms_crypto_key_iam_binding` can be used per role. Note that custom roles must be of the format
|
||||||
|
|
|
@ -22,7 +22,7 @@ the IAM policy for an existing Google Cloud KMS crypto key.
|
||||||
resource "google_kms_crypto_key_iam_member" "crypto_key" {
|
resource "google_kms_crypto_key_iam_member" "crypto_key" {
|
||||||
crypto_key_id = "your-crypto-key-id"
|
crypto_key_id = "your-crypto-key-id"
|
||||||
role = "roles/editor"
|
role = "roles/editor"
|
||||||
member = "user:jane@example.com"
|
member = "user:alice@gmail.com"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ resource "google_kms_crypto_key_iam_member" "crypto_key" {
|
||||||
|
|
||||||
The following arguments are supported:
|
The following arguments are supported:
|
||||||
|
|
||||||
* `member` - (Required) The user that the role should apply to.
|
* `member` - (Required) The user that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
* `role` - (Required) The role that should be applied. Note that custom roles must be of the format
|
* `role` - (Required) The role that should be applied. Note that custom roles must be of the format
|
||||||
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
||||||
|
|
|
@ -15,6 +15,10 @@ an existing Google Cloud Platform Organization.
|
||||||
`google_organization_iam_member` for the __same role__ or they will fight over
|
`google_organization_iam_member` for the __same role__ or they will fight over
|
||||||
what your policy should be.
|
what your policy should be.
|
||||||
|
|
||||||
|
~> **Note:** On create, this resource will overwrite members of any existing roles.
|
||||||
|
Use `terraform import` and inspect the `terraform plan` output to ensure
|
||||||
|
your existing members are preserved.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
@ -23,7 +27,7 @@ resource "google_organization_iam_binding" "binding" {
|
||||||
role = "roles/browser"
|
role = "roles/browser"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"user:jane@example.com",
|
"user:alice@gmail.com",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -38,7 +42,7 @@ The following arguments are supported:
|
||||||
`google_organization_iam_binding` can be used per role. Note that custom roles must be of the format
|
`google_organization_iam_binding` can be used per role. Note that custom roles must be of the format
|
||||||
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
||||||
|
|
||||||
* `members` - (Required) A list of users that the role should apply to.
|
* `members` - (Required) A list of users that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ the IAM policy for an existing Google Cloud Platform Organization.
|
||||||
resource "google_organization_iam_member" "binding" {
|
resource "google_organization_iam_member" "binding" {
|
||||||
org_id = "0123456789"
|
org_id = "0123456789"
|
||||||
role = "roles/editor"
|
role = "roles/editor"
|
||||||
member = "user:jane@example.com"
|
member = "user:alice@gmail.com"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ The following arguments are supported:
|
||||||
* `role` - (Required) The role that should be applied. Note that custom roles must be of the format
|
* `role` - (Required) The role that should be applied. Note that custom roles must be of the format
|
||||||
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
`[projects|organizations]/{parent-name}/roles/{role-name}`.
|
||||||
|
|
||||||
* `member` - (Required) The user that the role should apply to.
|
* `member` - (Required) The user that the role should apply to. For more details on format and restrictions see https://cloud.google.com/billing/reference/rest/v1/Policy#Binding
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ Upgrade topics:
|
||||||
- [Resource: `google_sql_database_instance`](#resource-google_sql_database_instance)
|
- [Resource: `google_sql_database_instance`](#resource-google_sql_database_instance)
|
||||||
- [Resource: `google_storage_default_object_acl`](#resource-google_storage_default_object_acl)
|
- [Resource: `google_storage_default_object_acl`](#resource-google_storage_default_object_acl)
|
||||||
- [Resource: `google_storage_object_acl`](#resource-google_storage_object_acl)
|
- [Resource: `google_storage_object_acl`](#resource-google_storage_object_acl)
|
||||||
|
- [Resource: `google_*_iam_binding`](#google_*_iam_binding)
|
||||||
|
|
||||||
<!-- /TOC -->
|
<!-- /TOC -->
|
||||||
|
|
||||||
|
@ -663,3 +664,31 @@ values that were added outside of Terraform should be added to the config.
|
||||||
Terraform will remove values not explicitly set in this field. Any `role_entity`
|
Terraform will remove values not explicitly set in this field. Any `role_entity`
|
||||||
values that were added outside of Terraform should be added to the config.
|
values that were added outside of Terraform should be added to the config.
|
||||||
For fine-grained management, use `google_storage_object_access_control`.
|
For fine-grained management, use `google_storage_object_access_control`.
|
||||||
|
|
||||||
|
## Resource: `google_*_iam_binding`
|
||||||
|
|
||||||
|
### Create is now authoritative
|
||||||
|
|
||||||
|
Every `iam_binding` resource will overwrite the existing member list for a given
|
||||||
|
role on Create. Running `terraform plan` for the first time will not show members
|
||||||
|
that have been added via other tools. *To ensure existing `members` are preserved
|
||||||
|
use `terraform import` instead of creating the resource.*
|
||||||
|
|
||||||
|
Previous versions of `google_*_iam_binding` resources would merge the existing
|
||||||
|
members of a role with the members defined in the terraform config. If there was
|
||||||
|
a difference between the members defined in the config and the existing members
|
||||||
|
defined for an existing role it would show a diff if `terraform plan` was run
|
||||||
|
immediately after create had succeeded.
|
||||||
|
|
||||||
|
Affected resources:
|
||||||
|
* `google_billing_account_iam_binding`
|
||||||
|
* `google_folder_iam_binding`
|
||||||
|
* `google_kms_key_ring_iam_binding`
|
||||||
|
* `google_kms_crypto_key_iam_binding`
|
||||||
|
* `google_spanner_instance_iam_binding`
|
||||||
|
* `google_spanner_database_iam_binding`
|
||||||
|
* `google_organization_iam_binding`
|
||||||
|
* `google_project_iam_binding`
|
||||||
|
* `google_pubsub_topic_iam_binding`
|
||||||
|
* `google_pubsub_subscription_iam_binding`
|
||||||
|
* `google_service_account_iam_binding`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user