Merge pull request #379 from terraform-google-modules/sa-upload-crt
SA key uploading and credentials json generation with terraform.
This commit is contained in:
commit
0fe5b6b03f
|
@ -23,7 +23,7 @@ Currently available examples:
|
||||||
- **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments)
|
- **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments)
|
||||||
- **networking** - [hub and spoke via peering](./networking/hub-and-spoke-peering/), [hub and spoke via VPN](./networking/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./networking/onprem-google-access-dns/), [Shared VPC with GKE support](./networking/shared-vpc-gke/), [ILB as next hop](./networking/ilb-next-hop), [PSC for on-premises Cloud Function invocation](./networking/private-cloud-function-from-onprem/), [decentralized firewall](./networking/decentralized-firewall)
|
- **networking** - [hub and spoke via peering](./networking/hub-and-spoke-peering/), [hub and spoke via VPN](./networking/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./networking/onprem-google-access-dns/), [Shared VPC with GKE support](./networking/shared-vpc-gke/), [ILB as next hop](./networking/ilb-next-hop), [PSC for on-premises Cloud Function invocation](./networking/private-cloud-function-from-onprem/), [decentralized firewall](./networking/decentralized-firewall)
|
||||||
- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/), [Cloud Storage to Bigquery with Cloud Dataflow](./data-solutions/gcs-to-bq-with-dataflow/)
|
- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/), [Cloud Storage to Bigquery with Cloud Dataflow](./data-solutions/gcs-to-bq-with-dataflow/)
|
||||||
- **cloud operations** - [Resource tracking and remediation via Cloud Asset feeds](.//cloud-operations/asset-inventory-feed-remediation), [Granular Cloud DNS IAM via Service Directory](./cloud-operations/dns-fine-grained-iam), [Granular Cloud DNS IAM for Shared VPC](./cloud-operations/dns-shared-vpc), [Compute Engine quota monitoring](./cloud-operations/quota-monitoring), [Scheduled Cloud Asset Inventory Export to Bigquery](./cloud-operations/scheduled-asset-inventory-export-bq), [Packer image builder](./cloud-operations/packer-image-builder)
|
- **cloud operations** - [Resource tracking and remediation via Cloud Asset feeds](.//cloud-operations/asset-inventory-feed-remediation), [Granular Cloud DNS IAM via Service Directory](./cloud-operations/dns-fine-grained-iam), [Granular Cloud DNS IAM for Shared VPC](./cloud-operations/dns-shared-vpc), [Compute Engine quota monitoring](./cloud-operations/quota-monitoring), [Scheduled Cloud Asset Inventory Export to Bigquery](./cloud-operations/scheduled-asset-inventory-export-bq), [Packer image builder](./cloud-operations/packer-image-builder), [On-prem SA key management](./cloud-operations/onprem-sa-key-management)
|
||||||
- **third party solutions** - [OpenShift cluster on Shared VPC](./third-party-solutions/openshift)
|
- **third party solutions** - [OpenShift cluster on Shared VPC](./third-party-solutions/openshift)
|
||||||
- **factories** - [Example environments](./factories/example-environments), [Hierarchical Firewall Policies](./factories/firewall-hierarchical-policies), [VPC Firewall Rules](./factories/firewall-vpc-rules), [Subnets](./factories/subnets)
|
- **factories** - [Example environments](./factories/example-environments), [Hierarchical Firewall Policies](./factories/firewall-hierarchical-policies), [VPC Firewall Rules](./factories/firewall-vpc-rules), [Subnets](./factories/subnets)
|
||||||
|
|
||||||
|
|
|
@ -45,3 +45,10 @@ The example's feed tracks changes to Google Compute instances, and the Cloud Fun
|
||||||
<a href="./packer-image-builder" title="Packer image builder"><img src="./packer-image-builder/diagram.png" align="left" width="280px"></a> This [example](./packer-image-builder) shows how to deploy infrastructure for a Compute Engine image builder based on [Hashicorp's Packer tool](https://www.packer.io).
|
<a href="./packer-image-builder" title="Packer image builder"><img src="./packer-image-builder/diagram.png" align="left" width="280px"></a> This [example](./packer-image-builder) shows how to deploy infrastructure for a Compute Engine image builder based on [Hashicorp's Packer tool](https://www.packer.io).
|
||||||
|
|
||||||
<br clear="left">
|
<br clear="left">
|
||||||
|
|
||||||
|
## On-prem Service Account key management
|
||||||
|
|
||||||
|
|
||||||
|
This [example](./onprem-sa-key-management) shows how to manage IAM Service Account Keys by manually generating a key pair and uploading the public part of the key to GCP.
|
||||||
|
s
|
||||||
|
<br clear="left">
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Managing on-prem service account keys by uploading public keys
|
||||||
|
|
||||||
|
When managing GCP Service Accounts with terraform, it's often a question on **how to avoid Service Account Key in the terraform state?**
|
||||||
|
|
||||||
|
This example shows how to manage IAM Service Account Keys by manually generating a key pair and uploading the public part of the key to GCP. It has the following benefits:
|
||||||
|
|
||||||
|
- no [passing keys between users](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys#pass-between-users) or systems
|
||||||
|
- no private keys stored in the terraform state (only public part of the key is in the state)
|
||||||
|
- let keys [expire automatically](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys#key-expiryhaving)
|
||||||
|
|
||||||
|
|
||||||
|
## Running the example
|
||||||
|
|
||||||
|
Clone this repository or [open it in cloud shell](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fcloud-foundation-fabric&cloudshell_print=cloud-shell-readme.txt&cloudshell_working_dir=cloud-operations%2Fonprem-sa-key-management&cloudshell_open_in_editor=cloudshell_open%2Fcloud-foundation-fabric%2Fcloud-operations%2Fonprem-sa-key-management%2Fvariables.tf), then go through the following steps to create resources:
|
||||||
|
|
||||||
|
Cleaning up example keys
|
||||||
|
```bash
|
||||||
|
rm -f /public-keys/data-uploader/
|
||||||
|
rm -f /public-keys/prisma-security/
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate keys for service accounts
|
||||||
|
```bash
|
||||||
|
mkdir keys && cd keys
|
||||||
|
openssl req -x509 -nodes -newkey rsa:2048 -days 30 \
|
||||||
|
-keyout data_uploader_private_key.pem \
|
||||||
|
-out ../public-keys/data-uploader/public_key.pem \
|
||||||
|
-subj "/CN=unused"
|
||||||
|
openssl req -x509 -nodes -newkey rsa:2048 -days 30 \
|
||||||
|
-keyout prisma_security_private_key.pem \
|
||||||
|
-out ../public-keys/prisma-security/public_key.pem \
|
||||||
|
-subj "/CN=unused"
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy service accounts and keys
|
||||||
|
```bash
|
||||||
|
cd ..
|
||||||
|
terraform init
|
||||||
|
terraform apply -var project_id=$GOOGLE_CLOUD_PROJECT
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract JSON credentials templates from terraform output and put the private part of the keys into templates
|
||||||
|
```bash
|
||||||
|
terraform show -json | jq '.values.outputs."sa-credentials".value."data-uploader"."public_key.pem" | fromjson' > data-uploader.json
|
||||||
|
terraform show -json | jq '.values.outputs."sa-credentials".value."prisma-security"."public_key.pem" | fromjson' > prisma-security.json
|
||||||
|
|
||||||
|
contents=$(jq --arg key "$(cat keys/data_uploader_private_key.pem)" '.private_key=$key' data-uploader.json) && echo "$contents" > data-uploader.json
|
||||||
|
contents=$(jq --arg key "$(cat keys/prisma_security_private_key.pem)" '.private_key=$key' prisma-security.json) && echo "$contents" > prisma-security.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing the example
|
||||||
|
Validate that service accounts json credentials are valid
|
||||||
|
```bash
|
||||||
|
gcloud auth activate-service-account --key-file prisma-security.json
|
||||||
|
gcloud auth activate-service-account --key-file data-uploader.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cleaning up
|
||||||
|
```bash
|
||||||
|
terraform destroy -var project_id=$GOOGLE_CLOUD_PROJECT
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- BEGIN TFDOC -->
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
| name | description | type | required | default |
|
||||||
|
|---|---|:---: |:---:|:---:|
|
||||||
|
| project_id | Project id. | <code title="">string</code> | ✓ | |
|
||||||
|
| *project_create* | Create project instead of using an existing one. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
|
| *service_accounts* | List of service accounts. | <code title="list(object({ name = string iam_project_roles = list(string) public_keys_path = string }))">list(object({...}))</code> | | <code title="[ { name = "data-uploader" iam_project_roles = [ "roles/bigquery.dataOwner", "roles/bigquery.jobUser", "roles/storage.objectAdmin" ] public_keys_path = "public-keys/data-uploader/" }, { name = "prisma-security" iam_project_roles = [ "roles/iam.securityReviewer" ] public_keys_path = "public-keys/prisma-security/" }, ]">...</code> |
|
||||||
|
| *services* | Service APIs to enable. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
|
||||||
|
| name | description | sensitive |
|
||||||
|
|---|---|:---:|
|
||||||
|
| sa-credentials | SA json key templates. | |
|
||||||
|
<!-- END TFDOC -->
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright 2021 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
|
||||||
|
#
|
||||||
|
# https://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.
|
||||||
|
|
||||||
|
# set a valid bucket below and rename this file to backend.tf
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
backend "gcs" {
|
||||||
|
bucket = ""
|
||||||
|
prefix = "fabric/operations/onprem-sa-key-management"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
|
||||||
|
################################# Quickstart #################################
|
||||||
|
|
||||||
|
# cleaning up example keys
|
||||||
|
|
||||||
|
- rm -f /public-keys/data-uploader/
|
||||||
|
- rm -f /public-keys/prisma-security/
|
||||||
|
|
||||||
|
# generate keys for service accounts
|
||||||
|
|
||||||
|
- mkdir keys && cd keys
|
||||||
|
- openssl req -x509 -nodes -newkey rsa:2048 -days 30 \
|
||||||
|
-keyout data_uploader_private_key.pem \
|
||||||
|
-out ../public-keys/data-uploader/public_key.pem \
|
||||||
|
-subj "/CN=unused"
|
||||||
|
- openssl req -x509 -nodes -newkey rsa:2048 -days 30 \
|
||||||
|
-keyout prisma_security_private_key.pem \
|
||||||
|
-out ../public-keys/prisma-security/public_key.pem \
|
||||||
|
-subj "/CN=unused"
|
||||||
|
|
||||||
|
# deploy service accounts and keys
|
||||||
|
|
||||||
|
- cd ..
|
||||||
|
- terraform init
|
||||||
|
- terraform apply -var project_id=$GOOGLE_CLOUD_PROJECT
|
||||||
|
|
||||||
|
|
||||||
|
# extract JSON credentials templates from terraform output and put the private part of the keys into templates
|
||||||
|
|
||||||
|
- terraform show -json | jq '.values.outputs."sa-credentials".value."data-uploader"."public_key.pem" | fromjson' > data-uploader.json
|
||||||
|
- terraform show -json | jq '.values.outputs."sa-credentials".value."prisma-security"."public_key.pem" | fromjson' > prisma-security.json
|
||||||
|
|
||||||
|
- contents=$(jq --arg key "$(cat keys/data_uploader_private_key.pem)" '.private_key=$key' data-uploader.json) && echo "$contents" > data-uploader.json
|
||||||
|
- contents=$(jq --arg key "$(cat keys/prisma_security_private_key.pem)" '.private_key=$key' prisma-security.json) && echo "$contents" > prisma-security.json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# validate that service accounts json credentials are valid
|
||||||
|
|
||||||
|
- gcloud auth activate-service-account --key-file prisma-security.json
|
||||||
|
- gcloud auth activate-service-account --key-file data-uploader.json
|
||||||
|
|
||||||
|
|
||||||
|
# cleaning up
|
||||||
|
- terraform destroy -var project_id=$GOOGLE_CLOUD_PROJECT
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
locals {
|
||||||
|
service_accounts = { for sa in var.service_accounts : sa.name => sa }
|
||||||
|
}
|
||||||
|
|
||||||
|
module "project" {
|
||||||
|
source = "../../modules/project"
|
||||||
|
name = var.project_id
|
||||||
|
project_create = var.project_create
|
||||||
|
services = var.services
|
||||||
|
}
|
||||||
|
|
||||||
|
module "integration-sa" {
|
||||||
|
source = "../../modules/iam-service-account"
|
||||||
|
for_each = local.service_accounts
|
||||||
|
project_id = module.project.project_id
|
||||||
|
name = each.value.name
|
||||||
|
iam_project_roles = {
|
||||||
|
(module.project.project_id) = each.value.iam_project_roles
|
||||||
|
}
|
||||||
|
public_keys_directory = each.value.public_keys_path
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 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 "sa-credentials" {
|
||||||
|
description = "SA json key templates."
|
||||||
|
value = { for key, value in module.integration-sa : key => value.service_account_credentials }
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICnjCCAYYCCQDhgw8htVCGmTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ1
|
||||||
|
bnVzZWQwHhcNMjExMjA2MDgwNTAyWhcNMzExMjA0MDgwNTAyWjARMQ8wDQYDVQQD
|
||||||
|
DAZ1bnVzZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0xlwdjkBS
|
||||||
|
1ovANJ1RXKpFdbPQWYlqKUUo+/KLClNYC9KxRqrc+u5FtPIdCPv5WRH5sz+z8gcf
|
||||||
|
3zJMht0dO7fOwJ9wSDKzvHkMUdXTGBPbm2i9PNA6f+YEwJQjWJlAHFH4Lp3x6ddT
|
||||||
|
4KO4FRQEkN/5V1+sfmyGGFaSXaoi+PcDcQHvfUUlp5iyX4I+8tqwh1kdg1M5orkE
|
||||||
|
7iBG0wHWzfOSmZq5in6t9+lWzOZeYapi8bVBm7Vz+dmHZPKS6EGmAXS1wpLCSKHB
|
||||||
|
uv23KXY4gAXOPHiDI70JpeNiSJBE9WgXs+nL78vNjLTvDhpC10b9nOxLjRc6wA5b
|
||||||
|
3q2Am0dW1DPRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJqyTIibNZM/q30Fn+vR
|
||||||
|
V9q++19CIervZig1uCarH1M86cpPYRfKcYHOi6tnoCTL9VG8Ky8pbmkZNkET7vnN
|
||||||
|
OQirpsPmqu3d+FBoqXUt8w1mT1JVr0YiTo3i07zTH8rvQKHjEfPxR73IAyYNvJ3D
|
||||||
|
k3SdUvU3xXOa+otOQcBKIxX6mJPLhzXgZd144KCfD95qOvpoQOsNW4UWXZ3sPC0k
|
||||||
|
VcMlN5O8/+D65y63nNtyECXvLicLdn/cdpA2H7Tqhz2ZZR+6tLcDW1kSsA8b6+rQ
|
||||||
|
1IaKpF+TYo0jMD+WLatRrOHXOWije8871zooAXq9MLVJrT889TdsmEIYT7YPWIeJ
|
||||||
|
Jcg=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,17 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICnjCCAYYCCQDXMv59IiZqfTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ1
|
||||||
|
bnVzZWQwHhcNMjExMjA2MDgwNjE3WhcNMzExMjA0MDgwNjE3WjARMQ8wDQYDVQQD
|
||||||
|
DAZ1bnVzZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOK6XwgTzL
|
||||||
|
icSITBrQBmhnYNOuggDhQr40j8/pIuTOiFZbd+ne3MhcFxpE58T9cOXgR0i/S4ok
|
||||||
|
+kcGE74H2U7RsRpNi7fJhi62T9e2CXpibURQNJD6y0lXBQkfx6kCrhyvXqHbTxm5
|
||||||
|
J0f5mpLlze+w7ATikmYI0mrU9XjtnRJOdxtGfiIaQ/suGTaZ0z4tZgAXy9RnwUAb
|
||||||
|
LPXn0BD1+GYpCs82+1q7HpMIf343VRH0AdsQJteQSj5LKfaZZTNUF9NIgKtMylck
|
||||||
|
z0Pt8TmBU0GtJX/XkSWCwMUdqdedXkvhY1XoAZPjaEBSSwq6P15PmdpDq9q2TYjD
|
||||||
|
8U3kuCX0AlWjAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADAmjI1sg150MK97DCSl
|
||||||
|
d5OpEShCypaEZSLb/mFONW6mTX2OSdF9ipd9B07BQ2DrL8Xou2/V1aDtQZOWPIGu
|
||||||
|
Hlm1LKw8sZY2rWX0Rq/v/NxY5iGRlwPMh7Rn9fnpHgaC1PktoDJEcvNMpzBjtfKn
|
||||||
|
beKP9MNSChAFTTbJVWO5xT/ljE/yoPL3jyJKzKHH7y7AfbonrbQjAENbX/WCRYh3
|
||||||
|
zOEWZG/fusRcKkZ/cO7wFFP1gzJFE9wFRu7LOA/FntCixtVSnclsOnunQfqQEVmp
|
||||||
|
Y0IjfceIerJysCTo0I5HfRw0DOFfZimallOa4Mv5BDmzMWWyX9TvppHCnmqvM2El
|
||||||
|
ISY=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 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_create" {
|
||||||
|
description = "Create project instead of using an existing one."
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_id" {
|
||||||
|
description = "Project id."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "service_accounts" {
|
||||||
|
description = "List of service accounts."
|
||||||
|
type = list(object({
|
||||||
|
name = string
|
||||||
|
iam_project_roles = list(string)
|
||||||
|
public_keys_path = string
|
||||||
|
}))
|
||||||
|
default = [
|
||||||
|
{
|
||||||
|
name = "data-uploader"
|
||||||
|
iam_project_roles = [
|
||||||
|
"roles/bigquery.dataOwner",
|
||||||
|
"roles/bigquery.jobUser",
|
||||||
|
"roles/storage.objectAdmin"
|
||||||
|
]
|
||||||
|
public_keys_path = "public-keys/data-uploader/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "prisma-security"
|
||||||
|
iam_project_roles = [
|
||||||
|
"roles/iam.securityReviewer"
|
||||||
|
]
|
||||||
|
public_keys_path = "public-keys/prisma-security/"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "services" {
|
||||||
|
description = "Service APIs to enable."
|
||||||
|
type = list(string)
|
||||||
|
default = []
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright 2021 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
|
||||||
|
#
|
||||||
|
# https://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.
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0.0"
|
||||||
|
required_providers {
|
||||||
|
google = {
|
||||||
|
source = "hashicorp/google"
|
||||||
|
version = ">= 4.0.0"
|
||||||
|
}
|
||||||
|
google-beta = {
|
||||||
|
source = "hashicorp/google-beta"
|
||||||
|
version = ">= 4.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Google Service Account Module
|
# Google Service Account Module
|
||||||
|
|
||||||
This module allows simplified creation and management of one a service account and its IAM bindings. A key can optionally be generated and will be stored in Terraform state. To use it create a sensitive output in your root modules referencing the `key` output, then extract the private key from the JSON formatted outputs.
|
This module allows simplified creation and management of one a service account and its IAM bindings. A key can optionally be generated and will be stored in Terraform state. To use it create a sensitive output in your root modules referencing the `key` output, then extract the private key from the JSON formatted outputs. Alternatively, the `key` can be generated with `openssl` library and only public part uploaded to the Service Account, for more refer to the [Onprem SA Key Management](../../cloud-operations/onprem-sa-key-management/) example.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ module "myproject-default-service-accounts" {
|
||||||
| *iam_project_roles* | Project roles granted to the service account, by project id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam_project_roles* | Project roles granted to the service account, by project id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_storage_roles* | Storage roles granted to the service account, by bucket name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam_storage_roles* | Storage roles granted to the service account, by bucket name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *prefix* | Prefix applied to service account names. | <code title="">string</code> | | <code title="">null</code> |
|
| *prefix* | Prefix applied to service account names. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
|
| *public_keys_directory* | Path to public keys data files to upload to the service account (should have `.pem` extension). | <code title="">string</code> | | <code title=""></code> |
|
||||||
| *service_account_create* | Create service account. When set to false, uses a data source to reference an existing service account. | <code title="">bool</code> | | <code title="">true</code> |
|
| *service_account_create* | Create service account. When set to false, uses a data source to reference an existing service account. | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
@ -52,4 +53,5 @@ module "myproject-default-service-accounts" {
|
||||||
| iam_email | IAM-format service account email. | |
|
| iam_email | IAM-format service account email. | |
|
||||||
| key | Service account key. | ✓ |
|
| key | Service account key. | ✓ |
|
||||||
| service_account | Service account resource. | |
|
| service_account | Service account resource. | |
|
||||||
|
| service_account_credentials | Service account json credential templates for uploaded public keys data. | |
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
||||||
|
|
|
@ -65,6 +65,29 @@ locals {
|
||||||
? try(google_service_account.service_account.0, null)
|
? try(google_service_account.service_account.0, null)
|
||||||
: try(data.google_service_account.service_account.0, null)
|
: try(data.google_service_account.service_account.0, null)
|
||||||
)
|
)
|
||||||
|
service_account_credential_templates = {
|
||||||
|
for file, _ in local.public_keys_data : file => jsonencode(
|
||||||
|
{
|
||||||
|
type : "service_account",
|
||||||
|
project_id : var.project_id,
|
||||||
|
private_key_id : split("/", google_service_account_key.upload_key[file].id)[5]
|
||||||
|
private_key : "REPLACE_ME_WITH_PRIVATE_KEY_DATA"
|
||||||
|
client_email : local.resource_email_static
|
||||||
|
client_id : local.service_account.unique_id,
|
||||||
|
auth_uri : "https://accounts.google.com/o/oauth2/auth",
|
||||||
|
token_uri : "https://oauth2.googleapis.com/token",
|
||||||
|
auth_provider_x509_cert_url : "https://www.googleapis.com/oauth2/v1/certs",
|
||||||
|
client_x509_cert_url : "https://www.googleapis.com/robot/v1/metadata/x509/${urlencode(local.resource_email_static)}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public_keys_data = (
|
||||||
|
var.public_keys_directory != ""
|
||||||
|
? {
|
||||||
|
for file in fileset("${path.root}/${var.public_keys_directory}", "*.pem")
|
||||||
|
: file => filebase64("${path.root}/${var.public_keys_directory}/${file}") }
|
||||||
|
: {}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +110,12 @@ resource "google_service_account_key" "key" {
|
||||||
service_account_id = local.service_account.email
|
service_account_id = local.service_account.email
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "google_service_account_key" "upload_key" {
|
||||||
|
for_each = local.public_keys_data
|
||||||
|
service_account_id = local.service_account.email
|
||||||
|
public_key_data = each.value
|
||||||
|
}
|
||||||
|
|
||||||
resource "google_service_account_iam_binding" "roles" {
|
resource "google_service_account_iam_binding" "roles" {
|
||||||
for_each = var.iam
|
for_each = var.iam
|
||||||
service_account_id = local.service_account.name
|
service_account_id = local.service_account.name
|
||||||
|
|
|
@ -40,3 +40,8 @@ output "service_account" {
|
||||||
description = "Service account resource."
|
description = "Service account resource."
|
||||||
value = local.service_account
|
value = local.service_account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "service_account_credentials" {
|
||||||
|
description = "Service account json credential templates for uploaded public keys data."
|
||||||
|
value = local.service_account_credential_templates
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,12 @@ variable "project_id" {
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "public_keys_directory" {
|
||||||
|
description = "Path to public keys data files to upload to the service account (should have `.pem` extension)."
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
variable "service_account_create" {
|
variable "service_account_create" {
|
||||||
description = "Create service account. When set to false, uses a data source to reference an existing service account."
|
description = "Create service account. When set to false, uses a data source to reference an existing service account."
|
||||||
type = bool
|
type = bool
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2021 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.
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 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 "test" {
|
||||||
|
source = "../../../../cloud-operations/onprem-sa-key-management"
|
||||||
|
project_create = var.project_create
|
||||||
|
project_id = var.project_id
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright 2021 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
|
||||||
|
#
|
||||||
|
# https://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_create" {
|
||||||
|
type = bool
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_id" {
|
||||||
|
type = string
|
||||||
|
default = "test"
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Copyright 2021 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.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
|
||||||
|
|
||||||
|
|
||||||
|
def test_resources(e2e_plan_runner):
|
||||||
|
"Test that plan works and the numbers of resources is as expected."
|
||||||
|
modules, resources = e2e_plan_runner(FIXTURES_DIR)
|
||||||
|
assert len(modules) == 3
|
||||||
|
assert len(resources) == 7
|
Loading…
Reference in New Issue