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

terraform Support for Managing Entitlements. #10334

Merged
merged 59 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
da05f83
terraform Support for Managing Entitlement.
varsharmavs Apr 1, 2024
d558874
Added privilegedacessmanager to './mmv1/third_party/terraform/.teamci…
varsharmavs Apr 1, 2024
dbea33a
Fixed Indentation and Removed Trailing Spaces
varsharmavs Apr 1, 2024
afff779
Fixed Indentation
varsharmavs Apr 1, 2024
f9251d7
Added delete url to support Cascading delete.
varsharmavs Apr 2, 2024
9bf29eb
Marked Manual Approvals as required inside Approval Workflow
varsharmavs Apr 3, 2024
9834fe3
Added a create test for privileged_access_manager_enttlement
varsharmavs Apr 3, 2024
97ef2a3
Added pre-delete to support updating the approver list, keeping the a…
varsharmavs Apr 4, 2024
d9e5f92
Fixed format in Entitlement.yaml
varsharmavs Apr 4, 2024
cc5309d
Updated approvalWorkflow to now support forceNew
varsharmavs Apr 5, 2024
baba2cf
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 5, 2024
9eff94e
Fixed url Update.
varsharmavs Apr 7, 2024
162c35d
Modified basic test file to include all fields.
varsharmavs Apr 8, 2024
cbf2a3b
Added Update tests
varsharmavs Apr 10, 2024
3ebb340
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 10, 2024
2799669
Added conditionExpression field and descriptions to two fields
varsharmavs Apr 12, 2024
99b4226
Merge remote-tracking branch 'upstream/main'
varsharmavs Apr 12, 2024
29f121f
Updated services_ga.kt to include privilegedaccessmanager and Entitle…
varsharmavs Apr 13, 2024
26b513e
Update mmv1/products/privilegedaccessmanager/product.yaml
varsharmavs Apr 13, 2024
3c0e974
Removed trailing spaces from Entitlement.yaml
varsharmavs Apr 13, 2024
e534e7f
Updated test file
varsharmavs Apr 13, 2024
9c85c80
Renamed the test file
varsharmavs Apr 13, 2024
264cbd0
Added 'min_version:beta' to Entitlement
varsharmavs Apr 15, 2024
9f82986
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 15, 2024
7a1ab4e
Removed Required from description to avoid repeatations in doc
varsharmavs Apr 15, 2024
f7cc768
Changed parent and location to include Environment Variables
varsharmavs Apr 15, 2024
1ec89f2
Replaced location with static values
varsharmavs Apr 15, 2024
0bfb66e
Replaced project name with the static value: 'ci-test-project-188019'
varsharmavs Apr 15, 2024
fb5ccd8
added min_size and max_size to approvers and principals
varsharmavs Apr 16, 2024
40785ff
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
189b863
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
5456703
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
2d166ca
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
b0661bb
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
4065574
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 17, 2024
98c5c08
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 18, 2024
5fc88d3
added condition_expression in test configs and set principal in appro…
varsharmavs Apr 18, 2024
4bca299
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 19, 2024
010d90a
Added Validation to entitlementId
varsharmavs Apr 19, 2024
edfe1c1
Merge branch 'GoogleCloudPlatform:main' into main
varsharmavs Apr 20, 2024
878ee4a
added Validation to check for deleted IAM Principals
varsharmavs Apr 20, 2024
321dce2
Imported envvar
varsharmavs Apr 22, 2024
d9ac902
Imported envvar
varsharmavs Apr 22, 2024
d8ec868
formatted "*_test.go.erb" file
varsharmavs Apr 22, 2024
09c3d2c
Updated constants for better error throw.
varsharmavs Apr 22, 2024
bd5905c
Fixed EntitlementId name to match the valid regex
varsharmavs Apr 22, 2024
0beb4fa
update test.go.erb
varsharmavs Apr 22, 2024
8e0869b
changed location to global
varsharmavs Apr 22, 2024
814d3ba
Updated import_format and added example emails to few fields
varsharmavs Apr 23, 2024
960a9c1
Resolved comments by gkmr
varsharmavs Apr 23, 2024
47ba84b
removed extra '/'
varsharmavs Apr 23, 2024
816858d
Update mmv1/products/privilegedaccessmanager/Entitlement.yaml
varsharmavs Apr 24, 2024
a2c8317
Update mmv1/third_party/terraform/services/privilegedaccessmanager/re…
varsharmavs Apr 24, 2024
39910f1
Update mmv1/products/privilegedaccessmanager/Entitlement.yaml
varsharmavs Apr 24, 2024
b0afcd0
Update mmv1/products/privilegedaccessmanager/Entitlement.yaml
varsharmavs Apr 24, 2024
afd9374
removed default value
varsharmavs Apr 24, 2024
323ce5c
updated Entitlement.yaml
varsharmavs Apr 24, 2024
b67ce82
added condition expression and a generic IAM principal
varsharmavs Apr 24, 2024
6b3ae09
updated condition expression
varsharmavs Apr 24, 2024
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
264 changes: 264 additions & 0 deletions mmv1/products/privilegedaccessmanager/Entitlement.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
# Copyright 2023 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

