diff --git a/CHANGELOG.md b/CHANGELOG.md index 022552dd2..605c8003f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,65 @@ +## 0.8.0 (2019-??-??) + +This release includes major changes due to being dependent on Terraform v0.12 internal API. While we try to keep backward compatibility as much as possible, it does include some breaking changes. + +We strongly recommend [upgrading to Terraform v0.12](https://www.terraform.io/upgrade-guides/0-12.html) before trying TFLint v0.8. `terraform 0.12upgrade` is helpful to upgrade your configuration files. + +### Breaking Changes + +- Always return an error when failed to evaluate an expression. + - Until now, except for module arguments, even if an error occurred, it was ignored. + - Expressions including unsupported named values (such as `${module.foo}`) are not evaluated, so no error occurs. +- Drop support for `${terraform.env}`. + - Previously `${terraform.env}` was a valid expression that returned the same as `${terraform.workspace}`. + - This is because Terraform v0.12 doesn't support `${terraform.env}`. +- The file name of a module includes module ID instead of the source attribute. + - Up to now it was output like `github.com/wata727/example-module/instance.tf`, but it will be changed like `module_id/instance.tf`. +- Always parse all configuration files under the current directory. + - When passing a file name as an argument, TFLint only parsed that file so far, but it now parses all configuration files under the current directory. + - Also, file arguments are only used to filter the issues obtained. Therefore, you cannot pass files other than under the current directory. + - As a known issue, If file arguments are passed, module's issues are not reported. This will be improved by changing handling of module's issues in the future. + - These behaviors have been changed as it depends on Terraform's `configload` package. + - In addition, modules are always loaded regardless of `ignore_module`. +- Raise an error when using invalid syntax as a Terraform configuration. + - For example, it didn't raise an error when using `resources`(not `resource`) block because it is valid as HCL syntax in previous versions. +- Remove `--debug` option. + - Please use `TFLINT_LOG` environment variables instead. +- Raise an error when a file passed by `--config` does not exist. + - Previously the error was ignored and the default config was referenced. +- Remove duplicate resource rules. + - This is due to technical difficulty and user experience. + +### Enhancements + +- HCL2 support + - See also https://www.hashicorp.com/blog/terraform-0-1-2-preview +- Built-in Functions support + - Until now, if an expression includes function calls, it was ignored. +- `TF_DATA_DIR` and `TF_WORKSPACE` environment variables are now available. + - Until now, these variables are ignored. +- It is now possible to handle values doesn't have a default without raising errors. + - In the past, an error occurred when there was a reference to a variable that had no default value in an attribute of a module. See [#205](https://github.com/wata727/tflint/issues/205) +- Terraform v0.11 module support + - Until now, it is failed to properly load a part of Terraform v0.11 module. See also [#167](https://github.com/wata727/tflint/issues/167) +- Support for automatic loading `*.auto.tfvars` files. + - Previously it was not loaded automatically. + +### BugFixes + +- Improve expression checks + - Since it used to be checked by a regular expression, there were many bugs, but it was greatly improved by using the `terraform/lang` package. See [#204](https://github.com/wata727/tflint/issues/204) [#160](https://github.com/wata727/tflint/issues/160) +- Stop overwriting the config under the current directory by the config under the homedir. + - Fixed the problem that overwrites the config under the current directory by homedir config. +- Improve to check for `aws_db_instance_readable_password`. + - Previously, false positive occurred when setting values files or environment variables, but this problem has been fixed. + +### Project Changes + +- Change license: MIT -> MPL 2.0 + - See [#245](https://github.com/wata727/tflint/pull/245) +- Update documentations + - See [#272](https://github.com/wata727/tflint/pull/272) + ## 0.7.6 (2019-05-17) ### BugFixes diff --git a/README.md b/README.md index 100f3b917..0debf4713 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,14 @@ [![Build Status](https://travis-ci.org/wata727/tflint.svg?branch=master)](https://travis-ci.org/wata727/tflint) [![GitHub release](https://img.shields.io/github/release/wata727/tflint.svg)](https://github.com/wata727/tflint/releases/latest) [![Docker Hub](https://img.shields.io/badge/docker-ready-blue.svg)](https://hub.docker.com/r/wata727/tflint/) -[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) +[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-blue.svg)](LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/wata727/tflint)](https://goreportcard.com/report/github.com/wata727/tflint) -TFLint is a [Terraform](https://www.terraform.io/) linter for detecting errors that can not be detected by `terraform plan` +TFLint is a [Terraform](https://www.terraform.io/) linter focused on possible errors, best practices, and so on. -## Current Project Status +## Why TFLint is required? -Currently, we don't encourage you to run TFLint on critical workflow due to incomplete features. See [#167](https://github.com/wata727/tflint/issues/167), [#168](https://github.com/wata727/tflint/issues/168). -This issue is scheduled to be fixed in the release of v0.8.0, but this release depends on Terraform v0.12.0, and we cannot release v0.8.0 until it is released. -For these reasons, feature requests and major changes have been suspended until v0.8.0 release. A small bug fixes for patch upgrade are welcome. - -## Why TFLint is Required? -Terraform is a great tool for infrastructure as a code. It generates an execution plan, we can rely on this plan to proceed with development. However, this plan does not verify values used in template. For example, following template is invalid configuration (t1.2xlarge is invalid instance type) +Terraform is a great tool for Infrastructure as Code. However, many of these tools don't validate provider-specific issues. For example, see the following configuration file: ```hcl resource "aws_instance" "web" { @@ -27,10 +22,22 @@ resource "aws_instance" "web" { } ``` -If you run `terraform apply` for this template, it will obviously produce an error. However, `terraform plan` can get an execution plan without causing an error. This is often not a desirable result. In order to solve this problem, TFLint validates values used in template. +Since `t1.2xlarge` is a nonexistent instance type, an error will occur when you run `terraform apply`. But `terraform plan` and `terraform validate` cannot find this possible error beforehand. That's because it's an AWS provider-specific issue and it's valid as a Terraform configuration. + +TFLint finds such errors in advance: + +``` +$ tflint +template.tf + ERROR:3 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) + +Result: 2 issues (1 errors , 0 warnings , 1 notices) +``` ## Installation -Download binary built for your architecture from [latest releases](https://github.com/wata727/tflint/releases/latest). After downloading, place the binary on the directory on the PATH. The following example is the installation in macOS. + +You can download the binary built for your architecture from [the latest release](https://github.com/wata727/tflint/releases/latest). The following is an example of installation on macOS: + ``` $ wget https://github.com/wata727/tflint/releases/download/v0.7.6/tflint_darwin_amd64.zip $ unzip tflint_darwin_amd64.zip @@ -42,7 +49,7 @@ $ install tflint /usr/local/tflint/bin $ tflint -v ``` -For Linux based OS, you can use the install_linux.sh to automate the installation process +For Linux based OS, you can use the [`install_linux.sh`](https://raw.githubusercontent.com/wata727/tflint/master/install_linux.sh) to automate the installation process. ### Homebrew @@ -53,39 +60,34 @@ $ brew tap wata727/tflint $ brew install tflint ``` -### Running in Docker -We provide Docker images for each version on [DockerHub](https://hub.docker.com/r/wata727/tflint/). With docker, you can run TFLint without installing it locally. +### Docker + +You can also use [TFLint via Docker](https://hub.docker.com/r/wata727/tflint/). ``` $ docker run --rm -v $(pwd):/data -t wata727/tflint ``` -## Quick Start -Try running TFLint under the directory where Terraform is executed. It detect if there is a issue and output the result. For example, run on the previous invalid template. +## Features -``` -$ tflint -template.tf - ERROR:3 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) +See [Rules](docs/rules). -Result: 2 issues (1 errors , 0 warnings , 1 notices) -``` +## Limitations -If you would like to know more about these issues and available features please check the [documentation](https://github.com/wata727/tflint/tree/master/docs). +TFLint currently only inspect Terraform-specific issues and AWS issues. -### Specify Template -If you want to parse only a specific template, not all templates, you can specify a filename as an argument. +Also, load configurations in the same way as Terraform v0.12. This means that it cannot inspect configurations that cannot be parsed on Terraform v0.12. -``` -$ tflint template.tf -``` +[Named values](https://www.terraform.io/docs/configuration/expressions.html#references-to-named-values) are supported only for [input variables](https://www.terraform.io/docs/configuration/variables.html) and [workspaces](https://www.terraform.io/docs/state/workspaces.html). Expressions that contain anything else are excluded from the inspection. [Built-in Functions](https://www.terraform.io/docs/configuration/functions.html) are fully supported. -## Available Options -Please show `tflint --help` +## Usage + +TFLint inspects all configurations under the current directory by default. You can also change the behavior with the following options: ``` +$ tflint --help Usage: - tflint [OPTIONS] [FILE] + tflint [OPTIONS] Application Options: -v, --version Print TFLint version @@ -99,26 +101,26 @@ Application Options: --aws-secret-key=SECRET_KEY AWS secret key used in deep check mode --aws-profile=PROFILE AWS shared credential profile name used in deep check mode --aws-region=REGION AWS region used in deep check mode - -d, --debug Enable debug mode --error-with-issues Return error code when issues exist - --fast Ignore slow rules. Currently, ignore only aws_instance_invalid_ami - -q, --quiet Do not output any message when no issues are found (Format=default only) + --fast Ignore slow rules (aws_instance_invalid_ami only) + -q, --quiet Do not output any message when no issues are found (default format only) Help Options: -h, --help Show this help message ``` -## Configuration -By default, TFLint loads `.tflint.hcl` according to the following priority: +### Config file + +By default, TFLint looks up `.tflint.hcl` according to the following priority: - Current directory (`./.tflint.hcl`) - Home directory (`~/.tflint.hcl`) -The configuration file is described in [HCL](https://github.com/hashicorp/hcl), and options available on the command line can be described in advance. Following example: +The config file is written in [HCL](https://github.com/hashicorp/hcl), and you can use this file instead of passing command line options. ```hcl config { - terraform_version = "0.9.11" + terraform_version = "0.12.0" deep_check = true aws_credentials = { @@ -143,16 +145,47 @@ rule "aws_instance_previous_type" { } ``` -If you want to create a configuration file with a different name, specify the file name with `--config` option. +You can also use another file as a config file with the `--config` option. ``` $ tflint --config other_config.hcl ``` -### Terraform Version -You can set the version of Terraform you are using. If it is set, TFLint will detect issues according to it. +### Rules + +You can make settings for each rule in the `rule` block. Currently, it can set only `enabled` option. If you set `enabled = false`, TFLint doesn't inspect configuration files by this rule. + +```hcl +rule "aws_instance_previous_type" { + enabled = false +} +``` + +You can also disable rules with the `--ignore-rule` option. + +``` +$ tflint --ignore-rule=aws_instance_invalid_type,aws_instance_previous_type +``` + +See also [list of available rules](docs/rules). + +### Deep Checking + +When deep checking is enabled, TFLint invokes the provider's API to do a more detailed inspection. For example, find a non-existent IAM profile name etc. You can enable it with the `--deep` option. + +``` +$ tflint --deep +template.tf + ERROR:3 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) + ERROR:4 "invalid_profile" is invalid IAM profile name. (aws_instance_invalid_iam_profile) + +Result: 2 issues (2 errors , 0 warnings , 0 notices) +``` + +In order to enable deep checking, [credentials](#credentials) are needed. ### Credentials + TFLint supports various credential providers. It is used with the following priority: - Static credentials @@ -161,7 +194,8 @@ TFLint supports various credential providers. It is used with the following prio - Default shared credentials #### Static Credentials -If you have access key and secret key, you can specify these credentials. + +If you have an access key and a secret key, you can pass these keys. ``` $ tflint --aws-access-key AWS_ACCESS_KEY --aws-secret-key AWS_SECRET_KEY --aws-region us-east-1 @@ -178,7 +212,8 @@ config { ``` #### Shared Credentials -If you have [shared credentials](https://aws.amazon.com/jp/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/), you can specify credentials profile name. However TFLint supports only `~/.aws/credentials` as shared credentials location. + +If you have [shared credentials](https://aws.amazon.com/jp/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/), you can pass the profile name. However, only `~/.aws/credentials` is supported as a credential location. ``` $ tflint --aws-profile AWS_PROFILE --aws-region us-east-1 @@ -194,52 +229,69 @@ config { ``` #### Environment Credentials -TFLint looks `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` environment values. This is useful when you do not want to explicitly specify credentials. + +TFLint looks up `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` environment variables. This is useful when you don't want to explicitly pass credentials. ``` $ export AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY $ export AWS_SECRET_ACCESS_KEY=AWS_SECRET_KEY ``` -### Rules +### Module Inspection -You can make settings for each rule in the `rule` block. Currently, it can set only `enabled` option. If you set `enabled = false`, TFLint doesn't check templates by this rule. +TFLint can also inspect [modules](https://www.terraform.io/docs/configuration/modules.html). In this case, it checks based on the input variables passed to the calling module. -``` -rule "aws_instance_previous_type" { - enabled = false +```hcl +module "aws_instance" { + source = "./module" + + ami = "ami-b73b63a0" + instance_type = "t1.2xlarge" } ``` -Please see the [documentation](https://github.com/wata727/tflint/tree/master/docs) for a list of rules. +``` +$ tflint +aws_instance/main.tf + ERROR:6 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) -## Interpolation Syntax Support -TFLint can interpret part of [interpolation syntax](https://www.terraform.io/docs/configuration/interpolation.html). We now support only variables and terraform meta information (e.g. "${terraform.env}"). So you cannot use attributes of resource, outputs of modules and built-in functions. If you are using them, TFLint ignores it. You can check what is ignored by executing it with `--debug` option. +Result: 1 issues (1 errors , 0 warnings , 0 notices) +``` -### Variable Files -If you use [variable files](https://www.terraform.io/docs/configuration/variables.html#variable-files), Please specify it by arguments or configuration file. TFLint interprets variables as well as Terraform. In other words, when variables are conflicting, It will be overridden or merged correctly. +TFLint loads modules in the same way as Terraform. So note that you need to run `terraform init` first. -## Deep Check -Deep check is an option that you can actually search resources on AWS and check invalid references and duplicate resources. You can activate it by executing it with `--deep` option as following: +You can use the `--ignore-module` option if you want to skip inspection for a particular module. Note that you need to pass module sources rather than module ids for backward compatibility. ``` -$ tflint --deep -template.tf - ERROR:3 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) - ERROR:4 "invalid_profile" is invalid IAM profile name. (aws_instance_invalid_iam_profile) +$ tflint --ignore-module=./module +``` + +### Run with a specific configuration file + +If you want to inspect only a specific configuration file, not all files, you can pass a file as an argument. -Result: 2 issues (2 errors , 0 warnings , 0 notices) +``` +$ tflint main.tf ``` -In the above example, an IAM instance profile that does not actually exist is specified, so it is an error. In order to refer to actual resources, AWS credentials are required. You can use command line options, configuration files, environment variables, shared credentials for these specifications. +### Terraform Version -## Developing -If you want to build TFLint at your environment, you can build with the following procedure. [Go](https://golang.org/) 1.9 or more is required. +You can set the version of Terraform you are using. If it is set, TFLint will detect issues according to it. + +NOTE: This option is now no longer used and will be removed in the future. + +## Debugging + +If you don't get the expected behavior, you can see the detailed logs when running with `TFLINT_LOG` environment variable. ``` -$ make build +$ TFLINT_LOG=debug tflint ``` +## Developing + +See [Developer Guides](docs/DEVELOPING.md). + ## Author [Kazuma Watanabe](https://github.com/wata727) diff --git a/docs/DEVELOPING.md b/docs/DEVELOPING.md new file mode 100644 index 000000000..f02f02528 --- /dev/null +++ b/docs/DEVELOPING.md @@ -0,0 +1,60 @@ +# TFLint Developer's Guide + +The goal of this guide is to quickly understand how TFLint works and to help more developers contribute. + +## Core Concept + +TFLint is just a thin wrapper of Terraform. Configuration loading and expression evaluation etc. depend on Terraform's internal API, and it only provides an interface to do them as linter. + +There are three important packages to understand its behavior: + +- `tflint` + - This package is the core of TFLint as a wrapper for Terraform. It allows accesses to `terraform/configs.Config` and `terraform/terraform.BuiltinEvalContext` and so on. +- `rules` + - This package is a provider of all rules. +- `cmd` + - This package is the entrypoint of the app. + +## How does it work + +These processes are described in [`cmd/cli.go`](https://github.com/wata727/tflint/blob/master/cmd/cli.go). + +### 1. Loading configurations + +All Terraform's configuration files are represented as `configs.Config`. [`tflint/tflint.Loader`](https://github.com/wata727/tflint/blob/master/tflint/loader.go) uses the `(*configs.Parser) LoadConfigDir` and `configs.BuildConfig` to access to `configs.Config` in the same way as Terraform. + +Similarly, prepare `terraform.InputValues` using `(*configs.Parser) LoadValuesFile`. + +### 2. Setting up a new Runner + +A [`tflint/tflint.Runner`](https://github.com/wata727/tflint/blob/master/tflint/runner.go) is initialized for each `configs.Config`. These have their own evaluation context for that module, represented as `terraform.BuiltinEvalContext`. + +it uses `(*terraform.BuiltinEvalContext) EvaluateExpr` to evaluate expressions. Unlike Terraform, it provides a mechanism to determine if an expression can be evaluated. + +### 3. Inspecting configurations + +It inspects `configs.Config` via `tflint.Runner`. All rules implement the `Check` method that takes `tflint.Runner` as an argument, and emits an issue if needed. + +## Building + +You need Go 1.12 or later to build. + +``` +$ make build +``` + +## Adding a new rule + +You can use the rule generator to add new rules (Currently, this generator supports only AWS rules). + +``` +$ make rule +go run tools/rule_generator.go +Rule name? (e.g. aws_instance_invalid_type): aws_instance_example +Create: rules/awsrules/aws_instance_example.go +Create: rules/awsrules/aws_instance_example_test.go +``` + +A template of rules and tests is generated. In order to inspect configuration files, you need to understand [the Runner API](https://github.com/wata727/tflint/blob/master/tflint/runner.go). + +Finally, don't forget to register the created rule with [the provider](https://github.com/wata727/tflint/blob/master/rules/provider.go). After that the rule you created is enabled in TFLint. diff --git a/docs/README.md b/docs/README.md index 2eb957df0..f7430f8c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,83 +1,5 @@ -# TFLint Issue Documentation -## Issue Type -Issues are classified into the following three types. +# TFLint Documentation -- **ERROR** - - There is a issue that an execution error occurs. We strongly recommend that you fix it if this is reported. -- **WARNING** - - It is reported if something that is explicitly unrecommended is used. We recommend that you fix it. -- **NOTICE** - - It is a issue that is considered desirable to fix. - -## General Issue - -- **AWS Instance** - - [aws_instance_invalid_type](aws_instance_invalid_type.md) - - [aws_instance_previous_type](aws_instance_previous_type.md) - - [aws_instance_default_standard_volume](aws_instance_default_standard_volume.md) -- **AWS DB Instance** - - [aws_db_instance_invalid_type](aws_db_instance_invalid_type.md) - - [aws_db_instance_previous_type](aws_db_instance_previous_type.md) - - [aws_db_instance_default_parameter_group](aws_db_instance_default_parameter_group.md) - - [aws_db_instance_readable_password](aws_db_instance_readable_password.md) -- **AWS ElastiCache Cluster** - - [aws_elasticache_cluster_invalid_type](aws_elasticache_cluster_invalid_type.md) - - [aws_elasticache_cluster_previous_type](aws_elasticache_cluster_previous_type.md) - - [aws_elasticache_cluster_default_parameter_group](aws_elasticache_cluster_default_parameter_group.md) -- **AWS Route** - - [aws_route_not_specified_target](aws_route_not_specified_target.md) - - [aws_route_specified_multiple_targets](aws_route_specified_multiple_targets.md) -- **AWS CloudWatch Metric Alarm** - - [aws_cloudwatch_metric_alarm_invalid_unit](aws_cloudwatch_metric_alarm_invalid_unit.md) -- **Terraform** - - [terraform_module_pinned_source](terraform_module_pinned_source.md) - -### Invalid Reference Issue -Report these issues if you have specified invalid resource ID, name, etc. All issues are reported as ERROR. These issues are reported when enabled deep check. In many cases, an incorrect value is specified, so please fix it. - -- **AWS Instance** - - aws_instance_invalid_iam_profile - - aws_instance_invalid_ami - - aws_instance_invalid_key_name - - aws_instance_invalid_subnet - - aws_instance_invalid_vpc_security_group -- **AWS ALB** - - aws_alb_invalid_security_group - - aws_alb_invalid_subnet -- **AWS ELB** - - aws_elb_invalid_security_group - - aws_elb_invalid_subnet - - aws_elb_invalid_instance -- **AWS DB Instance** - - aws_db_instance_invalid_vpc_security_group - - aws_db_instance_invalid_db_subnet_group - - aws_db_instance_invalid_parameter_group - - aws_db_instance_invalid_option_group -- **AWS ElastiCache Cluster** - - aws_elasticache_cluster_invalid_parameter_group - - aws_elasticache_cluster_invalid_subnet_group - - aws_elasticache_cluster_invalid_security_group -- **AWS Route** - - aws_route_invalid_route_table - - aws_route_invalid_gateway - - aws_route_invalid_egress_only_gateway - - aws_route_invalid_nat_gateway - - aws_route_invalid_vpc_peering_connection - - aws_route_invalid_instance - - aws_route_invalid_network_interface - -### Duplicate Resource Issue -Report these issues if you have specified resource ID, name, etc that already existed and must be unique. All issues are reported as ERROR. These issues are reported when enabled deep check. For example, it happens when resources with the same name is already created. Please check the actual resources again. - -- **AWS Security Group** - - aws_security_group_duplicate_name -- **AWS ALB** - - aws_alb_duplicate_name -- **AWS ELB** - - aws_elb_duplicate_name -- **AWS DB Instance** - - aws_db_instance_duplicate_identifier -- **AWS ElastiCache Cluster** - - aws_elasticache_cluster_duplicate_id -- **AWS ECS Cluster** - - aws_ecs_cluster_duplicate_name +- [User Guides](../README.md) (README) +- [Rules](rules) +- [Developer Guides](DEVELOPING.md) diff --git a/docs/aws_cloudwatch_metric_alarm_invalid_unit.md b/docs/aws_cloudwatch_metric_alarm_invalid_unit.md deleted file mode 100644 index cb24fc6cc..000000000 --- a/docs/aws_cloudwatch_metric_alarm_invalid_unit.md +++ /dev/null @@ -1,62 +0,0 @@ -# AWS CloudWatch Metric Alarm Invalid Unit -This issue reported if you specify invalid unit. This issue type is ERROR. - -## Example -``` -resource "aws_cloudwatch_metric_alarm" "rds-writer-memory" { - alarm_name = "terraform-test-foobar5" - comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "2" - metric_name = "CPUUtilization" - namespace = "AWS/EC2" - period = "120" - statistic = "Average" - threshold = "80" - unit = "percent" // valid unit is "Percent" - alarm_description = "This metric monitor ec2 cpu utilization" - insufficient_data_actions = [] -} -``` - -The following is the execution result of TFLint: - -``` -template.tf - ERROR:10 "percent" is invalid unit. (aws_cloudwatch_metric_alarm_invalid_unit) - -Result: 1 issues (1 errors , 0 warnings , 0 notices) -``` - -## Why -Only the followings are supported for CloudWatch alarm unit. If an invalid unit is specified, an error will occur at `terraform apply`. - -- Seconds -- Microseconds -- Milliseconds -- Bytes -- Kilobytes -- Megabytes -- Gigabytes -- Terabytes -- Bits -- Kilobits -- Megabits -- Gigabits -- Terabits -- Percent -- Count -- Bytes/Second -- Kilobytes/Second -- Megabytes/Second -- Gigabytes/Second -- Terabytes/Second -- Bits/Second -- Kilobits/Second -- Megabits/Second -- Gigabits/Second -- Terabits/Second -- Count/Second -- None - -## How To Fix -Check the unit and select a valid unit again. diff --git a/docs/aws_db_instance_invalid_type.md b/docs/aws_db_instance_invalid_type.md deleted file mode 100644 index bf79c9335..000000000 --- a/docs/aws_db_instance_invalid_type.md +++ /dev/null @@ -1,33 +0,0 @@ -# AWS DB Instance Invalid Type -Report this issue if you have specified the invalid instance type. This issue type is ERROR. - -## Example -``` -resource "aws_db_instance" "default" { - allocated_storage = 10 - engine = "mysql" - engine_version = "5.6.17" - instance_class = "t1.micro" // invalid type! - name = "mydb" - username = "foo" - password = "bar" - db_subnet_group_name = "my_database_subnet_group" - parameter_group_name = "default.mysql5.6" -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - ERROR:5 "t1.micro" is invalid instance type. (aws_db_instance_invalid_type) - -Result: 1 issues (1 errors , 0 warnings , 0 notices) -``` - -## Why -If an invalid instance type is specified, an error will occur at `terraform apply`. - -## How To Fix -Check the [instance type list](https://aws.amazon.com/rds/details/) and select a valid instance type again. diff --git a/docs/aws_db_instance_previous_type.md b/docs/aws_db_instance_previous_type.md deleted file mode 100644 index 3da140f17..000000000 --- a/docs/aws_db_instance_previous_type.md +++ /dev/null @@ -1,33 +0,0 @@ -# AWS DB Instance Previous Type -Report this issue if you have specified the previous instance type. This issue type is WARNING. - -## Example -``` -resource "aws_db_instance" "default" { - allocated_storage = 10 - engine = "mysql" - engine_version = "5.6.17" - instance_class = "db.t1.micro" // previous type! - name = "mydb" - username = "foo" - password = "bar" - db_subnet_group_name = "my_database_subnet_group" - parameter_group_name = "default.mysql5.6" -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - WARNING:5 "db.t1.micro" is previous generation instance type. (aws_db_instance_previous_type) - -Result: 1 issues (0 errors , 1 warnings , 0 notices) -``` - -## Why -There are two types of instance types, the current generation and the previous generation. The current generation is superior to the previous generation in terms of performance and fee. AWS also officially states that unless there is a special reason, you should use the instance type of the current generation. - -## How To Fix -Follow the [upgrade paths](https://aws.amazon.com/rds/previous-generation/) and confirm that the instance type of the current generation can be used, then select again. diff --git a/docs/aws_elasticache_cluster_invalid_type.md b/docs/aws_elasticache_cluster_invalid_type.md deleted file mode 100644 index 4bd953d6d..000000000 --- a/docs/aws_elasticache_cluster_invalid_type.md +++ /dev/null @@ -1,34 +0,0 @@ -# AWS ElastiCache Cluster Invalid Type -Report this issue if you have specified the invalid node type. This issue type is ERROR. - -## Example -``` -resource "aws_elasticache_cluster" "redis" { - cluster_id = "app" - engine = "redis" - engine_version = "3.2.4" - maintenance_window = "sun:00:00-sun:06:00" - node_type = "m4.large" // invalid type! - num_cache_nodes = 1 - port = 6379 - parameter_group_name = "default.redis3.2" - subnet_group_name = "app-subnet-group" - security_group_ids = ["${aws_security_group.redis.id}"] -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - ERROR:6 "m4.large" is invalid node type. (aws_elasticache_cluster_invalid_type) - -Result: 1 issues (1 errors , 0 warnings , 0 notices) -``` - -## Why -If an invalid node type is specified, an error will occur at `terraform apply`. - -## How To Fix -Check the [node type list](https://aws.amazon.com/elasticache/details/) and select a valid node type again. diff --git a/docs/aws_elasticache_cluster_previous_type.md b/docs/aws_elasticache_cluster_previous_type.md deleted file mode 100644 index 60c526227..000000000 --- a/docs/aws_elasticache_cluster_previous_type.md +++ /dev/null @@ -1,34 +0,0 @@ -# AWS ElastiCache Cluster Instance Previous Type -Report this issue if you have specified the previous node type. This issue type is WARNING. - -## Example -``` -resource "aws_elasticache_cluster" "redis" { - cluster_id = "app" - engine = "redis" - engine_version = "3.2.4" - maintenance_window = "sun:00:00-sun:06:00" - node_type = "cache.t1.micro" // previous type! - num_cache_nodes = 1 - port = 6379 - parameter_group_name = "default.redis3.2" - subnet_group_name = "app-subnet-group" - security_group_ids = ["${aws_security_group.redis.id}"] -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - WARNING:6 "cache.t1.micro" is previous generation node type. (aws_elasticache_cluster_previous_type) - -Result: 1 issues (0 errors , 1 warnings , 0 notices) -``` - -## Why -There are two types of node types, the current generation and the previous generation. The current generation is superior to the previous generation in terms of performance and fee. AWS also officially states that unless there is a special reason, you should use the node type of the current generation. - -## How To Fix -Follow the [upgrade paths](https://aws.amazon.com/elasticache/previous-generation/) and confirm that the node type of the current generation can be used, then select again. diff --git a/docs/aws_instance_invalid_type.md b/docs/aws_instance_invalid_type.md deleted file mode 100644 index 0ed272478..000000000 --- a/docs/aws_instance_invalid_type.md +++ /dev/null @@ -1,31 +0,0 @@ -# AWS Instance Invalid Type -Report this issue if you have specified the invalid instance type. This issue type is ERROR. - -## Example -``` -resource "aws_instance" "web" { - ami = "ami-b73b63a0" - instance_type = "t1.2xlarge" # invalid type! - iam_instance_profile = "app-service" - - tags { - Name = "HelloWorld" - } -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - ERROR:3 "t1.2xlarge" is invalid instance type. (aws_instance_invalid_type) - -Result: 1 issues (1 errors , 0 warnings , 0 notices) -``` - -## Why -If an invalid instance type is specified, an error will occur at `terraform apply`. - -## How To Fix -Check the [instance type list](https://aws.amazon.com/ec2/instance-types/) and select a valid instance type again. diff --git a/docs/aws_instance_previous_type.md b/docs/aws_instance_previous_type.md deleted file mode 100644 index b163933d7..000000000 --- a/docs/aws_instance_previous_type.md +++ /dev/null @@ -1,31 +0,0 @@ -# AWS Instance Previous Type -Report this issue if you have specified the previous instance type. This issue type is WARNING. - -## Example -``` -resource "aws_instance" "web" { - ami = "ami-b73b63a0" - instance_type = "t1.micro" # previous type! - iam_instance_profile = "app-service" - - tags { - Name = "HelloWorld" - } -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - WARNING:3 "t1.micro" is previous generation instance type. (aws_instance_previous_type) - -Result: 1 issues (0 errors , 1 warnings , 0 notices) -``` - -## Why -There are two types of instance types, the current generation and the previous generation. The current generation is superior to the previous generation in terms of performance and fee. AWS also officially states that unless there is a special reason, you should use the instance type of the current generation. - -## How To Fix -Follow the [upgrade paths](https://aws.amazon.com/ec2/previous-generation/) and confirm that the instance type of the current generation can be used, then select again. diff --git a/docs/aws_route_not_specified_target.md b/docs/aws_route_not_specified_target.md deleted file mode 100644 index 26481b716..000000000 --- a/docs/aws_route_not_specified_target.md +++ /dev/null @@ -1,30 +0,0 @@ -# AWS Route Not Specified Target - -Report this issue if routing target is not specified. This issue type is ERROR. - -## Example - -``` -resource "aws_route" "foo" { - route_table_id = "rtb-1234abcd" - destination_cidr_block = "10.0.1.0/22" -} -``` - -The following is the execution result of TFLint: - -``` -$ tflint -template.tf - ERROR:1 The routing target is not specified, each aws_route must contain either egress_only_gateway_id, gateway_id, instance_id, nat_gateway_id, network_interface_id, transit_gateway_id, or vpc_peering_connection_id. (aws_route_not_specified_target) - -Result: 1 issues (1 errors , 0 warnings , 0 notices) -``` - -## Why - -[`aws_route`](https://www.terraform.io/docs/providers/aws/r/route.html) creates new routing in route tables. If a routing target is not specified, an error will occur when run `terraform apply`. - -## How To Fix - -Please add a routing target. There are [kinds of](https://www.terraform.io/docs/providers/aws/r/route.html#argument-reference) `egress_only_gateway_id`, `gateway_id`, `instance_id`, `nat_gateway_id`, `network_interface_id`, `transit_gateway_id`, `vpc_peering_connection_id`. diff --git a/docs/rules/README.md b/docs/rules/README.md new file mode 100644 index 000000000..58a891048 --- /dev/null +++ b/docs/rules/README.md @@ -0,0 +1,553 @@ +# Rules + +Rules related to AWS provider and Terraform are available. These rules are enabled by default. + +## AWS Rules + +These rules relate to AWS provider. + +### Possible Errors + +These rules warn of possible errors that can occur at `terraform apply`. + +The following table shows the correspondence between resources and rules. Rules marked with `Deep` are only used when enabling deep checking: + +|Resource|Rule|Deep| +| --- | --- | --- | +|`aws_acm_certificate`||| +|`aws_acm_certificate_validation`||| +|`aws_acmpca_certificate_authority`||| +|`aws_api_gateway_account`||| +|`aws_api_gateway_api_key`||| +|`aws_api_gateway_authorizer`||| +|`aws_api_gateway_base_path_mapping`||| +|`aws_api_gateway_client_certificate`||| +|`aws_api_gateway_deployment`||| +|`aws_api_gateway_documentation_part`||| +|`aws_api_gateway_documentation_version`||| +|`aws_api_gateway_domain_name`||| +|`aws_api_gateway_gateway_response`||| +|`aws_api_gateway_integration`||| +|`aws_api_gateway_integration_response`||| +|`aws_api_gateway_method`||| +|`aws_api_gateway_method_response`||| +|`aws_api_gateway_method_settings`||| +|`aws_api_gateway_model`||| +|`aws_api_gateway_request_validator`||| +|`aws_api_gateway_resource`||| +|`aws_api_gateway_rest_api`||| +|`aws_api_gateway_stage`||| +|`aws_api_gateway_usage_plan`||| +|`aws_api_gateway_usage_plan_key`||| +|`aws_api_gateway_vpc_link`||| +|`aws_appautoscaling_policy`||| +|`aws_appautoscaling_scheduled_action`||| +|`aws_appautoscaling_target`||| +|`aws_appmesh_mesh`||| +|`aws_appmesh_route`||| +|`aws_appmesh_virtual_node`||| +|`aws_appmesh_virtual_router`||| +|`aws_appmesh_virtual_service`||| +|`aws_appsync_datasource`||| +|`aws_appsync_graphql_api`||| +|`aws_appsync_api_key`||| +|`aws_appsync_resolver`||| +|`aws_athena_database`||| +|`aws_athena_named_query`||| +|`aws_autoscaling_attachment`||| +|`aws_autoscaling_group`||| +|`aws_autoscaling_lifecycle_hook`||| +|`aws_autoscaling_notification`||| +|`aws_autoscaling_policy`||| +|`aws_autoscaling_schedule`||| +|`aws_backup_plan`||| +|`aws_backup_selection`||| +|`aws_backup_vault`||| +|`aws_batch_compute_environment`||| +|`aws_batch_job_definition`||| +|`aws_batch_job_queue`||| +|`aws_budgets_budget`||| +|`aws_cloud9_environment_ec2`||| +|`aws_cloudformation_stack`||| +|`aws_cloudformation_stack_set`||| +|`aws_cloudformation_stack_set_instance`||| +|`aws_cloudfront_distribution`||| +|`aws_cloudfront_origin_access_identity`||| +|`aws_cloudfront_public_key`||| +|`aws_cloudhsm_v2_cluster`||| +|`aws_cloudhsm_v2_hsm`||| +|`aws_cloudtrail`||| +|`aws_cloudwatch_dashboard`||| +|`aws_cloudwatch_event_permission`||| +|`aws_cloudwatch_event_rule`||| +|`aws_cloudwatch_event_target`||| +|`aws_cloudwatch_log_destination`||| +|`aws_cloudwatch_log_destination_policy`||| +|`aws_cloudwatch_log_group`||| +|`aws_cloudwatch_log_metric_filter`||| +|`aws_cloudwatch_log_resource_policy`||| +|`aws_cloudwatch_log_stream`||| +|`aws_cloudwatch_log_subscription_filter`||| +|`aws_cloudwatch_metric_alarm`|aws_cloudwatch_metric_alarm_invalid_unit|| +|`aws_codebuild_project`||| +|`aws_codebuild_webhook`||| +|`aws_codecommit_repository`||| +|`aws_codecommit_trigger`||| +|`aws_codedeploy_app`||| +|`aws_codedeploy_deployment_config`||| +|`aws_codedeploy_deployment_group`||| +|`aws_codepipeline`||| +|`aws_codepipeline_webhook`||| +|`aws_cognito_identity_pool`||| +|`aws_cognito_identity_pool_roles_attachment`||| +|`aws_cognito_identity_provider`||| +|`aws_cognito_resource_server`||| +|`aws_cognito_user_group`||| +|`aws_cognito_user_pool`||| +|`aws_cognito_user_pool_client`||| +|`aws_cognito_user_pool_domain`||| +|`aws_config_aggregate_authorization`||| +|`aws_config_configuration_aggregator`||| +|`aws_config_config_rule`||| +|`aws_config_configuration_recorder`||| +|`aws_config_configuration_recorder_status`||| +|`aws_config_delivery_channel`||| +|`aws_cur_report_definition`||| +|`aws_dlm_lifecycle_policy`||| +|`aws_dms_certificate`||| +|`aws_dms_endpoint`||| +|`aws_dms_replication_instance`||| +|`aws_dms_replication_subnet_group`||| +|`aws_dms_replication_task`||| +|`aws_datasync_agent`||| +|`aws_datasync_location_efs`||| +|`aws_datasync_location_nfs`||| +|`aws_datasync_location_s3`||| +|`aws_datasync_task`||| +|`aws_devicefarm_project`||| +|`aws_directory_service_directory`||| +|`aws_directory_service_conditional_forwarder`||| +|`aws_dx_bgp_peer`||| +|`aws_dx_connection`||| +|`aws_dx_connection_association`||| +|`aws_dx_gateway`||| +|`aws_dx_gateway_association`||| +|`aws_dx_gateway_association_proposal`||| +|`aws_dx_hosted_private_virtual_interface`||| +|`aws_dx_hosted_private_virtual_interface_accepter`||| +|`aws_dx_hosted_public_virtual_interface`||| +|`aws_dx_hosted_public_virtual_interface_accepter`||| +|`aws_dx_lag`||| +|`aws_dx_private_virtual_interface`||| +|`aws_dx_public_virtual_interface`||| +|`aws_dynamodb_global_table`||| +|`aws_dynamodb_table`||| +|`aws_dynamodb_table_item`||| +|`aws_dax_cluster`||| +|`aws_dax_parameter_group`||| +|`aws_dax_subnet_group`||| +|`aws_docdb_cluster`||| +|`aws_docdb_cluster_instance`||| +|`aws_docdb_cluster_parameter_group`||| +|`aws_docdb_cluster_snapshot`||| +|`aws_docdb_subnet_group`||| +|`aws_ami`||| +|`aws_ami_copy`||| +|`aws_ami_from_instance`||| +|`aws_ami_launch_permission`||| +|`aws_ebs_snapshot`||| +|`aws_ebs_snapshot_copy`||| +|`aws_ebs_volume`||| +|`aws_ec2_capacity_reservation`||| +|`aws_ec2_client_vpn_endpoint`||| +|`aws_ec2_client_vpn_network_association`||| +|`aws_ec2_fleet`||| +|`aws_ec2_transit_gateway`||| +|`aws_ec2_transit_gateway_route`||| +|`aws_ec2_transit_gateway_route_table`||| +|`aws_ec2_transit_gateway_route_table_association`||| +|`aws_ec2_transit_gateway_route_table_propagation`||| +|`aws_ec2_transit_gateway_vpc_attachment`||| +|`aws_eip`||| +|`aws_eip_association`||| +|`aws_instance`|aws_instance_invalid_type|| +||aws_instance_invalid_iam_profile|✔| +||aws_instance_invalid_ami|✔| +||aws_instance_invalid_key_name|✔| +||aws_instance_invalid_subnet|✔| +||aws_instance_invalid_vpc_security_group|✔| +|`aws_key_pair`||| +|`aws_launch_configuration`||| +|`aws_launch_template`||| +|`aws_placement_group`||| +|`aws_snapshot_create_volume_permission`||| +|`aws_spot_datafeed_subscription`||| +|`aws_spot_fleet_request`||| +|`aws_spot_instance_request`||| +|`aws_volume_attachment`||| +|`aws_ecr_lifecycle_policy`||| +|`aws_ecr_repository`||| +|`aws_ecr_repository_policy`||| +|`aws_ecs_cluster`||| +|`aws_ecs_service`||| +|`aws_ecs_task_definition`||| +|`aws_efs_file_system`||| +|`aws_efs_mount_target`||| +|`aws_eks_cluster`||| +|`aws_elasticache_cluster`|aws_elasticache_cluster_invalid_type|| +||aws_elasticache_cluster_invalid_parameter_group|✔| +||aws_elasticache_cluster_invalid_subnet_group|✔| +||aws_elasticache_cluster_invalid_security_group|✔| +|`aws_elasticache_parameter_group`||| +|`aws_elasticache_replication_group`||| +|`aws_elasticache_security_group`||| +|`aws_elasticache_subnet_group`||| +|`aws_elastic_beanstalk_application`||| +|`aws_elastic_beanstalk_application_version`||| +|`aws_elastic_beanstalk_configuration_template`||| +|`aws_elastic_beanstalk_environment`||| +|`aws_app_cookie_stickiness_policy`||| +|`aws_elb`|aws_elb_invalid_security_group|✔| +||aws_elb_invalid_subnet|✔| +||aws_elb_invalid_instance|✔| +|`aws_elb_attachment`||| +|`aws_lb_cookie_stickiness_policy`||| +|`aws_lb_ssl_negotiation_policy`||| +|`aws_load_balancer_backend_server_policy`||| +|`aws_load_balancer_listener_policy`||| +|`aws_load_balancer_policy`||| +|`aws_proxy_protocol_policy`||| +|`aws_lb`|aws_alb_invalid_security_group|✔| +||aws_alb_invalid_subnet|✔| +|`aws_lb_listener`||| +|`aws_lb_listener_certificate`||| +|`aws_lb_listener_rule`||| +|`aws_lb_target_group`||| +|`aws_lb_target_group_attachment`||| +|`aws_emr_cluster`||| +|`aws_emr_instance_group`||| +|`aws_emr_security_configuration`||| +|`aws_elasticsearch_domain`||| +|`aws_elasticsearch_domain_policy`||| +|`aws_elastictranscoder_pipeline`||| +|`aws_elastictranscoder_preset`||| +|`aws_gamelift_alias`||| +|`aws_gamelift_build`||| +|`aws_gamelift_fleet`||| +|`aws_gamelift_game_session_queue`||| +|`aws_glacier_vault`||| +|`aws_glacier_vault_lock`||| +|`aws_globalaccelerator_accelerator`||| +|`aws_globalaccelerator_listener`||| +|`aws_glue_catalog_database`||| +|`aws_glue_catalog_table`||| +|`aws_glue_classifier`||| +|`aws_glue_connection`||| +|`aws_glue_crawler`||| +|`aws_glue_job`||| +|`aws_glue_security_configuration`||| +|`aws_glue_trigger`||| +|`aws_guardduty_detector`||| +|`aws_guardduty_invite_accepter`||| +|`aws_guardduty_ipset`||| +|`aws_guardduty_member`||| +|`aws_guardduty_threatintelset`||| +|`aws_iam_access_key`||| +|`aws_iam_account_alias`||| +|`aws_iam_account_password_policy`||| +|`aws_iam_group`||| +|`aws_iam_group_membership`||| +|`aws_iam_group_policy`||| +|`aws_iam_group_policy_attachment`||| +|`aws_iam_instance_profile`||| +|`aws_iam_openid_connect_provider`||| +|`aws_iam_policy`||| +|`aws_iam_policy_attachment`||| +|`aws_iam_role`||| +|`aws_iam_role_policy`||| +|`aws_iam_role_policy_attachment`||| +|`aws_iam_saml_provider`||| +|`aws_iam_server_certificate`||| +|`aws_iam_service_linked_role`||| +|`aws_iam_user`||| +|`aws_iam_user_group_membership`||| +|`aws_iam_user_login_profile`||| +|`aws_iam_user_policy`||| +|`aws_iam_user_policy_attachment`||| +|`aws_iam_user_ssh_key`||| +|`aws_iot_certificate`||| +|`aws_iot_policy`||| +|`aws_iot_policy_attachment`||| +|`aws_iot_topic_rule`||| +|`aws_iot_thing`||| +|`aws_iot_thing_principal_attachment`||| +|`aws_iot_thing_type`||| +|`aws_iot_role_alias`||| +|`aws_inspector_assessment_target`||| +|`aws_inspector_assessment_template`||| +|`aws_inspector_resource_group`||| +|`aws_kinesis_analytics_application`||| +|`aws_kinesis_stream`||| +|`aws_kinesis_firehose_delivery_stream`||| +|`aws_kms_alias`||| +|`aws_kms_external_key`||| +|`aws_kms_grant`||| +|`aws_kms_ciphertext`||| +|`aws_kms_key`||| +|`aws_lambda_alias`||| +|`aws_lambda_event_source_mapping`||| +|`aws_lambda_function`||| +|`aws_lambda_layer_version`||| +|`aws_lambda_permission`||| +|`aws_licensemanager_association`||| +|`aws_licensemanager_license_configuration`||| +|`aws_lightsail_domain`||| +|`aws_lightsail_instance`||| +|`aws_lightsail_key_pair`||| +|`aws_lightsail_static_ip`||| +|`aws_lightsail_static_ip_attachment`||| +|`aws_macie_member_account_association`||| +|`aws_macie_s3_bucket_association`||| +|`aws_mq_broker`||| +|`aws_mq_configuration`||| +|`aws_media_package_channel`||| +|`aws_media_store_container`||| +|`aws_media_store_container_policy`||| +|`aws_neptune_parameter_group`||| +|`aws_neptune_subnet_group`||| +|`aws_neptune_cluster_parameter_group`||| +|`aws_neptune_cluster`||| +|`aws_neptune_cluster_instance`||| +|`aws_neptune_cluster_snapshot`||| +|`aws_neptune_event_subscription`||| +|`aws_opsworks_application`||| +|`aws_opsworks_custom_layer`||| +|`aws_opsworks_ganglia_layer`||| +|`aws_opsworks_haproxy_layer`||| +|`aws_opsworks_instance`||| +|`aws_opsworks_java_app_layer`||| +|`aws_opsworks_memcached_layer`||| +|`aws_opsworks_mysql_layer`||| +|`aws_opsworks_nodejs_app_layer`||| +|`aws_opsworks_permission`||| +|`aws_opsworks_php_app_layer`||| +|`aws_opsworks_rails_app_layer`||| +|`aws_opsworks_rds_db_instance`||| +|`aws_opsworks_stack`||| +|`aws_opsworks_static_web_layer`||| +|`aws_opsworks_user_profile`||| +|`aws_organizations_account`||| +|`aws_organizations_organization`||| +|`aws_organizations_policy`||| +|`aws_organizations_policy_attachment`||| +|`aws_pinpoint_app`||| +|`aws_pinpoint_adm_channel`||| +|`aws_pinpoint_apns_channel`||| +|`aws_pinpoint_apns_sandbox_channel`||| +|`aws_pinpoint_apns_voip_channel`||| +|`aws_pinpoint_apns_voip_sandbox_channel`||| +|`aws_pinpoint_baidu_channel`||| +|`aws_pinpoint_email_channel`||| +|`aws_pinpoint_event_stream`||| +|`aws_pinpoint_gcm_channel`||| +|`aws_pinpoint_sms_channel`||| +|`aws_ram_principal_association`||| +|`aws_ram_resource_association`||| +|`aws_ram_resource_share`||| +|`aws_db_cluster_snapshot`||| +|`aws_db_event_subscription`||| +|`aws_db_instance`|aws_db_instance_invalid_type|| +||aws_db_instance_invalid_vpc_security_group|✔| +||aws_db_instance_invalid_db_subnet_group|✔| +||aws_db_instance_invalid_parameter_group|✔| +||aws_db_instance_invalid_option_group|✔| +|`aws_db_option_group`||| +|`aws_db_parameter_group`||| +|`aws_db_security_group`||| +|`aws_db_snapshot`||| +|`aws_db_subnet_group`||| +|`aws_rds_cluster`||| +|`aws_rds_cluster_endpoint`||| +|`aws_rds_cluster_instance`||| +|`aws_rds_cluster_parameter_group`||| +|`aws_rds_global_cluster`||| +|`aws_redshift_cluster`||| +|`aws_redshift_event_subscription`||| +|`aws_redshift_parameter_group`||| +|`aws_redshift_security_group`||| +|`aws_redshift_snapshot_copy_grant`||| +|`aws_redshift_subnet_group`||| +|`aws_resourcegroups_group`||| +|`aws_route53_delegation_set`||| +|`aws_route53_health_check`||| +|`aws_route53_query_log`||| +|`aws_route53_record`||| +|`aws_route53_zone`||| +|`aws_route53_zone_association`||| +|`aws_route53_resolver_endpoint`||| +|`aws_route53_resolver_rule`||| +|`aws_route53_resolver_rule_association`||| +|`aws_s3_account_public_access_block`||| +|`aws_s3_bucket`||| +|`aws_s3_bucket_inventory`||| +|`aws_s3_bucket_metric`||| +|`aws_s3_bucket_notification`||| +|`aws_s3_bucket_object`||| +|`aws_s3_bucket_policy`||| +|`aws_s3_bucket_public_access_block`||| +|`aws_sagemaker_endpoint`||| +|`aws_sagemaker_endpoint_configuration`||| +|`aws_sagemaker_model`||| +|`aws_sagemaker_notebook_instance`||| +|`aws_sagemaker_notebook_instance_lifecycle_configuration`||| +|`aws_secretsmanager_secret`||| +|`aws_secretsmanager_secret_version`||| +|`aws_securityhub_account`||| +|`aws_securityhub_product_subscription`||| +|`aws_securityhub_standards_subscription`||| +|`aws_ses_active_receipt_rule_set`||| +|`aws_ses_domain_identity`||| +|`aws_ses_domain_identity_verification`||| +|`aws_ses_domain_dkim`||| +|`aws_ses_domain_mail_from`||| +|`aws_ses_receipt_filter`||| +|`aws_ses_receipt_rule`||| +|`aws_ses_receipt_rule_set`||| +|`aws_ses_configuration_set`||| +|`aws_ses_event_destination`||| +|`aws_ses_identity_notification_topic`||| +|`aws_ses_template`||| +|`aws_servicecatalog_portfolio`||| +|`aws_service_discovery_http_namespace`||| +|`aws_service_discovery_private_dns_namespace`||| +|`aws_service_discovery_public_dns_namespace`||| +|`aws_service_discovery_service`||| +|`aws_simpledb_domain`||| +|`aws_sns_platform_application`||| +|`aws_sns_sms_preferences`||| +|`aws_sns_topic`||| +|`aws_sns_topic_policy`||| +|`aws_sns_topic_subscription`||| +|`aws_sqs_queue`||| +|`aws_sqs_queue_policy`||| +|`aws_ssm_activation`||| +|`aws_ssm_association`||| +|`aws_ssm_document`||| +|`aws_ssm_maintenance_window`||| +|`aws_ssm_maintenance_window_target`||| +|`aws_ssm_maintenance_window_task`||| +|`aws_ssm_patch_baseline`||| +|`aws_ssm_patch_group`||| +|`aws_ssm_parameter`||| +|`aws_ssm_resource_data_sync`||| +|`aws_sfn_activity`||| +|`aws_sfn_state_machine`||| +|`aws_storagegateway_cache`||| +|`aws_storagegateway_cached_iscsi_volume`||| +|`aws_storagegateway_gateway`||| +|`aws_storagegateway_nfs_file_share`||| +|`aws_storagegateway_smb_file_share`||| +|`aws_storagegateway_upload_buffer`||| +|`aws_storagegateway_working_storage`||| +|`aws_swf_domain`||| +|`aws_transfer_server`||| +|`aws_transfer_ssh_key`||| +|`aws_transfer_user`||| +|`aws_customer_gateway`||| +|`aws_default_network_acl`||| +|`aws_default_route_table`||| +|`aws_default_security_group`||| +|`aws_default_subnet`||| +|`aws_default_vpc`||| +|`aws_default_vpc_dhcp_options`||| +|`aws_egress_only_internet_gateway`||| +|`aws_flow_log`||| +|`aws_internet_gateway`||| +|`aws_main_route_table_association`||| +|`aws_nat_gateway`||| +|`aws_network_acl`||| +|`aws_network_acl_rule`||| +|`aws_network_interface`||| +|`aws_network_interface_attachment`||| +|`aws_route`|[aws_route_not_specified_target](aws_route_not_specified_target.md)|| +||[aws_route_specified_multiple_targets](aws_route_specified_multiple_targets.md)|| +||aws_route_invalid_route_table|✔| +||aws_route_invalid_gateway|✔| +||aws_route_invalid_egress_only_gateway|✔| +||aws_route_invalid_nat_gateway|✔| +||aws_route_invalid_vpc_peering_connection|✔| +||aws_route_invalid_instance|✔| +||aws_route_invalid_network_interface|✔| +|`aws_route_table`||| +|`aws_route_table_association`||| +|`aws_security_group`||| +|`aws_network_interface_sg_attachment`||| +|`aws_security_group_rule`||| +|`aws_subnet`||| +|`aws_vpc`||| +|`aws_vpc_dhcp_options`||| +|`aws_vpc_dhcp_options_association`||| +|`aws_vpc_endpoint`||| +|`aws_vpc_endpoint_connection_notification`||| +|`aws_vpc_endpoint_route_table_association`||| +|`aws_vpc_endpoint_service`||| +|`aws_vpc_endpoint_service_allowed_principal`||| +|`aws_vpc_endpoint_subnet_association`||| +|`aws_vpc_ipv4_cidr_block_association`||| +|`aws_vpc_peering_connection`||| +|`aws_vpc_peering_connection_accepter`||| +|`aws_vpc_peering_connection_options`||| +|`aws_vpn_connection`||| +|`aws_vpn_connection_route`||| +|`aws_vpn_gateway`||| +|`aws_vpn_gateway_attachment`||| +|`aws_vpn_gateway_route_propagation`||| +|`aws_waf_byte_match_set`||| +|`aws_waf_geo_match_set`||| +|`aws_waf_ipset`||| +|`aws_waf_rate_based_rule`||| +|`aws_waf_regex_match_set`||| +|`aws_waf_regex_pattern_set`||| +|`aws_waf_rule`||| +|`aws_waf_rule_group`||| +|`aws_waf_size_constraint_set`||| +|`aws_waf_sql_injection_match_set`||| +|`aws_waf_web_acl`||| +|`aws_waf_xss_match_set`||| +|`aws_wafregional_byte_match_set`||| +|`aws_wafregional_geo_match_set`||| +|`aws_wafregional_ipset`||| +|`aws_wafregional_rate_based_rule`||| +|`aws_wafregional_regex_match_set`||| +|`aws_wafregional_regex_pattern_set`||| +|`aws_wafregional_rule`||| +|`aws_wafregional_rule_group`||| +|`aws_wafregional_size_constraint_set`||| +|`aws_wafregional_sql_injection_match_set`||| +|`aws_wafregional_web_acl`||| +|`aws_wafregional_web_acl_association`||| +|`aws_wafregional_xss_match_set`||| +|`aws_worklink_fleet`||| +|`aws_worklink_website_certificate_authority_association`||| + +### Best Practices + +These rules suggest to better ways. + +- [aws_instance_previous_type](aws_instance_previous_type.md) +- [aws_instance_default_standard_volume](aws_instance_default_standard_volume.md) +- [aws_db_instance_previous_type](aws_db_instance_previous_type.md) +- [aws_db_instance_default_parameter_group](aws_db_instance_default_parameter_group.md) +- [aws_db_instance_readable_password](aws_db_instance_readable_password.md) +- [aws_elasticache_cluster_previous_type](aws_elasticache_cluster_previous_type.md) +- [aws_elasticache_cluster_default_parameter_group](aws_elasticache_cluster_default_parameter_group.md) + +## Terraform Rules + +These rules relate to Terraform itself, not providers. + +### Best Practices + +These rules suggest to better ways. + +- [terraform_module_pinned_source](terraform_module_pinned_source.md) diff --git a/docs/aws_db_instance_default_parameter_group.md b/docs/rules/aws_db_instance_default_parameter_group.md similarity index 56% rename from docs/aws_db_instance_default_parameter_group.md rename to docs/rules/aws_db_instance_default_parameter_group.md index 9f19dba3d..05d7e64d7 100644 --- a/docs/aws_db_instance_default_parameter_group.md +++ b/docs/rules/aws_db_instance_default_parameter_group.md @@ -1,8 +1,10 @@ -# AWS DB Instance Default Parameter Group -Report this issue if you have specified the default parameter group. This issue type is NOTICE. +# aws_db_instance_default_parameter_group + +Disallow using default DB parameter group. ## Example -``` + +```hcl resource "aws_db_instance" "mysql" { identifier = "app" allocated_storage = 50 @@ -15,13 +17,11 @@ resource "aws_db_instance" "mysql" { publicly_accessible = false vpc_security_group_ids = ["${aws_security_group.mysql.id}"] db_subnet_group_name = "app-subnet-group" - parameter_group_name = "default.mysql5.7" + parameter_group_name = "default.mysql5.7" // default DB parameter group! multi_az = true } ``` -The following is the execution result of TFLint: - ``` $ tflint template.tf @@ -31,7 +31,9 @@ Result: 1 issues (0 errors , 0 warnings , 1 notices) ``` ## Why -RDS allows you to use a parameter group structure to change setting values ​​such as MySQL and PostgreSQL. However, the default parameter group can not be changed later, and if you want to change it, you need to create and modify a dedicated parameter group. + +You can modify parameter values in a custom DB parameter group, but you can't change the parameter values in a default DB parameter group. ## How To Fix -Please create a dedicated parameter group and change it to that. + +Create a new parameter group, and change the `parameter_group_name` to that. diff --git a/docs/rules/aws_db_instance_previous_type.md b/docs/rules/aws_db_instance_previous_type.md new file mode 100644 index 000000000..4202d819a --- /dev/null +++ b/docs/rules/aws_db_instance_previous_type.md @@ -0,0 +1,35 @@ +# aws_db_instance_previous_type + +Disallow using previous generation instance types. + +## Example + +```hcl +resource "aws_db_instance" "default" { + allocated_storage = 10 + engine = "mysql" + engine_version = "5.6.17" + instance_class = "db.t1.micro" // previous generation instance type! + name = "mydb" + username = "foo" + password = "bar" + db_subnet_group_name = "my_database_subnet_group" + parameter_group_name = "default.mysql5.6" +} +``` + +``` +$ tflint +template.tf + WARNING:5 "db.t1.micro" is previous generation instance type. (aws_db_instance_previous_type) + +Result: 1 issues (0 errors , 1 warnings , 0 notices) +``` + +## Why + +Previous generation instance types are inferior to current generation in terms of performance and fee. Unless there is a special reason, you should avoid to use these ones. + +## How To Fix + +Select a current generation instance type according to the [upgrade paths](https://aws.amazon.com/rds/previous-generation/). diff --git a/docs/aws_db_instance_readable_password.md b/docs/rules/aws_db_instance_readable_password.md similarity index 71% rename from docs/aws_db_instance_readable_password.md rename to docs/rules/aws_db_instance_readable_password.md index 34821c0ae..9d08a5595 100644 --- a/docs/aws_db_instance_readable_password.md +++ b/docs/rules/aws_db_instance_readable_password.md @@ -1,8 +1,10 @@ -# AWS DB Instance Readable Password -Report this issue if you write password for the master DB user directly. This issue type is WARNING. +# aws_db_instance_readable_password + +Disallow writing password directly to configuration files. ## Example -``` + +```hcl resource "aws_db_instance" "default" { allocated_storage = 10 engine = "mysql" @@ -16,8 +18,6 @@ resource "aws_db_instance" "default" { } ``` -The following is the execution result of TFLint: - ``` $ tflint template.tf @@ -28,7 +28,7 @@ Result: 1 issues (0 errors , 1 warnings , 0 notices) Also, detect the following case: -``` +```hcl variable "password" { description = "Password for MySQL master user" default = "jk4wu0o7" // readable passowrd! @@ -47,14 +47,15 @@ resource "aws_db_instance" "default" { } ``` - ## Why -Generally, it is a bad practice to directly embed passwords in source code and templates. One reason why is that there is a fear that it will be unintentionally published when using VCS. + +Generally, it is a bad practice to directly embed passwords in configuration files. One reason why is that there is a fear that it will be unintentionally published when using VCS. ## How To Fix + Instead of writing password directly, use environment variables. Terraform provides a way to set variables by environment variables. For example, edit and execute as following: -``` +```hcl variable "password" {} resource "aws_db_instance" "default" { @@ -74,7 +75,6 @@ resource "aws_db_instance" "default" { $ TF_VAR_password=jk4wu0o7 terraform apply ``` -In the above case, The password cannot be read from templates. For details on how to set variables, please see the [documentation](https://www.terraform.io/intro/getting-started/variables.html). - -NOTE: Unfortunately, even if you delete the password from templates, it will be stored in the state file. We recommend that encrypt state file and ignore that on VCS. +In the above case, The password cannot be read from files. For details on how to set variables, please see the [documentation](https://www.terraform.io/intro/getting-started/variables.html). +NOTE: Unfortunately, even if you delete the password from files, it will be stored in the state file. We recommend that encrypt state file and ignore that on VCS. diff --git a/docs/aws_elasticache_cluster_default_parameter_group.md b/docs/rules/aws_elasticache_cluster_default_parameter_group.md similarity index 50% rename from docs/aws_elasticache_cluster_default_parameter_group.md rename to docs/rules/aws_elasticache_cluster_default_parameter_group.md index b1db4b8ef..6c6d9671b 100644 --- a/docs/aws_elasticache_cluster_default_parameter_group.md +++ b/docs/rules/aws_elasticache_cluster_default_parameter_group.md @@ -1,8 +1,10 @@ -# AWS ElastiCache Cluster Default Parameter Group -Report this issue if you have specified the default parameter group. This issue type is NOTICE. +# aws_elasticache_cluster_default_parameter_group + +Disallow using default parameter group. ## Example -``` + +```hcl resource "aws_elasticache_cluster" "redis" { cluster_id = "app" engine = "redis" @@ -11,14 +13,12 @@ resource "aws_elasticache_cluster" "redis" { node_type = "cache.m4.large" num_cache_nodes = 1 port = 6379 - parameter_group_name = "default.redis3.2" + parameter_group_name = "default.redis3.2" // default paramete group! subnet_group_name = "app-subnet-group" security_group_ids = ["${aws_security_group.redis.id}"] } ``` -The following is the execution result of TFLint: - ``` $ tflint template.tf @@ -28,7 +28,9 @@ Result: 1 issues (0 errors , 0 warnings , 1 notices) ``` ## Why -In ElastiCache, parameter groups can be used for tuning setting values ​​such as Redis and Memcached. When creating a cluster for the first time, you can only select the default parameter group. However, the default parameter group can not be changed later, and if you want to change it, you need to change it to another parameter group. + +You can modify parameter values in a custom parameter group, but you can't change the parameter values in a default parameter group. ## How To Fix -Please create a dedicated parameter group and change it to that. + +Create a new parameter group, and change the `parameter_group_name` to that. diff --git a/docs/rules/aws_elasticache_cluster_previous_type.md b/docs/rules/aws_elasticache_cluster_previous_type.md new file mode 100644 index 000000000..f0029f8e6 --- /dev/null +++ b/docs/rules/aws_elasticache_cluster_previous_type.md @@ -0,0 +1,36 @@ +# aws_elasticache_cluster_previous_type + +Disallow using previous node types. + +## Example + +```hcl +resource "aws_elasticache_cluster" "redis" { + cluster_id = "app" + engine = "redis" + engine_version = "3.2.4" + maintenance_window = "sun:00:00-sun:06:00" + node_type = "cache.t1.micro" // previous node type! + num_cache_nodes = 1 + port = 6379 + parameter_group_name = "default.redis3.2" + subnet_group_name = "app-subnet-group" + security_group_ids = ["${aws_security_group.redis.id}"] +} +``` + +``` +$ tflint +template.tf + WARNING:6 "cache.t1.micro" is previous generation node type. (aws_elasticache_cluster_previous_type) + +Result: 1 issues (0 errors , 1 warnings , 0 notices) +``` + +## Why + +Previous node types are inferior to current generation in terms of performance and fee. Unless there is a special reason, you should avoid to use these ones. + +## How To Fix + +Select a current generation node type according to the [upgrade paths](https://aws.amazon.com/elasticache/previous-generation/). diff --git a/docs/aws_instance_default_standard_volume.md b/docs/rules/aws_instance_default_standard_volume.md similarity index 82% rename from docs/aws_instance_default_standard_volume.md rename to docs/rules/aws_instance_default_standard_volume.md index a0dac1022..8651edaf6 100644 --- a/docs/aws_instance_default_standard_volume.md +++ b/docs/rules/aws_instance_default_standard_volume.md @@ -1,8 +1,10 @@ -# AWS Instance Default Standard Volume -Report this issue if you have not specified the volume type in block device. This issue type is WARNING. +# aws_instance_default_standard_volume + +Disallow using default volume type. ## Example -``` + +```hcl resource "aws_instance" "web" { ami = "ami-b73b63a0" instance_type = "m4.2xlarge" @@ -14,8 +16,6 @@ resource "aws_instance" "web" { } ``` -The following is the execution result of TFLint: - ``` $ tflint template.tf @@ -25,7 +25,9 @@ Result: 1 issues (0 errors , 1 warnings , 0 notices) ``` ## Why + If you use EBS as instance volume, you can specify the volume type. If not specified, the "default" volume type will be used. This is an officially deprecated volume type, and it is generally recommended to use "gp2". ## How To Fix + Check the [EBS volume types](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) and specify volume type. If you want to use the "default", if you explicitly specify "default", TFLint will not report this issue. diff --git a/docs/rules/aws_instance_previous_type.md b/docs/rules/aws_instance_previous_type.md new file mode 100644 index 000000000..947d541fc --- /dev/null +++ b/docs/rules/aws_instance_previous_type.md @@ -0,0 +1,33 @@ +# aws_instance_previous_type + +Disallow using previous generation instance types. + +## Example + +```hcl +resource "aws_instance" "web" { + ami = "ami-b73b63a0" + instance_type = "t1.micro" # previous instance type! + iam_instance_profile = "app-service" + + tags { + Name = "HelloWorld" + } +} +``` + +``` +$ tflint +template.tf + WARNING:3 "t1.micro" is previous generation instance type. (aws_instance_previous_type) + +Result: 1 issues (0 errors , 1 warnings , 0 notices) +``` + +## Why + +Previous generation instance types are inferior to current generation in terms of performance and fee. Unless there is a special reason, you should avoid to use these ones. + +## How To Fix + +Select a current generation instance type according to the [upgrade paths](https://aws.amazon.com/ec2/previous-generation/). diff --git a/docs/rules/aws_route_not_specified_target.md b/docs/rules/aws_route_not_specified_target.md new file mode 100644 index 000000000..7170ad626 --- /dev/null +++ b/docs/rules/aws_route_not_specified_target.md @@ -0,0 +1,28 @@ +# aws_route_not_specified_target + +Disallow routes that have no targets. + +## Example + +```hcl +resource "aws_route" "foo" { + route_table_id = "rtb-1234abcd" + destination_cidr_block = "10.0.1.0/22" +} +``` + +``` +$ tflint +template.tf + ERROR:1 The routing target is not specified, each aws_route must contain either egress_only_gateway_id, gateway_id, instance_id, nat_gateway_id, network_interface_id, transit_gateway_id, or vpc_peering_connection_id. + +Result: 1 issues (1 errors , 0 warnings , 0 notices) +``` + +## Why + +It occurs an error. + +## How To Fix + +Add a routing target. There are [kinds of](https://www.terraform.io/docs/providers/aws/r/route.html#argument-reference) `egress_only_gateway_id`, `gateway_id`, `instance_id`, `nat_gateway_id`, `network_interface_id`, `transit_gateway_id`, `vpc_peering_connection_id`. diff --git a/docs/aws_route_specified_multiple_targets.md b/docs/rules/aws_route_specified_multiple_targets.md similarity index 55% rename from docs/aws_route_specified_multiple_targets.md rename to docs/rules/aws_route_specified_multiple_targets.md index d82157c21..e85ebf65e 100644 --- a/docs/aws_route_specified_multiple_targets.md +++ b/docs/rules/aws_route_specified_multiple_targets.md @@ -1,8 +1,10 @@ -# AWS Route Specified Multiple Targets -Report this issue if multiple routing targets are specified. This issue type is ERROR. +# aws_route_specified_muletiple_targets + +Disallow routes that have multiple targets. ## Example -``` + +```hcl resource "aws_route" "foo" { route_table_id = "rtb-1234abcd" destination_cidr_block = "10.0.1.0/22" @@ -11,9 +13,6 @@ resource "aws_route" "foo" { } ``` -The following is the execution result of TFLint: - - ``` $ tflint template.tf @@ -23,10 +22,12 @@ Result: 1 issues (1 errors , 0 warnings , 0 notices) ``` ## Why -`aws_route` does not allow to specify multiple routing targets. If multiple routing targets are specified, an error will occur when run `terraform apply`. + +It occurs an error. ## How To Fix -Please check if two or more of the following attributes are specified: + +Check if two or more of the following attributes are specified: - gateway_id - egress_only_gateway_id @@ -34,5 +35,3 @@ Please check if two or more of the following attributes are specified: - instance_id - vpc_peering_connection_id - network_interface_id - -If specified multiple attributes, please specify only one as needed. diff --git a/docs/terraform_module_pinned_source.md b/docs/rules/terraform_module_pinned_source.md similarity index 85% rename from docs/terraform_module_pinned_source.md rename to docs/rules/terraform_module_pinned_source.md index e2ae9efe7..f233efb98 100644 --- a/docs/terraform_module_pinned_source.md +++ b/docs/rules/terraform_module_pinned_source.md @@ -1,8 +1,10 @@ -# Terraform Module Pinned Source -This issue is reported if you specify a git or mercurial repository without pinning to a non-default version. +# terraform_module_pinned_source + +Disallow specifying a git or mercurial repository as a module source without pinning to a non-default version. ## Example -``` + +```hcl module "unpinned" { source = "git://hashicorp.com/consul.git" } @@ -16,8 +18,6 @@ module "default mercurial" { } ``` -The following is the execution result of TFLint: - ``` $ tflint template.tf @@ -29,7 +29,9 @@ Result: 3 issues (0 errors , 3 warnings , 0 notices) ``` ## Why + Terraform allows you to checkout module definitions from source control. If you do not pin the version to checkout, the dependency you require may introduce major breaking changes without your awareness. To prevent this, always specify an explicit version to checkout. ## How To Fix + Specify a version pin. For git repositories, it should not be "master". For Mercurial repositories, it should not be "default"