Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
LotteSara committed Nov 25, 2020
0 parents commit 8c6a080
Show file tree
Hide file tree
Showing 38 changed files with 753 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# OSX leaves these everywhere on SMB shares
._*

# OSX trash
.DS_Store
*.pyc*

# Emacs save files
*~
\#*\#
.\#*

# Vim-related files
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist

### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore

# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
#

**/terraform.tfvars

# Secrets
credentials.json

# Test files
.kitchen/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## v1.0.0 (2020-11-25)

* Initial release

### Features

* Initial release of this module based on Terraform 0.13
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
SHELL := /bin/bash

MODULE := $(notdir $(PWD))
USERID = $(shell id -u)
USERGROUP = $(shell id -g)
DATE_TIME = $(shell date +%s)
GCP_CREDS_FILE = $(notdir ${GOOGLE_CREDENTIALS})

.PHONY: readme test

clear-env-error:
$(eval ENV_ERROR =)

check-error:
@if [ ! "${ENV_ERROR}" = "" ]; then echo -e "${ENV_ERROR}" && exit 1; fi

check-env:
$(eval GOOGLE_AUTH = GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT})
ifeq ($(GOOGLE_CREDENTIALS), )
ifeq ('$(GOOGLE_IMPERSONATE_SERVICE_ACCOUNT)', '')
$(eval ENV_ERROR = $(ENV_ERROR)Either GOOGLE_CREDENTIALS or GOOGLE_IMPERSONATE_SERVICE_ACCOUNT should be set but was not found in environment.\n)
endif
endif
ifeq ($(GOOGLE_CLOUD_PROJECT), )
$(eval ENV_ERROR = $(ENV_ERROR)GOOGLE_CLOUD_PROJECT is not set in environment.\n)
endif

check-gcp-env: clear-env-error check-env check-error

test: check-gcp-env $(GOOGLE_CREDENTIALS)
docker run --rm -it \
-v ${GOOGLE_CREDENTIALS}:/root/$(GCP_CREDS_FILE):ro \
-v $(PWD):/go/src/app/ \
-e GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT} \
-e GOOGLE_APPLICATION_CREDENTIALS=/root/$(GCP_CREDS_FILE) \
-e $(GOOGLE_AUTH) \
-e TF_VAR_owner=$(USER) \
binxio/terratest-runner-gcp:0.0.3

readme:
docker run --rm -e MODULE=$(MODULE) --user $(USERID):$(USERGROUP) -it -v $(PWD):/go/src/app/$(MODULE) binxio/terraform-module-readme-generator:latest
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

# Module `terraform-google-secret-manager`

## Creating a new release
After adding your changed and committing the code to GIT, you will need to add a new tag.
```
git tag vx.x.x
git push --tag
```
If your changes might be breaking current implementations of this module, make sure to bump the major version up by 1.

If you want to see which tags are already there, you can use the following command:
```
git tag --list
```
Required APIs
=============
For the Secret Manager services to deploy, the following APIs should be enabled in your project:
* `iam.googleapis.com`
* `secretmanager.googleapis.com`

