Compare commits

...

31 Commits

Author SHA1 Message Date
c62b64f34b Merge pull request 'feat/stable-release' (#1) from feat/stable-release into main
All checks were successful
release / Bump version and create changelog with commitizen (push) Successful in 29s
Reviewed-on: #1
2024-05-28 20:45:33 +00:00
83d807d69e
fix: some more old naming things
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 22:25:55 +02:00
8d4263468f
fix: outputs using old reosurce naming
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 22:24:33 +02:00
c268547bd8
fix: variable validation using old names
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 22:23:10 +02:00
ca19309d2a
feat: refactor module, simplify naming and create additional entities for extra roles
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 22:14:00 +02:00
e4ddcb6be8
feat: create entities for each extra policies
All checks were successful
development / Check commit compliance (push) Successful in 4s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 19:22:34 +02:00
4975119e0b
feat: change approle path to <prefix>/approle instead of <prefix>-approle
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 4s
2024-05-26 16:27:38 +02:00
b1f512b85c
fix: make tenant group external
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 9s
2024-05-26 16:25:52 +02:00
47f53a2a20
fix: remove duplicate resource
All checks were successful
development / Check commit compliance (push) Successful in 4s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 16:24:57 +02:00
23ba2c3cea
fix: remove duplicate resource
All checks were successful
development / Check commit compliance (push) Successful in 4s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 16:24:12 +02:00
70c53fbef7
feat: move every approle role to dedicated backend, and add group to pass metadata along
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 37s
2024-05-26 16:22:18 +02:00
6872e4191a
fix: remount needs sudo
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-26 15:35:53 +02:00
154a3ba98a
fix: increase permissions for remounting secret engines
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 4s
2024-05-26 15:20:18 +02:00
e1128cf244
fix: wrong allowed_parameters type for params
All checks were successful
pull-requests-open / Check commit compliance (pull_request) Successful in 4s
development / Check commit compliance (push) Successful in 5s
2024-05-26 14:48:12 +02:00
a4e8e14096
feat: allow tenant admin to remount secret engines on tenant prefix
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 4s
2024-05-26 14:04:22 +02:00
ba09f9e4dc
fix: revert using locals for role policies
All checks were successful
pull-requests-open / Check commit compliance (pull_request) Successful in 34s
development / Check commit compliance (push) Successful in 36s
2024-05-26 12:45:35 +02:00
9a4f2837a0
fix: do not allow any token creation for now, will have to avoid child tokens in tf provider config
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 18:39:53 +02:00
0803966716
fix: templating not working for arrays
All checks were successful
development / Check commit compliance (push) Successful in 4s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 18:35:35 +02:00
8a5a85f33f
fix: circular dependency
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 18:27:03 +02:00
39371c8503
feat: only allow tenant admin to create tokens with its own policies
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 18:24:24 +02:00
8ab67a2ed6
fix: template of policy file
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 6s
2024-05-25 18:07:00 +02:00
61481d808d
fix: wrong permissions on token policy for tenant admin
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 18:05:49 +02:00
a1a7818c15
fix: wrong permissions on token/create for tenant admin
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 17:10:46 +02:00
9a30e25a80
fix: wrong permissions on token/create for tenant admin
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 16:59:55 +02:00
604a02683c
feat: allow tenant admin to create child token with its own permissions
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 6s
2024-05-25 16:27:53 +02:00
c1ea5253d5
fix: default policy file path for admin to null, and use built-in policy if value stays null
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 14:23:23 +02:00
9c4d1443f6
fix: wrong variable name in admin entity
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 24s
2024-05-25 14:14:12 +02:00
3597adb2fb
feat: add default admin policy
All checks were successful
development / Check commit compliance (push) Successful in 5s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 12:59:54 +02:00
5d84d0ef6f
feat: add version constraint to terraform providers
All checks were successful
development / Check commit compliance (push) Successful in 26s
pull-requests-open / Check commit compliance (pull_request) Successful in 5s
2024-05-25 00:33:58 +02:00
79ce376b04
feat: add outputs to module for policy names and role details
All checks were successful
development / Check commit compliance (push) Successful in 32s
2024-05-25 00:32:21 +02:00
f51a8bf1f1
feat: add first roles and approle auth method for tenant 2024-05-24 23:50:51 +02:00
15 changed files with 415 additions and 1 deletions

5
.cz.toml Normal file
View File

@ -0,0 +1,5 @@
[tool.commitizen]
name = "cz_conventional_commits"
version_provider = "scm"
update_changelog_on_bump = true
major_version_zero = true

View File

@ -0,0 +1,26 @@
---
name: development
on:
push:
branches-ignore:
- main
jobs:
commit-check:
name: Check commit compliance
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install commitizen
run: pip3 install commitizen
shell: bash
working-directory: ./
- name: Verify commit message compliance
run: |
echo "cz check --message '${{ github.event.head_commit.message }}'"
cz check --message "${{ github.event.head_commit.message }}"
shell: bash
working-directory: ./

View File

@ -0,0 +1,35 @@
---
name: pull-requests-open
on:
pull_request:
types:
- opened
- edited
- synchronize
branches:
- main
jobs:
commit-history-check:
name: Check commit compliance
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Install commitizen
run: pip3 install commitizen
shell: bash
working-directory: ./
- run: git log origin/${{ github.event.pull_request.base.ref }}..
- name: Verify commit message compliance
run: |
echo "cz check --rev-range origin/${{ gitea.event.pull_request.base.ref }}.."
cz check --rev-range origin/${{ gitea.event.pull_request.base.ref }}..
shell: bash
working-directory: ./

View File

@ -0,0 +1,54 @@
---
name: release
on:
push:
branches:
- main
jobs:
do-release:
if: "!startsWith(github.event.head_commit.message, 'bump:')"
runs-on: ubuntu-latest
name: Bump version and create changelog with commitizen
steps:
- name: Get secrets from vault
id: import-secrets
uses: hashicorp/vault-action@v3
with:
url: "https://vault.ednz.fr"
method: approle
roleId: ${{ secrets.VAULT_APPROLE_ID }}
secretId: ${{ secrets.VAULT_APPROLE_SECRET_ID }}
secrets: |
kv/data/applications/gitea/users/actions username | GITEA_ACTIONS_USERNAME ;
kv/data/applications/gitea/users/actions token_write | GITEA_ACTIONS_TOKEN ;
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_TOKEN }}
- name: Install commitizen
run: pip3 install commitizen
shell: bash
working-directory: ./
- name: Configure git credentials
uses: oleksiyrudenko/gha-git-credentials@v2
with:
global: true
name: "Gitea-Actions Bot"
email: "gitea-actions@ednz.fr"
actor: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_USERNAME }}
token: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_TOKEN }}
- name: Do release
run: cz -nr 21 bump --yes
shell: bash
working-directory: ./
- name: Push release
run: git push && git push --tags
shell: bash
working-directory: ./

