Skip to content

use tfsec for static analysing terraform code #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/terraform-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ jobs:
- name: Terraform Validate l2
working-directory: ./terraform/layer2-k8s
run: terraform validate -no-color .
- name: Upload files for l1
uses: actions/upload-artifact@v2
with:
name: l1
path: ./terraform/layer1-aws/.terraform
retention-days: 1
- name: Upload files for l2
uses: actions/upload-artifact@v2
with:
name: l2
path: ./terraform/layer2-k8s/.terraform
retention-days: 1

# Checks that all Terraform configuration files format
terraform-format:
Expand Down Expand Up @@ -63,3 +75,52 @@ jobs:
- name: Terraform tflint l2
working-directory: ./terraform/layer2-k8s
run: tflint --no-color

terraform-tfsec-l1:
name: 'Terraform-tfsec-l1'
needs: terraform-validate
runs-on: ubuntu-latest
container:
image: tfsec/tfsec
options: --user root
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download init for l1
uses: actions/download-artifact@v2
with:
name: l1
path: ./terraform/layer1-aws/.terraform
- name: tfsec l1
working-directory: ./terraform
run: tfsec layer1-aws
- uses: geekyeggo/delete-artifact@v1
with:
name: l1
failOnError: false
if: ${{ always() }}

terraform-tfsec-l2:
name: 'Terraform-tfsec-l2'
needs: terraform-validate
runs-on: ubuntu-latest
container:
image: tfsec/tfsec
options: --user root
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download init for l2
uses: actions/download-artifact@v2
with:
name: l2
path: ./terraform/layer2-k8s/.terraform
- name: Terraform tfsec l2
working-directory: ./terraform
run: tfsec layer2-k8s
- uses: geekyeggo/delete-artifact@v1
with:
name: l2
failOnError: false
if: ${{ always() }}

100 changes: 67 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,51 @@ You can find more about this project in Anton Babenko stream:

## Table of contents

