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

Access Approval custom signing key support #5865

Merged
merged 6 commits into from
Apr 4, 2022
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
55 changes: 55 additions & 0 deletions mmv1/products/accessapproval/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,25 @@ objects:
output: true
description: |
If the field is true, that indicates that at least one service is enrolled for Access Approval in one or more ancestors of the Folder.
- !ruby/object:Api::Type::String
name: activeKeyVersion
description: |
The asymmetric crypto key version to use for signing approval requests.
Empty active_key_version indicates that a Google-managed key should be used for signing.
This property will be ignored if set by an ancestor of the resource, and new non-empty values may not be set.
- !ruby/object:Api::Type::Boolean
name: ancestorHasActiveKeyVersion
output: true
description: |
If the field is true, that indicates that an ancestor of this Folder has set active_key_version.
- !ruby/object:Api::Type::Boolean
name: invalidKeyVersion
output: true
description: |
If the field is true, that indicates that there is some configuration issue with the active_key_version
configured on this Folder (e.g. it doesn't exist or the Access Approval service account doesn't have the
correct permissions on it, etc.) This key version is not necessarily the effective key version at this level,
as key versions are inherited top-down.
- !ruby/object:Api::Resource
name: ProjectSettings
base_url: "projects/{{project_id}}/accessApprovalSettings"
Expand Down Expand Up @@ -180,6 +199,25 @@ objects:
output: true
description: |
If the field is true, that indicates that at least one service is enrolled for Access Approval in one or more ancestors of the Project.
- !ruby/object:Api::Type::String
name: activeKeyVersion
description: |
The asymmetric crypto key version to use for signing approval requests.
Empty active_key_version indicates that a Google-managed key should be used for signing.
This property will be ignored if set by an ancestor of the resource, and new non-empty values may not be set.
- !ruby/object:Api::Type::Boolean
name: ancestorHasActiveKeyVersion
output: true
description: |
If the field is true, that indicates that an ancestor of this Project has set active_key_version.
- !ruby/object:Api::Type::Boolean
name: invalidKeyVersion
output: true
description: |
If the field is true, that indicates that there is some configuration issue with the active_key_version
configured on this Project (e.g. it doesn't exist or the Access Approval service account doesn't have the
correct permissions on it, etc.) This key version is not necessarily the effective key version at this level,
as key versions are inherited top-down.
- !ruby/object:Api::Type::String
name: project
description: |
Expand Down Expand Up @@ -256,3 +294,20 @@ objects:
output: true
description: |
This field will always be unset for the organization since organizations do not have ancestors.
- !ruby/object:Api::Type::String
name: activeKeyVersion
description: |
The asymmetric crypto key version to use for signing approval requests.
Empty active_key_version indicates that a Google-managed key should be used for signing.
- !ruby/object:Api::Type::Boolean
name: ancestorHasActiveKeyVersion
output: true
description: |
This field will always be unset for the organization since organizations do not have ancestors.
- !ruby/object:Api::Type::Boolean
name: invalidKeyVersion
output: true
description: |
If the field is true, that indicates that there is some configuration issue with the active_key_version
configured on this Organization (e.g. it doesn't exist or the Access Approval service account doesn't have the
correct permissions on it, etc.).
21 changes: 21 additions & 0 deletions mmv1/products/accessapproval/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ overrides: !ruby/object:Overrides::ResourceOverrides
folder_name: 'my-folder'
test_env_vars:
org_id: :ORG_ID
- !ruby/object:Provider::Terraform::Examples
skip_test: true
name: 'folder_access_approval_active_key_version'
primary_resource_id: 'folder_access_approval'
vars:
folder_name: 'my-folder'
test_env_vars:
org_id: :ORG_ID
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_delete: templates/terraform/custom_delete/clear_folder_access_approval_settings.go.erb
pre_create: templates/terraform/update_mask.erb
Expand All @@ -47,6 +55,13 @@ overrides: !ruby/object:Overrides::ResourceOverrides
test_env_vars:
project: :PROJECT_NAME
org_id: :ORG_ID
- !ruby/object:Provider::Terraform::Examples
skip_test: true
name: 'project_access_approval_active_key_version'
primary_resource_id: 'project_access_approval'
test_env_vars:
project: :PROJECT_NAME
org_id: :ORG_ID
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_delete: templates/terraform/custom_delete/clear_project_access_approval_settings.go.erb
pre_create: templates/terraform/update_mask.erb
Expand All @@ -67,6 +82,12 @@ overrides: !ruby/object:Overrides::ResourceOverrides
primary_resource_id: 'organization_access_approval'
test_env_vars:
org_id: :ORG_ID
- !ruby/object:Provider::Terraform::Examples
skip_test: true
name: 'organization_access_approval_active_key_version'
primary_resource_id: 'organization_access_approval'
test_env_vars:
org_id: :ORG_ID
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_delete: templates/terraform/custom_delete/clear_organization_access_approval_settings.go.erb
pre_create: templates/terraform/update_mask.erb
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
obj := make(map[string]interface{})
obj["notificationEmails"] = []string{}
obj["enrolledServices"] = []string{}
obj["activeKeyVersion"] = ""