27
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,27 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.86.0
hooks:
- id: terraform_fmt
- id: terraform_docs
args:
- "--hook-config=--path-to-file=README.md"
- "--hook-config=--add-to-existing-file=true"
- "--hook-config=--create-file-if-not-exist=true"
- "--args=--escape=false"
- "--args=--lockfile=false"
- "--args=--indent 3"
- "--args=--show all"
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/commitizen-tools/commitizen
rev: v3.24.0
hooks:
- id: commitizen
- id: commitizen-branch
stages:
- post-commit
- push

View File

@ -1,3 +1,66 @@
# terraform-vault-tenant
Terraform module to deploy tenant in Hashicorp Vault community version.
This module aims to provide a way for companies and individuals running the community version of vault, to segregate accesses between teams.
This "tenant" module requires that you have at least one approle auth method mounted prior to deploying it. It will create a tenant admin approle role on these mount, and apply the policy you define. It can also create an additional tenant-scoped approle auth mount, and create roles based on policies that you define.
The idea behind this is that outside of access control, a tenant is free to create whatever secret engine, secrets, etc... As long as those are prefixed with their tenant prefix.
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
### Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement_terraform) | >= 1.0.0 |
| <a name="requirement_random"></a> [random](#requirement_random) | ~> 3.6.2 |
| <a name="requirement_vault"></a> [vault](#requirement_vault) | ~> 4.2.0 |
### Providers
| Name | Version |
|------|---------|
| <a name="provider_random"></a> [random](#provider_random) | ~> 3.6.2 |
| <a name="provider_vault"></a> [vault](#provider_vault) | ~> 4.2.0 |
### Modules
No modules.
### Resources
| Name | Type |
|------|------|
| [random_uuid.extra_secret_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
| [random_uuid.root_secret_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
| [vault_approle_auth_backend_role.extra](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role) | resource |
| [vault_approle_auth_backend_role.root](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role) | resource |
| [vault_approle_auth_backend_role_secret_id.extra](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role_secret_id) | resource |
| [vault_approle_auth_backend_role_secret_id.root](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role_secret_id) | resource |
| [vault_auth_backend.approle](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/auth_backend) | resource |
| [vault_identity_entity.extra](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity) | resource |
| [vault_identity_entity.root](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity) | resource |
| [vault_identity_entity_alias.extra](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity_alias) | resource |
| [vault_identity_entity_alias.root](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity_alias) | resource |
| [vault_identity_group.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_group) | resource |
| [vault_policy.extra](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/policy) | resource |
| [vault_policy.root](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/policy) | resource |
### Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_additional_roles"></a> [additional_roles](#input_additional_roles) | A map of additional role names, with the path to the associated policy file to add for this tenant.<br> A separate approle auth method is created for this tenant (mounted at auth/<prefix>-approle) including all the roles declared in this variable.<br> The variable should look like:<br> additional_roles = {<br> devs = {<br> policy_file = "/some/path/to/policy.hcl"<br> }<br> admins = {...}<br> } | <pre>map(object({<br> policy_file = string<br> }))</pre> | `{}` | no |
| <a name="input_name"></a> [name](#input_name) | The name of the tenant you want to create | `string` | n/a | yes |
| <a name="input_prefix"></a> [prefix](#input_prefix) | The prefix to use for the tenant in vault (this will prefix mount points, policies, etc..) | `string` | n/a | yes |
| <a name="input_root_policy_file"></a> [root_policy_file](#input_root_policy_file) | The path to the admin policy file for this tenant | `string` | `null` | no |
### Outputs
| Name | Description |
|------|-------------|
| <a name="output_approle_mount"></a> [approle_mount](#output_approle_mount) | The approle mount for the tenant |
| <a name="output_extra_role_policies"></a> [extra_role_policies](#output_extra_role_policies) | The tenant extra role policy names |
| <a name="output_extra_roles"></a> [extra_roles](#output_extra_roles) | The tenant extra approle roles |
| <a name="output_root_policy"></a> [root_policy](#output_root_policy) | The tenant root policy name |
| <a name="output_root_role"></a> [root_role](#output_root_role) | The tenant root approle role |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

17
auth.tf Normal file
View File

@ -0,0 +1,17 @@
resource "vault_auth_backend" "approle" {
type = "approle"
path = "${var.prefix}/approle"
tune {
default_lease_ttl = "3600s"
max_lease_ttl = "14400s"
}
}
resource "vault_identity_group" "this" {
name = var.name
type = "internal"
metadata = {
tenant = var.name
prefix = var.prefix
}
}

0
examples/.gitkeep Normal file
View File

38
extra_policies.tf Normal file
View File

@ -0,0 +1,38 @@
resource "vault_approle_auth_backend_role" "extra" {
for_each = var.additional_roles
backend = vault_auth_backend.approle.path
role_name = each.key
token_policies = ["default", "${vault_policy.extra[each.key].name}"]
}
resource "random_uuid" "extra_secret_id" { for_each = var.additional_roles }
resource "vault_approle_auth_backend_role_secret_id" "extra" {
for_each = var.additional_roles
backend = vault_auth_backend.approle.path
role_name = vault_approle_auth_backend_role.extra[each.key].role_name
secret_id = random_uuid.extra_secret_id[each.key].result
}
resource "vault_policy" "extra" {
for_each = var.additional_roles
name = "${var.prefix}-${each.key}"
policy = file(each.value.policy_file)
}
resource "vault_identity_entity" "extra" {
for_each = var.additional_roles
name = "${var.prefix}-${each.key}"
}
resource "vault_identity_entity_alias" "extra" {
for_each = var.additional_roles
name = vault_approle_auth_backend_role.extra[each.key].role_id
mount_accessor = vault_auth_backend.approle.accessor
canonical_id = vault_identity_entity.extra[each.key].id
}

13
main.tf Normal file
View File

@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.0.0"
required_providers {
vault = {
source = "hashicorp/vault"
version = "~> 4.2.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.6.2"
}
}
}

0
modules/.gitkeep Normal file
View File

52
outputs.tf Normal file
View File

@ -0,0 +1,52 @@
output "approle_mount" {
value = vault_auth_backend.approle
sensitive = true
description = "The approle mount for the tenant"
}
output "root_role" {
value = {
role_id = vault_approle_auth_backend_role.root.role_name
secret_id = vault_approle_auth_backend_role_secret_id.root.secret_id
}
sensitive = true
description = "The tenant root approle role"
depends_on = [
vault_approle_auth_backend_role.root,
vault_approle_auth_backend_role_secret_id.root
]
}
output "root_policy" {
value = vault_policy.root.name
sensitive = false
description = "The tenant root policy name"
depends_on = [vault_policy.root]
}
output "extra_roles" {
value = {
for key, role in vault_approle_auth_backend_role.extra :
key => {
role_id = role.role_name
secret_id = vault_approle_auth_backend_role_secret_id.extra[key].secret_id
}
}
sensitive = true
description = "The tenant extra approle roles"
depends_on = [
vault_approle_auth_backend_role.extra,
vault_approle_auth_backend_role_secret_id.extra
]
}
output "extra_role_policies" {
value = {
for key, policy in vault_policy.extra :
key => policy.name
}
sensitive = false
description = "The tenant extra role policy names"
depends_on = [vault_policy.extra]
}

19
policies/root.policy.hcl Normal file
View File

@ -0,0 +1,19 @@
path "${tenant_prefix}/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}
path "sys/mounts/${tenant_prefix}/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}
path "sys/remount" {
capabilities = ["update", "sudo"]
allowed_parameters = {
"from" = ["${tenant_prefix}/*"]
"to" = ["${tenant_prefix}/*"]
}
}
path "sys/remount/status/*" {
capabilities = ["read"]
}

28
root.tf Normal file
View File

@ -0,0 +1,28 @@
resource "vault_approle_auth_backend_role" "root" {
backend = vault_auth_backend.approle.path
role_name = "${var.name}-root"
token_policies = ["default", vault_policy.root.name]
}
resource "random_uuid" "root_secret_id" {}
resource "vault_approle_auth_backend_role_secret_id" "root" {
backend = vault_auth_backend.approle.path
role_name = vault_approle_auth_backend_role.root.role_name
secret_id = random_uuid.root_secret_id.result
}
resource "vault_policy" "root" {
name = "${var.name}-root"
policy = var.root_policy_file == null ? templatefile("${path.module}/policies/root.policy.hcl", { tenant_prefix = var.prefix }) : file(var.root_policy_file)
}
resource "vault_identity_entity" "root" {
name = "${var.prefix}-root"
}
resource "vault_identity_entity_alias" "root" {
name = vault_approle_auth_backend_role.root.role_id
mount_accessor = vault_auth_backend.approle.accessor
canonical_id = vault_identity_entity.root.id
}

37
variables.tf Normal file
View File

@ -0,0 +1,37 @@
variable "name" {
type = string
description = "The name of the tenant you want to create"
validation {
condition = can(regex("^[-a-zA-Z0-9_]*$", var.name))
error_message = "The tenant name must only contain alphanumeric characters, dashes, and underscores."
}
}
variable "prefix" {
type = string
description = "The prefix to use for the tenant in vault (this will prefix mount points, policies, etc..)"
}
variable "root_policy_file" {
type = string
default = null
description = "The path to the admin policy file for this tenant"
}
variable "additional_roles" {
type = map(object({
policy_file = string
}))
default = {}
description = <<EOT
A map of additional role names, with the path to the associated policy file to add for this tenant.
A separate approle auth method is created for this tenant (mounted at auth/<prefix>-approle) including all the roles declared in this variable.
The variable should look like:
additional_roles = {
devs = {
policy_file = "/some/path/to/policy.hcl"
}
admins = {...}
}
EOT
}