Skip to content

Commit

Permalink
[DM] Shared VPC Subnet IAM refactoring
Browse files Browse the repository at this point in the history
Refactored shared_vpc_subnet_iam template. Added bindings and policy syntax tests(in addition to legacy syntax check) (#215)
  • Loading branch information
ivankorn authored and ocsig committed Jul 11, 2019
1 parent 2517803 commit d99d2e5
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 61 deletions.
10 changes: 8 additions & 2 deletions dm/templates/shared_vpc_subnet_iam/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,11 @@ See `properties` section in the schema file(s):
```

## Examples

- [Shared VPC Subnet IAM](examples/shared_vpc_subnet_iam.yaml)
- [Shared VPC Subnet IAM Bindings syntax](examples/shared_vpc_subnet_iam_bindings.yaml)
- [Shared VPC Subnet IAM Policy syntax](examples/shared_vpc_subnet_iam_policy.yaml)
- [Shared VPC Subnet IAM Legacy](examples/shared_vpc_subnet_iam_legacy.yaml)

## Tests Cases
- [Shared VPC Subnet IAM Bindings syntax](tests/integration/bindings.bats)
- [Shared VPC Subnet IAM Policy syntax](tests/integration/policy.bats)
- [Shared VPC Subnet IAM Legacy syntax](tests/integration/legacy.bats)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Example usage of the shared VPC subnet IAM template
#
# The `members` property is a list of members to
# grant IAM roles on a shared VPC subnetwork.
# A member can be a user, service account, group, or domain.
#
# Replace `resourceId` with a valid subnet ID.

imports:
- path: templates/shared_vpc_subnet_iam/shared_vpc_subnet_iam.py
name: shared_vpc_subnet_iam.py

resources:
- name: test-shared-vpc-subnet-iam-policy
type: shared_vpc_subnet_iam.py
properties:
bindings:
- resourceId: test-subnet-1
region: us-east1
role: roles/compute.networkUser
members:
- user:[email protected]
- serviceAccount:[email protected]
- resourceId: <FIXME:subnetId>
region: us-east1
role: roles/compute.networkUser
members:
- group:[email protected]
- domain:example.com
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Example usage of the shared VPC subnet IAM template
#
# The `members` property is a list of members to
# grant IAM roles on a shared VPC subnetwork.
# A member can be a user, service account, group, or domain.
#
# Replace `resourceId` with a valid subnet ID.

imports:
- path: templates/shared_vpc_subnet_iam/shared_vpc_subnet_iam.py
name: shared_vpc_subnet_iam.py

resources:
- name: test-shared-vpc-subnet-iam-policy
type: shared_vpc_subnet_iam.py
properties:
policy:
bindings:
- resourceId: test-subnet-1
region: us-east1
role: roles/compute.networkUser
members:
- user:[email protected]
- serviceAccount:[email protected]
- resourceId: <FIXME:subnetId>
region: us-east1
role: roles/compute.networkUser
members:
- group:[email protected]
- domain:example.com
68 changes: 41 additions & 27 deletions dm/templates/shared_vpc_subnet_iam/shared_vpc_subnet_iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,57 @@
# 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.
""" This template grants IAM roles to a user on a shared VPC subnetwork. """
"""This template grants IAM roles to a user on a shared VPC subnetwork."""


def generate_config(context):
""" Entry point for the deployment resources. """

def _append_resource(subnets, project, name_id):
"""Append subnets to resources."""
resources = []
out = {}
for subnet in context.properties['subnets']:
subnet_id = subnet['subnetId']
policy_name = 'iam-subnet-policy-{}'.format(subnet_id)

policies_to_add = [
{
'role': subnet['role'],
'members': subnet['members']
for subnet in subnets:
policy_name = 'iam-subnet-policy-{}'.format(subnet[name_id])
resources.append({
'name': policy_name,
# https://cloud.google.com/compute/docs/reference/rest/beta/subnetworks/setIamPolicy
'type': 'gcp-types/compute-beta:compute.subnetworks.setIamPolicy',
'properties': {
'name': subnet[name_id],
'project': project,
'region': subnet['region'],
'bindings': [{
'role': subnet['role'],
'members': subnet['members']
}]
}
]

resources.append(
{
'name': policy_name,
'type': 'gcp-types/compute-beta:compute.subnetworks.setIamPolicy', # pylint: disable=line-too-long
'properties':
{
'name': subnet_id,
'project': context.env['project'],
'region': subnet['region'],
'bindings': policies_to_add
}
}
)
})

out[policy_name] = {
'etag': '$(ref.' + policy_name + '.etag)'
}
return resources, out


def generate_config(context):
"""Entry point for the deployment resources."""
try:
resources, out = _append_resource(
context.properties['subnets'], # Legacy syntax
context.env['project'],
'subnetId'
)
except KeyError:
try:
resources, out = _append_resource(
context.properties['policy']['bindings'], # Policy syntax
context.env['project'],
'resourceId'
)
except KeyError:
resources, out = _append_resource(
context.properties['bindings'], # Bindings syntax
context.env['project'],
'resourceId'
)
outputs = [{'name': 'policies', 'value': out}]

return {'resources': resources, 'outputs': outputs}
196 changes: 164 additions & 32 deletions dm/templates/shared_vpc_subnet_iam/shared_vpc_subnet_iam.py.schema
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,176 @@
info:
title: Shared VPC Subnet IAM
author: Sourced Group Inc.
description: Grants IAM roles to a user on a shared VPC subnetwork
version: 1.0.0
description: |
Grants IAM roles to a user on a shared VPC subnetwork

For more information on this resource:
https://cloud.google.com/compute/docs/reference/rest/beta/subnetworks

APIs endpoints used by this template:
- gcp-types/compute-beta:compute.subnetworks.setIamPolicy =>
https://cloud.google.com/compute/docs/reference/rest/beta/subnetworks/setIamPolicy

imports:
- path: shared_vpc_subnet_iam.py

oneOf:
- required:
- bindings
- required:
- policy
- required:
- subnets # Legacy

additionalProperties: false

required:
- subnets
project:
type: string
description: The Project ID.

properties:
subnets:
type: array
description: An array of subnetworks and members to grant IAM roles to.
items:
subnetId:
type: string
description: The subnet ID.
region:
type: string
description: The region the subnetId resides in.
role:
type: string
description: The role to grant.
members:
definitions:
policy:
type: object
description: |
REQUIRED: The complete policy to be applied to the 'resource'.
The size of the policy is limited to a few 10s of KB. An empty policy is
in general a valid policy but certain services (like Projects) might
reject them.
additionalProperties: false
properties:
version:
type: integer
description: Deprecated
bindings:
type: array
description: A list of member identities.
description: |
Associates a list of members to a role. bindings with no members will
result in an error.
uniqItems: true
items:
type: string
description: |
The identity of a member requesting access for a Cloud Platform
resource. Can have the following values:
- user:{emailid} - An email address that represents a specific
Google account. For example, user:[email protected]
- serviceAccount:{emailid} - An email address that represents a
service account. For example,
serviceAccount:[email protected]
- group:{emailid} - An email address that represents a Google group.
For example, group:[email protected]
- domain:{domain} - A Google Apps domain name that represents all
the users of that domain. For example, google.com or example.com.
subnetId: # legacy
type: string
description: The subnet ID.
requestId:
type: string
description: Name or id of the resource for this request.
role:
type: string
description: |
Role that is assigned to members. For example,
roles/viewer, roles/editor, or roles/owner.
members:
type: array
description: A list of member identities.
uniqItems: true
items:
type: string
description: |
Specifies the identities requesting access for a Cloud Platform
resource. `members` can have the following values:
- allUsers: A special identifier that represents anyone who
is on the internet; with or without a Google account.
- allAuthenticatedUsers: A special identifier that represents
anyone who is authenticated with a Google account or a
service account.
- user:{emailid} - An email address that represents a
specific Google account. For example, user:[email protected]
- serviceAccount:{emailid} - An email address that represents
a service account. For example,
serviceAccount:[email protected]
- group:{emailid} - An email address that represents a Google
group. For example, group:[email protected]
- domain:{domain} - A Google Apps domain name that represents
all the users of that domain. For example,
google.com or example.com.
condition:
type: object
description: |
The condition that is associated with this binding. NOTE: An
unsatisfied condition will not allow user access via current
binding. Different bindings, including their conditions, are
examined independently.
additionalProperties: false
properties:
expression:
type: string
description: |
Textual representation of an expression in Common Expression
Language syntax. The application context of the containing
message determines which well-known feature set of CEL is
supported.
title:
type: string
description: |
An optional title for the expression, i.e. a short string
describing its purpose. This can be used e.g. in UIs which
allow to enter the expression.
description:
type: string
description: |
An optional description of the expression. This is a longer
text which describes the expression, e.g. when hovered over
it in a UI.
location:
type: string
description: |
An optional string indicating the location of the expression
for error reporting, e.g. a file name and a position in the
file.
auditConfigs:
type: object
description: |
Specifies cloud audit logging configuration for this policy.
additionalProperties: false
properties:
service:
type: string
description: |
Specifies a service that will be enabled for audit logging.
For example, storage.googleapis.com, cloudsql.googleapis.com.
allServices is a special value that covers all services.
auditLogConfigs:
type: object
description: |
The configuration for logging of each type of permission.
additionalProperties: false
properties:
logType:
type: string
description: The log type that this config enables.
exemptedMembers:
type: array
description: |
Specifies the identities that do not cause logging for this
type of permission. Follows the same format of
Binding.members.
uniqItems: true
items:
type: string
etag:
type: string
description: |
etag is used for optimistic concurrency control as a way to help
prevent simultaneous updates of a policy from overwriting each other.
It is strongly suggested that systems make use of the etag in the
read-modify-write cycle to perform policy updates in order to avoid
race conditions: An etag is returned in the response to getIamPolicy,
and systems are expected to put that etag in the request to
setIamPolicy to ensure that their change will be applied to the same
version of the policy. If no etag is provided in the call to
setIamPolicy, then the existing policy is overwritten blindly.
A base64-encoded string.

properties:
policy:
$ref: '#/definitions/policy'
bindings:
$ref: '#/definitions/policy/properties/bindings'
subnets: # legacy
$ref: '#/definitions/policy/properties/bindings'
etag:
$ref: '#/definitions/policy/properties/etag'

outputs:
properties:
Expand Down
25 changes: 25 additions & 0 deletions dm/templates/shared_vpc_subnet_iam/tests/integration/bindings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Test of the shared VPC subnet IAM template.
#
# Variables:
# RAND: A random string used by the testing suite.
#

imports:
- path: templates/shared_vpc_subnet_iam/shared_vpc_subnet_iam.py
name: shared_vpc_subnet_iam.py

resources:
- name: test-shared-vpc-subnet-iam-${RAND}
type: shared_vpc_subnet_iam.py
properties:
bindings:
- resourceId: subnet-${RAND}-1
region: us-east1
role: roles/compute.networkUser
members:
- serviceAccount:${TEST_SERVICE_ACCOUNT}@${CLOUD_FOUNDATION_PROJECT_ID}.iam.gserviceaccount.com
- resourceId: subnet-${RAND}-2
region: us-east1
role: roles/compute.networkUser
members:
- serviceAccount:${TEST_SERVICE_ACCOUNT}@${CLOUD_FOUNDATION_PROJECT_ID}.iam.gserviceaccount.com
Loading

0 comments on commit d99d2e5

Please sign in to comment.