Skip to content

Commit

Permalink
Improve module structure (#2)
Browse files Browse the repository at this point in the history
* OPS-5899 Update Makefile

* OPS-5899 add optional parameters

* OPS-5899 fix output

* OPS-5899 Add examples

* OPS-5899 Fix lint
  • Loading branch information
snovikov authored Apr 22, 2024
1 parent ff98f4e commit 1d2cf21
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 35 deletions.
58 changes: 37 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ test: _pull-tf
echo "------------------------------------------------------------"; \
echo "# Terraform init"; \
echo "------------------------------------------------------------"; \
if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \
if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" \
--workdir "$${DOCKER_PATH}" --network host \
hashicorp/terraform:$(TF_VERSION) \
init \
-lock=false \
-upgrade \
Expand All @@ -88,22 +90,30 @@ test: _pull-tf
echo "OK"; \
else \
echo "Failed"; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" \
--workdir "$${DOCKER_PATH}" --network none --entrypoint=rm \
hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
exit 1; \
fi; \
echo; \
echo "------------------------------------------------------------"; \
echo "# Terraform validate"; \
echo "------------------------------------------------------------"; \
if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \
if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" \
--workdir "$${DOCKER_PATH}" --network host \
hashicorp/terraform:$(TF_VERSION) \
validate \
$(ARGS) \
.; then \
echo "OK"; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" \
--workdir "$${DOCKER_PATH}" --network none --entrypoint=rm \
hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
else \
echo "Failed"; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" \
--workdir "$${DOCKER_PATH}" --network none --entrypoint=rm \
hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \
exit 1; \
fi; \
echo; \
Expand All @@ -117,7 +127,7 @@ _gen-main:
@echo "------------------------------------------------------------"
@echo "# Main module"
@echo "------------------------------------------------------------"
@if docker run $$(tty -s && echo "-it" || echo) --rm \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='<!-- TFDOCS_HEADER_START -->' \
-e DELIM_CLOSE='<!-- TFDOCS_HEADER_END -->' \
Expand All @@ -128,7 +138,7 @@ _gen-main:
echo "Failed"; \
exit 1; \
fi
@if docker run $$(tty -s && echo "-it" || echo) --rm \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='<!-- TFDOCS_PROVIDER_START -->' \
-e DELIM_CLOSE='<!-- TFDOCS_PROVIDER_END -->' \
Expand All @@ -139,7 +149,7 @@ _gen-main:
echo "Failed"; \
exit 1; \
fi
@if docker run $$(tty -s && echo "-it" || echo) --rm \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='<!-- TFDOCS_REQUIREMENTS_START -->' \
-e DELIM_CLOSE='<!-- TFDOCS_REQUIREMENTS_END -->' \
Expand All @@ -150,7 +160,7 @@ _gen-main:
echo "Failed"; \
exit 1; \
fi
@if docker run $$(tty -s && echo "-it" || echo) --rm \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='<!-- TFDOCS_INPUTS_START -->' \
-e DELIM_CLOSE='<!-- TFDOCS_INPUTS_END -->' \
Expand All @@ -161,7 +171,7 @@ _gen-main:
echo "Failed"; \
exit 1; \
fi
@if docker run $$(tty -s && echo "-it" || echo) --rm \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='<!-- TFDOCS_OUTPUTS_START -->' \
-e DELIM_CLOSE='<!-- TFDOCS_OUTPUTS_END -->' \
Expand All @@ -180,7 +190,7 @@ _gen-examples:
echo "------------------------------------------------------------"; \
echo "# $${DOCKER_PATH}"; \
echo "------------------------------------------------------------"; \
if docker run $$(tty -s && echo "-it" || echo) --rm \
if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='$(DELIM_START)' \
-e DELIM_CLOSE='$(DELIM_CLOSE)' \
Expand All @@ -200,7 +210,7 @@ _gen-modules:
echo "------------------------------------------------------------"; \
echo "# $${DOCKER_PATH}"; \
echo "------------------------------------------------------------"; \
if docker run $$(tty -s && echo "-it" || echo) --rm \
if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v $(CURRENT_DIR):/data \
-e DELIM_START='$(DELIM_START)' \
-e DELIM_CLOSE='$(DELIM_CLOSE)' \
Expand All @@ -218,12 +228,12 @@ _lint-files: _pull-fl
@echo "################################################################################"
@echo "# File-lint"
@echo "################################################################################"
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-cr --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-crlf --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-single-newline --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-space --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8 --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8-bom --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-cr --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-crlf --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-single-newline --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-space --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8 --text --ignore '$(FL_IGNORE_PATHS)' --path .
@docker run $$(tty -s && echo "-it" || echo) --rm --network none -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8-bom --text --ignore '$(FL_IGNORE_PATHS)' --path .

_lint-fmt: _pull-tf
@# Lint all Terraform files
Expand All @@ -234,7 +244,9 @@ _lint-fmt: _pull-tf
@echo "------------------------------------------------------------"
@echo "# *.tf files"
@echo "------------------------------------------------------------"
@if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t:ro" --workdir "/t" hashicorp/terraform:$(TF_VERSION) \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network host \
-v "$(CURRENT_DIR):/t:ro" --workdir "/t" \
hashicorp/terraform:$(TF_VERSION) \
fmt -recursive -check=true -diff=true -write=true -list=true .; then \
echo "OK"; \
else \
Expand All @@ -245,7 +257,9 @@ _lint-fmt: _pull-tf
@echo "------------------------------------------------------------"
@echo "# *.tfvars files"
@echo "------------------------------------------------------------"
@if docker run $$(tty -s && echo "-it" || echo) --rm --entrypoint=/bin/sh -v "$(CURRENT_DIR):/t:ro" --workdir "/t" hashicorp/terraform:$(TF_VERSION) \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network host \
--entrypoint=/bin/sh -v "$(CURRENT_DIR):/t:ro" --workdir "/t" \
hashicorp/terraform:$(TF_VERSION) \
-c "find . -name '*.tfvars' -type f -print0 | xargs -0 -n1 terraform fmt -check=true -write=true -diff=true -list=true"; then \
echo "OK"; \
else \
Expand All @@ -259,7 +273,9 @@ _lint-json: _pull-jl
@echo "################################################################################"
@echo "# Jsonlint"
@echo "################################################################################"
@if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/data:ro" cytopia/jsonlint:$(JL_VERSION) \
@if docker run $$(tty -s && echo "-it" || echo) --rm --network none \
-v "$(CURRENT_DIR):/data:ro" \
cytopia/jsonlint:$(JL_VERSION) \
-t ' ' -i '*.terraform/*' '*.json'; then \
echo "OK"; \
else \
Expand Down
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,36 @@ Description: Cloudflare domain to apply rules for.

Type: `string`

### <a name="input_name"></a> [name](#input\_name)

Description: Name of the ruleset.

Type: `string`

### <a name="input_kind"></a> [kind](#input\_kind)

Description: Type of Ruleset to create.

Type: `string`

### <a name="input_phase"></a> [phase](#input\_phase)

Description: Point in the request/response lifecycle where the ruleset will be created.

Type: `string`

## Optional Inputs

The following input variables are optional (have default values):

### <a name="input_description"></a> [description](#input\_description)

Description: Brief summary of the ruleset and its intended use.

Type: `string`

Default: `null`

### <a name="input_rules"></a> [rules](#input\_rules)

Description: List of Cloudflare firewall rule objects.
Expand All @@ -61,11 +87,11 @@ Type:

```hcl
list(object({
description = string
enabled = bool
action = string
expression = string
products = list(string)
action = optional(string)
description = optional(string)
enabled = optional(bool, true)
products = optional(list(string), [])
}))
```

Expand Down
39 changes: 39 additions & 0 deletions examples/bots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Example

This example will create multiple rulesets for `http_request_firewall_custom` phase.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_rulesets"></a> [rulesets](#module\_rulesets) | ./../../ | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_api_token"></a> [api\_token](#input\_api\_token) | The Cloudflare API token. | `string` | n/a | yes |
| <a name="input_domain"></a> [domain](#input\_domain) | Cloudflare domain name to create | `string` | `"example.com"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_records"></a> [records](#output\_records) | Cloudflare Zone DNS Records |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Copyright (c) 2024 **[Flaconi GmbH](https://github.com/flaconi)**
43 changes: 43 additions & 0 deletions examples/bots/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module "rulesets" {
source = "./../../"
api_token = var.api_token
domain = var.domain
name = "default"
kind = "zone"
phase = "http_request_firewall_custom"
rules = [
{
description = "User-Agent: skip"
enabled = true
action = "skip"
expression = <<-EOT
(http.user_agent contains "Bot/" and http.request.uri.path eq "/api/v1")
EOT
products = ["waf"]
},
{
description = "User-Agent: log"
enabled = false
action = "log"
expression = <<-EOT
(http.user_agent contains "Bot/" and http.request.uri.path eq "/api/v1")
EOT
products = []
},
{
description = "Bots: log"
action = "log"
expression = <<-EOT
(cf.bot_management.score eq 2)
EOT
},
{
description = "Bots: challenge"
enabled = false
action = "managed_challenge"
expression = <<-EOT
(cf.bot_management.score eq 9)
EOT
},
]
}
4 changes: 4 additions & 0 deletions examples/bots/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "records" {
description = "Cloudflare Zone DNS Records"
value = module.rulesets.rules
}
10 changes: 10 additions & 0 deletions examples/bots/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
variable "api_token" {
description = "The Cloudflare API token."
type = string
}

variable "domain" {
description = "Cloudflare domain name to create"
type = string
default = "example.com"
}
11 changes: 6 additions & 5 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
resource "cloudflare_ruleset" "http_request_firewall_custom" {
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
name = "default"
kind = "zone"
phase = "http_request_firewall_custom"
resource "cloudflare_ruleset" "this" {
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
name = var.name
kind = var.kind
phase = var.phase
description = var.description

dynamic "rules" {
for_each = local.rules
Expand Down
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ output "domain" {

output "rules" {
description = "Created Cloudflare rules for the current zone."
value = cloudflare_ruleset.http_request_firewall_custom.rules
value = cloudflare_ruleset.this.rules
}
43 changes: 39 additions & 4 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,49 @@ variable "domain" {
type = string
}

variable "name" {
description = "Name of the ruleset."
type = string
}

variable "kind" {
description = "Type of Ruleset to create."
type = string

# Ensure we specify only allowed kind values
# https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/ruleset#kind
validation {
condition = can(contains(["custom", "managed", "root", "zone"], var.kind))
error_message = "Only the following kind types are allowed: custom, managed, root, zone."
}
}

variable "phase" {
description = "Point in the request/response lifecycle where the ruleset will be created."
type = string

# Ensure we specify only allowed kind values
# https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/ruleset#phase
validation {
condition = can(contains(["ddos_l4", "ddos_l7", "http_config_settings", "http_custom_errors", "http_log_custom_fields", "http_ratelimit", "http_request_cache_settings", "http_request_dynamic_redirect", "http_request_firewall_custom", "http_request_firewall_managed", "http_request_late_transform", "http_request_origin", "http_request_redirect", "http_request_sanitize", "http_request_sbfm", "http_request_transform", "http_response_compression", "http_response_firewall_managed", "http_response_headers_transform", "magic_transit"], var.phase))
error_message = "Only the following phase types are allowed: ddos_l4, ddos_l7, http_config_settings, http_custom_errors, http_log_custom_fields, http_ratelimit, http_request_cache_settings, http_request_dynamic_redirect, http_request_firewall_custom, http_request_firewall_managed, http_request_late_transform, http_request_origin, http_request_redirect, http_request_sanitize, http_request_sbfm, http_request_transform, http_response_compression, http_response_firewall_managed, http_response_headers_transform, magic_transit."
}
}

variable "description" {
description = "Brief summary of the ruleset and its intended use."
type = string
default = null
}

variable "rules" {
description = "List of Cloudflare firewall rule objects."
type = list(object({
description = string
enabled = bool
action = string
expression = string
products = list(string)
action = optional(string)
description = optional(string)
enabled = optional(bool, true)
products = optional(list(string), [])
}))
default = []

Expand Down

0 comments on commit 1d2cf21

Please sign in to comment.