From 188bea5404ed2fa0e17794b4d4a2e9ad597438e8 Mon Sep 17 00:00:00 2001 From: spy86 Date: Tue, 5 Mar 2024 21:43:10 +0100 Subject: [PATCH 1/4] Add Terraform module for Azure Network Security Group --- LICENSE | 21 ------- README.md | 52 ++++++++++++++++ backend.tf | 9 +++ examples/network_security_group/README.md | 76 +++++++++++++++++++++++ examples/network_security_group/main.tf | 0 main.tf | 10 +++ network_security_group.tf | 29 +++++++++ network_security_group_association.tf | 12 ++++ output.tf | 41 ++++++++++++ variables.tf | 53 ++++++++++++++++ 10 files changed, 282 insertions(+), 21 deletions(-) delete mode 100644 LICENSE create mode 100644 README.md create mode 100644 backend.tf create mode 100644 examples/network_security_group/README.md create mode 100644 examples/network_security_group/main.tf create mode 100644 main.tf create mode 100644 network_security_group.tf create mode 100644 network_security_group_association.tf create mode 100644 output.tf create mode 100644 variables.tf diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5860527..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Maciej Michalski - -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 the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce96b7c --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6.4 | +| [azurerm](#requirement\_azurerm) | 3.94.0 | + +## Providers + +| Name | Version | +|------|---------| +| [azurerm](#provider\_azurerm) | 3.94.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [azurerm_network_security_group.main](https://registry.terraform.io/providers/hashicorp/azurerm/3.94.0/docs/resources/network_security_group) | resource | +| [azurerm_network_security_rule.main](https://registry.terraform.io/providers/hashicorp/azurerm/3.94.0/docs/resources/network_security_rule) | resource | +| [azurerm_subnet_network_security_group_association.main](https://registry.terraform.io/providers/hashicorp/azurerm/3.94.0/docs/resources/subnet_network_security_group_association) | resource | +| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/3.94.0/docs/data-sources/client_config) | data source | +| [azurerm_resource_group.main](https://registry.terraform.io/providers/hashicorp/azurerm/3.94.0/docs/data-sources/resource_group) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [associate\_with\_subnet](#input\_associate\_with\_subnet) | Controls whether the Network Security Group should be associated with a subnet. When set to true, an association with the specified subnet is created; when set to false, no subnet association is established. | `bool` | `false` | no | +| [default\_tags](#input\_default\_tags) | A mapping of tags to assign to the resource. | `map(any)` |
{
"ManagedByTerraform": "True"
}
| no | +| [environment](#input\_environment) | Variable that defines the name of the environment. | `string` | `"dev"` | no | +| [network\_security\_group\_list](#input\_network\_security\_group\_list) | List of security\_rule objects representing security rules, as defined below. | `map(any)` |
{
"AllowHTTPAndHTTPS": {
"access": "Allow",
"destination_address_prefix": "*",
"destination_port_range": "80,443",
"direction": "Inbound",
"priority": "1001",
"protocol": "Tcp",
"source_address_prefix": "*",
"source_port_range": "*"
}
}
| no | +| [network\_security\_group\_name](#input\_network\_security\_group\_name) | Specifies the name of the network security group. Changing this forces a new resource to be created. | `string` | n/a | yes | +| [region](#input\_region) | Region in which resources are deployed. | `string` | `"weu"` | no | +| [resource\_group\_location](#input\_resource\_group\_location) | Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. | `any` | n/a | yes | +| [resource\_group\_name](#input\_resource\_group\_name) | The name of the resource group in which to create the network security group. Changing this forces a new resource to be created. | `any` | n/a | yes | +| [subnet\_id](#input\_subnet\_id) | The ID of the Subnet. Changing this forces a new resource to be created. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [network\_security\_group\_id](#output\_network\_security\_group\_id) | The ID of the NSG | +| [network\_security\_group\_name](#output\_network\_security\_group\_name) | The name of the NSG | +| [network\_security\_group\_resource\_group\_name](#output\_network\_security\_group\_resource\_group\_name) | The name of the resource group the nsg is in | +| [network\_security\_group\_rules](#output\_network\_security\_group\_rules) | List of network security rules | +| [network\_security\_group\_subnet\_association](#output\_network\_security\_group\_subnet\_association) | Information about the subnet association with the Network Security Group. | + \ No newline at end of file diff --git a/backend.tf b/backend.tf new file mode 100644 index 0000000..7f32883 --- /dev/null +++ b/backend.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "3.94.0" + } + } + required_version = ">= 1.6.4" +} \ No newline at end of file diff --git a/examples/network_security_group/README.md b/examples/network_security_group/README.md new file mode 100644 index 0000000..6a809a8 --- /dev/null +++ b/examples/network_security_group/README.md @@ -0,0 +1,76 @@ +# Terraform Module: Azure Network Security Group + +This Terraform module provisions an Azure Network Security Group (NSG) with associated security rules. It provides flexibility in configuring security rules for inbound and outbound traffic. + +## Features + +* Create an Azure Network Security Group. +* Define custom security rules for the NSG. +* Optionally associate the NSG with a subnet. + +## Usage + +### Example + +```hcl +provider "azurerm" { +features {} +} + +module "example_nsg" { + source = "Think-Cube/network-security-group/azure" + version = "1.0.0" + resource_group_name = "test" + environment = "dev" + region = "weu" + resource_group_location = "West Europe" + network_security_group_name = "test" + network_security_group_list = { + "AllowHTTPAndHTTPS" = { + priority = "1001" + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "80,443" + source_address_prefix = "*" + destination_address_prefix = "*" + } + # Add additional security rules as needed + } + associate_with_subnet = true + subnet_id = "example-subnet-id" + default_tags = { + Administrator = "John Doe" + Department = "IT" + CostCentre = "CC123" + ContactPerson = "Jane Smith" + ManagedByTerraform = "True" +} +} +``` + +### Variables + +* `environment`: Name of the environment (default: "dev"). +* `resource_group_name`: Name of the Azure Resource Group. +* `network_security_group_name`: Name of the Network Security Group. +* `network_security_group_list`: List of security rules. +* `associate_with_subnet`: Controls subnet association. +* `subnet_id`: ID of the subnet to associate with (if associate_with_subnet is set to true). + +### Outputs + +* `network_security_group_id`: ID of the NSG. +* `network_security_group_name`: Name of the NSG. +* `network_security_group_resource_group_name`: Name of the resource group containing the NSG. +* `network_security_group_rules`: List of network security rules. +* `network_security_group_subnet_association`: Subnet association information (if applicable). + +## License + +This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). + +## Contribution + +Feel free to contribute by opening issues or pull requests. Your feedback and improvements are highly appreciated! diff --git a/examples/network_security_group/main.tf b/examples/network_security_group/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..735861e --- /dev/null +++ b/main.tf @@ -0,0 +1,10 @@ +provider "azurerm" { + + features {} +} + +data "azurerm_client_config" "current" {} + +data "azurerm_resource_group" "main" { + name = var.resource_group_name +} \ No newline at end of file diff --git a/network_security_group.tf b/network_security_group.tf new file mode 100644 index 0000000..2fa11af --- /dev/null +++ b/network_security_group.tf @@ -0,0 +1,29 @@ +resource "azurerm_network_security_group" "main" { + name = "${var.environment}-${var.network_security_group_name}-${var.region}-nsg" + location = data.azurerm_resource_group.rg.location + resource_group_name = data.azurerm_resource_group.rg.name + tags = var.default_tags + + timeouts { + create = "5m" + delete = "10m" + } +} + +resource "azurerm_network_security_rule" "main" { + for_each = var.network_security_group_list + + name = each.key + priority = each.value.priority + direction = each.value.direction + access = each.value.access + protocol = each.value.protocol + source_port_range = each.value.source_port_range + destination_port_range = each.value.destination_port_range + source_address_prefix = each.value.source_address_prefix + destination_address_prefix = each.value.destination_address_prefix + resource_group_name = data.azurerm_resource_group.rg.name + network_security_group_name = azurerm_network_security_group.main.name + + depends_on = [azurerm_network_security_group.main] +} \ No newline at end of file diff --git a/network_security_group_association.tf b/network_security_group_association.tf new file mode 100644 index 0000000..b65747e --- /dev/null +++ b/network_security_group_association.tf @@ -0,0 +1,12 @@ +resource "azurerm_subnet_network_security_group_association" "main" { + count = var.associate_with_subnet ? 1 : 0 + subnet_id = var.subnet_id + network_security_group_id = azurerm_network_security_group.main.id + + timeouts { + create = "5m" + delete = "10m" + } + + depends_on = [azurerm_network_security_group.main] +} \ No newline at end of file diff --git a/output.tf b/output.tf new file mode 100644 index 0000000..6c39788 --- /dev/null +++ b/output.tf @@ -0,0 +1,41 @@ +output "network_security_group_id" { + value = azurerm_network_security_group.main.id + description = "The ID of the NSG" +} + +output "network_security_group_name" { + value = azurerm_network_security_group.main.name + description = "The name of the NSG" +} + +output "network_security_group_resource_group_name" { + value = azurerm_network_security_group.main.resource_group_name + description = "The name of the resource group the nsg is in" +} + +output "network_security_group_rules" { + description = "List of network security rules" + value = { + for rule in var.network_security_group_list : rule.key => { + name = rule.key + priority = rule.priority + direction = rule.direction + access = rule.access + protocol = rule.protocol + source_port_range = rule.source_port_range + destination_port_range = rule.destination_port_range + source_address_prefix = rule.source_address_prefix + destination_address_prefix = rule.destination_address_prefix + resource_group_name = data.azurerm_resource_group.rg.name + network_security_group_name = azurerm_network_security_group.main.name + } + } +} + +output "network_security_group_subnet_association" { + description = "Information about the subnet association with the Network Security Group." + value = var.associate_with_subnet ? { + subnet_id = azurerm_subnet_network_security_group_association.main[0].subnet_id + network_security_group_id = azurerm_subnet_network_security_group_association.main[0].network_security_group_id + } : null +} \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..a2315e8 --- /dev/null +++ b/variables.tf @@ -0,0 +1,53 @@ +########################### +# Common vars +########################### +variable "environment" { + description = "Variable that defines the name of the environment." + type = string + default = "dev" +} +variable "default_tags" { + description = "A mapping of tags to assign to the resource." + type = map(any) + default = { + "ManagedByTerraform" = "True" + } +} +variable "region" { + description = "Region in which resources are deployed." + type = string + default = "weu" +} +############################ +#Resource gropus vars +############################ +variable "resource_group_location" { + description = "Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created." +} +variable "resource_group_name" { + description = "The name of the resource group in which to create the network security group. Changing this forces a new resource to be created." +} +############################### +#Network scurity group variable +############################### +variable "network_security_group_name" { + description = "Specifies the name of the network security group. Changing this forces a new resource to be created." + type = string +} +variable "network_security_group_list" { + description = "List of security_rule objects representing security rules, as defined below." + type = map(any) + default = { + "AllowHTTPAndHTTPS" = { priority = "1001", direction = "Inbound", access = "Allow", protocol = "Tcp", source_port_range = "*", destination_port_range = "80,443", source_address_prefix = "*", destination_address_prefix = "*" }, + } +} +variable "associate_with_subnet" { + description = "Controls whether the Network Security Group should be associated with a subnet. When set to true, an association with the specified subnet is created; when set to false, no subnet association is established." + type = bool + default = false +} +variable "subnet_id" { + description = "The ID of the Subnet. Changing this forces a new resource to be created." + type = string + default = "" +} \ No newline at end of file From 4afa3e3a669b653267c2a58d4b04e9b565615db0 Mon Sep 17 00:00:00 2001 From: Maciej Michalski <5445923+spy86@users.noreply.github.com> Date: Tue, 5 Mar 2024 21:44:39 +0100 Subject: [PATCH 2/4] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a990273 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 ThinkCube + +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 the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 7389f01627f8cb56c206cc8568a12518c81afa39 Mon Sep 17 00:00:00 2001 From: Maciej Michalski <5445923+spy86@users.noreply.github.com> Date: Tue, 5 Mar 2024 21:46:16 +0100 Subject: [PATCH 3/4] Create tfsec.yml --- .github/workflows/tfsec.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/tfsec.yml diff --git a/.github/workflows/tfsec.yml b/.github/workflows/tfsec.yml new file mode 100644 index 0000000..a768f1a --- /dev/null +++ b/.github/workflows/tfsec.yml @@ -0,0 +1,27 @@ +name: tfsec +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '31 16 * * 5' +jobs: + tfsec: + name: Run tfsec sarif report + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Clone repo + uses: actions/checkout@v3 + - name: Run tfsec + uses: aquasecurity/tfsec-sarif-action@9a83b5c3524f825c020e356335855741fd02745f + with: + sarif_file: tfsec.sarif + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: tfsec.sarif From da75a3567af9c57bb4f3e68c568f1dd329b5708b Mon Sep 17 00:00:00 2001 From: Maciej Michalski <5445923+spy86@users.noreply.github.com> Date: Tue, 5 Mar 2024 21:54:50 +0100 Subject: [PATCH 4/4] Update variables.tf --- variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variables.tf b/variables.tf index a2315e8..b0d6c7e 100644 --- a/variables.tf +++ b/variables.tf @@ -38,7 +38,7 @@ variable "network_security_group_list" { description = "List of security_rule objects representing security rules, as defined below." type = map(any) default = { - "AllowHTTPAndHTTPS" = { priority = "1001", direction = "Inbound", access = "Allow", protocol = "Tcp", source_port_range = "*", destination_port_range = "80,443", source_address_prefix = "*", destination_address_prefix = "*" }, + "AllowHTTPAndHTTPS" = { priority = "1001", direction = "Inbound", access = "Allow", protocol = "Tcp", source_port_range = "*", destination_port_range = "80,443", source_address_prefix = "192.168.1.0/24", destination_address_prefix = "10.1.0.0/16" }, } } variable "associate_with_subnet" { @@ -50,4 +50,4 @@ variable "subnet_id" { description = "The ID of the Subnet. Changing this forces a new resource to be created." type = string default = "" -} \ No newline at end of file +}