Skip to content

Commit c516de9

Browse files
greutvthiery
andauthored
feat: MySQL DB and Vault (#1)
Signed-off-by: Yoan Blanc <yblanc@edgelab.ch> Co-authored-by: Vincent Thiery <vjmthiery@gmail.com>
1 parent 8b56cc8 commit c516de9

File tree

6 files changed

+156
-0
lines changed

6 files changed

+156
-0
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
11
# terraform-mysql-db
22

33
This module offers default conventions when creating a new MySQL database.
4+
5+
In particular:
6+
7+
- It creates a database 👋
8+
- Optionally, it creates a user named after the database when not specified.
9+
- Optionally, it creates two roles to obtain credentials via Vault:
10+
11+
- `${vault_backend_path}/${DBNAME}-all-privileges` with `ALL PRIVILEGES` permissions.
12+
- `${vault_backend_path}/${DBNAME}-read-only` with `SELECT` permissions.
13+
14+
- When the intent is to use Vault, it's recommended to **NOT** provide the `plaintext_password`.
15+
16+
17+
## Usage
18+
19+
```hcl
20+
module "my_database" {
21+
source = "git@github.com:edgelaboratories/terraform-mysql-db?ref=v0.1.0"
22+
23+
database = "my-database"
24+
25+
# By default, the database name is used
26+
# user = "my-database"
27+
28+
# Optional user password. Not required when using Vault roles
29+
plaintext_password = "a very hard to guess password"
30+
31+
# Default values are utf8mb4 and utf8mb4_unicode_ci
32+
default_character_set = "utf8"
33+
default_collation = "utf8_unicode_ci"
34+
35+
# Optional
36+
vault_backend_path = "mysql/my-cluster"
37+
vault_db_connection_name = "my-cluster"
38+
}
39+
```

main.tf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
locals {
2+
user = coalesce(var.user, var.database)
3+
}
4+
5+
resource "mysql_database" "this" {
6+
name = var.database
7+
8+
default_character_set = var.default_character_set
9+
default_collation = var.default_collation
10+
}
11+
12+
resource "mysql_user" "this" {
13+
count = var.plaintext_password != null ? 1 : 0
14+
15+
user = local.user
16+
host = "%"
17+
plaintext_password = var.plaintext_password
18+
}
19+
20+
resource "mysql_grant" "this" {
21+
count = var.plaintext_password != null ? 1 : 0
22+
23+
user = mysql_user.this[count.index].user
24+
host = "%"
25+
database = mysql_database.this.name
26+
27+
privileges = ["ALL PRIVILEGES"]
28+
}

outputs.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
output "database" {
2+
value = mysql_database.this.name
3+
}
4+
5+
output "user" {
6+
value = mysql_user.this.*.name
7+
}

provider.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
terraform {
2+
required_providers {
3+
mysql = {
4+
source = "winebarrel/mysql"
5+
}
6+
7+
vault = {
8+
source = "cyrilgdn/vault"
9+
}
10+
}
11+
}

variables.tf

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
variable "database" {
2+
description = "The name of the database"
3+
}
4+
5+
variable "user" {
6+
description = "Name of the main user. Defaults to the database name"
7+
default = ""
8+
}
9+
10+
variable "plaintext_password" {
11+
description = "Required to create the default user."
12+
type = string
13+
sensitive = true
14+
default = null
15+
}
16+
17+
variable "default_character_set" {
18+
default = "utf8mb4"
19+
}
20+
21+
variable "default_collation" {
22+
default = "utf8mb4_unicode_ci"
23+
}
24+
25+
variable "vault_backend_path" {
26+
type = string
27+
default = null
28+
}
29+
30+
variable "vault_db_connection_name" {
31+
type = string
32+
default = null
33+
}
34+
35+
variable "vault_role_default_ttl" {
36+
default = 3600
37+
}

vault.tf

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
locals {
2+
roles = var.vault_backend_path == null ? {} : {
3+
"${var.database}-all-privileges" = "ALL PRIVILEGES"
4+
"${var.database}-read-only" = "SELECT"
5+
}
6+
}
7+
8+
resource "vault_database_secret_backend_role" "this" {
9+
for_each = local.roles
10+
11+
name = each.key
12+
backend = var.vault_backend_path
13+
db_name = var.vault_db_connection_name
14+
15+
creation_statements = [
16+
"CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';",
17+
"GRANT ${each.value} ON ${var.database}.* TO '{{name}}'@'%';",
18+
]
19+
20+
default_ttl = var.vault_role_default_ttl
21+
}
22+
23+
data "vault_policy_document" "this" {
24+
for_each = local.roles
25+
26+
rule {
27+
path = "${var.vault_backend_path}/creds/${each.key}"
28+
capabilities = ["read"]
29+
}
30+
}
31+
32+
resource "vault_policy" "this" {
33+
for_each = local.roles
34+
35+
name = "${var.vault_backend_path}/${each.key}"
36+
policy = data.vault_policy_document.this[each.key].hcl
37+
}

0 commit comments

Comments
 (0)