Skip to content

Commit

Permalink
feat: Added Service Account key distributor submodule (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Canty authored Nov 25, 2020
1 parent 0844ae1 commit fb794a5
Show file tree
Hide file tree
Showing 32 changed files with 926 additions and 42 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ crash.log
**/*.tfvars

credentials.json
**/go.sum
**/*.gpg
**/get-key
**/*.zip
8 changes: 8 additions & 0 deletions kitchen.yml → .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,11 @@ suites:
backend: gcp
controls:
- gcp
- name: key_distributor
driver:
root_module_directory: test/fixtures/key_distributor/
verifier:
color: false
systems:
- name: key_distributor
backend: local
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ Functional examples are included in the
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| billing\_account\_id | If assigning billing role, specificy a billing account (default is to assign at the organizational level). | string | `""` | no |
| description | Descriptions of the created service accounts (defaults to no description) | string | `""` | no |
| display\_name | Display names of the created service accounts (defaults to 'Terraform-managed service account') | string | `"Terraform-managed service account"` | no |
| generate\_keys | Generate keys for service accounts. | bool | `"false"` | no |
| grant\_billing\_role | Grant billing user role. | bool | `"false"` | no |
| grant\_xpn\_roles | Grant roles for shared VPC management. | bool | `"true"` | no |
| names | Names of the service accounts to create. | list(string) | `<list>` | no |
| org\_id | Id of the organization for org-level roles. | string | `""` | no |
| prefix | Prefix applied to service account names. | string | `""` | no |
| project\_id | Project id where service account will be created. | string | n/a | yes |
| project\_roles | Common roles to apply to all service accounts, project=>role as elements. | list(string) | `<list>` | no |
|------|-------------|------|---------|:--------:|
| billing\_account\_id | If assigning billing role, specificy a billing account (default is to assign at the organizational level). | `string` | `""` | no |
| description | Descriptions of the created service accounts (defaults to no description) | `string` | `""` | no |
| display\_name | Display names of the created service accounts (defaults to 'Terraform-managed service account') | `string` | `"Terraform-managed service account"` | no |
| generate\_keys | Generate keys for service accounts. | `bool` | `false` | no |
| grant\_billing\_role | Grant billing user role. | `bool` | `false` | no |
| grant\_xpn\_roles | Grant roles for shared VPC management. | `bool` | `true` | no |
| names | Names of the service accounts to create. | `list(string)` | `[]` | no |
| org\_id | Id of the organization for org-level roles. | `string` | `""` | no |
| prefix | Prefix applied to service account names. | `string` | `""` | no |
| project\_id | Project id where service account will be created. | `string` | n/a | yes |
| project\_roles | Common roles to apply to all service accounts, project=>role as elements. | `list(string)` | `[]` | no |

## Outputs

Expand Down
46 changes: 46 additions & 0 deletions examples/key_distributor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Key Distributor Cloud Function

This example illustrates how to use the `key-distributor` submodule to generate a secure service account key distribution Cloud Function.

## Exporting GPG Public Key

On top of the typical Terraform setup, we need to export the public key the Cloud Function will use. Make sure you have the key you need in your local
gpg key chain. If it's in a public key server you can download it with:

```
gpg --receive-keys <key-id>
```

Once it's there locally, you can export the ASCII armored version of it with this and store it into a file:

```
gpg --export --armor <key-id> > pubkey.asc
```

For usage instructions, see the [module README](../../modules/key-distributor/README.md)

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| cfn\_members | List of Cloud Function invokers in IAM member format(ex. `["user:[email protected]"]`). | `list(string)` | n/a | yes |
| project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes |
| public\_key\_file | ASCII armored PGP public key file | `string` | n/a | yes |
| region | Region where the Cloud Function will be launched | `string` | `"us-central1"` | no |

## Outputs

| Name | Description |
|------|-------------|
| function\_name | n/a |
| project\_id | n/a |
| region | n/a |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

To provision this example, run the following from within this directory:
- `terraform init` to get the plugins
- `terraform plan` to see the infrastructure plan
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure
23 changes: 23 additions & 0 deletions examples/key_distributor/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright 2020 Google LLC
*
* 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.
*/

module "distributor" {
source = "../../modules/key-distributor"

project_id = var.project_id
public_key_file = var.public_key_file
function_members = var.cfn_members
}
27 changes: 27 additions & 0 deletions examples/key_distributor/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright 2020 Google LLC
*
* 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.
*/

output "project_id" {
value = var.project_id
}

output "function_name" {
value = module.distributor.function_name
}

output "region" {
value = module.distributor.region
}
35 changes: 35 additions & 0 deletions examples/key_distributor/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2020 Google LLC
*
* 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.
*/

variable "project_id" {
description = "The ID of the project in which to provision resources."
type = string
}

variable "public_key_file" {
description = "ASCII armored PGP public key file"
type = string
}

variable "cfn_members" {
description = "List of Cloud Function invokers in IAM member format(ex. `[\"user:[email protected]\"]`)."
type = list(string)
}

variable "region" {
description = "Region where the Cloud Function will be launched"
default = "us-central1"
}
4 changes: 2 additions & 2 deletions examples/multiple_service_accounts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This example illustrates how to use the `service-accounts` module to generate mu
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| project\_id | The ID of the project in which to provision resources. | string | n/a | yes |
|------|-------------|------|---------|:--------:|
| project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes |

## Outputs

Expand Down
6 changes: 3 additions & 3 deletions examples/single_service_account/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ This example illustrates how to use the `service-accounts` module to generate a
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| prefix | Prefix applied to service account names. | string | `""` | no |
| project\_id | The ID of the project in which to provision resources. | string | n/a | yes |
|------|-------------|------|---------|:--------:|
| prefix | Prefix applied to service account names. | `string` | `""` | no |
| project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes |

## Outputs

Expand Down
24 changes: 14 additions & 10 deletions helpers/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@
import re
import json


def get_key_for_each_key(state, old_resource):
account_id = state.resource_value(old_resource, "service_account_id")
name = account_id.split('@')[0]
return name
account_id = state.resource_value(old_resource, "service_account_id")
name = account_id.split('@')[0]
return name


def get_iam_for_each_key(state, old_resource):
account_id = state.resource_value(old_resource, "service_account_id")
name = account_id.split('@')[0]
return name
account_id = state.resource_value(old_resource, "service_account_id")
name = account_id.split('@')[0]
return name


MIGRATIONS = [
{
Expand All @@ -48,6 +51,7 @@ def get_iam_for_each_key(state, old_resource):
}
]


class ModuleMigration:
"""
Migrate the resources from a flat project factory to match the new
Expand Down Expand Up @@ -113,11 +117,11 @@ def for_each_moves(self, for_each_migrations):
# Whole collection is moved to new location. Now needs right index
new.plural = True
new_indexed = copy.deepcopy(new)
if callable(migration["for_each_migration_key"]):
new_indexed.key = migration["for_each_migration_key"](self.state, old)
mig = migration["for_each_migration_key"]
if callable(mig):
new_indexed.key = mig(self.state, old)
else:
new_indexed.key = self.state.resource_value(
old, migration["for_each_migration_key"])
new_indexed.key = self.state.resource_value(old, mig)
pair = (new.path(), new_indexed.path())
moves.append(pair)

Expand Down
Loading

0 comments on commit fb794a5

Please sign in to comment.