--- !ruby/object:Api::Resource
base_url: '{{parent}}/locations/{{location}}/entitlements'
create_url: '{{parent}}/locations/{{location}}/entitlements?entitlementId={{entitlement_id}}'
delete_url: '{{parent}}/locations/{{location}}/entitlements/{{entitlement_id}}?force=true'
self_link: '{{parent}}/locations/{{location}}/entitlements/{{entitlement_id}}'
id_format: '{{parent}}/locations/{{location}}/entitlements/{{entitlement_id}}'
import_format: ['{{%parent}}/locations/{{location}}/entitlements/{{entitlement_id}}']
name: Entitlement
description: |
An Entitlement defines the eligibility of a set of users to obtain a predefined access for some time possibly after going through an approval workflow.
update_verb: :PATCH
update_mask: true
min_version: beta
autogen_async: true
examples:
- !ruby/object:Provider::Terraform::Examples
name: "privileged_access_manager_entitlement_basic"
min_version: beta
primary_resource_id: "tfentitlement"
vars:
entitlement_id: "example-entitlement"
test_env_vars:
project: :PROJECT_NAME
properties:
- !ruby/object:Api::Type::String
name: name
description: |
Output Only. The entitlement's name follows a hierarchical structure, comprising the organization, folder, or project, alongside the region and a unique entitlement ID.
Formats: organizations/{organization-number}/locations/{region}/entitlements/{entitlement-id}, folders/{folder-number}/locations/{region}/entitlements/{entitlement-id}, and projects/{project-id|project-number}/locations/{region}/entitlements/{entitlement-id}.
output: true
- !ruby/object:Api::Type::String
name: createTime
description: |
Output only. Create time stamp. A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits.
Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z"
output: true
- !ruby/object:Api::Type::String
name: updateTime
description: |
Output only. Update time stamp. A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits.
Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".
output: true
- !ruby/object:Api::Type::Array
name: eligibleUsers
description: |
Who can create Grants using Entitlement. This list should contain at most one entry
required: true
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::Array
name: principals
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
is_set: true
required: true
description: |
Users who are being allowed for the operation. Each entry should be a valid v1 IAM Principal Identifier. Format for these is documented at "https://cloud.google.com/iam/docs/principal-identifiers#v1"
item_type: Api::Type::String
item_validation: !ruby/object:Provider::Terraform::Validation
function: 'validateDeletedPrincipals'
- !ruby/object:Api::Type::NestedObject
name: approvalWorkflow
immutable: true
description: |
The approvals needed before access will be granted to a requester.
No approvals will be needed if this field is null. Different types of approval workflows that can be used to gate privileged access granting.
properties:
- !ruby/object:Api::Type::NestedObject
name: manualApprovals
required: true
description: |
A manual approval workflow where users who are designated as approvers need to call the ApproveGrant/DenyGrant APIs for an Grant.
The workflow can consist of multiple serial steps where each step defines who can act as Approver in that step and how many of those users should approve before the workflow moves to the next step.
This can be used to create approval workflows such as
* Require an approval from any user in a group G.
* Require an approval from any k number of users from a Group G.
* Require an approval from any user in a group G and then from a user U. etc.
A single user might be part of `approvers` ACL for multiple steps in this workflow but they can only approve once and that approval will only be considered to satisfy the approval step at which it was granted.
properties:
- !ruby/object:Api::Type::Boolean
name: requireApproverJustification
description: |
Optional. Do the approvers need to provide a justification for their actions?
- !ruby/object:Api::Type::Array
name: steps
required: true
description: |
List of approval steps in this workflow. These steps would be followed in the specified order sequentially. 1 step is supported for now.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::Array
name: approvers
required: true
min_size: 1
max_size: 1
description: |
The potential set of approvers in this step. This list should contain at only one entry.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::Array
name: principals
required: true
min_size: 1
is_set: true
item_type: Api::Type::String
item_validation: !ruby/object:Provider::Terraform::Validation
function: 'validateDeletedPrincipals'
description: |
Users who are being allowed for the operation. Each entry should be a valid v1 IAM Principal Identifier. Format for these is documented at: https://cloud.google.com/iam/docs/principal-identifiers#v1
- !ruby/object:Api::Type::Integer
name: approvalsNeeded
description: |
How many users from the above list need to approve.
If there are not enough distinct users in the list above then the workflow
will indefinitely block. Should always be greater than 0. Currently 1 is the only
supported value.
- !ruby/object:Api::Type::Array
name: approverEmailRecipients
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
item_type: Api::Type::String
is_set: true
description: |
Optional. Additional email addresses to be notified when a grant is pending approval.
- !ruby/object:Api::Type::NestedObject
name: privilegedAccess
description: |
Privileged access that this service can be used to gate.
required: true
properties:
- !ruby/object:Api::Type::NestedObject
name: gcpIamAccess
description: |
GcpIamAccess represents IAM based access control on a GCP resource. Refer to https://cloud.google.com/iam/docs to understand more about IAM.
required: true
properties:
- !ruby/object:Api::Type::String
name: resourceType
description: |
The type of this resource.
required: true
- !ruby/object:Api::Type::String
name: resource
description: |
Name of the resource.
required: true
- !ruby/object:Api::Type::Array
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
name: roleBindings
description: |
Role bindings to be created on successful grant.
required: true
item_type: !ruby/object:Api::Type::NestedObject
properties:
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
- !ruby/object:Api::Type::String
name: role
description: |
IAM role to be granted. https://cloud.google.com/iam/docs/roles-overview.
required: true
- !ruby/object:Api::Type::String
name: conditionExpression
description: |
The expression field of the IAM condition to be associated with the role. If specified, a user with an active grant for this entitlement would be able to access the resource only if this condition evaluates to true for their request.
https://cloud.google.com/iam/docs/conditions-overview#attributes.
- !ruby/object:Api::Type::String
name: maxRequestDuration
description: |
The maximum amount of time for which access would be granted for a request.
A requester can choose to ask for access for less than this duration but never more.
Format: calculate the time in seconds and concatenate it with 's' i.e. 2 hours = "7200s", 45 minutes = "2700s"
required: true
- !ruby/object:Api::Type::String
name: state
description: Output only. The current state of the Entitlement.
output: true
- !ruby/object:Api::Type::Fingerprint
name: etag
description: |
For Resource freshness validation (https://google.aip.dev/154)
output: true
- !ruby/object:Api::Type::NestedObject
name: requesterJustificationConfig
description: |
Defines the ways in which a requester should provide the justification while requesting for access.
required: true
allow_empty_object: true
send_empty_value: true
properties:
- !ruby/object:Api::Type::NestedObject
name: notMandatory
description: |
The justification is not mandatory but can be provided in any of the supported formats.
properties: []
allow_empty_object: true
send_empty_value: true
conflicts:
- unstructured
- !ruby/object:Api::Type::NestedObject
name: unstructured
description: |
The requester has to provide a justification in the form of free flowing text.
properties: []
allow_empty_object: true
send_empty_value: true
conflicts:
- not_mandatory
- !ruby/object:Api::Type::NestedObject
name: additionalNotificationTargets
allow_empty_object: true
send_empty_value: true
description: |
AdditionalNotificationTargets includes email addresses to be notified.
properties:
- !ruby/object:Api::Type::Array
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
name: adminEmailRecipients
is_set: true
description: |
Optional. Additional email addresses to be notified when a principal(requester) is granted access.
item_type: Api::Type::String
allow_empty_object: true
- !ruby/object:Api::Type::Array
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
name: requesterEmailRecipients
item_type: Api::Type::String
is_set: true
description: |
Optional. Additional email address to be notified about an eligible entitlement.
allow_empty_object: true
parameters:
- !ruby/object:Api::Type::String
name: location
description: |
The region of the Entitlement resource.
url_param_only: true
required: true
immutable: true
- !ruby/object:Api::Type::String
name: entitlementId
description: |
The ID to use for this Entitlement. This will become the last part of the resource name.
This value should be 4-63 characters, and valid characters are "[a-z]", "[0-9]", and "-". The first character should be from [a-z].
This value should be unique among all other Entitlements under the specified `parent`.
url_param_only: true
required: true
immutable: true
validation: !ruby/object:Provider::Terraform::Validation
function: validateEntitlementId
- !ruby/object:Api::Type::String
name: parent
immutable: true
required: true
url_param_only: true
description: |
Format: project/{project_id} or organization/{organization_number} or folder/{folder_number}
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
custom_code: !ruby/object:Provider::Terraform::CustomCode
pre_update: templates/terraform/pre_update/privileged_access_manager_entitlement.go.erb
constants: templates/terraform/constants/privileged_access_manager_entitlement.go.erb
40 changes: 40 additions & 0 deletions mmv1/products/privilegedaccessmanager/product.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2020 google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

--- !ruby/object:Api::Product
versions:
- !ruby/object:Api::Product::Version
base_url: https://privilegedaccessmanager.googleapis.com/v1beta/
name: beta
name: PrivilegedAccessManager
display_name: Privileged Access Manager
scopes:
- https://www.googleapis.com/auth/cloud-platform
async: !ruby/object:Api::OpAsync
operation: !ruby/object:Api::OpAsync::Operation
path: name
base_url: "{{op_id}}"
wait_ms: 1000
timeouts:
result: !ruby/object:Api::OpAsync::Result
path: response
resource_inside_response: true
status: !ruby/object:Api::OpAsync::Status
path: done
complete: true
allowed:
- true
- false
error: !ruby/object:Api::OpAsync::Error
path: error
message: message
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const deletedRegexp = `^deleted:`

func validateDeletedPrincipals(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if regexp.MustCompile(deletedRegexp).MatchString(value) {
errors = append(errors, fmt.Errorf(
"Terraform does not support IAM policies for deleted principals: %s", k))
}

return
}

const entitlementIdRegexp = `^[a-z][a-z0-9-]{3,62}$`

func validateEntitlementId(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(entitlementIdRegexp).MatchString(value) {
errors = append(errors, fmt.Errorf(
"Entitlement Id should be 4-63 characters, and valid characters are '[a-z]', '[0-9]', and '-'. The first character should be from [a-z]. : %s", k))
}

return
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
resource "google_privileged_access_manager_entitlement" "<%= ctx[:primary_resource_id] %>" {
provider = google-beta
entitlement_id = "<%= ctx[:vars]['entitlement_id'] %>"
location = "global"
max_request_duration = "43200s"
parent = "projects/<%= ctx[:test_env_vars]['project'] %>"
requester_justification_config {
unstructured{}
}
eligible_users {
principals = ["group:[email protected]"]
}
privileged_access{
gcp_iam_access{
role_bindings{
role = "roles/storage.admin"
condition_expression = "request.time < timestamp(\"2024-04-23T18:30:00.000Z\")"
}
resource = "//cloudresourcemanager.googleapis.com/projects/<%= ctx[:test_env_vars]['project'] %>"
resource_type = "cloudresourcemanager.googleapis.com/Project"
}
}
additional_notification_targets {
admin_email_recipients = ["[email protected]"]
varsharmavs marked this conversation as resolved.
Show resolved Hide resolved
requester_email_recipients = ["[email protected]"]
}
approval_workflow {
manual_approvals {
require_approver_justification = true
steps {
approvals_needed = 1
approver_email_recipients = ["[email protected]"]
approvers {
principals = ["group:[email protected]"]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
approvalWorkflowProp, err := expandPrivilegedAccessManagerEntitlementApprovalWorkflow(d.Get("approval_workflow"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("approval_workflow"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, approvalWorkflowProp)) {
obj["approvalWorkflow"] = approvalWorkflowProp
}
if d.HasChange("approval_workflow") {
updateMask = append(updateMask, "approvalWorkflow")
}
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
if err != nil {
return err
}
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,11 @@ var ServicesListBeta = mapOf(
"displayName" to "Privateca",
"path" to "./google-beta/services/privateca"
),
"privilegedaccessmanager" to mapOf(
"name" to "privilegedaccessmanager",
"displayName" to "Privilegedaccessmanager",
"path" to "./google-beta/services/privilegedaccessmanager"
),
"publicca" to mapOf(
"name" to "publicca",
"displayName" to "Publicca",
Expand Down
Loading
Loading