- [Architecture diagram](#architecture-diagram)
- [Current infrastructure cost](#current-infrastructure-cost)
- [Namespace structure in the K8S cluster](#namespace-structure-in-the-k8s-cluster)
- [Useful tools](#useful-tools)
- [Useful VSCode extensions](#useful-vscode-extensions)
- [AWS account](#aws-account)
- [IAM settings](#iam-settings)
- [Setting up awscli](#setting-up-awscli)
- [How to use this repo](#how-to-use-this-repo)
- [Getting ready](#getting-ready)
- [S3 state backend](#s3-state-backend)
- [Secrets](#secrets)
- [Domain and SSL](#domain-and-ssl)
- [Working with terraform](#working-with-terraform)
- [init](#init)
- [plan](#plan)
- [apply](#apply)
- [terragrunt](#terragrunt)
- [What to do after deployment](#what-to-do-after-deployment)
- [examples](#examples)
- [Coding conventions](#coding-conventions)
- [Names and approaches used in code](#names-and-approaches-used-in-code)
- [Base project name](#base-project-name)
- [Unique prefix of resource names](#unique-prefix-of-resource-names)
- [Separators](#separators)
- [Resource names](#resource-names)
- [Variable names](#variable-names)
- [Output names](#output-names)
- [Names of terraform files, directories, and modules](#names-of-terraform-files-directories-and-modules)
- [General configuration files](#general-configuration-files)
- [Specific configuration files](#specific-configuration-files)
- [Modules](#modules)
- [Project structure](#project-structure)
- [Boilerplate for a basic AWS infrastructure with EKS cluster](#boilerplate-for-a-basic-aws-infrastructure-with-eks-cluster)
- [Advantages of this boilerplate](#advantages-of-this-boilerplate)
- [Why you should use this boilerplate](#why-you-should-use-this-boilerplate)
- [Description](#description)
- [Table of contents](#table-of-contents)
- [Architecture diagram](#architecture-diagram)
- [Current infrastructure cost](#current-infrastructure-cost)
- [Namespace structure in the K8S cluster](#namespace-structure-in-the-k8s-cluster)
- [Useful tools](#useful-tools)
- [Useful VSCode extensions](#useful-vscode-extensions)
- [AWS account](#aws-account)
- [IAM settings](#iam-settings)
- [Setting up awscli](#setting-up-awscli)
- [How to use this repo](#how-to-use-this-repo)
- [Getting ready](#getting-ready)
- [S3 state backend](#s3-state-backend)
- [Inputs](#inputs)
- [Secrets](#secrets)
- [Domain and SSL](#domain-and-ssl)
- [Working with terraform](#working-with-terraform)
- [init](#init)
- [plan](#plan)
- [apply](#apply)
- [terragrunt](#terragrunt)
- [Apply infrastructure by layers with `terragrunt`](#apply-infrastructure-by-layers-with-terragrunt)
- [Target apply by `terragrunt`](#target-apply-by-terragrunt)
- [Destroy infrastructure by `terragrunt`](#destroy-infrastructure-by-terragrunt)
- [What to do after deployment](#what-to-do-after-deployment)
- [Update terraform version](#update-terraform-version)
- [Updated terraform providers](#updated-terraform-providers)
- [examples](#examples)
- [TFSEC](#tfsec)
- [Coding conventions](#coding-conventions)
- [Names and approaches used in code](#names-and-approaches-used-in-code)
- [Base project name](#base-project-name)
- [Unique prefix of resource names](#unique-prefix-of-resource-names)
- [Separators](#separators)
- [Resource names](#resource-names)
- [Variable names](#variable-names)
- [Output names](#output-names)
- [Names of terraform files, directories, and modules](#names-of-terraform-files-directories-and-modules)
- [General configuration files](#general-configuration-files)
- [Specific configuration files](#specific-configuration-files)
- [Modules](#modules)
- [Project structure](#project-structure)

## Architecture diagram

Expand Down Expand Up @@ -455,6 +467,28 @@ Each layer has an `examples/` directory that contains working examples that expa

This will allow you to expand your basic functionality by launching a monitoring system based on ELK or Prometheus Stack, etc.

## TFSEC
We use GitHub Actions and [tfsec](https://github.com/aquasecurity/tfsec) to check our terraform code using static analysis to spot potential security issues. However, we needed to skip some checks. The list of those checks is below:

| Layer | Security issue | Description | Why skipped? |
|---------------|--------------------------|----------------|-----------------|
| layer1-aws/aws-eks.tf | aws-vpc-no-public-egress-sgr | Resource 'module.eks:aws_security_group_rule.cluster_egress_internet[0]' defines a fully open egress security group rule. | We use recommended option. [More info](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html) |
| layer1-aws/aws-eks.tf | aws-eks-enable-control-plane-logging | Resource 'module.eks:aws_eks_cluster.this[0]' is missing the control plane log type 'scheduler' | By default we enable only audit logs. Can be changed via variable eks_cluster_enabled_log_types |
| layer1-aws/aws-eks.tf | aws-eks-encrypt-secrets | Resource 'module.eks:aws_eks_cluster.this[0]' has no encryptionConfigBlock block | By default encryption is disabled, but can be enabled via setting *eks_cluster_encryption_config_enable = true* in your tfvars file. |
| layer1-aws/aws-eks.tf | aws-eks-no-public-cluster-access | Resource 'module.eks:aws_eks_cluster.this[0]' has public access is explicitly set to enabled | By default we create public accessible EKS cluster from anywhere |
| layer1-aws/aws-eks.tf | aws-eks-no-public-cluster-access-to-cidr | Resource 'module.eks:aws_eks_cluster.this[0]' has public access cidr explicitly set to wide open | By default we create public accessible EKS cluster from anywhere |
| layer1-aws/aws-eks.tf | aws-vpc-no-public-egress-sgr | Resource 'module.eks:aws_security_group_rule.workers_egress_internet[0]' defines a fully open egress security group rule | We use recommended option. [More info](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html) |
| modules/aws-iam-ssm/iam.tf | aws-iam-no-policy-wildcards | Resource 'module.aws_iam_external_secrets:data.aws_iam_policy_document.this' defines a policy with wildcarded resources. | We use aws-iam-ssm module for external-secrets and grant it access to all secrets. |
| modules/aws-iam-autoscaler/iam.tf | aws-iam-no-policy-wildcards | Resource 'module.aws_iam_autoscaler:data.aws_iam_policy_document.this' defines a policy with wildcarded resources | We use condition to allow run actions only for certain autoscaling groups |
| modules/kubernetes-network-policy-namespace/main.tf | kubernetes-network-no-public-ingress | Resource 'module.dev_ns_network_policy:kubernetes_network_policy.deny-all' allows all ingress traffic by default | We deny all ingress trafic by default, but tfsec doesn't work as expected (bug) |
| modules/kubernetes-network-policy-namespace/main.tf | kubernetes-network-no-public-egress | Resource 'module.dev_ns_network_policy:kubernetes_network_policy.deny-all' allows all egress traffic by default | We don't want to deny egress traffic in a default installation |
| kubernetes-network-policy-namespace/main.tf | kubernetes-network-no-public-egress | Resource 'module.dev_ns_network_policy:kubernetes_network_policy.allow-from-this' allows all egress traffic by default | We don't want to deny egress traffic in a default installation |
| modules/kubernetes-network-policy-namespace/main.tf | kubernetes-network-no-public-egress | Resource 'module.dev_ns_network_policy:kubernetes_network_policy.allow-from-ns[0]' allows all egress traffic by default | We don't want to deny egress traffic in a default installation |
| modules/aws-iam-aws-loadbalancer-controller/iam.tf | aws-iam-no-policy-wildcards | Resource 'module.eks_alb_ingress[0]:module.aws_iam_aws_loadbalancer_controller:aws_iam_role_policy.this' defines a policy with wildcarded resources | We use recommended [policy](https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json) |
| layer2-k8s/locals.tf | general-secrets-sensitive-in-local | Local 'locals.' includes a potentially sensitive value which is defined within the project | tfsec complains on helm_repo_external_secrets url because it contains the word *secret* |
| modules/aws-iam-external-dns/main.tf | aws-iam-no-policy-wildcards | Resource 'module.aws_iam_external_dns:aws_iam_role_policy.this' defines a policy with wildcarded resources | We use the policy from the [documentation](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#iam-policy)
| modules/aws-iam-external-dns/main.tf | aws-iam-no-policy-wildcards | Resource 'module.aws_iam_cert_manager:aws_iam_role_policy.this' defines a policy with wildcarded resources | Certmanager uses Route53 to create DNS records and validate wildcard certificates. By default we allow it to manage all zones |

## Coding conventions

This section contains the most basic recommendations for users and contributors on coding, naming, etc. The goal is consistent, standardized, readable code. Additions, suggestions and changes are welcome.
Expand Down
1 change: 1 addition & 0 deletions terraform/layer1-aws/aws-eks.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ locals {
]
}

#tfsec:ignore:aws-vpc-no-public-egress-sgr tfsec:ignore:aws-eks-enable-control-plane-logging tfsec:ignore:aws-eks-encrypt-secrets tfsec:ignore:aws-eks-no-public-cluster-access tfsec:ignore:aws-eks-no-public-cluster-access-to-cidr
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "17.1.0"
Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-aws-loadbalancer-controller.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#tfsec:ignore:aws-iam-no-policy-wildcards
module "eks_alb_ingress" {
source = "../modules/eks-aws-loadbalancer-controller"
count = var.aws_loadbalancer_controller_enable ? 1 : 0
Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-cert-manager.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#tfsec:ignore:aws-iam-no-policy-wildcards
module "aws_iam_cert_manager" {
source = "../modules/aws-iam-external-dns"

Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-cluster-autoscaler.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#tfsec:ignore:aws-iam-no-policy-wildcards
module "aws_iam_autoscaler" {
source = "../modules/aws-iam-autoscaler"

Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-external-dns.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#tfsec:ignore:aws-iam-no-policy-wildcards
module "aws_iam_external_dns" {
source = "../modules/aws-iam-external-dns"

Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-external-secrets.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#tfsec:ignore:aws-iam-no-policy-wildcards
module "aws_iam_external_secrets" {
source = "../modules/aws-iam-ssm"

Expand Down
1 change: 1 addition & 0 deletions terraform/layer2-k8s/eks-network-policy.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ resource "helm_release" "calico_daemonset" {
]
}

#tfsec:ignore:kubernetes-network-no-public-egress tfsec:ignore:kubernetes-network-no-public-ingress
module "dev_ns_network_policy" {
source = "../modules/kubernetes-network-policy-namespace"
namespace = kubernetes_namespace.dev.metadata[0].name
Expand Down
2 changes: 1 addition & 1 deletion terraform/layer2-k8s/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ locals {
helm_repo_eks = "https://aws.github.io/eks-charts"
helm_repo_softonic = "https://charts.softonic.io"
helm_repo_elastic = "https://helm.elastic.co"
helm_repo_external_secrets = "https://external-secrets.github.io/kubernetes-external-secrets"
helm_repo_external_secrets = "https://external-secrets.github.io/kubernetes-external-secrets" #tfsec:ignore:general-secrets-sensitive-in-local
helm_repo_stakater = "https://stakater.github.io/stakater-charts"
helm_repo_cluster_autoscaler = "https://kubernetes.github.io/autoscaler"
helm_repo_ingress_nginx = "https://kubernetes.github.io/ingress-nginx"
Expand Down