Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add IAM conditions support for project IAM #2575

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/terraform
2 changes: 1 addition & 1 deletion build/terraform-beta
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package google

import (
Expand Down Expand Up @@ -150,6 +151,10 @@ func resourceGoogleProjectIamPolicyImport(d *schema.ResourceData, meta interface
}

func setProjectIamPolicy(policy *cloudresourcemanager.Policy, config *Config, pid string) error {
<% unless version == 'ga' -%>
policy.Version = iamPolicyVersion

<% end -%>
// Apply the policy
pbytes, _ := json.Marshal(policy)
log.Printf("[DEBUG] Setting policy %#v for project: %s", string(pbytes), pid)
Expand All @@ -175,8 +180,17 @@ func getResourceIamPolicy(d *schema.ResourceData) (*cloudresourcemanager.Policy,

// Retrieve the existing IAM Policy for a Project
func getProjectIamPolicy(project string, config *Config) (*cloudresourcemanager.Policy, error) {
<% if version == 'ga' -%>
p, err := config.clientResourceManager.Projects.GetIamPolicy(project,
&cloudresourcemanager.GetIamPolicyRequest{}).Do()
<% else -%>
p, err := config.clientResourceManager.Projects.GetIamPolicy(project,
&cloudresourcemanager.GetIamPolicyRequest{
Options: &cloudresourcemanager.GetPolicyOptions{
RequestedPolicyVersion: iamPolicyVersion,
},
}).Do()
<% end -%>

if err != nil {
return nil, fmt.Errorf("Error retrieving IAM policy for project %q: %s", project, err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package google

import (
Expand Down Expand Up @@ -213,6 +214,41 @@ func TestAccProjectIamBinding_noMembers(t *testing.T) {
})
}

<% unless version == 'ga' -%>
func TestAccProjectIamBinding_withCondition(t *testing.T) {
t.Skipf("IAM Conditions is not whitelisted for new projects in this org, enable this test once it's public beta")
t.Parallel()

org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
role := "roles/compute.instanceAdmin"
conditionTitle := "expires_after_2019_12_31"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project
{
Config: testAccProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccProjectExistingPolicy(pid),
),
},
// Apply an IAM binding
{
Config: testAccProjectAssociateBinding_withCondition(pid, pname, org, role, conditionTitle),
},
{
ResourceName: "google_project_iam_binding.acceptance",
ImportStateId: fmt.Sprintf("%s %s %s", pid, role, conditionTitle),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
<% end -%>

func testAccProjectAssociateBindingBasic(pid, name, org, role string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
Expand Down Expand Up @@ -298,3 +334,26 @@ resource "google_project_iam_binding" "acceptance" {
}
`, pid, name, org, role)
}

<% unless version == 'ga' -%>
func testAccProjectAssociateBinding_withCondition(pid, name, org, role, conditionTitle string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
}

resource "google_project_iam_binding" "acceptance" {
project = "${google_project.acceptance.project_id}"
members = ["user:[email protected]"]
role = "%s"
condition {
title = "%s"
description = "Expiring at midnight of 2019-12-31"
expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")"
}
}
`, pid, name, org, role, conditionTitle)
}
<% end -%>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package google

import (
Expand Down Expand Up @@ -130,6 +131,43 @@ func TestAccProjectIamMember_remove(t *testing.T) {
})
}

<% unless version == 'ga' -%>
func TestAccProjectIamMember_withCondition(t *testing.T) {
t.Skipf("IAM Conditions is not whitelisted for new projects in this org, enable this test once it's public beta")
t.Parallel()

org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
resourceName := "google_project_iam_member.acceptance"
role := "roles/compute.instanceAdmin"
member := "user:[email protected]"
conditionTitle := "expires_after_2019_12_31"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project
{
Config: testAccProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccProjectExistingPolicy(pid),
),
},
// Apply an IAM binding
{
Config: testAccProjectAssociateMember_withCondition(pid, pname, org, role, member, conditionTitle),
},
{
ResourceName: resourceName,
ImportStateId: fmt.Sprintf("%s %s %s %s", pid, role, member, conditionTitle),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
<% end -%>

func testAccProjectAssociateMemberBasic(pid, name, org, role, member string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
Expand Down Expand Up @@ -167,3 +205,26 @@ resource "google_project_iam_member" "multiple" {
}
`, pid, name, org, role, member, role2, member2)
}

<% unless version == 'ga' -%>
func testAccProjectAssociateMember_withCondition(pid, name, org, role, member, conditionTitle string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
}

resource "google_project_iam_member" "acceptance" {
project = "${google_project.acceptance.project_id}"
role = "%s"
member = "%s"
condition {
title = "%s"
description = "Expiring at midnight of 2019-12-31"
expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")"
}
}
`, pid, name, org, role, member, conditionTitle)
}
<% end -%>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package google

import (
Expand Down Expand Up @@ -128,6 +129,38 @@ func TestAccProjectIamPolicy_expandedAuditConfig(t *testing.T) {
})
}

<% unless version == 'ga' -%>
func TestAccProjectIamPolicy_withCondition(t *testing.T) {
t.Skipf("IAM Conditions is not whitelisted for new projects in this org, enable this test once it's public beta")
t.Parallel()

org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project
{
Config: testAccProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccProjectExistingPolicy(pid),
),
},
// Apply an IAM policy from a data source. The application
// merges policies, so we validate the expected state.
{
Config: testAccProjectAssociatePolicy_withCondition(pid, pname, org),
},
{
ResourceName: "google_project_iam_policy.acceptance",
ImportState: true,
},
},
})
}
<% end -%>

func getStatePrimaryResource(s *terraform.State, res, expectedID string) (*terraform.InstanceState, error) {
// Get the project resource
resource, ok := s.RootModule().Resources[res]
Expand Down Expand Up @@ -393,3 +426,41 @@ data "google_iam_policy" "expanded" {
}
}`, pid, name, org)
}

<% unless version == 'ga' -%>
func testAccProjectAssociatePolicy_withCondition(pid, name, org string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
}

resource "google_project_iam_policy" "acceptance" {
project = "${google_project.acceptance.id}"
policy_data = "${data.google_iam_policy.admin.policy_data}"
}

data "google_iam_policy" "admin" {
binding {
role = "roles/storage.objectViewer"
members = [
"user:[email protected]",
]
}
binding {
role = "roles/compute.instanceAdmin"
members = [
"user:[email protected]",
"user:[email protected]",
]
condition {
title = "expires_after_2019_12_31"
description = "Expiring at midnight of 2019-12-31"
expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")"
}
}
}
`, pid, name, org)
}
<% end -%>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package google

import (
Expand Down Expand Up @@ -42,8 +43,17 @@ func ProjectIdParseFunc(d *schema.ResourceData, _ *Config) error {
}

func (u *ProjectIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
<% if version == 'ga' -%>
p, err := u.Config.clientResourceManager.Projects.GetIamPolicy(u.resourceId,
&cloudresourcemanager.GetIamPolicyRequest{}).Do()
<% else -%>
p, err := u.Config.clientResourceManager.Projects.GetIamPolicy(u.resourceId,
&cloudresourcemanager.GetIamPolicyRequest{
Options: &cloudresourcemanager.GetPolicyOptions{
RequestedPolicyVersion: iamPolicyVersion,
},
}).Do()
<% end -%>

if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err)
Expand Down
Loading