My previous article RBAC with Fine Grained Access - Apigee X was a quick solution at the project level to show the necessary configuration. This article provides a more robust solution using organizational groups, plus it shows how to configure using Google APIs and Terraform.
User Story
As a security stakeholder, I want to restrict access to Apigee resources so that I can assign them to separate business units or projects.
- Business unit leads should be able to grant user access to their own environment(s).
- Business unit members should only be able to access Apigee resources that belong to the business unit. These resources should include:
- API Proxy
- Shared Flow
- Deployments
- Debug Sessions
- Flow Hooks- API Products
- Rate Plans (see Limitations and Caveats)
- App Developers (see Limitations and Caveats)
- Applications (see Limitations and Caveats)- KVMs
- Resource files
- TargetServers
- References
- KeyStores
- Environment resources: (see Environment Access)
Overview and Background
Supported Resource Types
Apigee supports adding resource conditions in IAM policies to these supported resources types using conditional role bindings during role assignment. Conditions can be based on time (e.g. schedule, expiry) or a named resource (e.g. type and name starts with “bu1-”). Roles can be assigned to individual users or to a group, the later being a better practice. Assigning conditional access to a group simplifies management as once the conditions have been specified for the group, individual users are simply added to the group. This avoids updating the conditions on every user assignment.
Environment Access
Environments do not support conditional role assignment directly. Rather, access to an environment and its resources is granted via “Access” in the UI or via the Apigee API Environments Set IAM Policy API. Assigning a user as an “Apigee Environment Admin” to an environment (e.g. bu1-test) controls access to environment specific resources such as KVMs, Resource files, TargetServers, References, and KeyStores. It also controls access to deployments and debug sessions for the environment.
Unsupported Resource Types
These resource types do not support “conditional” role based assignment, access to these resources can be managed via built in roles or custom roles.
- Analytics Dashboards
- Custom Reports
- Advanced API Security
- Advanced API Ops
- Integrated Developer Portals
- Integrations
- Connectors
Limitations and Caveats
- Rate Plans
- Rate Plans are associated with an API Product, therefore access can be protected by the API Product name.
- Rate Plans are identified using a UUID; it’s not demonstrated how to apply conditional role assignment.1. App Developers
- Developers are identified using either an email or a UUID; it’s not demonstrated how to apply conditional role assignment.1. Applications
- Although Applications can be restricted by name, The “Apps” list page in the UI performs a “GET /apps?expand=true” API call which returns all the details for an App thereby allowing the user to see any App’s keys.
Overview of Steps
Prerequisites
- Apigee X organization with 2 environments (e.g. bu1-test, bu2-test).
- Users in the organization and Service Accounts in project to exist.
Steps
- Create groups (e.g. business-unit-1, business-unit-2)
- Create a custom role “Custom Role Apigee Deploy and Debug” with get and list permissions for environments and deployments to users without conditions. This fixes UI errors preventing deployments and debug sessions.
- Assign Apigee API Admin and Apigee Developer Admin roles to group with conditions on role assignment.
- Assign a custom role “Custom Role Apigee Deploy and Debug” to group without conditions.
- Assign Apigee Environment Admin “Access” for the user to specific Environments (e.g. bu1-test, bu2-test).
Solution Details - Using the UI
Enable API
Apigee supports adding resource conditions in IAM policies on specific resource types (proxies, shared flows) used in the Apigee builtin rules through GCP IAM. Not all resource types are “conditional”, in particular Environments. Access to environments is done via “Access” in the UI or via the Apigee API Environments Set IAM Policy API. Assigning a user or group as an “Apigee Environment Admin” to an environment (e.g. bu1-test, bu2-test) controls access to environment specific resources such as KVMs, Resource files, TargetServers, References, and KeyStores.
Create Groups and Add Members
In IAM and Admin for the organization, select Groups and create the context specific groups (e.g. bu1, bu2, bu3).
NOTE: this assumes individual users are already created in the organization.
The resulting details:
Repeat for other groups.
NOTES:
- Adding a Service Account to a group is generally not a best practice.
- The Service Account was created in the project without any roles.
See: Service Accounts and Google Groups and Avoid using groups for granting service accounts access to resources.
Create Custom Role at Organization Level
This is required to allow the user to manage deployments and debug sessions in the Apigee UI. It also enables configuring Flow Hooks, for the assigned environment.
Create a custom role (e.g. Custom Role Apigee Deploy and Debug) that allows get and list permissions on deployments and environments.
apigee.deployments.get
apigee.deployments.list
apigee.entitlements.get
apigee.envgroupattachments.get
apigee.envgroupattachments.list
apigee.envgroups.get
apigee.envgroups.list
apigee.environments.get
apigee.environments.getStats
apigee.environments.list
apigee.operations.get
apigee.operations.list
apigee.projectorganizations.get
apigee.setupcontexts.get
Assign Roles with Conditions to Groups
The Apigee built in roles for Apigee API Admin and Apigee Developer Admin are required for an “API proxy developer” to create and test.
Apigee API Admin role is required to create API proxies, shared flows and related artifacts such as API Products.
Apigee Developer Admin role is required to create Developers and Apps for testing.
The custom role Custom Role Apigee Deploy and Debug avoids errors in the UI, it is assigned without conditions.
Assign Conditions to Assigned Roles
Add the following conditions to both the Apigee API Admin and Apigee Developer Admin role assignments.
- The use of (resource.type == ‘apigee.googleapis.com/Developer’) allows users to list Developers and their Apps.
- The use of (resource.type == ‘apigee.googleapis.com/DeveloperApp’ && resource.name.extract(‘/apps/{name}’).startsWith(‘bu1-’)) allows access to named Developer Apps.
NOTE: the resource.name.startsWith() condition uses the name of the Apigee X project (e.g. apigeex-exp), replace with your value.
resource.name.startsWith('organizations/apigeex-exp/apis/bu1-') ||
resource.name.startsWith('organizations/apigeex-exp/sharedflows/bu1-') ||
resource.name.startsWith('organizations/apigeex-exp/apiproducts/bu1-') ||
(resource.type == 'apigee.googleapis.com/Developer') ||
(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu1-')) ||
resource.type == 'cloudresourcemanager.googleapis.com/Project'
Steps:
- Navigate to IAM & Admin → IAM in the GCP Console
- Add a principal and assign Apigee API Admin role.
- Click the pencil to “Edit principal”
- Click the pencil to add the Condition
Select “CONDITION EDITOR” and paste the condition from above, adjusting “bu1-” to be your resource prefix.
Repeat for the Apigee Developer Admin role.
Then repeat for other groups, changing the prefix value accordingly.
Assign Access to Environment for Groups
Access for users to specific environments is done in Apigee UI or via APIs on the environment.
Access to environments is required to allow management of environment specific resources such as Target Servers, KVMs and PropertySets, since these are not named resources and cannot be used in conditional role assignments.
Access to environments is also required to manage deployments for the specific environment.
Role assignment in the Apigee Management UI
Solution Details - Using APIs
TIP: Create an alias to simplify curl commands to GCP and Apigee APIs.
alias curlx='curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)"'
Create Groups
Enable API
You’ll need to use the customer ID (e.g. customers/C03rq1yqp) which you can find in the Admin console under Account → Account Settings at: https://admin.google.com/ac/accountsettings/profile.
curlx -X POST 'https://cloudidentity.googleapis.com/v1/groups?initialGroupConfig=WITH_INITIAL_OWNER' \
--header 'X-Goog-User-Project: apigeex-exp' \
--header 'Content-Type: application/json' \
--data-raw '{
"groupKey": {
"id": "bu1@kurtkanaskie.altostrat.com"
},
"parent": "customers/C03rq1yqp",
"displayName": "Business Unit 1",
"description": "Business Unit 1 Group",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
}'
# response
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.apps.cloudidentity.groups.v1.Group",
"name": "groups/02ce457m220civc",
"groupKey": {
"id": "bu3@kurtkanaskie.altostrat.com"
},
"parent": "customers/C03rq1yqp",
"displayName": "Business Unit 1",
"description": "Business Unit 1 Group",
"createTime": "2022-09-13T14:12:40.425818Z",
"updateTime": "2022-09-13T14:12:40.425818Z",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
}
}
Add Users to Group
NOTE: This assumes users are already onboarded in the organization.
curlx -X POST 'https://cloudidentity.googleapis.com/v1/groups/02ce457m220civc/memberships' \
--header 'X-Goog-User-Project: apigeex-exp' \
--header 'Content-Type: application/json' \
--data-raw '{
"preferredMemberKey": {
"id": "dev1.bu1@kurtkanaskie.altostrat.com"
},
"roles": [
{
"name": "MEMBER"
}
]
}'
# response
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.apps.cloudidentity.groups.v1.Membership",
"name": "groups/02ce457m220civc/memberships/109834938926743824778",
"preferredMemberKey": {
"id": "dev1.bu1@kurtkanaskie.altostrat.com"
},
"roles": [
{
"name": "MEMBER"
}
]
}
}
Create Custom Role
See: Creating and managing custom roles
NOTES:
- ORG_ID is the unique identifier of your organization (e.g. 785287799950) which you can find from the GCP Console project selector dropdown.
- Ensure the user performing these steps has the “Role Administrator” role assigned.
curlx -X POST https://iam.googleapis.com/v1/organization/$ORG_ID/roles \
--header 'Content-Type: application/json' \
--data-raw '{
"roleId": "CustomRoleApigeeDeployDebug",
"role": {
"title": "Custom Role Apigee Deploy and Debug",
"description": "Custom role for fine grained access with deployment and debug",
"includedPermissions": [
"apigee.deployments.get",
"apigee.deployments.list",
"apigee.entitlements.get",
"apigee.envgroupattachments.get",
"apigee.envgroupattachments.list",
"apigee.envgroups.get",
"apigee.envgroups.list",
"apigee.environments.get",
"apigee.environments.getStats",
"apigee.environments.list",
"apigee.operations.get",
"apigee.operations.list",
"apigee.projectorganizations.get"
],
"stage": "ALPHA"
}
}'
# response
{
"name": "organizations/785287799950/roles/CustomRoleApigeeDeployDebug",
"title": "Custom Role Apigee Deploy and Debug",
"description": "Custom role for fine grained access with deployment and debug",
"includedPermissions": [
"apigee.deployments.get",
"apigee.deployments.list",
"apigee.entitlements.get",
"apigee.envgroupattachments.get",
"apigee.envgroupattachments.list",
"apigee.envgroups.get",
"apigee.envgroups.list",
"apigee.environments.get",
"apigee.environments.getStats",
"apigee.environments.list",
"apigee.operations.get",
"apigee.operations.list",
"apigee.projectorganizations.get"
],
"etag": "BwXoB+k8g6E="
}
Assign Roles
See: Manage conditional role bindings and Grant or revoke multiple roles.
Assign Group to Roles with Conditions
NOTE: Updating the policy for users requires a complete update of all bindings.
Get the current policy and save it in a file.
curlx -X POST https://cloudresourcemanager.googleapis.com/v1/organizations/$ORG_ID:getIamPolicy --header 'Content-Type: application/json' --data-raw '{
"options": {
"requestedPolicyVersion": 3
}
}' > current_allow_policy_org.json
cat current_allow_policy_org.json
{
"version": 3,
"etag": "BwXoG4rcZMQ=",
"bindings": [
... content clipped ...
]
}
Copy the policy to a new file (e.g. update_allow_policy_org.json) and edit to add the outer “policy” element
cp current_allow_policy_org.json update_allow_policy_org.json
{
"policy":
content from current_allow_policy_org.json
}
Add in the new role assignments
curlx -X POST -H "Content-Type: application/json; charset=utf-8" -d @update_allow_policy.json "https://cloudresourcemanager.googleapis.com/v1/organizations/$ORG_ID:setIamPolicy"
cat update_allow_policy.json
{
"policy": {
"version": 3,
"etag": "BwXofUXVZlY=",
"bindings": [{
"role": "organizations/785287799950/roles/CustomRoleApigeeDeployDebug",
"members": [
"group:business-unit-1@kurtkanaskie.altostrat.com",
"group:business-unit-2@kurtkanaskie.altostrat.com"
]
},
{
"role": "roles/apigee.apiAdminV2",
"members": [
"group:business-unit-1@kurtkanaskie.altostrat.com"
],
"condition": {
"expression": "resource.name.startsWith('organizations/apigeex-exp/apis/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu1-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu1-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'\n",
"title": "business-unit-1"
}
},
{
"role": "roles/apigee.developerAdmin",
"members": [
"group:business-unit-1@kurtkanaskie.altostrat.com"
],
"condition": {
"expression": "resource.name.startsWith('organizations/apigeex-exp/apis/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu1-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu1-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'",
"title": "business-unit-1"
}
},
{
"role": "roles/apigee.apiAdminV2",
"members": [
"group:business-unit-2@kurtkanaskie.altostrat.com"
],
"condition": {
"expression": "resource.name.startsWith('organizations/apigeex-exp/apis/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu2-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu2-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'",
"title": "business-unit-2"
}
},
{
"role": "roles/apigee.developerAdmin",
"members": [
"group:business-unit-2@kurtkanaskie.altostrat.com"
],
"condition": {
"expression": "resource.name.startsWith('organizations/apigeex-exp/apis/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu2-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu2-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'",
"title": "business-unit-2"
}
}
... content clipped ...
]
}
Assign Group Environment Access via Apigee API
This is a two step process:
- Environments Get IAM Policy API - Gets the IAM policy on an environment.
- Environments Set IAM Policy API - Sets the IAM policy on an environment. If the policy already exists, it will be replaced.
Get and set policy for bu1-test environment.
Get the current policy
curlx 'https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test:getIamPolicy?options.requestedPolicyVersion=3'
# response
{
"etag": "ACAB"
}
Update policy for group business-unit-1
curlx -X POST 'https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test:setIamPolicy' \
--header 'Content-Type: application/json' \
--data-raw '{
"policy": {
"bindings": [
{
"role": "roles/apigee.environmentAdmin",
"members": [
"group:business-unit-1@kurtkanaskie.altostrat.com"
]
}
],
"etag": "ACAB",
"version": 1
}
}'
# response
{
"version": 1,
"etag": "BwXoflPFvoc=",
"bindings": [
{
"role": "roles/apigee.environmentAdmin",
"members": [
"group:business-unit-1@kurtkanaskie.altostrat.com"
]
}
]
}
Get and set policy for bu2-test environment.
Get the current policy
curlx 'https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu2-test:getIamPolicy?options.requestedPolicyVersion=3'
# response
{
"etag": "ACAB"
}
Update policy for group business-unit-2
curlx -X POST 'https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu2-test:setIamPolicy' \
--header 'Content-Type: application/json' \
--data-raw '{
"policy": {
"bindings": [
{
"role": "roles/apigee.environmentAdmin",
"members": [
"group:business-unit-2@kurtkanaskie.altostrat.com"
]
}
],
"etag": "ACAB",
"version": 1
}
}'
# response
{
"version": 1,
"etag": "BwXoflPFvoc=",
"bindings": [
{
"role": "roles/apigee.environmentAdmin",
"members": [
"group:business-unit-2@kurtkanaskie.altostrat.com"
]
}
]
}
Terraform Organization and Groups
Overview
- Create GCP custom role, groups, group role assignment with conditions and memberships.
- Assign Apigee Environment Access
NOTE: Expects users in organization and Service Accounts in project to exist.
Terraform Providers (terraform.tf)
terraform {
required_providers {
google = {
source = "hashicorp/google"
}
}
}
Variables (variables.tf)
variable "domain" {
type = string
default = "kurtkanaskie.altostrat.com"
}
variable "customer_id" {
type = string
default = "C03rq1yqp"
}
variable "org_id" {
type = string
default = "785287799950"
}
variable "project_id" {
type = string
default = "apigeex-exp"
}
Custom Role, Conditions and Bindings (main.tf)
provider "google" {
user_project_override = true
# How do I set permissions at org level? Organization Admin role - nope
# credentials = file("sa-apigeex-exp-terraform.json")
billing_project = var.project_id
project = var.project_id
}
#######################################################################
### Custom Apigee X Deploy and Debug Role
#######################################################################
resource "google_organization_iam_custom_role" "CustomRoleApigeeXDeployDebug" {
org_id = var.org_id
role_id = "CustomRoleApigeeXDeployDebug"
title = "Custom Role Apigee X Deploy and Debug"
description = "Custom role for Apigee X fine grained access with deployment and debug"
permissions = [
"apigee.deployments.get",
"apigee.deployments.list",
"apigee.entitlements.get",
"apigee.envgroupattachments.get",
"apigee.envgroupattachments.list",
"apigee.envgroups.get",
"apigee.envgroups.list",
"apigee.environments.get",
"apigee.environments.getStats",
"apigee.environments.list",
"apigee.operations.get",
"apigee.operations.list",
"apigee.projectorganizations.get"
]
}
#######################################################################
### BU 1
### Groups and memberships BU 1
#######################################################################
resource "google_cloud_identity_group" "business_unit_1" {
display_name = "Business Unit One"
description = "Business Unit One Group"
initial_group_config = "WITH_INITIAL_OWNER"
parent = "customers/${var.customer_id}"
group_key {
id = "business-unit-1@${var.domain}"
}
labels = {
"cloudidentity.googleapis.com/groups.discussion_forum" = ""
}
}
resource "google_cloud_identity_group_membership" "business_unit_1_membership_1" {
group = google_cloud_identity_group.business_unit_1.id
preferred_member_key {
id = "dev1.bu1@${var.domain}"
}
roles {
name = "MEMBER"
}
}
resource "google_cloud_identity_group_membership" "business_unit_1_membership_2" {
group = google_cloud_identity_group.business_unit_1.id
preferred_member_key {
id = "dev2.bu1@${var.domain}"
}
roles {
name = "MEMBER"
}
}
resource "google_cloud_identity_group_membership" "business_unit_1_membership_3" {
group = google_cloud_identity_group.business_unit_1.id
preferred_member_key {
id = "cicd-test-bu1@${var.project_id}.iam.gserviceaccount.com"
}
roles {
name = "MEMBER"
}
}
#######################################################################
### Role assignment to groups with conditions BU 1
#######################################################################
resource "google_organization_iam_member" "business_unit_1_custom" {
org_id = var.org_id
role = "organizations/${var.org_id}/roles/CustomRoleApigeeXDeployDebug"
member = "group:business-unit-1@${var.domain}"
}
resource "google_organization_iam_member" "business_unit_1_api_admin" {
org_id = var.org_id
role = "roles/apigee.apiAdminV2"
member = "group:business-unit-1@${var.domain}"
condition {
title = "business-unit-1"
description = "Conditions for business unit to edit bu1- prefixed proxies, shared flows and test"
expression = "resource.name.startsWith('organizations/apigeex-exp/apis/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu1-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu1-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'"
}
}
resource "google_organization_iam_member" "business_unit_1_developer_admin" {
org_id = var.org_id
role = "roles/apigee.developerAdmin"
member = "group:business-unit-1@${var.domain}"
condition {
title = "business-unit-1"
description = "Conditions for business unit to edit bu1- prefixed proxies, shared flows and test"
expression = "resource.name.startsWith('organizations/apigeex-exp/apis/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu1-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu1-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu1-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'"
}
}
#######################################################################
### Environment Access for BU 1
#######################################################################
resource "google_apigee_environment_iam_member" "member-bu1-test" {
org_id = "organizations/${var.project_id}"
env_id = "bu1-test"
role = "roles/apigee.environmentAdmin"
member = "group:business-unit-1@${var.domain}"
}
#######################################################################
### BU 2
### Groups and memberships BU 2
#######################################################################
resource "google_cloud_identity_group" "business_unit_2" {
display_name = "Business Unit Two"
description = "Business Unit Two Group"
initial_group_config = "WITH_INITIAL_OWNER"
parent = "customers/${var.customer_id}"
group_key {
id = "business-unit-2@${var.domain}"
}
labels = {
"cloudidentity.googleapis.com/groups.discussion_forum" = ""
}
}
resource "google_cloud_identity_group_membership" "business_unit_2_membership_1" {
group = google_cloud_identity_group.business_unit_2.id
preferred_member_key {
id = "dev1.bu2@${var.domain}"
}
roles {
name = "MEMBER"
}
}
resource "google_cloud_identity_group_membership" "business_unit_2_membership_2" {
group = google_cloud_identity_group.business_unit_2.id
preferred_member_key {
id = "dev2.bu2@${var.domain}"
}
roles {
name = "MEMBER"
}
}
resource "google_cloud_identity_group_membership" "business_unit_2_membership_3" {
group = google_cloud_identity_group.business_unit_2.id
preferred_member_key {
id = "cicd-test-bu2@${var.project_id}.iam.gserviceaccount.com"
}
roles {
name = "MEMBER"
}
}
#######################################################################
### Role assignment to groups with conditions BU 2
#######################################################################
resource "google_organization_iam_member" "business_unit_2_custom" {
org_id = var.org_id
role = "organizations/${var.org_id}/roles/CustomRoleApigeeXDeployDebug"
member = "group:business-unit-2@${var.domain}"
}
resource "google_organization_iam_member" "business_unit_2_api_admin" {
org_id = var.org_id
role = "roles/apigee.apiAdminV2"
member = "group:business-unit-2@${var.domain}"
condition {
title = "business-unit-2"
description = "Conditions for business unit to edit bu2- prefixed proxies, shared flows and test"
expression = "resource.name.startsWith('organizations/apigeex-exp/apis/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu2-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu2-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'"
}
}
resource "google_organization_iam_member" "business_unit_2_developer_admin" {
org_id = var.org_id
role = "roles/apigee.developerAdmin"
member = "group:business-unit-2@${var.domain}"
condition {
title = "business-unit-2"
description = "Conditions for business unit to edit bu2- prefixed proxies, shared flows and test"
expression = "resource.name.startsWith('organizations/apigeex-exp/apis/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/sharedflows/bu2-') ||\nresource.name.startsWith('organizations/apigeex-exp/apiproducts/bu2-') ||\n(resource.type == 'apigee.googleapis.com/Developer') ||\n(resource.type == 'apigee.googleapis.com/DeveloperApp' && resource.name.extract('/apps/{name}').startsWith('bu2-')) ||\nresource.type == 'cloudresourcemanager.googleapis.com/Project'"
}
}
#######################################################################
### Environment Access for BU 2
#######################################################################
resource "google_apigee_environment_iam_member" "member-bu2-test" {
org_id = "organizations/${var.project_id}"
env_id = "bu2-test"
role = "roles/apigee.environmentAdmin"
member = "group:business-unit-2@${var.domain}"
}
Test
Users and service accounts created for role assignment:
dev1-bu1@kurtkanaskie.altostrat.com
dev2-bu1@kurtkanaskie.altostrat.com
dev1-bu2@kurtkanaskie.altostrat.com
dev2-bu2@kurtkanaskie.altostrat.com
cicd-test-bu1@apigeex-exp.iam.gserviceaccount.com
cicd-test-bu2@apigeex-exp.iam.gserviceaccount.com
Set up gcloud configuration (optional)
gcloud config configurations create $YOUR_PROJECT
gcloud config set project $YOUR_PROJECT
gcloud config set account dev1.bu1@kurtkanaskie.altostrat.com
Activate a Service Account
gcloud config set account cicd-test-bu1@apigeex-exp.iam.gserviceaccount.com
Sample API calls
# KVMs, Target Servers, Key Stores, References and Properties (OK)
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test/targetservers
403 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu2-test/targetservers
# Environments and deployments (OK)
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/deployments
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test/deployments
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu2-test/deployments (expected)
# Conditional proxies, revisions, deployments (OK)
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu1-proxy-1/revisions
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu1-proxy-1/deployments
403 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu2-proxy-1/revisions (expected)
403 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu2-proxy-1/deployments (expected)
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu1-proxy-1/revisions/7
200 - curlx -X DELETE https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu1-proxy-1/revisions/7
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/apis/bu1-proxy-1/revisions/7/deployments
200 - curlx https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test/apis/bu1-proxy-1/revisions/7/deployments
200 - curlx -X DELETE https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test/apis/bu1-proxy-1/revisions/7/deployments
200 - curlx -X POST https://apigee.googleapis.com/v1/organizations/apigeex-exp/environments/bu1-test/apis/bu1-proxy-1/revisions/6/deployments
References
GCP IAM and Roles
Apigee Users and Roles
- Users and Roles Overview
- Add user accounts in the UI
- Adding resource conditions
- Complete list of Apigee API REST resources.
Terraform