forked from GoogleCloudPlatform/magic-modules
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
terraform Support for Managing Entitlements. (GoogleCloudPlatform#10334)
Co-authored-by: Nick Elliot <[email protected]>
- Loading branch information
Showing
8 changed files
with
526 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
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 | ||
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 | ||
name: roleBindings | ||
description: | | ||
Role bindings to be created on successful grant. | ||
required: true | ||
item_type: !ruby/object:Api::Type::NestedObject | ||
properties: | ||
- !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 | ||
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 | ||
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} | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
23 changes: 23 additions & 0 deletions
23
mmv1/templates/terraform/constants/privileged_access_manager_entitlement.go.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
39 changes: 39 additions & 0 deletions
39
mmv1/templates/terraform/examples/privileged_access_manager_entitlement_basic.tf.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]"] | ||
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]"] | ||
} | ||
} | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
mmv1/templates/terraform/pre_update/privileged_access_manager_entitlement.go.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.