url, err := replaceVars(d, config, "{{AccessApprovalBasePath}}folders/{{folder_id}}/accessApprovalSettings")
if err != nil {
Expand All @@ -12,6 +13,7 @@ updateMask := []string{}

updateMask = append(updateMask, "notificationEmails")
updateMask = append(updateMask, "enrolledServices")
updateMask = append(updateMask, "activeKeyVersion")

// updateMask is a URL parameter but not present in the schema, so replaceVars
// won't set it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
obj := make(map[string]interface{})
obj["notificationEmails"] = []string{}
obj["enrolledServices"] = []string{}
obj["activeKeyVersion"] = ""

url, err := replaceVars(d, config, "{{AccessApprovalBasePath}}organizations/{{organization_id}}/accessApprovalSettings")
if err != nil {
Expand All @@ -12,6 +13,7 @@ updateMask := []string{}

updateMask = append(updateMask, "notificationEmails")
updateMask = append(updateMask, "enrolledServices")
updateMask = append(updateMask, "activeKeyVersion")

// updateMask is a URL parameter but not present in the schema, so replaceVars
// won't set it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
obj := make(map[string]interface{})
obj["notificationEmails"] = []string{}
obj["enrolledServices"] = []string{}
obj["activeKeyVersion"] = ""

url, err := replaceVars(d, config, "{{AccessApprovalBasePath}}projects/{{project_id}}/accessApprovalSettings")
if err != nil {
Expand All @@ -12,6 +13,7 @@ updateMask := []string{}

updateMask = append(updateMask, "notificationEmails")
updateMask = append(updateMask, "enrolledServices")
updateMask = append(updateMask, "activeKeyVersion")

// updateMask is a URL parameter but not present in the schema, so replaceVars
// won't set it
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
resource "google_folder" "my_folder" {
display_name = "<%= ctx[:vars]['folder_name'] %>"
parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>"
}

resource "google_project" "my_project" {
name = "My Project"
project_id = "your-project-id"
folder_id = google_folder.my_folder.name
}

resource "google_kms_key_ring" "key_ring" {
name = "key-ring"
location = "global"
project = google_project.my_project.project_id
}

resource "google_kms_crypto_key" "crypto_key" {
name = "crypto-key"
key_ring = google_kms_key_ring.key_ring.id
purpose = "ASYMMETRIC_SIGN"

version_template {
algorithm = "EC_SIGN_P384_SHA384"
}
}

data "google_access_approval_folder_service_account" "service_account" {
folder_id = google_folder.my_folder.folder_id
}

resource "google_kms_crypto_key_iam_member" "iam" {
crypto_key_id = google_kms_crypto_key.crypto_key.id
role = "roles/cloudkms.signerVerifier"
member = "serviceAccount:${data.google_access_approval_folder_service_account.service_account.account_email}"
}

data "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
}

resource "google_folder_access_approval_settings" "<%= ctx[:primary_resource_id] %>" {
folder_id = google_folder.my_folder.folder_id
active_key_version = data.google_kms_crypto_key_version.crypto_key_version.name

enrolled_services {
cloud_product = "all"
}

depends_on = [google_kms_crypto_key_iam_member.iam]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
resource "google_project" "my_project" {
name = "My Project"
project_id = "your-project-id"
org_id = "<%= ctx[:test_env_vars]['org_id'] %>"
}

resource "google_kms_key_ring" "key_ring" {
name = "key-ring"
location = "global"
project = google_project.my_project.project_id
}

resource "google_kms_crypto_key" "crypto_key" {
name = "crypto-key"
key_ring = google_kms_key_ring.key_ring.id
purpose = "ASYMMETRIC_SIGN"

version_template {
algorithm = "EC_SIGN_P384_SHA384"
}
}

data "google_access_approval_organization_service_account" "service_account" {
organization_id = "<%= ctx[:test_env_vars]['org_id'] %>"
}

resource "google_kms_crypto_key_iam_member" "iam" {
crypto_key_id = google_kms_crypto_key.crypto_key.id
role = "roles/cloudkms.signerVerifier"
member = "serviceAccount:${data.google_access_approval_organization_service_account.service_account.account_email}"
}

data "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
}

resource "google_organization_access_approval_settings" "<%= ctx[:primary_resource_id] %>" {
organization_id = "<%= ctx[:test_env_vars]['org_id'] %>"
active_key_version = data.google_kms_crypto_key_version.crypto_key_version.name

enrolled_services {
cloud_product = "all"
}

depends_on = [google_kms_crypto_key_iam_member.iam]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
resource "google_kms_key_ring" "key_ring" {
name = "key-ring"
location = "global"
project = "<%= ctx[:test_env_vars]['project'] %>"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "crypto-key"
key_ring = google_kms_key_ring.key_ring.id
purpose = "ASYMMETRIC_SIGN"

version_template {
algorithm = "EC_SIGN_P384_SHA384"
}
}

data "google_access_approval_project_service_account" "service_account" {
project_id = "<%= ctx[:test_env_vars]['project'] %>"
}

resource "google_kms_crypto_key_iam_member" "iam" {
crypto_key_id = google_kms_crypto_key.crypto_key.id
role = "roles/cloudkms.signerVerifier"
member = "serviceAccount:${data.google_access_approval_project_service_account.service_account.account_email}"
}

data "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
}

resource "google_project_access_approval_settings" "<%= ctx[:primary_resource_id] %>" {
project_id = "<%= ctx[:test_env_vars]['project'] %>"
active_key_version = data.google_kms_crypto_key_version.crypto_key_version.name

enrolled_services {
cloud_product = "all"
}

depends_on = [google_kms_crypto_key_iam_member.iam]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package google

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceAccessApprovalFolderServiceAccount() *schema.Resource {
return &schema.Resource{
Read: dataSourceAccessApprovalFolderServiceAccountRead,
Schema: map[string]*schema.Schema{
"folder_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"account_email": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAccessApprovalFolderServiceAccountRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

url, err := replaceVars(d, config, "{{AccessApprovalBasePath}}folders/{{folder_id}}/serviceAccount")
if err != nil {
return err
}

billingProject := ""

// err == nil indicates that the billing_project value was found
if bp, err := getBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("AccessApprovalFolderServiceAccount %q", d.Id()))
}

if err := d.Set("name", res["name"]); err != nil {
return fmt.Errorf("Error setting name: %s", err)
}
if err := d.Set("account_email", res["accountEmail"]); err != nil {
return fmt.Errorf("Error setting account_email: %s", err)
}
d.SetId(res["name"].(string))

return nil
}
Loading