From dbba1e70b124ba3119852685298aeb3c9e5d6dbc Mon Sep 17 00:00:00 2001 From: SweetOps Date: Sat, 30 Jan 2021 14:44:02 +0200 Subject: [PATCH] upd --- README.md | 164 +++++++++++++------- README.yaml | 81 +++++++--- docs/terraform.md | 20 ++- examples/complete/context.tf | 3 +- examples/complete/fixtures.us-east-2.tfvars | 18 ++- examples/complete/main.tf | 51 +++++- examples/complete/outputs.tf | 48 ++++-- examples/complete/variables.tf | 9 +- examples/complete/versions.tf | 7 +- main.tf | 57 +++++-- outputs.tf | 12 +- test/src/examples_complete_test.go | 58 +++---- test/src/go.sum | 1 + variables.tf | 51 +++--- versions.tf | 2 +- 15 files changed, 394 insertions(+), 188 deletions(-) diff --git a/README.md b/README.md index 40b4383..faa9ab9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# terraform-example-module [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-example-module.svg)](https://github.com/cloudposse/terraform-example-module/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) [![Discourse Forum](https://img.shields.io/discourse/https/ask.sweetops.com/posts.svg)](https://ask.sweetops.com/) + +# terraform-aws-security-group [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-security-group.svg)](https://github.com/cloudposse/terraform-aws-security-group/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) + [![README Header][readme_header_img]][readme_header_link] @@ -25,8 +27,7 @@ --> -This is `terraform-example-module` project provides all the scaffolding for a typical well-built Cloud Posse module. It's a template repository you can -use when creating new repositories. +Terraform module to create AWS Security Group and rules. --- @@ -63,16 +64,66 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are ## Usage -**IMPORTANT:** The `master` branch is used in `source` just as an example. In your code, do not pin to `master` because there may be breaking changes between releases. -Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest releases](https://github.com/cloudposse/terraform-example-module/releases). +**IMPORTANT:** We do not pin modules to versions in our examples because of the +difficulty of keeping the versions in the documentation in sync with the latest released versions. +We highly recommend that in your code you pin the version to the exact version you are +using so that your infrastructure remains stable, and update versions in a +systematic way so that they do not catch you by surprise. + +Also, because of a bug in the Terraform registry ([hashicorp/terraform#21417](https://github.com/hashicorp/terraform/issues/21417)), +the registry shows many of our inputs as required when in fact they are optional. +The table below correctly indicates which inputs are required. -Here's how to invoke this example module in your projects ```hcl -module "example" { - source = "https://github.com/cloudposse/terraform-example-module.git?ref=master" - example = "Hello world!" +module "label" { + source = "cloudposse/label/null" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + namespace = "eg" + stage = "prod" + name = "bastion" + attributes = ["public"] + delimiter = "-" + + tags = { + "BusinessUnit" = "XYZ", + "Snapshot" = "true" + } +} + +module "vpc" { + source = "cloudposse/vpc/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + cidr_block = "10.0.0.0/16" + + context = module.label.context +} + +module "vpc" { + source = "cloudposse/security-group/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + sg_rules = [ + { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + }, + { + type = "egress" + from_port = 0 + to_port = 65535 + protocol = "all" + cidr_blocks = ["0.0.0.0/0"] + } + ] + + context = module.label.context } ``` @@ -82,7 +133,7 @@ module "example" { ## Examples Here is an example of using this module: -- [`examples/complete`](https://github.com/cloudposse/terraform-example-module/) - complete example of using this module +- [`examples/complete`](https://github.com/cloudposse/terraform-aws-security-group/) - complete example of using this module @@ -103,15 +154,14 @@ Available targets: | Name | Version | |------|---------| -| terraform | >= 0.12.0, < 0.14.0 | -| local | ~> 1.2 | -| random | ~> 2.2 | +| terraform | >= 0.12.26 | +| aws | >= 2.0 | ## Providers | Name | Version | |------|---------| -| random | ~> 2.2 | +| aws | >= 2.0 | ## Inputs @@ -121,24 +171,29 @@ Available targets: | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| description | The Security Group description. | `string` | `"Managed by Terraform"` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| example | Example variable | `string` | `"hello world"` | no | | id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| security\_group\_enabled | Whether to create Security Group. | `bool` | `true` | no | +| sg\_id | The external Security Group ID to which Security Group rules will be assigned.
Required to set `security_group_enabled` to `false`. | `string` | `""` | no | +| sg\_rules | A list of maps of Security Group rules.
The values of map is fully complated with `aws_security_group_rule` resource.
To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule . | `list(any)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| use\_name\_prefix | Whether to create a unique name beginning with the normalized prefix. | `bool` | `false` | no | +| vpc\_id | The VPC ID where Security Group will be created. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| example | Example output | -| id | ID of the created example | -| random | Stable random number for this example | +| sg\_arn | The Security Group ARN | +| sg\_id | The Security Group ID | +| sg\_name | The Security Group Name | @@ -146,7 +201,7 @@ Available targets: ## Share the Love -Like this project? Please give it a ★ on [our GitHub](https://github.com/cloudposse/terraform-example-module)! (it helps us **a lot**) +Like this project? Please give it a ★ on [our GitHub](https://github.com/cloudposse/terraform-aws-security-group)! (it helps us **a lot**) Are you using this project or any of our other projects? Consider [leaving a testimonial][testimonial]. =) @@ -164,17 +219,14 @@ Check out these related projects. For additional context, refer to some of these links. -- [Terraform Standard Module Structure](https://www.terraform.io/docs/modules/index.html#standard-module-structure) - HashiCorp's standard module structure is a file and directory layout we recommend for reusable modules distributed in separate repositories. -- [Terraform Module Requirements](https://www.terraform.io/docs/registry/modules/publish.html#requirements) - HashiCorp's guidance on all the requirements for publishing a module. Meeting the requirements for publishing a module is extremely easy. -- [Terraform `random_integer` Resource](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) - The resource random_integer generates random values from a given range, described by the min and max attributes of a given resource. -- [Terraform Version Pinning](https://www.terraform.io/docs/configuration/terraform.html#specifying-a-required-terraform-version) - The required_version setting can be used to constrain which versions of the Terraform CLI can be used with your configuration +- [terraform-provider-aws](https://registry.terraform.io/providers/hashicorp/aws/latest) - Terraform AWS provider ## Help **Got a question?** We got answers. -File a GitHub [issue](https://github.com/cloudposse/terraform-example-module/issues), send us an [email][email] or join our [Slack Community][slack]. +File a GitHub [issue](https://github.com/cloudposse/terraform-aws-security-group/issues), send us an [email][email] or join our [Slack Community][slack]. [![README Commercial Support][readme_commercial_support_img]][readme_commercial_support_link] @@ -222,7 +274,7 @@ Sign up for [our newsletter][newsletter] that covers everything on our technolog ### Bug Reports & Feature Requests -Please use the [issue tracker](https://github.com/cloudposse/terraform-example-module/issues) to report any bugs or file feature requests. +Please use the [issue tracker](https://github.com/cloudposse/terraform-aws-security-group/issues) to report any bugs or file feature requests. ### Developing @@ -242,7 +294,7 @@ In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. ## Copyrights -Copyright © 2020-2020 [Cloud Posse, LLC](https://cloudposse.com) +Copyright © 2021-2021 [Cloud Posse, LLC](https://cloudposse.com) @@ -301,42 +353,46 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply ### Contributors -| [![Erik Osterman][osterman_avatar]][osterman_homepage]
[Erik Osterman][osterman_homepage] | -|---| + +| [![Erik Osterman][osterman_avatar]][osterman_homepage]
[Erik Osterman][osterman_homepage] | [![Vladimir][SweetOps_avatar]][SweetOps_homepage]
[Vladimir][SweetOps_homepage] | +|---|---| + [osterman_homepage]: https://github.com/osterman [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png + [SweetOps_homepage]: https://github.com/SweetOps + [SweetOps_avatar]: https://img.cloudposse.com/150x150/https://github.com/SweetOps.png [![README Footer][readme_footer_img]][readme_footer_link] [![Beacon][beacon]][website] [logo]: https://cloudposse.com/logo-300x69.svg - [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=docs - [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=website - [github]: https://cpco.io/github?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=github - [jobs]: https://cpco.io/jobs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=jobs - [hire]: https://cpco.io/hire?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=hire - [slack]: https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=slack - [linkedin]: https://cpco.io/linkedin?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=linkedin - [twitter]: https://cpco.io/twitter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=twitter - [testimonial]: https://cpco.io/leave-testimonial?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=testimonial - [office_hours]: https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=office_hours - [newsletter]: https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=newsletter - [discourse]: https://ask.sweetops.com/?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=discourse - [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=email - [commercial_support]: https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=commercial_support - [we_love_open_source]: https://cpco.io/we-love-open-source?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=we_love_open_source - [terraform_modules]: https://cpco.io/terraform-modules?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=terraform_modules + [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=docs + [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=website + [github]: https://cpco.io/github?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=github + [jobs]: https://cpco.io/jobs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=jobs + [hire]: https://cpco.io/hire?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=hire + [slack]: https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=slack + [linkedin]: https://cpco.io/linkedin?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=linkedin + [twitter]: https://cpco.io/twitter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=twitter + [testimonial]: https://cpco.io/leave-testimonial?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=testimonial + [office_hours]: https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=office_hours + [newsletter]: https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=newsletter + [discourse]: https://ask.sweetops.com/?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=discourse + [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=email + [commercial_support]: https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=commercial_support + [we_love_open_source]: https://cpco.io/we-love-open-source?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=we_love_open_source + [terraform_modules]: https://cpco.io/terraform-modules?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=terraform_modules [readme_header_img]: https://cloudposse.com/readme/header/img - [readme_header_link]: https://cloudposse.com/readme/header/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=readme_header_link + [readme_header_link]: https://cloudposse.com/readme/header/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=readme_header_link [readme_footer_img]: https://cloudposse.com/readme/footer/img - [readme_footer_link]: https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=readme_footer_link + [readme_footer_link]: https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=readme_footer_link [readme_commercial_support_img]: https://cloudposse.com/readme/commercial-support/img - [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-example-module&utm_content=readme_commercial_support_link - [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-example-module&url=https://github.com/cloudposse/terraform-example-module - [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-example-module&url=https://github.com/cloudposse/terraform-example-module - [share_reddit]: https://reddit.com/submit/?url=https://github.com/cloudposse/terraform-example-module - [share_facebook]: https://facebook.com/sharer/sharer.php?u=https://github.com/cloudposse/terraform-example-module - [share_googleplus]: https://plus.google.com/share?url=https://github.com/cloudposse/terraform-example-module - [share_email]: mailto:?subject=terraform-example-module&body=https://github.com/cloudposse/terraform-example-module - [beacon]: https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-example-module?pixel&cs=github&cm=readme&an=terraform-example-module + [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-security-group&utm_content=readme_commercial_support_link + [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-aws-security-group&url=https://github.com/cloudposse/terraform-aws-security-group + [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-aws-security-group&url=https://github.com/cloudposse/terraform-aws-security-group + [share_reddit]: https://reddit.com/submit/?url=https://github.com/cloudposse/terraform-aws-security-group + [share_facebook]: https://facebook.com/sharer/sharer.php?u=https://github.com/cloudposse/terraform-aws-security-group + [share_googleplus]: https://plus.google.com/share?url=https://github.com/cloudposse/terraform-aws-security-group + [share_email]: mailto:?subject=terraform-aws-security-group&body=https://github.com/cloudposse/terraform-aws-security-group + [beacon]: https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-aws-security-group?pixel&cs=github&cm=readme&an=terraform-aws-security-group diff --git a/README.yaml b/README.yaml index a570d1f..4f89b20 100644 --- a/README.yaml +++ b/README.yaml @@ -7,6 +7,13 @@ # Name of this project name: terraform-aws-security-group +# Tags of this project +tags: + - aws + - security-group + - terraform + - terraform-modules + # Logo for this project #logo: docs/logo.png @@ -30,9 +37,6 @@ badges: - name: "Slack Community" image: "https://slack.cloudposse.com/badge.svg" url: "https://slack.cloudposse.com" - - name: "Discourse Forum" - image: "https://img.shields.io/discourse/https/ask.sweetops.com/posts.svg" - url: "https://ask.sweetops.com/" # List any related terraform modules that this module may be used with or that this module depends on. related: @@ -42,23 +46,13 @@ related: # List any resources helpful for someone to get started. For example, link to the hashicorp documentation or AWS documentation. references: - - name: "Terraform Standard Module Structure" - description: "HashiCorp's standard module structure is a file and directory layout we recommend for reusable modules distributed in separate repositories." - url: "https://www.terraform.io/docs/modules/index.html#standard-module-structure" - - name: "Terraform Module Requirements" - description: "HashiCorp's guidance on all the requirements for publishing a module. Meeting the requirements for publishing a module is extremely easy." - url: "https://www.terraform.io/docs/registry/modules/publish.html#requirements" - - name: "Terraform `random_integer` Resource" - description: "The resource random_integer generates random values from a given range, described by the min and max attributes of a given resource." - url: "https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer" - - name: "Terraform Version Pinning" - description: "The required_version setting can be used to constrain which versions of the Terraform CLI can be used with your configuration" - url: "https://www.terraform.io/docs/configuration/terraform.html#specifying-a-required-terraform-version" + - name: terraform-provider-aws + description: Terraform AWS provider + url: https://registry.terraform.io/providers/hashicorp/aws/latest # Short description of this project description: |- - This is `terraform-aws-security-group` project provides all the scaffolding for a typical well-built Cloud Posse module. It's a template repository you can - use when creating new repositories. + Terraform module to create AWS Security Group and rules. # Introduction to the project #introduction: |- @@ -66,12 +60,55 @@ description: |- # How to use this module. Should be an easy example to copy and paste. usage: |- - Here's how to invoke this example module in your projects ```hcl - module "example" { - source = "https://github.com/cloudposse/terraform-aws-security-group.git?ref=master" - example = "Hello world!" + module "label" { + source = "cloudposse/label/null" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + namespace = "eg" + stage = "prod" + name = "bastion" + attributes = ["public"] + delimiter = "-" + + tags = { + "BusinessUnit" = "XYZ", + "Snapshot" = "true" + } + } + + module "vpc" { + source = "cloudposse/vpc/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + cidr_block = "10.0.0.0/16" + + context = module.label.context + } + + module "vpc" { + source = "cloudposse/security-group/aws" + # Cloud Posse recommends pinning every module to a specific version + # version = "x.x.x" + sg_rules = [ + { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + }, + { + type = "egress" + from_port = 0 + to_port = 65535 + protocol = "all" + cidr_blocks = ["0.0.0.0/0"] + } + ] + + context = module.label.context } ``` @@ -93,3 +130,5 @@ include: contributors: - name: "Erik Osterman" github: "osterman" + - name: "Vladimir" + github: "SweetOps" \ No newline at end of file diff --git a/docs/terraform.md b/docs/terraform.md index 7fdf496..8e2a034 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -3,15 +3,14 @@ | Name | Version | |------|---------| -| terraform | >= 0.12.0, < 0.14.0 | -| local | ~> 1.2 | -| random | ~> 2.2 | +| terraform | >= 0.12.26 | +| aws | >= 2.0 | ## Providers | Name | Version | |------|---------| -| random | ~> 2.2 | +| aws | >= 2.0 | ## Inputs @@ -21,23 +20,28 @@ | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| description | The Security Group description. | `string` | `"Managed by Terraform"` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| example | Example variable | `string` | `"hello world"` | no | | id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| security\_group\_enabled | Whether to create Security Group. | `bool` | `true` | no | +| sg\_id | The external Security Group ID to which Security Group rules will be assigned.
Required to set `security_group_enabled` to `false`. | `string` | `""` | no | +| sg\_rules | A list of maps of Security Group rules.
The values of map is fully complated with `aws_security_group_rule` resource.
To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule . | `list(any)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| use\_name\_prefix | Whether to create a unique name beginning with the normalized prefix. | `bool` | `false` | no | +| vpc\_id | The VPC ID where Security Group will be created. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| example | Example output | -| id | ID of the created example | -| random | Stable random number for this example | +| sg\_arn | The Security Group ARN | +| sg\_id | The Security Group ID | +| sg\_name | The Security Group Name | diff --git a/examples/complete/context.tf b/examples/complete/context.tf index bae0cf1..f5f2797 100644 --- a/examples/complete/context.tf +++ b/examples/complete/context.tf @@ -19,7 +19,8 @@ # module "this" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + source = "cloudposse/label/null" + version = "0.22.1" // requires Terraform >= 0.12.26 enabled = var.enabled namespace = var.namespace diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index 1e0ce68..22a7e64 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -6,5 +6,21 @@ environment = "ue2" stage = "test" -name = "example" +name = "sg" +sg_rules = [ + { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + }, + { + type = "egress" + from_port = 0 + to_port = 65535 + protocol = "all" + cidr_blocks = ["0.0.0.0/0"] + } +] \ No newline at end of file diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 38880b7..8d988b9 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -1,7 +1,54 @@ -module "example" { +provider "aws" { + region = var.region +} + +module "vpc" { + source = "cloudposse/vpc/aws" + version = "v0.18.2" + + cidr_block = "10.0.0.0/16" + + context = module.this.context +} + +# Create new one security group + +module "new_security_group" { + source = "../.." + + vpc_id = module.vpc.vpc_id + sg_rules = var.sg_rules + + context = module.this.context +} + +# Create rules for pre-created security group + +resource "aws_security_group" "external" { + name_prefix = format("%s-%s-", module.this.id, "external") + vpc_id = module.vpc.vpc_id + tags = module.this.tags +} + +module "external_security_group" { source = "../.." - example = var.example + vpc_id = module.vpc.vpc_id + sg_id = aws_security_group.external.id + sg_rules = var.sg_rules + security_group_enabled = false context = module.this.context } + +# Disabled module + +module "disabled_security_group" { + source = "../.." + + vpc_id = module.vpc.vpc_id + sg_id = aws_security_group.external.id + sg_rules = var.sg_rules + context = module.this.context + enabled = false +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 20aa3e3..7c7eff9 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,14 +1,44 @@ -output "id" { - description = "ID of the created example" - value = module.example.id +output "new_sg_id" { + description = "The new one Security Group ID" + value = module.new_security_group.sg_id } -output "example" { - description = "Output \"example\" from example module" - value = module.example.example +output "new_sg_arn" { + description = "The new one Security Group ARN" + value = module.new_security_group.sg_arn } -output "random" { - description = "Output \"random\" from example module" - value = module.example.random +output "new_sg_name" { + description = "The new one Security Group Name" + value = module.new_security_group.sg_name +} + +output "external_sg_id" { + description = "The external Security Group ID" + value = module.external_security_group.sg_id +} + +output "external_sg_arn" { + description = "The external Security Group ARN" + value = module.external_security_group.sg_arn +} + +output "external_sg_name" { + description = "The external Security Group Name" + value = module.external_security_group.sg_name +} + +output "disabled_sg_id" { + description = "The disabled Security Group ID (should be empty)" + value = module.disabled_security_group.sg_id +} + +output "disabled_sg_arn" { + description = "The disabled Security Group ARN (should be empty)" + value = module.disabled_security_group.sg_arn +} + +output "disabled_sg_name" { + description = "The disabled Security Group Name (should be empty)" + value = module.disabled_security_group.sg_name } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 9a04f21..adc2d9e 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -1,4 +1,7 @@ -variable "example" { - type = string - description = "The value which will be passed to the example module" +variable "region" { + type = string +} + +variable "sg_rules" { + type = list(any) } diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index 572ee1f..9a98376 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -1,7 +1,10 @@ terraform { - required_version = ">= 0.12.0, < 0.14" + required_version = ">= 0.12.26" required_providers { - local = "~> 1.2" + aws = { + source = "hashicorp/aws" + version = ">= 2.0" + } } } diff --git a/main.tf b/main.tf index c8348eb..4947add 100644 --- a/main.tf +++ b/main.tf @@ -1,34 +1,61 @@ locals { - security_group_enabled = module.this.enabled && var.security_group_enabled ? 1 : 0 + security_group_enabled = module.this.enabled && var.security_group_enabled + is_external = module.this.enabled && var.security_group_enabled == false name = var.use_name_prefix ? null : module.this.id - name_prefix = var.use_name_prefix ? format("%s%s", module.this.id, module.delimiter) : null - sg_id = local.security_group_enabled ? try(aws_security_group.default.id, "") : var.sg_id - sg_rules = module.this.enabled ? var.sg_rules : [] + name_prefix = var.use_name_prefix ? format("%s%s", module.this.id, module.this.delimiter) : null + sg_id = local.is_external ? join("", data.aws_security_group.external.*.id) : join("", aws_security_group.default.*.id) + sg_arn = local.is_external ? join("", data.aws_security_group.external.*.arn) : join("", aws_security_group.default.*.arn) + sg_name = local.is_external ? join("", data.aws_security_group.external.*.name) : join("", aws_security_group.default.*.name) + sg_rules = module.this.enabled && var.sg_rules != null ? { + for rule in flatten(distinct(var.sg_rules)) : + format("%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", + rule.type, + rule.protocol, + rule.from_port, + rule.to_port, + lookup(rule, "cidr_blocks", null) == null ? "no_ipv4" : "ipv4", + lookup(rule, "ipv6_cidr_blocks", null) == null ? "no_ipv6" : "ipv6", + lookup(rule, "security_group_id", null) == null ? "no_ssg" : "ssg", + lookup(rule, "prefix_list_ids", null) == null ? "no_pli" : "pli", + lookup(rule, "self", null) == null ? "no_self" : "self", + lookup(rule, "description", null) == null ? "no_desc" : "desc" + ) => rule + } : {} } +data "aws_security_group" "external" { + count = local.is_external ? 1 : 0 + id = var.sg_id + vpc_id = var.vpc_id +} + resource "aws_security_group" "default" { - count = local.security_group_enabled + count = local.security_group_enabled && local.is_external == false ? 1 : 0 name = local.name name_prefix = local.name_prefix description = var.description vpc_id = var.vpc_id tags = module.this.tags + + lifecycle { + create_before_destroy = true + } } resource "aws_security_group_rule" "default" { for_each = local.sg_rules - type = each.value.type # Required - from_port = each.value.from_port # Required - to_port = each.value.to_port # Required - protocol = each.value.protocol # Required - cidr_blocks = try(each.value.cidr_blocks, null) - ipv6_cidr_blocks = try(each.value.ipv6_cidr_blocks, null) - prefix_list_ids = try(each.value.prefix_list_ids, null) security_group_id = local.sg_id - source_security_group_id = try(each.value.source_security_group_id, null) - self = try(each.value.self, null) - description = try(each.value.self, "Managed by Terraform") + type = each.value.type + from_port = each.value.from_port + to_port = each.value.to_port + protocol = each.value.protocol + cidr_blocks = lookup(each.value, "cidr_blocks", null) + ipv6_cidr_blocks = lookup(each.value, "ipv6_cidr_blocks", null) + prefix_list_ids = lookup(each.value, "prefix_list_ids", null) + source_security_group_id = lookup(each.value, "source_security_group_id", null) + self = lookup(each.value, "self", null) == null ? false : each.value.self + description = lookup(each.value, "description", null) == null ? "Managed by Terraform" : each.value.description } diff --git a/outputs.tf b/outputs.tf index a5986a4..96dd2ed 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,4 +1,14 @@ output "sg_id" { description = "The Security Group ID" - value = module.this.enabled ? local.sg_id : null + value = try(local.sg_id, null) +} + +output "sg_arn" { + description = "The Security Group ARN" + value = try(local.sg_arn, null) +} + +output "sg_name" { + description = "The Security Group Name" + value = try(local.sg_name, null) } diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index cb8ed00..b70ece2 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -18,8 +18,6 @@ func TestExamplesComplete(t *testing.T) { randID := strconv.Itoa(rand.Intn(100000)) attributes := []string{randID} - exampleInput := "Hello, world!" - terraformOptions := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../../examples/complete", @@ -30,7 +28,6 @@ func TestExamplesComplete(t *testing.T) { // and AWS resources do not interfere with each other Vars: map[string]interface{}{ "attributes": attributes, - "example": exampleInput, }, } // At the end of the test, run `terraform destroy` to clean up any resources that were created @@ -40,44 +37,31 @@ func TestExamplesComplete(t *testing.T) { terraform.InitAndApply(t, terraformOptions) // Run `terraform output` to get the value of an output variable - id := terraform.Output(t, terraformOptions, "id") - example := terraform.Output(t, terraformOptions, "example") - random := terraform.Output(t, terraformOptions, "random") - - // Verify we're getting back the outputs we expect - // Ensure we get a random number appended - assert.Equal(t, exampleInput+" "+random, example) - // Ensure we get the attribute included in the ID - assert.Equal(t, "eg-ue2-test-example-"+randID, id) - - // ************************************************************************ - // This steps below are unusual, not generally part of the testing - // but included here as an example of testing this specific module. - // This module has a random number that is supposed to change - // only when the example changes. So we run it again to ensure - // it does not change. - - // This will run `terraform apply` a second time and fail the test if there are any errors - terraform.Apply(t, terraformOptions) - id2 := terraform.Output(t, terraformOptions, "id") - example2 := terraform.Output(t, terraformOptions, "example") - random2 := terraform.Output(t, terraformOptions, "random") + // Verify that outputs are valid when `security_group_enabled=true` + newSgID := terraform.Output(t, terraformOptions, "new_sg_id") + newSgARN := terraform.Output(t, terraformOptions, "new_sg_arn") + newSgName := terraform.Output(t, terraformOptions, "new_sg_name") - assert.Equal(t, id, id2, "Expected `id` to be stable") - assert.Equal(t, example, example2, "Expected `example` to be stable") - assert.Equal(t, random, random2, "Expected `random` to be stable") + assert.Contains(t, newSgID, "sg-", "SG ID should contains substring 'sg-'") + assert.Contains(t, newSgARN, "arn:aws:ec2", "SG ID should contains substring 'arn:aws:ec2'") + assert.Equal(t, "eg-ue2-test-sg-"+randID, newSgName) - // Then we run change the example and run it a third time and - // verify that the random number changed - newExample := "Goodbye" - terraformOptions.Vars["example"] = newExample - terraform.Apply(t, terraformOptions) + // Verify that outputs are valid when `security_group_enabled=false` and `sg_id` set to external SG ID + externalSgID := terraform.Output(t, terraformOptions, "external_sg_id") + externalSgARN := terraform.Output(t, terraformOptions, "external_sg_arn") + externalSgName := terraform.Output(t, terraformOptions, "external_sg_name") - example3 := terraform.Output(t, terraformOptions, "example") - random3 := terraform.Output(t, terraformOptions, "random") + assert.Contains(t, externalSgID, "sg-", "SG ID should contains substring 'sg-'") + assert.Contains(t, externalSgARN, "arn:aws:ec2", "SG ID should contains substring 'arn:aws:ec2'") + assert.Contains(t, externalSgName, "eg-ue2-test-sg-"+randID) - assert.NotEqual(t, random, random3, "Expected `random` to change when `example` changed") - assert.Equal(t, newExample+" "+random3, example3, "Expected `example` to use new random number") + // Verify that outputs are empty when module is disabled + disabledSgID := terraform.Output(t, terraformOptions, "disabled_sg_id") + disabledSgARN := terraform.Output(t, terraformOptions, "disabled_sg_arn") + disabledSgName := terraform.Output(t, terraformOptions, "disabled_sg_name") + assert.Empty(t, disabledSgID) + assert.Empty(t, disabledSgARN) + assert.Empty(t, disabledSgName) } diff --git a/test/src/go.sum b/test/src/go.sum index 1dd19f3..d3b4236 100644 --- a/test/src/go.sum +++ b/test/src/go.sum @@ -284,6 +284,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/variables.tf b/variables.tf index 8d1a582..c4b42ba 100644 --- a/variables.tf +++ b/variables.tf @@ -1,17 +1,6 @@ -variable "description" { - type = string - default = "Managed by Terraform" - description = "The Security Group description." -} - variable "vpc_id" { type = string description = "The VPC ID where Security Group will be created." - - validation { - condition = substr(var.vpc_id, 0, 4) == "vpc-" && length(var.vpc_id) > 4 - error_message = "The ami_id value must start with `ami-`." - } } variable "security_group_enabled" { @@ -26,31 +15,27 @@ variable "use_name_prefix" { description = "Whether to create a unique name beginning with the normalized prefix." } +variable "description" { + type = string + default = "Managed by Terraform" + description = "The Security Group description." +} + variable "sg_id" { type = string - default = null - description = "The external Security Group ID to which Security Group rules will be assigned." - validation { - condition = var.sg_id == null ? true : substr(var.sg_id, 0, 3) == "sg-" && length(var.sg_id) > 3 - error_message = "The sg_id value must start with `sg-`." - } + default = "" + description = <<-EOT + The external Security Group ID to which Security Group rules will be assigned. + Required to set `security_group_enabled` to `false`. + EOT } variable "sg_rules" { - type = list(object({ - type = string - cidr_blocks = list(string) - ipv6_cidr_blocks = list(string) - prefix_list_ids = list(string) - from_port = number - to_port = number - protocol = string - security_group_id = string - source_security_group_id = string - self = bool - description = string - })) - - default = [] - description = "Change me" + type = list(any) + default = null + description = <<-EOT + A list of maps of Security Group rules. + The values of map is fully complated with `aws_security_group_rule` resource. + To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule . + EOT } diff --git a/versions.tf b/versions.tf index 5b2c49b..9a98376 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 0.13.0" + required_version = ">= 0.12.26" required_providers { aws = {