From 23df367218ce7e1cc4f13ee055ac3160de4780ae Mon Sep 17 00:00:00 2001 From: Bertrand Lanson Date: Thu, 3 Oct 2024 20:56:18 +0200 Subject: [PATCH] feat: add raw output for the security group objects --- .cz.toml | 6 ++ .gitea/workflows/development.yml | 26 +++++ .gitea/workflows/pull-request-open.yml | 128 +++++++++++++++++++++++++ .gitea/workflows/release.yml | 54 +++++++++++ .gitignore | 38 ++++++++ .pre-commit-config.yaml | 19 +++- .terraform.lock.hcl | 41 ++++++++ LICENSE | 2 +- README.md | 48 ++++++++++ examples/.gitkeep | 0 modules/.gitkeep | 0 outputs.tf | 25 +++++ tests/complex.tftest.hcl | 87 +++++++++++++++++ tests/module/.terraform.lock.hcl | 41 ++++++++ tests/module/README.md | 46 +++++++++ tests/module/locals.tf | 9 ++ tests/module/main.tf | 52 ++++++++++ tests/module/variables.tf | 58 +++++++++++ tests/self.tftest.hcl | 56 +++++++++++ tests/simple.tftest.hcl | 55 +++++++++++ 20 files changed, 785 insertions(+), 6 deletions(-) create mode 100644 .cz.toml create mode 100644 .gitea/workflows/development.yml create mode 100644 .gitea/workflows/pull-request-open.yml create mode 100644 .gitea/workflows/release.yml create mode 100644 .gitignore create mode 100644 .terraform.lock.hcl delete mode 100644 examples/.gitkeep delete mode 100644 modules/.gitkeep create mode 100644 tests/complex.tftest.hcl create mode 100644 tests/module/.terraform.lock.hcl create mode 100644 tests/module/README.md create mode 100644 tests/module/locals.tf create mode 100644 tests/module/main.tf create mode 100644 tests/module/variables.tf create mode 100644 tests/self.tftest.hcl create mode 100644 tests/simple.tftest.hcl diff --git a/.cz.toml b/.cz.toml new file mode 100644 index 0000000..7866eab --- /dev/null +++ b/.cz.toml @@ -0,0 +1,6 @@ +[tool.commitizen] +name = "cz_conventional_commits" +version_provider = "scm" +update_changelog_on_bump = true +major_version_zero = true +tag_format = "v$version" diff --git a/.gitea/workflows/development.yml b/.gitea/workflows/development.yml new file mode 100644 index 0000000..19cb03e --- /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: ${{ gitea.workspace }} + + - 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: ${{ gitea.workspace }} diff --git a/.gitea/workflows/pull-request-open.yml b/.gitea/workflows/pull-request-open.yml new file mode 100644 index 0000000..af6d4fd --- /dev/null +++ b/.gitea/workflows/pull-request-open.yml @@ -0,0 +1,128 @@ +--- +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: ${{ gitea.workspace }} + + - 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: ${{ gitea.workspace }} + + pre-commit-check: + name: Check pre-commit status + runs-on: ubuntu-latest + needs: commit-history-check + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install pre-commit + run: pip3 install pre-commit + shell: bash + working-directory: ${{ gitea.workspace }} + + - name: Install pre-commit dependencies + run: | + # terraform-docs + curl -sSLo /tmp/terraform-docs.tar.gz \ + https://terraform-docs.io/dl/${TERRAFORM_DOCS_VERSION}/terraform-docs-${TERRAFORM_DOCS_VERSION}-$(uname)-amd64.tar.gz + tar -xzf /tmp/terraform-docs.tar.gz -C /tmp + chmod +x /tmp/terraform-docs + mv /tmp/terraform-docs /usr/local/bin/terraform-docs + rm -rf /tmp/* + + # opentofu + curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh \ + -o install-opentofu.sh + chmod +x install-opentofu.sh + ./install-opentofu.sh --install-method standalone --opentofu-version $OPENTOFU_VERSION + rm -f install-opentofu.sh + shell: bash + working-directory: ${{ gitea.workspace }} + env: + OPENTOFU_VERSION: 1.8.0 + TERRAFORM_DOCS_VERSION: v0.18.0 + + - name: Verify pre-commit status + run: pre-commit run --all + shell: bash + working-directory: ${{ gitea.workspace }} + + end-to-end-tests: + name: Run E2E tofu tests + runs-on: ubuntu-latest + needs: pre-commit-check + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install required packages + run: | + export DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install -y curl jq + + curl https://vault.ednz.fr/v1/ednz-root-ca/ca -o /tmp/ednz_ca + openssl x509 -inform DER -in /tmp/ednz_ca -out /usr/local/share/ca-certificates/ednz_ca.crt -outform pem + update-ca-certificates + + - name: Install OpenTofu + uses: opentofu/setup-opentofu@v1 + with: + tofu_version: 1.8.2 + + - 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/cicd/vault/infrabuilder approle_id | VAULT_INFRABUILDER_APPROLE_ID ; + kv/data/cicd/vault/infrabuilder approle_secret_id | VAULT_INFRABUILDER_APPROLE_SECRET_ID ; + + - name: Get required credentials + id: tofu-auth + run: | + VAULT_TOKEN=$(curl --silent --request POST --data '{"role_id": "${{ steps.import-secrets.outputs.VAULT_INFRABUILDER_APPROLE_ID }}","secret_id": "${{ steps.import-secrets.outputs.VAULT_INFRABUILDER_APPROLE_SECRET_ID }}"}' https://vault.ednz.fr/v1/auth/approle/login | jq -r .auth.client_token) + echo "vault_token=$VAULT_TOKEN" >> $GITHUB_OUTPUT + + - name: Tofu init + run: tofu init + shell: bash + working-directory: ${{ gitea.workspace }} + + - name: Tofu test + run: tofu test + shell: bash + working-directory: ${{ gitea.workspace }} + env: + VAULT_TOKEN: ${{ steps.tofu-auth.outputs.vault_token }} diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..472ddaa --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,54 @@ +--- +name: build-deploy +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: ${{ gitea.workspace }} + + - 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: ${{ gitea.workspace }} + + - name: Push release + run: git push && git push --tags + shell: bash + working-directory: ${{ gitea.workspace }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cd8e68 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which are likely to contain sentitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +# +#*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Credentials files +credentials.auto.tfvars + +# Local plan files +plan.out +**temp.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c54adef..d4ea4c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,28 @@ repos: - - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.86.0 + - repo: https://github.com/tofuutils/pre-commit-opentofu + rev: v2.0.0 hooks: - - id: terraform_fmt - - id: terraform_docs + - id: tofu_fmt + - id: tofu_docs args: - "--hook-config=--path-to-file=README.md" - "--hook-config=--add-to-existing-file=true" - "--hook-config=--create-file-if-not-exist=true" + - "--hook-config=--use-standard-markers=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 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer + - repo: https://github.com/commitizen-tools/commitizen + rev: v3.29.1 + hooks: + - id: commitizen + - id: commitizen-branch + stages: + - post-commit + - push diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..59aa238 --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,41 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/vault" { + version = "4.4.0" + hashes = [ + "h1:s0t6P9ZfUQnHLxtUcnpPWpME68KwO/OxZqHAKSIvOoo=", + "zh:0309ea8f81386e17ab13c06c5991ca959708c55c815b0cfba2bbcd865e0d606e", + "zh:40e56199ccd266bffa216e8ebbcdc2e29b6ef5145b39377be766e763cac759c8", + "zh:6fad1f073bd2e53e34736e000f98db581137e153ac80bbb5c4f1a1e38b46a1d2", + "zh:74564fd4759decccf7f3c952aa2feba1012f103a66ec354aa3b3292a2f1b2412", + "zh:7aae012c1a43e6e5dae6f608ec0f08cdb3f95fa121a32e413fe7ee37cb99947f", + "zh:7c83f508e164844b1dd9bafe9de0fe60c7be7b55a02e704a6e2f50cff38b7d96", + "zh:873a42322b68d9fba4a38217b97ee04a1eb617e811d7f9954016f5c3eb6cb0bc", + "zh:9db2b13472cf91a5f18f0a7c6ae532277c05b0980d87f492341426b981679f7b", + "zh:ac1cbd2926265db80efe3f1814bed82901f7d8a7d4e5b1e22592e1eef234b1c7", + "zh:f465a955cc96f640e7426a648ba672c169a4a2959bad6146fe61583d67642561", + ] +} + +provider "registry.opentofu.org/terraform-provider-openstack/openstack" { + version = "2.1.0" + constraints = ">= 1.54.0, ~> 2.1.0" + hashes = [ + "h1:2TcmfEzBOGQPALErrXTaL6v+k/WAL40adao4izRYmdw=", + "zh:113661750398bf21c8fe36aade9fb6f5eb82b5bcd3bcd30bd37ac805d83398f4", + "zh:1b3c26347b9cd61e413ee93c2f422cc3278a77f55fd3516eaabb3e2a85f65281", + "zh:1b751bbf1e4152829a643b532fd3f5967a2e89a41fac381257e0b41665be3306", + "zh:1b967bbfd9b344419c0e0df0c3a15fcbd731e91f19a18955a55aace8d9ec039a", + "zh:1bc0fc7c0a21e568db043b654501ce668ba19bf7628d37a7d2aaa512fd6e5aeb", + "zh:425cbf61757d4b503e7bf0f409ea59835ca3afbd2432d56ad552c2e5d234a572", + "zh:67d4f059cb4d73bf6c060313ec32962c4e5bd8dc7be2542a6f2098ab32575cd9", + "zh:7fe841ac5b68a4f52fb3cf45070828f3845de44746679d434e4349f3c23e3ef2", + "zh:ac1ed4c6ef0b6a3410568a05d3f9933d184497f065988503c43da0b2f0786ab2", + "zh:c5c0d14c86fabd9ab6a5d555e6a8d511942665fb5fa948dd452b0d1934068344", + "zh:c9ae5c210192275185d6823566a9421983e8e64c2665a4cae00b92dd0706bd19", + "zh:ee9865ccc053e7f345e532654fb628d1cf1e81cd2e929643c1691bebffcf7b98", + "zh:f3416d2f666095e740522c4964e436470bb9ec17bd53aaae8169ad93297d07bd", + "zh:fbca85457dd49e17168989d64f7cfc4a519d55ef4e00e89cea2859e87ad87f83", + ] +} diff --git a/LICENSE b/LICENSE index 475d657..f412dc0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 Bertrand Lanson +Copyright (c) 2023 Bertrand Lanson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index d3faa78..b269d4c 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,51 @@ No modules. | [id](#output_id) | The id of the security group | | [name](#output_name) | The name of the security group | + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement_terraform) | >= 1.0.0 | +| [openstack](#requirement_openstack) | >= 1.54 | + +### Providers + +| Name | Version | +|------|---------| +| [openstack](#provider_openstack) | >= 1.54 | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [openstack_networking_secgroup_rule_v2.egress](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_secgroup_rule_v2) | resource | +| [openstack_networking_secgroup_rule_v2.ingress](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_secgroup_rule_v2) | resource | +| [openstack_networking_secgroup_v2.this](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_secgroup_v2) | resource | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [delete_default_rules](#input_delete_default_rules) | Whether or not to delete the default egress rules applied to the security group.
Default rules allow egress ipv4 and ipv6 to 0.0.0.0/0. | `bool` | `false` | no | +| [description](#input_description) | Description for the security group. | `string` | `null` | no | +| [egress_rules](#input_egress_rules) | The list of egress rules to attach to the security group.
You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource
provided by the openstack provider, except region, which defaults to the region of the provider used,
and direction, which defaults to egress.
By default, if ethertype is not specified, it will by IPv4. | `map(map(string))` | `{}` | no | +| [ingress_rules](#input_ingress_rules) | The list of ingress rules to attach to the security group.
You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource
provided by the openstack provider, except region, which defaults to the region of the provider used,
and direction, which defaults to ingress.
By default, if ethertype is not specified, it will by IPv4. | `map(map(string))` | `{}` | no | +| [name](#input_name) | The name of the security group. | `string` | n/a | yes | +| [tags](#input_tags) | A list of tags (strings) to apply to the security group | `list(string)` | `[]` | no | +| [tenant_id](#input_tenant_id) | The tenant for which to create the security group.
This is only required for admins creating security groups for other tenant. | `string` | `null` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [id](#output_id) | The id of the security group | +| [name](#output_name) | The name of the security group | +| [sg_egress_rules_raw](#output_sg_egress_rules_raw) | The raw security group egress rules, if any (except the default ones, if created) | +| [sg_ingress_rules_raw](#output_sg_ingress_rules_raw) | The raw security group ingress rules, if any | +| [sg_raw](#output_sg_raw) | The raw security group object, with all its values | + diff --git a/examples/.gitkeep b/examples/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/modules/.gitkeep b/modules/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/outputs.tf b/outputs.tf index f9aab26..4653a95 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,9 +1,34 @@ output "name" { value = openstack_networking_secgroup_v2.this.name + sensitive = false description = "The name of the security group" + depends_on = [] } output "id" { value = openstack_networking_secgroup_v2.this.id + sensitive = false description = "The id of the security group" + depends_on = [] +} + +output "sg_raw" { + value = openstack_networking_secgroup_v2.this + sensitive = false + description = "The raw security group object, with all its values" + depends_on = [] +} + +output "sg_ingress_rules_raw" { + value = length(openstack_networking_secgroup_rule_v2.ingress) > 0 ? openstack_networking_secgroup_rule_v2.ingress : null + sensitive = false + description = "The raw security group ingress rules, if any" + depends_on = [] +} + +output "sg_egress_rules_raw" { + value = length(openstack_networking_secgroup_rule_v2.egress) > 0 ? openstack_networking_secgroup_rule_v2.egress : null + sensitive = false + description = "The raw security group egress rules, if any (except the default ones, if created)" + depends_on = [] } diff --git a/tests/complex.tftest.hcl b/tests/complex.tftest.hcl new file mode 100644 index 0000000..7678cc1 --- /dev/null +++ b/tests/complex.tftest.hcl @@ -0,0 +1,87 @@ +run "complex" { + module { + source = "./tests/module" + } + + variables { + name = "complex-sg" + description = "Tofu automated tests." + delete_default_rules = true + ingress_rules = { + http = { + protocol = "tcp" + port_range_min = 80 + port_range_max = 80 + remote_ip_prefix = "0.0.0.0/0" + } + https = { + protocol = "tcp" + port_range_min = 443 + port_range_max = 443 + remote_ip_prefix = "0.0.0.0/0" + } + cluster = { + protocol = "" + port_range_min = 0 + port_range_max = 0 + remote_group_id = "self" + } + ssh = { + protocol = "tcp" + port_range_min = 22 + port_range_max = 22 + remote_ip_prefix = "0.0.0.0/0" + } + } + egress_rules = { + icmp = { + protocol = "icmp" + remote_ip_prefix = "0.0.0.0/0" + } + } + tags = [ + "tofu=true", + "env=testing", + ] + } + + assert { + condition = module.security_group.name == "complex-sg" + error_message = "The security group name is not what was set as input" + } + + assert { + condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", module.security_group.id)) + error_message = "The security group id is not a valid uuid" + } + + assert { + condition = length(module.security_group.sg_ingress_rules_raw) == 4 + error_message = "There are not the expected amount of ingress rules" + } + + assert { + condition = length(module.security_group.sg_egress_rules_raw) == 1 + error_message = "There are not the expected amount of egress rules" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["http"].remote_ip_prefix == "0.0.0.0/0" + error_message = "The http ingress rule is not scoped to the correct remote cidr" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["https"].remote_ip_prefix == "0.0.0.0/0" + error_message = "The https ingress rule is not scoped to the correct remote cidr" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["cluster"].remote_group_id == module.security_group.id + error_message = "The cluster ingress rule is not scoped to itself" + } + + assert { + condition = module.security_group.sg_egress_rules_raw["icmp"].remote_ip_prefix == "0.0.0.0/0" + error_message = "The icmp egress rule is not scoped to the correct remote cidr" + } +} diff --git a/tests/module/.terraform.lock.hcl b/tests/module/.terraform.lock.hcl new file mode 100644 index 0000000..59aa238 --- /dev/null +++ b/tests/module/.terraform.lock.hcl @@ -0,0 +1,41 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/vault" { + version = "4.4.0" + hashes = [ + "h1:s0t6P9ZfUQnHLxtUcnpPWpME68KwO/OxZqHAKSIvOoo=", + "zh:0309ea8f81386e17ab13c06c5991ca959708c55c815b0cfba2bbcd865e0d606e", + "zh:40e56199ccd266bffa216e8ebbcdc2e29b6ef5145b39377be766e763cac759c8", + "zh:6fad1f073bd2e53e34736e000f98db581137e153ac80bbb5c4f1a1e38b46a1d2", + "zh:74564fd4759decccf7f3c952aa2feba1012f103a66ec354aa3b3292a2f1b2412", + "zh:7aae012c1a43e6e5dae6f608ec0f08cdb3f95fa121a32e413fe7ee37cb99947f", + "zh:7c83f508e164844b1dd9bafe9de0fe60c7be7b55a02e704a6e2f50cff38b7d96", + "zh:873a42322b68d9fba4a38217b97ee04a1eb617e811d7f9954016f5c3eb6cb0bc", + "zh:9db2b13472cf91a5f18f0a7c6ae532277c05b0980d87f492341426b981679f7b", + "zh:ac1cbd2926265db80efe3f1814bed82901f7d8a7d4e5b1e22592e1eef234b1c7", + "zh:f465a955cc96f640e7426a648ba672c169a4a2959bad6146fe61583d67642561", + ] +} + +provider "registry.opentofu.org/terraform-provider-openstack/openstack" { + version = "2.1.0" + constraints = ">= 1.54.0, ~> 2.1.0" + hashes = [ + "h1:2TcmfEzBOGQPALErrXTaL6v+k/WAL40adao4izRYmdw=", + "zh:113661750398bf21c8fe36aade9fb6f5eb82b5bcd3bcd30bd37ac805d83398f4", + "zh:1b3c26347b9cd61e413ee93c2f422cc3278a77f55fd3516eaabb3e2a85f65281", + "zh:1b751bbf1e4152829a643b532fd3f5967a2e89a41fac381257e0b41665be3306", + "zh:1b967bbfd9b344419c0e0df0c3a15fcbd731e91f19a18955a55aace8d9ec039a", + "zh:1bc0fc7c0a21e568db043b654501ce668ba19bf7628d37a7d2aaa512fd6e5aeb", + "zh:425cbf61757d4b503e7bf0f409ea59835ca3afbd2432d56ad552c2e5d234a572", + "zh:67d4f059cb4d73bf6c060313ec32962c4e5bd8dc7be2542a6f2098ab32575cd9", + "zh:7fe841ac5b68a4f52fb3cf45070828f3845de44746679d434e4349f3c23e3ef2", + "zh:ac1ed4c6ef0b6a3410568a05d3f9933d184497f065988503c43da0b2f0786ab2", + "zh:c5c0d14c86fabd9ab6a5d555e6a8d511942665fb5fa948dd452b0d1934068344", + "zh:c9ae5c210192275185d6823566a9421983e8e64c2665a4cae00b92dd0706bd19", + "zh:ee9865ccc053e7f345e532654fb628d1cf1e81cd2e929643c1691bebffcf7b98", + "zh:f3416d2f666095e740522c4964e436470bb9ec17bd53aaae8169ad93297d07bd", + "zh:fbca85457dd49e17168989d64f7cfc4a519d55ef4e00e89cea2859e87ad87f83", + ] +} diff --git a/tests/module/README.md b/tests/module/README.md new file mode 100644 index 0000000..80d2df5 --- /dev/null +++ b/tests/module/README.md @@ -0,0 +1,46 @@ +# module + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement_terraform) | >= 1.0.0 | +| [openstack](#requirement_openstack) | ~> 2.1.0 | + +### Providers + +| Name | Version | +|------|---------| +| [vault](#provider_vault) | n/a | + +### Modules + +| Name | Source | Version | +|------|--------|---------| +| [security_group](#module_security_group) | ../../ | n/a | + +### Resources + +| Name | Type | +|------|------| +| [vault_kv_secret_v2.openstack_provider_project_info](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/data-sources/kv_secret_v2) | data source | +| [vault_kv_secret_v2.openstack_provider_project_user](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/data-sources/kv_secret_v2) | data source | +| [vault_kv_secret_v2.openstack_provider_region](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/data-sources/kv_secret_v2) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [delete_default_rules](#input_delete_default_rules) | Whether or not to delete the default egress rules applied to the security group.
Default rules allow egress ipv4 and ipv6 to 0.0.0.0/0. | `bool` | `false` | no | +| [description](#input_description) | Description for the security group. | `string` | `null` | no | +| [egress_rules](#input_egress_rules) | The list of egress rules to attach to the security group.
You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource
provided by the openstack provider, except region, which defaults to the region of the provider used,
and direction, which defaults to egress.
By default, if ethertype is not specified, it will by IPv4. | `map(map(string))` | `{}` | no | +| [ingress_rules](#input_ingress_rules) | The list of ingress rules to attach to the security group.
You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource
provided by the openstack provider, except region, which defaults to the region of the provider used,
and direction, which defaults to ingress.
By default, if ethertype is not specified, it will by IPv4. | `map(map(string))` | `{}` | no | +| [name](#input_name) | The name of the security group. | `string` | n/a | yes | +| [tags](#input_tags) | A list of tags (strings) to apply to the security group | `list(string)` | `[]` | no | +| [tenant_id](#input_tenant_id) | The tenant for which to create the security group.
This is only required for admins creating security groups for other tenant. | `string` | `null` | no | + +### Outputs + +No outputs. + diff --git a/tests/module/locals.tf b/tests/module/locals.tf new file mode 100644 index 0000000..cdeaf5f --- /dev/null +++ b/tests/module/locals.tf @@ -0,0 +1,9 @@ +locals { + name = var.name + description = var.description + tenant_id = var.tenant_id + delete_default_rules = var.delete_default_rules + ingress_rules = var.ingress_rules + egress_rules = var.egress_rules + tags = var.tags +} diff --git a/tests/module/main.tf b/tests/module/main.tf new file mode 100644 index 0000000..53419ec --- /dev/null +++ b/tests/module/main.tf @@ -0,0 +1,52 @@ +terraform { + required_version = ">= 1.0.0" + required_providers { + vault = { + source = "hashicorp/vault" + } + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 2.1.0" + } + } +} + +provider "vault" { + address = "https://active.vault.service.consul:8200" + skip_tls_verify = true +} + +provider "openstack" { + auth_url = data.vault_kv_secret_v2.openstack_provider_region.data["auth_url"] + region = data.vault_kv_secret_v2.openstack_provider_region.data["region_name"] + tenant_name = data.vault_kv_secret_v2.openstack_provider_project_info.data["tenant_name"] + application_credential_id = data.vault_kv_secret_v2.openstack_provider_project_user.data["application_credential_id"] + application_credential_secret = data.vault_kv_secret_v2.openstack_provider_project_user.data["application_credential_secret"] +} + +data "vault_kv_secret_v2" "openstack_provider_region" { + mount = "kv" + name = "infrastructure/openstack/regions/dc3_a" +} + +data "vault_kv_secret_v2" "openstack_provider_project_user" { + mount = "kv" + name = "infrastructure/openstack/projects/pcp_dawxdax/users/tofu" +} + +data "vault_kv_secret_v2" "openstack_provider_project_info" { + mount = "kv" + name = "infrastructure/openstack/projects/pcp_dawxdax/info" +} + +module "security_group" { + source = "../../" + + name = local.name + description = local.description + tenant_id = local.tenant_id + delete_default_rules = local.delete_default_rules + ingress_rules = local.ingress_rules + egress_rules = local.egress_rules + tags = local.tags +} diff --git a/tests/module/variables.tf b/tests/module/variables.tf new file mode 100644 index 0000000..22f087f --- /dev/null +++ b/tests/module/variables.tf @@ -0,0 +1,58 @@ +variable "name" { + type = string + description = "The name of the security group." +} + +variable "description" { + type = string + description = "Description for the security group." + default = null +} + +variable "tenant_id" { + type = string + description = <<-EOT + The tenant for which to create the security group. + This is only required for admins creating security groups for other tenant. + EOT + default = null +} + +variable "delete_default_rules" { + type = bool + description = <<-EOT + Whether or not to delete the default egress rules applied to the security group. + Default rules allow egress ipv4 and ipv6 to 0.0.0.0/0. + EOT + default = false +} + +variable "ingress_rules" { + type = map(map(string)) + description = <<-EOT + The list of ingress rules to attach to the security group. + You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource + provided by the openstack provider, except region, which defaults to the region of the provider used, + and direction, which defaults to ingress. + By default, if ethertype is not specified, it will by IPv4. + EOT + default = {} +} + +variable "egress_rules" { + type = map(map(string)) + description = <<-EOT + The list of egress rules to attach to the security group. + You can use all regular entries from the openstack_networking_secgroup_rule_v2 resource + provided by the openstack provider, except region, which defaults to the region of the provider used, + and direction, which defaults to egress. + By default, if ethertype is not specified, it will by IPv4. + EOT + default = {} +} + +variable "tags" { + type = list(string) + description = "A list of tags (strings) to apply to the security group" + default = [] +} diff --git a/tests/self.tftest.hcl b/tests/self.tftest.hcl new file mode 100644 index 0000000..0891564 --- /dev/null +++ b/tests/self.tftest.hcl @@ -0,0 +1,56 @@ +run "self" { + module { + source = "./tests/module" + } + + variables { + name = "self-sg" + description = "Tofu automated tests." + delete_default_rules = false + ingress_rules = { + cluster = { + protocol = "" + port_range_min = 0 + port_range_max = 0 + remote_group_id = "self" + } + } + egress_rules = { + cluster = { + protocol = "" + port_range_min = 0 + port_range_max = 0 + remote_group_id = "self" + } + } + tags = [ + "tofu=true", + "env=testing", + ] + } + + assert { + condition = module.security_group.name == "self-sg" + error_message = "The security group name is not what was set as input" + } + + assert { + condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", module.security_group.id)) + error_message = "The security group id is not a valid uuid" + } + + assert { + condition = length(module.security_group.sg_ingress_rules_raw) == 1 + error_message = "There are not the expected amount of ingress rules" + } + + assert { + condition = length(module.security_group.sg_egress_rules_raw) == 1 + error_message = "There are not the expected amount of egress rules" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["cluster"].remote_group_id == module.security_group.id + error_message = "The cluster ingress rule is not scoped to itself" + } +} diff --git a/tests/simple.tftest.hcl b/tests/simple.tftest.hcl new file mode 100644 index 0000000..fc0861c --- /dev/null +++ b/tests/simple.tftest.hcl @@ -0,0 +1,55 @@ +run "simple" { + module { + source = "./tests/module" + } + + variables { + name = "simple-sg" + description = "Tofu automated tests." + delete_default_rules = false + ingress_rules = { + http = { + protocol = "tcp" + port_range_min = 80 + port_range_max = 80 + remote_ip_prefix = "0.0.0.0/0" + } + https = { + protocol = "tcp" + port_range_min = 443 + port_range_max = 443 + remote_ip_prefix = "0.0.0.0/0" + } + } + egress_rules = {} + tags = [ + "tofu=true", + "env=testing", + ] + } + + assert { + condition = module.security_group.name == "simple-sg" + error_message = "The security group name is not what was set as input" + } + + assert { + condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", module.security_group.id)) + error_message = "The security group id is not a valid uuid" + } + + assert { + condition = length(module.security_group.sg_ingress_rules_raw) == 2 + error_message = "There are not the expected amount of ingress rules" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["http"].remote_ip_prefix == "0.0.0.0/0" + error_message = "The http ingress rule is not scoped to the correct remote cidr" + } + + assert { + condition = module.security_group.sg_ingress_rules_raw["https"].remote_ip_prefix == "0.0.0.0/0" + error_message = "The https ingress rule is not scoped to the correct remote cidr" + } +}