Testing
=======
This module comes with [terratest](https://github.com/gruntwork-io/terratest) scripts for both unit testing and integration testing.
A Makefile is provided to run the tests using docker, but you can also run the tests directly on your machine if you have terratest installed.

### Run with make
Make sure to set GOOGLE_CLOUD_PROJECT to the right project and GOOGLE_CREDENTIALS to the right credentials json file
You can now run the tests with docker:
```
make test
```

### Run locally
From the module directory, run:
```
cd test && TF_VAR_owner=$(id -nu) go test
```
23 changes: 23 additions & 0 deletions README/appendix.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Required APIs
=============
For the Secret Manager services to deploy, the following APIs should be enabled in your project:
* `iam.googleapis.com`
* `secretmanager.googleapis.com`

Testing
=======
This module comes with [terratest](https://github.com/gruntwork-io/terratest) scripts for both unit testing and integration testing.
A Makefile is provided to run the tests using docker, but you can also run the tests directly on your machine if you have terratest installed.

### Run with make
Make sure to set GOOGLE_CLOUD_PROJECT to the right project and GOOGLE_CREDENTIALS to the right credentials json file
You can now run the tests with docker:
```
make test
```

### Run locally
From the module directory, run:
```
cd test && TF_VAR_owner=$(id -nu) go test
```
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This file is left empty intentionally. Use the nested modules instead.
10 changes: 10 additions & 0 deletions modules/secret/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SHELL := /bin/bash

MODULE := $(notdir $(PWD))
USERID = $(shell id -u)
USERGROUP = $(shell id -g)

.PHONY: readme

readme:
docker run --rm -e MODULE=$(MODULE) --user $(USERID):$(USERGROUP) -it -v $(PWD):/go/src/app/$(MODULE) binxio/terraform-module-readme-generator:latest
40 changes: 40 additions & 0 deletions modules/secret/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

# Module `secret`

Core Version Constraints:
* `>= 0.13`

Provider Requirements:
* **google (`hashicorp/google`):** (any version)

## Input Variables
* `environment` (required): Company environment for which the resources are created (e.g. dev, tst, acc, prd, all).
* `owner` (required): Owner of the resource. This variable is used to set the 'owner' label. Will be used as default for each subnet, but can be overridden using the subnet settings.
* `project` (required): Company project name.
* `purpose` (required): The purpose of the secret. This variable is appended to the secret_id and used to set the 'purpose' label.
* `replication` (default `{"automatic":true}`): The replication to be used
* `roles` (required): Map of role name's as `key` and members list as `value` to bind permissions

## Output Values
* `id`: Id of the secret
* `secret_id`: Id of the secret

## Managed Resources
* `google_secret_manager_secret.secret` from `google`
* `google_secret_manager_secret_iam_policy.map` from `google`

## Data Resources
* `data.google_iam_policy.map` from `google`

## Creating a new release
After adding your changed and committing the code to GIT, you will need to add a new tag.
```
git tag vx.x.x
git push --tag
```
If your changes might be breaking current implementations of this module, make sure to bump the major version up by 1.

If you want to see which tags are already there, you can use the following command:
```
git tag --list
```
19 changes: 19 additions & 0 deletions modules/secret/asserts.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#######################################################################################################
#
# Terraform does not have a easy way to check if the input parameters are in the correct format.
# On top of that, terraform will sometimes produce a valid plan but then fail during apply.
# To handle these errors beforehad, we're using the 'file' hack to throw errors on known mistakes.
#
#######################################################################################################
locals {
# Regular expressions
regex_secret_id = "[a-zA-Z0-9](?:[a-zA-Z0-9_-]{4,253}[a-zA-Z0-9])"

# Terraform assertion hack
assert_head = "\n\n-------------------------- /!\\ ASSERTION FAILED /!\\ --------------------------\n\n"
assert_foot = "\n\n-------------------------- /!\\ ^^^^^^^^^^^^^^^^ /!\\ --------------------------\n"
asserts = {
secret_id_too_long = length(local.secret_id) > 255 ? file(format("%sSecret's generated id is too long:\n%s\n%s > 255 chars!%s", local.assert_head, local.secret_id, length(local.secret_id), local.assert_foot)) : "ok"
secret_id_regex = length(regexall("^${local.regex_secret_id}$", local.secret_id)) == 0 ? file(format("%sSecret's generated id [%s] does not match regex ^%s$%s", local.assert_head, local.secret_id, local.regex_secret_id, local.assert_foot)) : "ok"
}
}
64 changes: 64 additions & 0 deletions modules/secret/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
locals {
project = var.project
environment = var.environment
owner = var.owner

labels = {
"project" = substr(replace(lower(local.project), "/[^\\p{Ll}\\p{Lo}\\p{N}_-]+/", "_"), 0, 63)
"env" = substr(replace(lower(local.environment), "/[^\\p{Ll}\\p{Lo}\\p{N}_-]+/", "_"), 0, 63)
"owner" = substr(replace(local.owner, "/[^\\p{Ll}\\p{Lo}\\p{N}_-]+/", "_"), 0, 63)
"creator" = "terraform"
}

# We like to have the project and env in the secret name, so it's obvious what the secret belongs to
# without checking the GCP project it's part of
# This also allows for central secret management since the naming is more unique by default.
secret_id = replace(lower(format("%s-%s-%s", local.project, local.environment, var.purpose)), " ", "-")

# Map role members to GCP expected format
roles = { for role, members in try(var.roles, {}) : role => [for member, type in members : format("%s:%s", type, member)] }
}

resource "google_secret_manager_secret" "secret" {
secret_id = local.secret_id

replication {
automatic = lookup(var.replication, "automatic", null)

dynamic "user_managed" {
for_each = lookup(var.replication, "user_managed", [])

content {
dynamic "replicas" {
for_each = lookup(user_managed.value, "replicas", [])

content {
location = replicas.value.location
}
}
}
}
}

labels = local.labels
}

data "google_iam_policy" "map" {
for_each = (length(keys(local.roles)) > 0 ? { policy = {} } : {})

dynamic "binding" {
for_each = local.roles

content {
role = binding.key
members = binding.value
}
}
}

resource "google_secret_manager_secret_iam_policy" "map" {
for_each = data.google_iam_policy.map

secret_id = google_secret_manager_secret.secret.secret_id
policy_data = each.value.policy_data
}
9 changes: 9 additions & 0 deletions modules/secret/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "secret_id" {
description = "Id of the secret"
value = google_secret_manager_secret.secret.secret_id
}

output "id" {
description = "Id of the secret"
value = google_secret_manager_secret.secret.id
}
43 changes: 43 additions & 0 deletions modules/secret/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#------------------------------------------------------------------------------------------------------------------------
#
# Generic variables
#
#------------------------------------------------------------------------------------------------------------------------
variable "owner" {
description = "Owner of the resource. This variable is used to set the 'owner' label. Will be used as default for each subnet, but can be overridden using the subnet settings."
type = string
}

variable "project" {
description = "Company project name."
type = string
}

variable "environment" {
description = "Company environment for which the resources are created (e.g. dev, tst, acc, prd, all)."
type = string
}

#------------------------------------------------------------------------------------------------------------------------
#
# secret variables
#
#------------------------------------------------------------------------------------------------------------------------
variable "purpose" {
description = "The purpose of the secret. This variable is appended to the secret_id and used to set the 'purpose' label."
type = string
}

variable "replication" {
description = "The replication to be used"
type = any
default = {
automatic = true
}
}

variable "roles" {
description = "Map of role name's as `key` and members list as `value` to bind permissions"
type = map(map(string))
default = {}
}
8 changes: 8 additions & 0 deletions modules/secret/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
}
}
required_version = ">= 0.13"
}
10 changes: 10 additions & 0 deletions modules/secret_version/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SHELL := /bin/bash

MODULE := $(notdir $(PWD))
USERID = $(shell id -u)
USERGROUP = $(shell id -g)

.PHONY: readme

readme:
docker run --rm -e MODULE=$(MODULE) --user $(USERID):$(USERGROUP) -it -v $(PWD):/go/src/app/$(MODULE) binxio/terraform-module-readme-generator:latest
Loading

0 comments on commit 8c6a080

Please sign in to comment.