Enable creation of organization- and folder-level service agents (#3877)
* Enable creation of organization- and folder-level service agents * formatting * Add folder test * Add org tests * linting * more linting * Fix tests
This commit is contained in:
@@ -18,6 +18,7 @@ To manage organization policies, the `orgpolicy.googleapis.com` service should b
|
||||
- [Example](#example)
|
||||
- [IAM](#iam)
|
||||
- [Conditional IAM by Principals](#conditional-iam-by-principals)
|
||||
- [Service Agents](#service-agents)
|
||||
- [Organization Policies](#organization-policies)
|
||||
- [Organization Policy Factory](#organization-policy-factory)
|
||||
- [Organization Policy Custom Constraints](#organization-policy-custom-constraints)
|
||||
@@ -166,6 +167,25 @@ module "org" {
|
||||
# tftest modules=1 resources=2 inventory=iam-bpc.yaml
|
||||
```
|
||||
|
||||
## Service Agents
|
||||
|
||||
The module allows managing service agents at the organization level. Service agent creation is triggered by adding them to the `service_agents_config.services` variable.
|
||||
|
||||
```hcl
|
||||
module "org" {
|
||||
source = "./fabric/modules/organization"
|
||||
organization_id = var.organization_id
|
||||
service_agents_config = {
|
||||
services = [
|
||||
"osconfig.googleapis.com",
|
||||
"privilegedaccessmanager.googleapis.com",
|
||||
"progressiverollout.googleapis.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
# tftest inventory=agents.yaml
|
||||
```
|
||||
|
||||
## Organization Policies
|
||||
|
||||
### Organization Policy Factory
|
||||
@@ -269,19 +289,22 @@ custom.dataprocNoMoreThan10Workers:
|
||||
|
||||
Note that using PAM entitlements requires specific roles to be granted to the users and groups that will be using them. For more information, see the [official documentation](https://cloud.google.com/iam/docs/pam-permissions-and-setup#before-you-begin).
|
||||
|
||||
Additionally, the Privileged Access Manager Service Agent must be created and granted the `roles/privilegedaccessmanager.organizationServiceAgent` role. The service agent is not created automatically, and you can find the `gcloud` command to create it in the `service_agents` output of this module. For more information on service agents, see the [official documentation](https://cloud.google.com/iam/docs/service-agents).
|
||||
Additionally, the Privileged Access Manager Service Agent must be created and granted the `roles/privilegedaccessmanager.organizationServiceAgent` role. The service agent can be created automatically by adding `privilegedaccessmanager.googleapis.com` to the `services` list in the `service_agents_config` variable.
|
||||
|
||||
The following example shows how to grant the required role to the PAM service agent:
|
||||
The following example shows how to create the service agent and grant the required role:
|
||||
|
||||
```hcl
|
||||
module "organization" {
|
||||
source = "./fabric/modules/organization"
|
||||
organization_id = var.org_id
|
||||
organization_id = var.organization_id
|
||||
factories_config = {
|
||||
pam_entitlements = "factory/"
|
||||
}
|
||||
service_agents_config = {
|
||||
services = ["privilegedaccessmanager.googleapis.com"]
|
||||
}
|
||||
iam = {
|
||||
"roles/privilegedaccessmanager.serviceAgent" = [
|
||||
"roles/privilegedaccessmanager.organizationServiceAgent" = [
|
||||
module.organization.service_agents.pam.iam_email
|
||||
]
|
||||
}
|
||||
@@ -991,7 +1014,7 @@ module "org" {
|
||||
| [pam.tf](./pam.tf) | None | <code>google_privileged_access_manager_entitlement</code> |
|
||||
| [scc-mute-configs.tf](./scc-mute-configs.tf) | Organization-level SCC mute configurations. | <code>google_scc_v2_organization_mute_config</code> |
|
||||
| [scc-sha-custom-modules.tf](./scc-sha-custom-modules.tf) | Organization-level Custom modules with Security Health Analytics. | <code>google_scc_management_organization_security_health_analytics_custom_module</code> |
|
||||
| [service-agents.tf](./service-agents.tf) | Service agents supporting resources. | |
|
||||
| [service-agents.tf](./service-agents.tf) | Service agents supporting resources. | <code>google_organization_service_identity</code> |
|
||||
| [tags.tf](./tags.tf) | Manages GCP Secure Tags, keys, values, and IAM. | <code>google_tags_tag_binding</code> · <code>google_tags_tag_key</code> · <code>google_tags_tag_key_iam_binding</code> · <code>google_tags_tag_key_iam_member</code> · <code>google_tags_tag_value</code> · <code>google_tags_tag_value_iam_binding</code> · <code>google_tags_tag_value_iam_member</code> |
|
||||
| [variables-iam.tf](./variables-iam.tf) | None | |
|
||||
| [variables-identity-providers.tf](./variables-identity-providers.tf) | None | |
|
||||
@@ -1030,6 +1053,7 @@ module "org" {
|
||||
| [pam_entitlements](variables-pam.tf#L17) | Privileged Access Manager entitlements for this resource, keyed by entitlement ID. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [scc_mute_configs](variables-scc.tf#L17) | SCC mute configurations keyed by name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [scc_sha_custom_modules](variables-scc.tf#L28) | SCC custom modules keyed by module name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [service_agents_config](variables.tf#L182) | Service agents configuration. | <code>object({…})</code> | | <code>{}</code> |
|
||||
| [tag_bindings](variables-tags.tf#L89) | Tag bindings for this organization, in key => tag value id format. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [tags](variables-tags.tf#L96) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [tags_config](variables-tags.tf#L161) | Fine-grained control on tag resource and IAM creation. | <code>object({…})</code> | | <code>{}</code> |
|
||||
@@ -1053,10 +1077,10 @@ module "org" {
|
||||
| [scc_custom_sha_modules_ids](outputs.tf#L118) | Map of SCC CUSTOM SHA MODULES => ID in the organization. | |
|
||||
| [scc_mute_configs](outputs.tf#L123) | SCC mute configurations. | |
|
||||
| [service_agents](outputs.tf#L128) | Identities of all organization-level service agents. | |
|
||||
| [sink_writer_identities](outputs.tf#L133) | Writer identities created for each sink. | |
|
||||
| [tag_keys](outputs.tf#L141) | Tag key resources. | |
|
||||
| [tag_values](outputs.tf#L150) | Tag value resources. | |
|
||||
| [workforce_identity_pool_ids](outputs.tf#L158) | Workforce identity pool ids. | |
|
||||
| [workforce_identity_provider_names](outputs.tf#L165) | Workforce Identity provider names. | |
|
||||
| [workforce_identity_providers](outputs.tf#L172) | Workforce Identity provider attributes. | |
|
||||
| [sink_writer_identities](outputs.tf#L136) | Writer identities created for each sink. | |
|
||||
| [tag_keys](outputs.tf#L144) | Tag key resources. | |
|
||||
| [tag_values](outputs.tf#L153) | Tag value resources. | |
|
||||
| [workforce_identity_pool_ids](outputs.tf#L161) | Workforce identity pool ids. | |
|
||||
| [workforce_identity_provider_names](outputs.tf#L168) | Workforce Identity provider names. | |
|
||||
| [workforce_identity_providers](outputs.tf#L175) | Workforce Identity provider attributes. | |
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -128,6 +128,9 @@ output "scc_mute_configs" {
|
||||
output "service_agents" {
|
||||
description = "Identities of all organization-level service agents."
|
||||
value = local.service_agents
|
||||
depends_on = [
|
||||
google_organization_service_identity.default
|
||||
]
|
||||
}
|
||||
|
||||
output "sink_writer_identities" {
|
||||
|
||||
@@ -18,27 +18,25 @@
|
||||
|
||||
locals {
|
||||
_sa_raw = yamldecode(file("${path.module}/service-agents.yaml"))
|
||||
_sa0 = {
|
||||
service_agents = {
|
||||
for agent in local._sa_raw :
|
||||
agent.name => {
|
||||
create_command = (
|
||||
"gcloud beta services identity create --service=${agent.api} --organization=${local.organization_id_numeric}"
|
||||
)
|
||||
name = agent.name
|
||||
api = agent.api
|
||||
display_name = agent.display_name
|
||||
email = templatestring(agent.identity, {
|
||||
organization_number = local.organization_id_numeric
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
service_agents = {
|
||||
for k, v in local._sa0 :
|
||||
k => merge(v, {
|
||||
iam_email = "serviceAccount:${v.email}"
|
||||
})
|
||||
email = templatestring(agent.identity, { organization_number = local.organization_id_numeric })
|
||||
iam_email = "serviceAccount:${templatestring(agent.identity, { organization_number = local.organization_id_numeric })}"
|
||||
} if contains(var.service_agents_config.services, agent.api)
|
||||
}
|
||||
service_agents_ctx = {
|
||||
for k, v in local.service_agents :
|
||||
"$service_agents:${k}" => v.iam_email
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_organization_service_identity" "default" {
|
||||
provider = google-beta
|
||||
for_each = var.service_agents_config.create_agents ? local.service_agents : {}
|
||||
organization = local.organization_id_numeric
|
||||
service = each.value.api
|
||||
}
|
||||
|
||||
@@ -16,208 +16,104 @@
|
||||
display_name: Access Approval Service Agent
|
||||
api: accessapproval.googleapis.com
|
||||
identity: service-o${organization_number}@gcp-sa-accessapproval.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: assuredoss
|
||||
display_name: Assured OSS Service Agent
|
||||
api: assuredoss.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-assuredoss.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: asm-hpsa
|
||||
display_name: Attack Surface Management Service Agent
|
||||
api: securitycenter.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-asm-hpsa.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: audit-manager
|
||||
display_name: Audit Manager Service Agent
|
||||
api: auditmanager.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-audit-manager.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: chronicle-soar
|
||||
display_name: Chronicle Soar Service Agent
|
||||
api: chronicle.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-chronicle-soar.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: effectivepolicy
|
||||
display_name: Cloud Asset Effective Policy Service Agent
|
||||
api: cloudasset.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-effectivepolicy.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: othercloudcfg
|
||||
display_name: Cloud Asset Other Cloud Config Service Agent
|
||||
api: cloudasset.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-othercloudcfg.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: cloudkms
|
||||
display_name: Cloud KMS Organization Service Agent
|
||||
api: cloudkms.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-cloudkms.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: logging
|
||||
display_name: Cloud Logging Service Agent
|
||||
api: logging.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-logging.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: nss-hpsa
|
||||
display_name: Cloud Notebook Security Scanner Service Agent
|
||||
api: notebooksecurityscanner.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-nss-hpsa.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: observability
|
||||
display_name: Cloud Observability Service Account
|
||||
api: observability.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-observability.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: cloudresourcemanager
|
||||
display_name: Cloud Resource Manager Service Agent
|
||||
api: cloudresourcemanager.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-cloudresourcemanager.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: riskmanager
|
||||
display_name: Cloud Risk Manager Service Agent
|
||||
api: dlp.googleapis.com
|
||||
identity: organizations-${organization_number}@gcp-sa-riskmanager.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: scc-bulk-export
|
||||
display_name: Cloud Security Command Center Bulk Export Service Account
|
||||
api: securitycenter.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-scc-bulk-export.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: scc-notification
|
||||
display_name: Cloud Security Command Center Notification Service Account
|
||||
api: securitycenter.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-scc-notification.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: security-center-api
|
||||
display_name: Cloud Security Command Center Service Agent
|
||||
api: securitycenter.googleapis.com
|
||||
identity: service-org-${organization_number}@security-center-api.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: csc-hpsa
|
||||
display_name: Cloud Security Compliance Service Agent
|
||||
api: cloudsecuritycompliance.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-csc-hpsa.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: ktd-hpsa
|
||||
display_name: Container Threat Detection Service Agent
|
||||
api: containerthreatdetection.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-ktd-hpsa.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: dataplex-cmek
|
||||
display_name: Dataplex Cmek Service Agent
|
||||
api: dataplex.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-dataplex-cmek.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: dataplex
|
||||
display_name: Dataplex Service Agent
|
||||
api: dataplex.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-dataplex.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: osconfig-rollout
|
||||
display_name: Google Cloud OS Config Rollout Service Agent
|
||||
api: osconfig.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-osconfig-rollout.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: osconfig
|
||||
display_name: Google Cloud OS Config Service Agent
|
||||
api: osconfig.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-osconfig.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: v1-remediator
|
||||
display_name: Policy Remediator Service Agent (prod)
|
||||
api: policyremediator.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-v1-remediator.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: pam
|
||||
display_name: Privileged Access Manager Service Agent
|
||||
api: privilegedaccessmanager.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-pam.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: progrollout
|
||||
display_name: Progressive Rollout Service Agent
|
||||
api: progressiverollout.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-progrollout.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
- name: sccspanner
|
||||
display_name: SCC CMEK Spanner Service Agent (PROD)
|
||||
api: securitycenter.googleapis.com
|
||||
identity: service-org-${organization_number}@gcp-sa-sccspanner.iam.gserviceaccount.com
|
||||
role: null
|
||||
is_primary: false
|
||||
aliases: []
|
||||
skip_iam: false
|
||||
|
||||
|
||||
@@ -178,3 +178,13 @@ variable "organization_id" {
|
||||
error_message = "The organization_id must in the form organizations/nnn."
|
||||
}
|
||||
}
|
||||
|
||||
variable "service_agents_config" {
|
||||
description = "Service agents configuration."
|
||||
type = object({
|
||||
services = optional(list(string), [])
|
||||
create_agents = optional(bool, true)
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user