diff --git a/.cz.toml b/.cz.toml new file mode 100644 index 0000000..52d405f --- /dev/null +++ b/.cz.toml @@ -0,0 +1,6 @@ +[tool.commitizen] +name = "cz_conventional_commits" +version_provider = "scm" +# version_files = ["galaxy.yml:^version"] +update_changelog_on_bump = true +major_version_zero = true diff --git a/.gitea/workflows/development.yml b/.gitea/workflows/development.yml new file mode 100644 index 0000000..bfba126 --- /dev/null +++ b/.gitea/workflows/development.yml @@ -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: ./ diff --git a/.gitea/workflows/pull-request-open.yml b/.gitea/workflows/pull-request-open.yml new file mode 100644 index 0000000..ea2a600 --- /dev/null +++ b/.gitea/workflows/pull-request-open.yml @@ -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: ./ diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..e617278 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -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: ./ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b7141fe --- /dev/null +++ b/.pre-commit-config.yaml @@ -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 diff --git a/README.md b/README.md index 3345f7a..294bc72 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,50 @@ # terraform-vault-tenant -Terraform module to deploy tenant in Hashicorp Vault community version. \ No newline at end of file +Terraform module to deploy tenant in Hashicorp Vault community version. +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement_terraform) | >= 1.0.0 | + +### Providers + +| Name | Version | +|------|---------| +| [random](#provider_random) | n/a | +| [vault](#provider_vault) | n/a | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [random_uuid.extra_roles_secret_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource | +| [random_uuid.tenant_admin_secret_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource | +| [vault_approle_auth_backend_role.extra_roles](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role) | resource | +| [vault_approle_auth_backend_role.tenant_admin](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role) | resource | +| [vault_approle_auth_backend_role_secret_id.extra_roles](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/approle_auth_backend_role_secret_id) | resource | +| [vault_approle_auth_backend_role_secret_id.tenant_admin](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_roles](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity) | resource | +| [vault_identity_entity.tenant_admin](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_entity) | resource | +| [vault_policy.extra_policies](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/policy) | resource | +| [vault_policy.tenant_admin](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/policy) | resource | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [global_approle_mount](#input_global_approle_mount) | The mount path for the global AppRole authentication method | `string` | `"approle"` | no | +| [tenant_additional_roles](#input_tenant_additional_roles) | 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/-approle) including all the roles declared in this variable.
The variable should look like:
tenant_additional_roles = {
devs = {
policy_file = "/some/path/to/policy.hcl"
}
admins = {...}
} |
map(object({
policy_file = string
}))
| `{}` | no | +| [tenant_admin_policy_file](#input_tenant_admin_policy_file) | The path to the admin policy file for this tenant | `string` | n/a | yes | +| [tenant_name](#input_tenant_name) | The name of the tenant you want to create | `string` | n/a | yes | +| [tenant_prefix](#input_tenant_prefix) | The prefix to use for the tenant in vault (this will prefix mount points, policies, etc..) | `string` | n/a | yes | + +### Outputs + +No outputs. + diff --git a/admin_approle.tf b/admin_approle.tf new file mode 100644 index 0000000..1c11833 --- /dev/null +++ b/admin_approle.tf @@ -0,0 +1,26 @@ +resource "vault_approle_auth_backend_role" "tenant_admin" { + backend = var.global_approle_mount + role_name = "${var.tenant_name}-admin" + token_policies = ["default", "${vault_policy.tenant_admin.name}"] +} + +resource "random_uuid" "tenant_admin_secret_id" {} + +resource "vault_approle_auth_backend_role_secret_id" "tenant_admin" { + backend = var.global_approle_mount + role_name = vault_approle_auth_backend_role.tenant_admin.role_name + secret_id = random_uuid.tenant_admin_secret_id.result +} + +resource "vault_identity_entity" "tenant_admin" { + name = "${each.value.prefix}-admin" + metadata = { + tenant = var.tenant_name + prefix = var.tenant_prefix + } +} + +resource "vault_policy" "tenant_admin" { + name = "${var.tenant_name}-admin" + policy = file(var.tenant_admin_policy_file) +} diff --git a/extra_policies.tf b/extra_policies.tf new file mode 100644 index 0000000..634f8c1 --- /dev/null +++ b/extra_policies.tf @@ -0,0 +1,43 @@ +resource "vault_policy" "extra_policies" { + for_each = var.tenant_additional_roles + + name = "${var.tenant_prefix}-${each.key}" + policy = file(each.value.policy_file) +} + +resource "vault_auth_backend" "approle" { + type = "approle" + path = "${var.tenant_prefix}-approle" + tune { + default_lease_ttl = "3600s" + max_lease_ttl = "14400s" + } +} + +resource "vault_approle_auth_backend_role" "extra_roles" { + for_each = var.tenant_additional_roles + + backend = vault_auth_backend.approle.path + role_name = each.key + token_policies = ["default", "${vault_policy.extra_policies[each.key].name}"] +} + +resource "random_uuid" "extra_roles_secret_id" { for_each = var.tenant_additional_roles } + +resource "vault_approle_auth_backend_role_secret_id" "extra_roles" { + for_each = var.tenant_additional_roles + + backend = vault_auth_backend.approle.path + role_name = vault_approle_auth_backend_role.extra_roles[each.key].role_name + secret_id = random_uuid.extra_roles_secret_id[each.key].result +} + +resource "vault_identity_entity" "extra_roles" { + for_each = var.tenant_additional_roles + + name = "${var.tenant_prefix}-${each.key}" + metadata = { + tenant = var.tenant_name + prefix = var.tenant_prefix + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..08e0a47 --- /dev/null +++ b/main.tf @@ -0,0 +1,11 @@ +terraform { + required_version = ">= 1.0.0" + required_providers { + vault = { + source = "hashicorp/vault" + } + random = { + source = "hashicorp/random" + } + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..90cd9cb --- /dev/null +++ b/variables.tf @@ -0,0 +1,42 @@ +variable "global_approle_mount" { + type = string + default = "approle" + description = "The mount path for the global AppRole authentication method" +} + +variable "tenant_name" { + type = string + description = "The name of the tenant you want to create" + validation { + condition = can(regex("^[-a-zA-Z0-9_]*$", var.tenant_name)) + error_message = "The tenant name must only contain alphanumeric characters, dashes, and underscores." + } +} + +variable "tenant_prefix" { + type = string + description = "The prefix to use for the tenant in vault (this will prefix mount points, policies, etc..)" +} + +variable "tenant_admin_policy_file" { + type = string + description = "The path to the admin policy file for this tenant" +} + +variable "tenant_additional_roles" { + type = map(object({ + policy_file = string + })) + default = {} + description = <-approle) including all the roles declared in this variable. + The variable should look like: + tenant_additional_roles = { + devs = { + policy_file = "/some/path/to/policy.hcl" + } + admins = {...} + } + EOT +}