├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── main.yml
├── go.mod
├── .dockerignore
├── versions.tf
├── .pre-commit-config.yaml
├── test
├── secure-s3-bucket
│ ├── outputs.tf
│ ├── variables.tf
│ └── main.tf
├── terraform_aws_s3_bucket_test.go
└── README.md
├── .gitignore
├── examples
├── README.md
└── secure-s3-bucket
│ ├── main.tf
│ └── README.md
├── outputs.tf
├── CONTRIBUTING.md
├── CHANGELOG.md
├── Makefile
├── variables.tf
├── LICENSE
├── main.tf
├── README.md
├── README.tfdoc.hcl
└── go.sum
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @mariux @mineiros-io/terraform-service-catalog
2 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/mineiros-io/terraform-aws-s3-bucket/v2
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/gruntwork-io/terratest v0.34.0
7 | github.com/stretchr/testify v1.4.0
8 | )
9 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Idea
2 | .idea
3 |
4 | # Misc
5 | CODEOWNERS
6 | Makefile
7 | README.*
8 | LICENSE
9 |
10 | # Terraform
11 | .terraform
12 |
13 | # Go vendors
14 | vendor
15 |
16 | # Git
17 | #.git required for pre-commit
18 | .gitignore
19 |
20 | # CI
21 | .semaphore
22 |
23 | # Docker
24 | Dockerfile
25 |
--------------------------------------------------------------------------------
/versions.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE
3 | # ---------------------------------------------------------------------------------------------------------------------
4 |
5 | terraform {
6 | required_version = ">= 0.12.20, < 2.0"
7 |
8 | required_providers {
9 | aws = ">= 2.51, < 4.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/mineiros-io/pre-commit-hooks
3 | rev: v0.3.1
4 | hooks:
5 | - id: terraform-fmt
6 | - id: terraform-validate
7 | exclude: ^examples|.terraform/
8 | - id: tflint
9 | - id: golangci-lint
10 | - id: phony-targets
11 | - id: markdown-link-check
12 | args: ['-p'] # When adding the -p flag, markdown-link-check will always with an exit code 0, even if dead links are found
13 | verbose: true # Forces the output of the hook to be printed even when the hook passes.
14 |
--------------------------------------------------------------------------------
/test/secure-s3-bucket/outputs.tf:
--------------------------------------------------------------------------------
1 | output "example-app-bucket" {
2 | description = "The outputs of our example app bucket."
3 | value = module.example-app-bucket
4 | }
5 |
6 | output "example-log-bucket" {
7 | description = "The outputs of our example log bucket."
8 | value = module.example-log-bucket
9 | }
10 |
11 | output "example-elb-log-bucket" {
12 | description = "The outputs of our example elb log bucket."
13 | value = module.example-elb-log-bucket
14 | }
15 |
16 | output "example-no-bucket" {
17 | description = "The outputs of our example no bucket."
18 | value = module.example-no-bucket
19 | }
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Let us know about an issue in expected behavior.
4 | labels: bug
5 | ---
6 | ### Module Version
7 |
10 |
11 | ### Module use
12 |
15 |
16 | ```hcl
17 | ...
18 | ```
19 |
20 | ### Expected Behavior
21 |
24 |
25 | ### Actual Behavior
26 |
29 |
30 | ### Steps to Reproduce
31 |
34 |
35 | ### References
36 |
39 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI/CD Pipeline
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | env:
12 | AWS_SECRET_ACCESS_KEY: ${{ secrets.MINEIROS_TESTING_AWS_SECRET_ACCESS_KEY }}
13 | AWS_ACCESS_KEY_ID: ${{ secrets.MINEIROS_TESTING_AWS_ACCESS_KEY_ID }}
14 |
15 | jobs:
16 | pre-commit:
17 | runs-on: ubuntu-latest
18 | name: Static Analysis
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v2
22 | - name: Run pre-commit
23 | run: make test/pre-commit
24 |
25 | unit-tests:
26 | runs-on: ubuntu-latest
27 | name: Unit Tests
28 | steps:
29 | - name: Checkout
30 | uses: actions/checkout@v2
31 | - name: Run Unit Tests
32 | run: make test/unit-tests
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Local .terraform directories
2 | **/.terraform/*
3 |
4 | # .tfstate files
5 | *.tfstate
6 | *.tfstate.*
7 |
8 | # Crash log files
9 | crash.log
10 |
11 | # Terraform lock
12 | *.terraform
13 |
14 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most
15 | # .tfvars files are managed as part of configuration and so should be included in
16 | # version control.
17 | #
18 | # example.tfvars
19 |
20 | # Ignore override files as they are usually used to override resources locally and so
21 | # are not checked in
22 | override.tf
23 | override.tf.json
24 | *_override.tf
25 | *_override.tf.json
26 |
27 | # Include override files you do wish to add to version control using negated pattern
28 | #
29 | # !example_override.tf
30 |
31 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
32 | # example: *tfplan*
33 |
34 | # Go best practices dictate that libraries should not include the vendor directory
35 | vendor
36 |
37 | # IntelliJ files
38 | .idea_modules
39 | *.iml
40 | *.iws
41 | *.ipr
42 | .idea/
43 | build/
44 | */build/
45 | out/
46 |
47 | # local env
48 | .env
49 |
--------------------------------------------------------------------------------
/test/secure-s3-bucket/variables.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # ENVIRONMENT VARIABLES
3 | # Define these secrets as environment variables
4 | # ---------------------------------------------------------------------------------------------------------------------
5 |
6 | # AWS_ACCESS_KEY_ID
7 | # AWS_SECRET_ACCESS_KEY
8 |
9 | # ---------------------------------------------------------------------------------------------------------------------
10 | # REQUIRED VARIABLES
11 | # These variables must be set when using this module.
12 | # ---------------------------------------------------------------------------------------------------------------------
13 |
14 | variable "aws_region" {
15 | description = "The AWS region in which all resources will be created."
16 | type = string
17 | }
18 |
19 | # ---------------------------------------------------------------------------------------------------------------------
20 | # OPTIONAL VARIABLES
21 | # These variables have defaults, but may be overridden.
22 | # ---------------------------------------------------------------------------------------------------------------------
23 |
--------------------------------------------------------------------------------
/test/terraform_aws_s3_bucket_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/gruntwork-io/terratest/modules/aws"
7 | "github.com/gruntwork-io/terratest/modules/terraform"
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestSecureS3Bucket(t *testing.T) {
12 | t.Parallel()
13 |
14 | awsRegion := aws.GetRandomRegion(t, nil, nil)
15 |
16 | terraformOptions := &terraform.Options{
17 | // The path to where your Terraform code is located
18 | TerraformDir: "./secure-s3-bucket",
19 | Vars: map[string]interface{}{
20 | "aws_region": awsRegion,
21 | },
22 | Upgrade: true,
23 | }
24 |
25 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
26 | defer terraform.Destroy(t, terraformOptions)
27 |
28 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
29 | terraform.InitAndApply(t, terraformOptions)
30 |
31 | stdout := terraform.Plan(t, terraformOptions)
32 |
33 | resourceCount := terraform.GetResourceCount(t, stdout)
34 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add)
35 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change)
36 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy)
37 | }
38 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | [
][homepage]
2 |
3 | [![GitHub tag (latest SemVer)][badge-semver]][releases-github]
4 | [![license][badge-license]][apache20]
5 | [![Terraform Version][badge-terraform]][releases-terraform]
6 | [![Join Slack][badge-slack]][slack]
7 |
8 | # Examples for using this Mineiros Module
9 |
10 | - [examples/secure-s3-bucket] creates two secure AWS S3-Buckets using the `mineiros-io/terraform-aws-s3-bucket` module.
11 |
12 |
13 |
14 | [examples/secure-s3-bucket]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/examples/secure-s3-bucket
15 |
16 | [homepage]: https://mineiros.io/?ref=terraform-aws-s3-bucket
17 |
18 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg
19 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform
20 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack
21 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-s3-bucket.svg?label=latest&sort=semver
22 |
23 | [releases-github]: https://github.com/mineiros-io/terraform-aws-s3-bucket/releases
24 | [releases-terraform]: https://github.com/hashicorp/terraform/releases
25 | [apache20]: https://opensource.org/licenses/Apache-2.0
26 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a new feature.
4 | labels: enhancement
5 | ---
6 | ### Current Version
7 |
10 |
11 | ### Use-cases
12 |
19 |
20 | ### Attempted Solutions
21 |
26 |
27 | ### Proposal
28 |
35 |
36 | ### References
37 |
40 |
--------------------------------------------------------------------------------
/examples/secure-s3-bucket/main.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # CREATE TWO SECURE S3 BUCKETS INSIDE THE SAME AWS ACCOUNT
3 | # This example creates a S3 Bucket and another Log S3 Bucket.
4 | # ---------------------------------------------------------------------------------------------------------------------
5 |
6 | provider "aws" {
7 | region = "us-east-1"
8 | }
9 |
10 | # ---------------------------------------------------------------------------------------------------------------------
11 | # Create the Example App S3 Bucket
12 | # ---------------------------------------------------------------------------------------------------------------------
13 |
14 | module "example-app-bucket" {
15 | source = "mineiros-io/s3-bucket/aws"
16 | version = "~> 0.6.0"
17 |
18 | bucket_prefix = "app"
19 |
20 | access_points = [{ name = "app" }]
21 |
22 | versioning = true
23 |
24 | logging = {
25 | target_bucket = module.example-log-bucket.id
26 | target_prefix = "log/app/"
27 | }
28 |
29 | tags = {
30 | Name = "SPA S3 Bucket"
31 | }
32 | }
33 |
34 | # ---------------------------------------------------------------------------------------------------------------------
35 | # Create the Example Log S3 Bucket
36 | # ---------------------------------------------------------------------------------------------------------------------
37 |
38 | module "example-log-bucket" {
39 | source = "mineiros-io/s3-bucket/aws"
40 | version = "~> 0.6.0"
41 |
42 | bucket_prefix = "log"
43 |
44 | acl = "log-delivery-write"
45 |
46 | # allow elb log delivery from multiple regions
47 | elb_regions = ["us-east-1", "eu-west-1"]
48 |
49 | lifecycle_rules = [
50 | {
51 | id = "log"
52 | enabled = true
53 |
54 | prefix = "log/"
55 |
56 | tags = {
57 | "rule" = "log"
58 | "autoclean" = "true"
59 | }
60 |
61 | transition = [
62 | {
63 | days = 30
64 | storage_class = "STANDARD_IA"
65 | },
66 | {
67 | days = 60
68 | storage_class = "GLACIER"
69 | }
70 | ]
71 |
72 | expiration = {
73 | days = 90
74 | }
75 | }
76 | ]
77 | }
78 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------------------------
2 | # OUTPUT CALCULATED VARIABLES (prefer full objects)
3 | # ------------------------------------------------------------------------------
4 | output "id" {
5 | description = "The name of the bucket."
6 | value = join("", aws_s3_bucket.bucket.*.id)
7 | }
8 |
9 | output "arn" {
10 | description = "The ARN of the bucket."
11 | value = join("", aws_s3_bucket.bucket.*.arn)
12 | }
13 |
14 | output "bucket_domain_name" {
15 | description = "The domain name of the bucket."
16 | value = join("", aws_s3_bucket.bucket.*.bucket_domain_name)
17 | }
18 |
19 | output "bucket_regional_domain_name" {
20 | description = "The region-specific domain name of the bucket."
21 | value = join("", aws_s3_bucket.bucket.*.bucket_regional_domain_name)
22 | }
23 |
24 | output "hosted_zone_id" {
25 | description = "The Route 53 Hosted Zone ID for this bucket's region."
26 | value = join("", aws_s3_bucket.bucket.*.hosted_zone_id)
27 | }
28 |
29 | output "region" {
30 | description = "The AWS region this bucket resides in."
31 | value = join("", aws_s3_bucket.bucket.*.region)
32 | }
33 |
34 | # ------------------------------------------------------------------------------
35 | # OUTPUT ALL RESOURCES AS FULL OBJECTS
36 | # ------------------------------------------------------------------------------
37 |
38 | locals {
39 |
40 | # fix tf13 / aws3 output change detection issues (no github issue)
41 | # terraform detects whitespace only changes in jsonencode() and claims
42 | # changes
43 | o_bucket_policy_policy = try(aws_s3_bucket_policy.bucket[0].policy, "{}")
44 | o_bucket_policy = try(merge(aws_s3_bucket_policy.bucket[0], {
45 | policy = jsonencode(jsondecode(local.o_bucket_policy_policy))
46 | }), null)
47 | # o_bucket_policy = try(aws_s3_bucket_policy.bucket[0], null)
48 |
49 | # fix tf13 / aws3 output change detection issues (no github issue)
50 | # bucket always detects change in tags out put from null => {}
51 | o_bucket_tags = try(aws_s3_bucket.bucket[0].tags, "{}")
52 | o_bucket = try(merge(aws_s3_bucket.bucket[0], {
53 | tags = local.o_bucket_tags != null ? local.o_bucket_tags : {}
54 | }), null)
55 | }
56 |
57 | output "bucket" {
58 | description = "The full bucket object."
59 | value = local.o_bucket
60 | }
61 |
62 | output "bucket_policy" {
63 | description = "The full bucket object."
64 | value = local.o_bucket_policy
65 | }
66 |
67 | output "origin_access_identity" {
68 | description = "The AWS Cloudfront Origin Access Identity object."
69 | value = try(aws_cloudfront_origin_access_identity.oai[0], {})
70 | }
71 |
72 | output "access_point" {
73 | description = "A map of acccess points keyed by name."
74 | value = aws_s3_access_point.ap
75 | }
76 |
77 | # ------------------------------------------------------------------------------
78 | # OUTPUT ALL INPUT VARIABLES AS-IS
79 | # ------------------------------------------------------------------------------
80 |
81 | # ------------------------------------------------------------------------------
82 | # OUTPUT MODULE CONFIGURATION
83 | # ------------------------------------------------------------------------------
84 |
85 | output "module_enabled" {
86 | description = "Whether the module is enabled"
87 | value = var.module_enabled
88 | }
89 |
--------------------------------------------------------------------------------
/test/secure-s3-bucket/main.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # CREATE TWO SECURE S3 BUCKETS INSIDE THE SAME AWS ACCOUNT
3 | # This template creates an Example S3 Bucket and another Log S3 Bucket.
4 | # ---------------------------------------------------------------------------------------------------------------------
5 |
6 | provider "aws" {
7 | region = var.aws_region
8 | }
9 |
10 | # ---------------------------------------------------------------------------------------------------------------------
11 | # Create the Example App S3 Bucket
12 | # ---------------------------------------------------------------------------------------------------------------------
13 |
14 | module "example-app-bucket" {
15 | source = "../.."
16 |
17 | versioning = true
18 |
19 | logging = {
20 | target_bucket = module.example-log-bucket.id
21 | target_prefix = "log/"
22 | }
23 |
24 | create_origin_access_identity = true
25 |
26 | access_points = [
27 | {
28 | name = "app"
29 | }
30 | ]
31 |
32 | cors_rule = {
33 | allowed_headers = ["*"]
34 | allowed_methods = ["PUT", "POST"]
35 | allowed_origins = ["https://s3-website-test.mineiros.io"]
36 | expose_headers = ["ETag"]
37 | max_age_seconds = 3000
38 | }
39 |
40 | tags = {
41 | Name = "Just a S3 Bucket"
42 | Environment = "Testing"
43 | }
44 | }
45 |
46 | # ---------------------------------------------------------------------------------------------------------------------
47 | # Create the Example Log S3 Bucket
48 | # ---------------------------------------------------------------------------------------------------------------------
49 |
50 | module "example-log-bucket" {
51 | source = "../.."
52 |
53 | acl = "log-delivery-write"
54 |
55 | # this is just for running the example even if logs already exist
56 | # this should not be set in production as all objects will be unrecoverably destroyed
57 | force_destroy = true
58 |
59 | lifecycle_rules = [
60 | {
61 | id = "log"
62 | enabled = true
63 |
64 | prefix = "log/"
65 |
66 | tags = {
67 | "rule" = "log"
68 | "autoclean" = "true"
69 | }
70 |
71 | transition = [
72 | {
73 | days = 30
74 | storage_class = "STANDARD_IA" # or "ONEZONE_IA"
75 | },
76 | {
77 | days = 60
78 | storage_class = "GLACIER"
79 | }
80 | ]
81 |
82 | expiration = {
83 | days = 90
84 | }
85 | }
86 | ]
87 | }
88 |
89 | # ---------------------------------------------------------------------------------------------------------------------
90 | # Create the Example ELB Log S3 Bucket
91 | # ---------------------------------------------------------------------------------------------------------------------
92 | module "example-elb-log-bucket" {
93 | source = "../.."
94 |
95 | elb_regions = ["us-east-1", "eu-west-1"]
96 | }
97 |
98 | # ---------------------------------------------------------------------------------------------------------------------
99 | # Do not create the bucket
100 | # ---------------------------------------------------------------------------------------------------------------------
101 | module "example-no-bucket" {
102 | source = "../.."
103 |
104 | module_enabled = false
105 | }
106 |
--------------------------------------------------------------------------------
/examples/secure-s3-bucket/README.md:
--------------------------------------------------------------------------------
1 | [
][homepage]
2 |
3 | [![GitHub tag (latest SemVer)][badge-semver]][releases-github]
4 | [![license][badge-license]][apache20]
5 | [![Terraform Version][badge-terraform]][releases-terraform]
6 | [![Join Slack][badge-slack]][slack]
7 |
8 | # What this example shows
9 |
10 | This code example creates two secure AWS S3-Buckets using the `mineiros-io/terraform-aws-s3-bucket` module.
11 |
12 | One bucket is the `app` bucket which could be used to store a single-page-applications static files.
13 |
14 | The other bucket is a `log` bucket to store access logs from the app bucket and additional logs from
15 | ELBs in two different regions. Lifecycle rules are set up on the log bucket to migrate older logs into
16 | cheaper storage.
17 |
18 | ## Basic usage
19 | The code in [main.tf] defines...
20 | ```hcl
21 | module "example-app-bucket" {
22 | source = "mineiros-io/s3-bucket/aws"
23 | version = "~> 0.6.0"
24 |
25 | bucket_prefix = "app"
26 |
27 | access_points = [{ name = "app" }]
28 |
29 | versioning = true
30 |
31 | logging = {
32 | target_bucket = module.example-log-bucket.id
33 | target_prefix = "log/app/"
34 | }
35 |
36 | tags = {
37 | Name = "SPA S3 Bucket"
38 | }
39 | }
40 |
41 | module "example-log-bucket" {
42 | source = "mineiros-io/s3-bucket/aws"
43 | version = "~> 0.6.0"
44 |
45 | bucket_prefix = "log"
46 |
47 | acl = "log-delivery-write"
48 |
49 | # allow elb log delivery from multiple regions
50 | elb_regions = ["us-east-1", "eu-west-1"]
51 |
52 | lifecycle_rules = [
53 | {
54 | id = "log"
55 | enabled = true
56 |
57 | prefix = "log/"
58 |
59 | tags = {
60 | "rule" = "log"
61 | "autoclean" = "true"
62 | }
63 |
64 | transition = [
65 | {
66 | days = 30
67 | storage_class = "STANDARD_IA"
68 | },
69 | {
70 | days = 60
71 | storage_class = "GLACIER"
72 | }
73 | ]
74 |
75 | expiration = {
76 | days = 90
77 | }
78 | }
79 | ]
80 | }
81 | ```
82 |
83 | ## Running the example
84 |
85 | ### Cloning the repository
86 | ```
87 | git clone https://github.com/mineiros-io/terraform-aws-s3-bucket.git
88 | cd terraform-aws-s3-bucket/examples/example
89 | ```
90 |
91 | ### Initializing Terraform
92 | Run `terraform init` to initialize the example. The output should look like:
93 |
94 | ### Applying the example
95 | Run `terraform apply -auto-approve` to create the resources.
96 |
97 | ### Destroying the example
98 | Run `terraform destroy -refresh=false -auto-approve` to destroy all resources again.
99 |
100 |
101 |
102 | [homepage]: https://mineiros.io/?ref=terraform-aws-s3-bucket
103 |
104 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg
105 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform
106 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack
107 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-s3-bucket.svg?label=latest&sort=semver
108 |
109 | [releases-github]: https://github.com/mineiros-io/terraform-aws-s3-bucket/releases
110 | [releases-terraform]: https://github.com/hashicorp/terraform/releases
111 | [apache20]: https://opensource.org/licenses/Apache-2.0
112 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg
113 |
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | [
][homepage]
2 |
3 | [![license][badge-license]][apache20]
4 | [![Terraform Version][badge-terraform]][releases-terraform]
5 | [![Join Slack][badge-slack]][slack]
6 |
7 | # Tests
8 |
9 | This directory contains a number of automated tests that cover the functionality
10 | of the modules that ship with this repository.
11 |
12 | ## Introduction
13 |
14 | We are using [Terratest] for automated tests that are located in the
15 | [`test/` directory][Testdirectory]. Terratest deploys _real_ infrastructure
16 | (e.g., servers) in a _real_ environment (e.g., AWS).
17 |
18 | The basic usage pattern for writing automated tests with Terratest is to:
19 |
20 | 1. Write tests using Go's built-in [package testing]: you create a file ending
21 | in `_test.go` and run tests with the `go test` command.
22 | 2. Use Terratest to execute your _real_ IaC tools (e.g., Terraform, Packer, etc.)
23 | to deploy _real_ infrastructure (e.g., servers) in a _real_ environment (e.g., AWS).
24 | 3. Validate that the infrastructure works correctly in that environment by
25 | making HTTP requests, API calls, SSH connections, etc.
26 | 4. Undeploy everything at the end of the test.
27 |
28 | **Note #1**: Many of these tests create real resources in an AWS account.
29 | That means they cost money to run, especially if you don't clean up after
30 | yourself. Please be considerate of the resources you create and take extra care
31 | to clean everything up when you're done!
32 |
33 | **Note #2**: Never hit `CTRL + C` or cancel a build once tests are running or
34 | the cleanup tasks won't run!
35 |
36 | **Note #3**: We set `-timeout 45m` on all tests not because they necessarily
37 | take 45 minutes, but because Go has a default test timeout of 10 minutes, after
38 | which it does a `SIGQUIT`, preventing the tests from properly cleaning up after
39 | themselves. Therefore, we set a timeout of 45 minutes to make sure all tests
40 | have enough time to finish and cleanup.
41 |
42 | ## How to run the tests
43 |
44 | This repository comes with a [Makefile], that helps you to run the
45 | tests in a convenient way.
46 | Alternatively, you can also run the tests without Docker.
47 |
48 | ### Run the tests with Docker
49 |
50 | 1. Install [Docker]
51 | 2. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`
52 | 3. Run `make test/unit-tests`
53 |
54 | ### Run the tests without Docker
55 |
56 | 1. Install the latest version of [Go].
57 | 2. Install [Terraform].
58 | 3. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`
59 | 4. Install go dependencies: `go mod download`
60 | 5. Run all tests: `go test -v -count 1 -timeout 45m -parallel 128 ./test/...`
61 | or use the convenient `make test/unit-tests` Makefile target.
62 | 6. Run a specific test: `go test -count 1 -v -timeout 45m -parallel 128 test/example_test.go`
63 |
64 |
65 |
66 | [Makefile]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/Makefile
67 | [Testdirectory]: https://github.com/mineiros-io/terraform-aws-s3-bucket/tree/master/test
68 |
69 | [homepage]: https://mineiros.io/?ref=terraform-aws-s3-bucket
70 | [Terratest]: https://github.com/gruntwork-io/terratest
71 | [package testing]: https://golang.org/pkg/testing/
72 | [Docker]: https://docs.docker.com/get-started/
73 | [Go]: https://golang.org/
74 | [Terraform]: https://www.terraform.io/downloads.html
75 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg
76 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform
77 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack
78 |
79 | [releases-terraform]: https://github.com/hashicorp/terraform/releases
80 | [apache20]: https://opensource.org/licenses/Apache-2.0
81 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg
82 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 |
3 | First and foremost, we'd like to express our gratitude to you for taking the time to contribute.
4 | We welcome and appreciate any and all contributions via
5 | [Pull Requests] along the [GitHub Flow].
6 |
7 | 1. [Open a GitHub issue](#open-a-github-issue)
8 | 2. [Fork the repository on GitHub](#fork-the-repository-on-github)
9 | 3. [Install the pre-commit hooks](#install-the-pre-commit-hooks)
10 | 4. [Update the documentation](#update-the-documentation)
11 | 5. [Update the tests](#update-the-tests)
12 | 6. [Update the code](#update-the-code)
13 | 7. [Create a pull request](#create-a-pull-request)
14 | 8. [Merge and release](#merge-and-release)
15 |
16 | ## Open a GitHub issue
17 |
18 | For bug reports or requests, please submit your issue in the appropriate repository.
19 |
20 | We advise that you open an issue and ask the
21 | [CODEOWNERS] and community prior to starting a contribution.
22 | This is your chance to ask questions and receive feedback before
23 | writing (potentially wrong) code. We value the direct contact with our community
24 | a lot, so don't hesitate to ask any questions.
25 |
26 | ## Fork the repository on GitHub
27 |
28 | [Fork] the repository into your own GitHub account and [create a new branch] as
29 | described in the [GitHub Flow].
30 |
31 | ## Install the pre-commit hooks
32 |
33 | If the repository you're working on ships with a
34 | [`.pre-commit-config.yaml`][pre-commit-file],
35 | make sure the necessary hooks have been installed before you begin working
36 | (e.g. a `pre-commit install`).
37 |
38 | ## Update the documentation
39 |
40 | We encourage you to update the documentation before writing any code (please see
41 | [Readme Driven Development]. This ensures the
42 | documentation stays up to date and allows you to think through the problem fully before you begin implementing any
43 | changes.
44 |
45 | ## Update the tests
46 |
47 | We also recommend updating the automated tests before updating any code
48 | (see [Test Driven Development].
49 |
50 | That means that you should add or update a test case, run all tests and verify
51 | that the new test fails with a clear error message and then start implementing
52 | the code changes to get that test to pass.
53 |
54 | The test folder in every repository will have documentation on how to run the
55 | tests locally.
56 |
57 | ## Update the code
58 |
59 | At this point, make your code changes and constantly test again your new test case to make sure that everything working
60 | properly. Do [commit] early and often and make useful commit messages.
61 |
62 | If a backwards incompatible change cannot be avoided, please make sure to call that out when you submit a pull request,
63 | explaining why the change is absolutely necessary.
64 |
65 | ## Create a pull request
66 |
67 | [Create a pull request] with your changes.
68 | Please make sure to include the following:
69 |
70 | 1. A description of the change, including a link to your GitHub issue.
71 | 1. Any notes on backwards incompatibility or downtime.
72 |
73 | ## Merge and release
74 |
75 | The [CODEOWNERS] of the repository will review your code and provide feedback.
76 | If everything looks good, they will merge the code and release a new version while following the principles of [Semantic Versioning (SemVer)].
77 |
78 |
79 |
80 | [Pull Requests]: https://github.com/mineiros-io/terraform-aws-s3-bucket/pulls
81 | [pre-commit-file]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/.pre-commit-config.yaml
82 |
83 | [Github Flow]: https://guides.github.com/introduction/flow/
84 | [CODEOWNERS]: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
85 | [Fork]: https://help.github.com/en/github/getting-started-with-github/fork-a-repo
86 | [create a new branch]: https://guides.github.com/introduction/flow/
87 | [Readme Driven Development]: https://tom.preston-werner.com/2010/08/23/readme-driven-development.html
88 | [commit]: https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project
89 | [create a pull request]: https://help.github.com/articles/creating-a-pull-request/
90 | [Semantic Versioning (SemVer)]: https://semver.org/
91 | [Test Driven Development]: https://en.wikipedia.org/wiki/Test-driven_development
92 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.6.0]
11 |
12 | ### Added
13 |
14 | - Add support for Terraform `v1.x`
15 |
16 | ## [0.5.0]
17 |
18 | ### Added
19 |
20 | - Add support for Terraform `v0.15`
21 |
22 | ## [0.4.2]
23 |
24 | ### Added
25 |
26 | - Add support for Terraform `v0.14.x`
27 |
28 | ## [0.4.1]
29 |
30 | ### Added
31 |
32 | - Prepare support for Terraform `v0.14.x`
33 |
34 | ## [0.4.0]
35 |
36 | ### Added
37 |
38 | - Add support for Terraform `v0.13.x`
39 | - Add support for `module_tags`.
40 |
41 | ## [0.3.0] - 2020-08-03
42 |
43 | ### Changed
44 |
45 | - Add support for Terraform AWS Provider `v3.x`
46 |
47 | ### Removed
48 |
49 | - Remove deprecated `region` argument (BREAKING CHANGE)
50 |
51 | ## [0.2.2] - 2020-07-23
52 |
53 | ### Added
54 |
55 | - Add Changelog.md.
56 |
57 | ### Changed
58 |
59 | - Migrate CI from SemaphoreCI to GitHub Actions.
60 | - Migrate to [golangci-lint](https://github.com/golangci/golangci-lint) instead
61 | of native go tools for pre-commit hooks.
62 |
63 | ## [0.2.1] - 2020-06-13
64 |
65 | ### Added
66 |
67 | - Work around a terraform issue in `module_depends_on` argument.
68 |
69 | ## [0.2.0] - 2020-06-08
70 |
71 | ### Added
72 |
73 | - Implement `module_enabled` and `module_depends_on` this replaces the `create` flag.
74 | - This replaces the backward-incompatible v0.1.5 which we removed right after
75 | noticing the issue.
76 |
77 | ### Changed
78 |
79 | - Upgrade documentation.
80 |
81 | ## [0.1.4] - 2020-04-14
82 |
83 | ### Added
84 |
85 | - Add access point support.
86 |
87 | ### Changed
88 |
89 | - Refactored examples.
90 |
91 | ## [0.1.3] - 2020-03-23
92 |
93 | ### Added
94 |
95 | - Allow log delivery from ELBs in different regions.
96 |
97 | ## [0.1.2] - 2020-03-19
98 |
99 | ### Added
100 |
101 | - Add ELB log delivery option to the module.
102 |
103 | ## [0.1.1] - 2020-03-04
104 |
105 | ### Added
106 |
107 | - Add the option to grant read-only access to existing Cloudfront Origin Access
108 | Identities via `origin_access_identities`.
109 |
110 | ## [0.1.0] - 2020-02-29
111 |
112 | ### Added
113 |
114 | - Add support for Origin Access Identity Access from Cloudfront.
115 |
116 | ## [0.0.3] - 2020-01-24
117 |
118 | ### Changed
119 |
120 | - Update minimum Terraform version to `v0.12.20` so we can take advantage of `try()` and `can()`
121 | - Update README.md with and align it with our new format
122 |
123 | ## [0.0.2] - 2020-01-20
124 |
125 | ### Added
126 |
127 | - SemaphoreCI Integration that will run build, pre-commit checks and unit tests.
128 | - Add an example and a simple test case.
129 | - Further elaboration in README.md.
130 |
131 | ## [0.0.1] - 2020-01-02
132 |
133 | ### Added
134 |
135 | - Bucket public access blocking all set to true by default.
136 | - Server-Side-Encryption (SSE) at rest enabled by default (AES256).
137 | - Bucket ACL defaults to canned private ACL.
138 | - Server-Side-Encryption (SSE) enabled by default
139 | - Added support for Versioning, Bucket Logging, Lifecycle Rules, Request Payer,
140 | Cross-Origin Resource Sharing (CORS), Acceleration Status, Bucket Policy and Tags.
141 |
142 |
143 |
144 | [unreleased]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.6.0...HEAD
145 | [0.6.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.5.0...v0.6.0
146 |
147 |
148 |
149 | [0.5.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.4.2...v0.5.0
150 | [0.4.2]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.4.1...v0.4.2
151 | [0.4.1]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.4.0...v0.4.1
152 | [0.4.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.3.0...v0.4.0
153 | [0.3.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.2.2...v0.3.0
154 | [0.2.2]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.2.1...v0.2.2
155 | [0.2.1]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.2.0...v0.2.1
156 | [0.2.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.1.4...v0.2.0
157 | [0.1.4]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.1.3...v0.1.4
158 | [0.1.3]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.1.2...v0.1.3
159 | [0.1.2]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.1.1...v0.1.2
160 | [0.1.1]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.1.0...v0.1.1
161 | [0.1.0]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.0.3...v0.1.0
162 | [0.0.3]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.0.2...v0.0.3
163 | [0.0.2]: https://github.com/mineiros-io/terraform-aws-s3-bucket/compare/v0.0.1...v0.0.2
164 | [0.0.1]: https://github.com/mineiros-io/terraform-aws-s3-bucket/releases/tag/v0.0.1
165 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Set default shell to bash
2 | SHELL := /bin/bash -o pipefail
3 |
4 | BUILD_TOOLS_VERSION ?= v0.13.0
5 | BUILD_TOOLS_DOCKER_REPO ?= mineiros/build-tools
6 | BUILD_TOOLS_DOCKER_IMAGE ?= ${BUILD_TOOLS_DOCKER_REPO}:${BUILD_TOOLS_VERSION}
7 |
8 | # Some CI providers such as GitHub Actions, CircleCI, and TravisCI are setting
9 | # the CI environment variable to a non-empty value by default to indicate that
10 | # the current workflow is running in a Continuous Integration environment.
11 | #
12 | # If TF_IN_AUTOMATION is set to any non-empty value, Terraform adjusts its
13 | # output to avoid suggesting specific commands to run next.
14 | # https://www.terraform.io/docs/commands/environment-variables.html#tf_in_automation
15 | #
16 | # We are using GNU style quiet commands to disable set V to non-empty e.g. V=1
17 | # https://www.gnu.org/software/automake/manual/html_node/Debugging-Make-Rules.html
18 | #
19 | ifdef CI
20 | TF_IN_AUTOMATION ?= yes
21 | export TF_IN_AUTOMATION
22 |
23 | V ?= 1
24 | endif
25 |
26 | ifndef NOCOLOR
27 | GREEN := $(shell tput -Txterm setaf 2)
28 | YELLOW := $(shell tput -Txterm setaf 3)
29 | WHITE := $(shell tput -Txterm setaf 7)
30 | RESET := $(shell tput -Txterm sgr0)
31 | endif
32 |
33 | GIT_TOPLEVEl = $(shell git rev-parse --show-toplevel)
34 |
35 | # Generic docker run flags
36 | DOCKER_RUN_FLAGS += -v ${GIT_TOPLEVEl}:/build
37 | DOCKER_RUN_FLAGS += --rm
38 | DOCKER_RUN_FLAGS += -e TF_IN_AUTOMATION
39 | # If TF_VERSION is defined, TFSwitch will switch to the desired version on
40 | # container startup. If TF_VERSION is omitted, the default version installed
41 | # inside the docker image will be used.
42 | DOCKER_RUN_FLAGS += -e TF_VERSION
43 |
44 | # If SSH_AUTH_SOCK is set, we forward the SSH agent of the host system into
45 | # the docker container. This is useful when working with private repositories
46 | # and dependencies that might need to be cloned inside the container (e.g.
47 | # private Terraform modules).
48 | ifdef SSH_AUTH_SOCK
49 | DOCKER_SSH_FLAGS += -e SSH_AUTH_SOCK=/ssh-agent
50 | DOCKER_SSH_FLAGS += -v ${SSH_AUTH_SOCK}:/ssh-agent
51 | endif
52 |
53 | # If AWS_ACCESS_KEY_ID is defined, we are likely running inside an AWS provider
54 | # module. To enable AWS authentication inside the docker container, we inject
55 | # the relevant environment variables.
56 | ifdef AWS_ACCESS_KEY_ID
57 | DOCKER_AWS_FLAGS += -e AWS_ACCESS_KEY_ID
58 | DOCKER_AWS_FLAGS += -e AWS_SECRET_ACCESS_KEY
59 | DOCKER_AWS_FLAGS += -e AWS_SESSION_TOKEN
60 | endif
61 |
62 | # If GITHUB_OWNER is defined, we are likely running inside a GitHub provider
63 | # module. To enable GitHub authentication inside the docker container,
64 | # we inject the relevant environment variables.
65 | ifdef GITHUB_OWNER
66 | DOCKER_GITHUB_FLAGS += -e GITHUB_TOKEN
67 | DOCKER_GITHUB_FLAGS += -e GITHUB_OWNER
68 | endif
69 |
70 | .PHONY: default
71 | default: help
72 |
73 | # Not exposed as a callable target by `make help`, since this is a one-time shot to simplify the development of this module.
74 | .PHONY: template/adjust
75 | template/adjust: FILTER = -path ./.git -prune -a -type f -o -type f -not -name Makefile
76 | template/adjust:
77 | @find . $(FILTER) -exec sed -i -e "s,terraform-module-template,$${PWD##*/},g" {} \;
78 |
79 | ## Run pre-commit hooks inside a build-tools docker container.
80 | .PHONY: test/pre-commit
81 | test/pre-commit: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS}
82 | test/pre-commit:
83 | $(call docker-run,pre-commit run -a)
84 |
85 | ## Run all Go tests inside a build-tools docker container. This is complementary to running 'go test ./test/...'.
86 | .PHONY: test/unit-tests
87 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS}
88 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_GITHUB_FLAGS}
89 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_AWS_FLAGS}
90 | test/unit-tests: DOCKER_FLAGS += -e TF_DATA_DIR=.terratest
91 | test/unit-tests: TEST ?= "TestUnit"
92 | test/unit-tests:
93 | @echo "${YELLOW}[TEST] ${GREEN}Start Running Go Tests in Docker Container.${RESET}"
94 | $(call go-test,./test -run $(TEST))
95 |
96 | ## Clean up cache and temporary files
97 | .PHONY: clean
98 | clean:
99 | $(call rm-command,.terraform)
100 | $(call rm-command,.terraform.lock.hcl)
101 | $(call rm-command,*.tfplan)
102 | $(call rm-command,*/*/.terraform)
103 | $(call rm-command,*/*/*.tfplan)
104 | $(call rm-command,*/*/.terraform.lock.hcl)
105 |
106 | ## Display help for all targets
107 | .PHONY: help
108 | help:
109 | @awk '/^.PHONY: / { \
110 | msg = match(lastLine, /^## /); \
111 | if (msg) { \
112 | cmd = substr($$0, 9, 100); \
113 | msg = substr(lastLine, 4, 1000); \
114 | printf " ${GREEN}%-30s${RESET} %s\n", cmd, msg; \
115 | } \
116 | } \
117 | { lastLine = $$0 }' $(MAKEFILE_LIST)
118 |
119 | ## Generate README.md with Terradoc
120 | .PHONY: terradoc
121 | terradoc:
122 | $(call quiet-command,terradoc -o README.md README.tfdoc.hcl)
123 |
124 | # Define helper functions
125 | DOCKER_FLAGS += ${DOCKER_RUN_FLAGS}
126 | DOCKER_RUN_CMD = docker run ${DOCKER_FLAGS} ${BUILD_TOOLS_DOCKER_IMAGE}
127 |
128 | quiet-command = $(if ${V},${1},$(if ${2},@echo ${2} && ${1}, @${1}))
129 | docker-run = $(call quiet-command,${DOCKER_RUN_CMD} ${1} | cat,"${YELLOW}[DOCKER RUN] ${GREEN}${1}${RESET}")
130 | go-test = $(call quiet-command,${DOCKER_RUN_CMD} go test -v -count 1 -timeout 45m -parallel 128 ${1} | cat,"${YELLOW}[TEST] ${GREEN}${1}${RESET}")
131 | rm-command = $(call quiet-command,rm -rf ${1},"${YELLOW}[CLEAN] ${GREEN}${1}${RESET}")
132 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # REQUIRED PARAMETERS
3 | # These variables must be set when using this module.
4 | # ---------------------------------------------------------------------------------------------------------------------
5 |
6 | # ---------------------------------------------------------------------------------------------------------------------
7 | # OPTIONAL PARAMETERS
8 | # These variables have defaults, but may be overridden.
9 | # ---------------------------------------------------------------------------------------------------------------------
10 |
11 | variable "bucket" {
12 | description = "The name of the bucket. (forces new resource, default: unique random name)"
13 | type = string
14 | default = null
15 | }
16 |
17 | variable "bucket_prefix" {
18 | description = "Creates a unique bucket name beginning with the specified prefix. Conflicts with bucket. (forces new resource)"
19 | type = string
20 | default = null
21 | }
22 |
23 | variable "acl" {
24 | description = "The canned ACL to apply. https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl"
25 | type = string
26 | default = "private"
27 | }
28 |
29 | variable "policy" {
30 | description = "A bucket policy in JSON format."
31 | type = string
32 | default = null
33 | }
34 |
35 | variable "tags" {
36 | description = "A mapping of tags to assign to the bucket."
37 | type = map(string)
38 | default = {}
39 |
40 | # Example:
41 | #
42 | # tags = {
43 | # Name = "Just an Example"
44 | # Environment = "Testing"
45 | # }
46 | }
47 |
48 | variable "force_destroy" {
49 | description = "A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable."
50 | type = bool
51 | default = false
52 | }
53 |
54 | variable "acceleration_status" {
55 | description = "Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended."
56 | type = string
57 | default = null
58 | }
59 |
60 | variable "request_payer" {
61 | description = "Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. See Requester Pays Buckets developer guide for more information."
62 | type = string
63 | default = "BucketOwner"
64 | }
65 |
66 | variable "cors_rule" {
67 | description = "Object containing a rule of Cross-Origin Resource Sharing."
68 | type = any
69 | default = {}
70 |
71 | # Example:
72 | #
73 | # cors_rule = {
74 | # allowed_headers = ["*"]
75 | # allowed_methods = ["PUT", "POST"]
76 | # allowed_origins = ["https://s3-website-test.example.com"]
77 | # expose_headers = ["ETag"]
78 | # max_age_seconds = 3000
79 | # }
80 | }
81 |
82 | variable "versioning" {
83 | description = "Boolean specifying enabled state of versioning or object containing detailed versioning configuration."
84 | type = any
85 | default = false
86 |
87 | # Examples:
88 | #
89 | # versioning = true
90 | # versioning = {
91 | # enabled = true
92 | # mfa_delete = true
93 | # }
94 | }
95 |
96 | variable "logging" {
97 | description = "Map containing access bucket logging configuration."
98 | type = map(string)
99 | default = {}
100 |
101 | # Example:
102 | #
103 | # logging = {
104 | # target_bucket = "example-bucket"
105 | # target_prefix = "log/"
106 | # }
107 | }
108 |
109 | variable "apply_server_side_encryption_by_default" {
110 | description = "Map containing server-side encryption configuration."
111 | type = map(string)
112 | default = {
113 | sse_algorithm = "AES256"
114 | }
115 | }
116 |
117 | variable "lifecycle_rules" {
118 | description = "List of maps containing configuration of object lifecycle management."
119 | type = any
120 | default = []
121 |
122 | # Example:
123 | #
124 | # lifecycle_rules = [
125 | # {
126 | # id = "log"
127 | # enabled = true
128 | #
129 | # prefix = "log/"
130 | #
131 | # tags = {
132 | # "rule" = "log"
133 | # "autoclean" = "true"
134 | # }
135 | #
136 | # transition = [
137 | # {
138 | # days = 30
139 | # storage_class = "STANDARD_IA" # or "ONEZONE_IA"
140 | # },
141 | # {
142 | # days = 60
143 | # storage_class = "GLACIER"
144 | # }
145 | # ]
146 | #
147 | # expiration = {
148 | # days = 90
149 | # }
150 | # }
151 | # ]
152 | }
153 |
154 | variable "block_public_acls" {
155 | type = bool
156 | description = "Whether Amazon S3 should block public ACLs for this bucket."
157 | default = true
158 | }
159 |
160 | variable "block_public_policy" {
161 | type = bool
162 | description = "Whether Amazon S3 should block public bucket policies for this bucket."
163 | default = true
164 | }
165 |
166 | variable "ignore_public_acls" {
167 | type = bool
168 | description = "Whether Amazon S3 should ignore public ACLs for this bucket."
169 | default = true
170 | }
171 |
172 | variable "restrict_public_buckets" {
173 | type = bool
174 | description = "Whether Amazon S3 should restrict public bucket policies for this bucket."
175 | default = true
176 | }
177 |
178 | variable "cross_account_identifiers" {
179 | type = list(string)
180 | description = "Identifiers that you want to grant cross account access to."
181 | default = []
182 |
183 | # Example:
184 | #
185 | # cross_account_identifiers = [
186 | # "112233445566",
187 | # "112233445566"
188 | # ]
189 | }
190 |
191 | variable "cross_account_bucket_actions" {
192 | type = list(string)
193 | description = "Actions on the bucket to allow"
194 | default = [
195 | "s3:ListBucket"
196 | ]
197 | }
198 |
199 | variable "cross_account_object_actions" {
200 | type = list(string)
201 | description = "Actions on bucket objects to allow"
202 | default = [
203 | "s3:GetObject"
204 | ]
205 | }
206 |
207 | variable "cross_account_object_actions_with_forced_acl" {
208 | type = list(string)
209 | description = "Actions on bucket objects to allow only with forced acl"
210 | default = [
211 | "s3:PutObject",
212 | "s3:PutObjectAcl"
213 | ]
214 | }
215 |
216 | variable "cross_account_forced_acls" {
217 | type = list(string)
218 | description = "ACLs to force on new objects for cross account xs"
219 | default = [
220 | "bucket-owner-full-control"
221 | ]
222 | }
223 |
224 | variable "create_origin_access_identity" {
225 | type = bool
226 | description = "Whether to create an origin access identity (OAI) and policy to be accessible from Cloudfront."
227 | default = false
228 | }
229 |
230 | variable "origin_access_identities" {
231 | type = list(string)
232 | description = "Cloudfront Origin Access Identities to grant read-only access to."
233 | default = []
234 | }
235 |
236 | variable "elb_log_delivery" {
237 | type = bool
238 | description = "Whether to allow log delivery from ELBs."
239 | default = null
240 | }
241 |
242 | variable "elb_regions" {
243 | type = list(string)
244 | description = "The names of the region whose AWS ELB account IDs are desired."
245 | default = []
246 | }
247 |
248 | variable "access_points" {
249 | type = any
250 | description = "A List of Access Point configurations."
251 | default = []
252 | }
253 |
254 | # ------------------------------------------------------------------------------
255 | # OPTIONAL MODULE CONFIGURATION PARAMETERS
256 | # These variables are used to configure the module.
257 | # See https://medium.com/mineiros/the-ultimate-guide-on-how-to-write-terraform-modules-part-1-81f86d31f024
258 | # ------------------------------------------------------------------------------
259 |
260 | variable "module_enabled" {
261 | type = bool
262 | description = "(optional) Whether to create resources within the module or not. Default is true."
263 | default = true
264 | }
265 |
266 | variable "module_tags" {
267 | type = map(string)
268 | description = "(Optional) A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be overwritten by resource-specific tags."
269 | default = {}
270 | }
271 |
272 | variable "module_depends_on" {
273 | type = any
274 | description = "(optional) A list of external resources the module depends_on. Default is []."
275 | default = []
276 | }
277 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [2020] [Mineiros GmbH]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | # ---------------------------------------------------------------------------------------------------------------------
2 | # CREATE A S3 BUCKET THAT IS SECURED BY DEFAULT
3 | # - Bucket public access blocking all set to true
4 | # - Server-Side-Encryption (SSE) at rest enabled by default (AES256),
5 | # ---------------------------------------------------------------------------------------------------------------------
6 |
7 | # ---------------------------------------------------------------------------------------------------------------------
8 | # Set default values for the S3 Bucket
9 | # ---------------------------------------------------------------------------------------------------------------------
10 |
11 | locals {
12 | cors_enabled = length(keys(var.cors_rule)) > 0
13 | logging_enabled = length(keys(var.logging)) > 0
14 | sse_enabled = length(keys(var.apply_server_side_encryption_by_default)) > 0
15 |
16 | cors = local.cors_enabled ? [var.cors_rule] : []
17 | logging = local.logging_enabled ? [var.logging] : []
18 | encryption = local.sse_enabled ? [var.apply_server_side_encryption_by_default] : []
19 |
20 | versioning = try(
21 | [{ enabled = tobool(var.versioning) }],
22 | length(keys(var.versioning)) > 0 ? [var.versioning] : [],
23 | []
24 | )
25 | }
26 |
27 | # ---------------------------------------------------------------------------------------------------------------------
28 | # Create the S3 Bucket
29 | # ---------------------------------------------------------------------------------------------------------------------
30 |
31 | locals {
32 | tags = merge(var.module_tags, var.tags)
33 | bucket_tags = length(local.tags) > 0 ? local.tags : null
34 | }
35 |
36 | resource "aws_s3_bucket" "bucket" {
37 | count = var.module_enabled ? 1 : 0
38 |
39 | bucket = var.bucket
40 | bucket_prefix = var.bucket_prefix
41 | acl = var.acl
42 | tags = local.bucket_tags
43 | force_destroy = var.force_destroy
44 | acceleration_status = var.acceleration_status
45 | request_payer = var.request_payer
46 |
47 | dynamic "cors_rule" {
48 | for_each = local.cors
49 |
50 | content {
51 | allowed_headers = lookup(cors_rule.value, "allowed_headers", null)
52 | allowed_methods = cors_rule.value.allowed_methods
53 | allowed_origins = cors_rule.value.allowed_origins
54 | expose_headers = lookup(cors_rule.value, "expose_headers", null)
55 | max_age_seconds = lookup(cors_rule.value, "max_age_seconds", null)
56 | }
57 | }
58 |
59 | dynamic "versioning" {
60 | for_each = local.versioning
61 |
62 | content {
63 | enabled = lookup(versioning.value, "enabled", null)
64 | mfa_delete = lookup(versioning.value, "mfa_delete", false)
65 | }
66 | }
67 |
68 | dynamic "logging" {
69 | for_each = local.logging
70 |
71 | content {
72 | target_bucket = logging.value.target_bucket
73 | target_prefix = lookup(logging.value, "target_prefix", null)
74 | }
75 | }
76 |
77 | dynamic "server_side_encryption_configuration" {
78 | for_each = local.encryption
79 | iterator = sse
80 |
81 | content {
82 | rule {
83 | apply_server_side_encryption_by_default {
84 | kms_master_key_id = lookup(sse.value, "kms_master_key_id", null)
85 | sse_algorithm = lookup(sse.value, "sse_algorithm",
86 | lookup(sse.value, "kms_master_key_id", null) == null ? "AES256" : "aws:kms"
87 | )
88 | }
89 | }
90 | }
91 | }
92 |
93 | dynamic "lifecycle_rule" {
94 | for_each = var.lifecycle_rules
95 | iterator = rule
96 |
97 | content {
98 | id = lookup(rule.value, "id", null)
99 | prefix = lookup(rule.value, "prefix", null)
100 | tags = lookup(rule.value, "tags", null)
101 | abort_incomplete_multipart_upload_days = lookup(rule.value, "abort_incomplete_multipart_upload_days", null)
102 | enabled = rule.value.enabled
103 |
104 | dynamic "expiration" {
105 | for_each = length(keys(lookup(rule.value, "expiration", {}))) == 0 ? [] : [rule.value.expiration]
106 |
107 | content {
108 | date = lookup(expiration.value, "date", null)
109 | days = lookup(expiration.value, "days", null)
110 | expired_object_delete_marker = lookup(expiration.value, "expired_object_delete_marker", null)
111 | }
112 | }
113 |
114 | dynamic "transition" {
115 | for_each = lookup(rule.value, "transition", [])
116 |
117 | content {
118 | date = lookup(transition.value, "date", null)
119 | days = lookup(transition.value, "days", null)
120 | storage_class = transition.value.storage_class
121 | }
122 | }
123 |
124 | dynamic "noncurrent_version_expiration" {
125 | for_each = length(keys(lookup(rule.value, "noncurrent_version_expiration", {}))) == 0 ? [] : [rule.value.noncurrent_version_expiration]
126 | iterator = expiration
127 |
128 | content {
129 | days = lookup(expiration.value, "days", null)
130 | }
131 | }
132 |
133 | dynamic "noncurrent_version_transition" {
134 | for_each = lookup(rule.value, "noncurrent_version_transition", [])
135 | iterator = transition
136 |
137 | content {
138 | days = lookup(transition.value, "days", null)
139 | storage_class = transition.value.storage_class
140 | }
141 | }
142 | }
143 | }
144 |
145 | depends_on = [var.module_depends_on]
146 | }
147 |
148 | # ---------------------------------------------------------------------------------------------------------------------
149 | # Set default values for the S3 Bucket Policy
150 | # ---------------------------------------------------------------------------------------------------------------------
151 |
152 | locals {
153 | bucket_id = join("", aws_s3_bucket.bucket.*.id)
154 | bucket_arn = join("", aws_s3_bucket.bucket.*.arn)
155 |
156 | cross_account_enabled = length(var.cross_account_identifiers) > 0
157 |
158 | cross_account_bucket_actions_enabled = local.cross_account_enabled && length(var.cross_account_bucket_actions) > 0
159 | cross_account_object_actions_enabled = local.cross_account_enabled && length(var.cross_account_object_actions) > 0
160 | cross_account_object_actions_with_forced_acl_enabled = local.cross_account_enabled && length(var.cross_account_object_actions_with_forced_acl) > 0
161 |
162 | cross_account_actions_enabled = local.cross_account_bucket_actions_enabled || local.cross_account_object_actions_enabled || local.cross_account_object_actions_with_forced_acl_enabled
163 |
164 | origin_access_identities_enabled = var.module_enabled && (var.create_origin_access_identity || length(var.origin_access_identities) > 0)
165 |
166 | elb_log_delivery = var.elb_log_delivery != null ? var.elb_log_delivery : var.acl == "log-delivery-write" || length(var.elb_regions) > 0
167 |
168 | policy_enabled = var.module_enabled && (var.policy != null || local.cross_account_actions_enabled || local.origin_access_identities_enabled || local.elb_log_delivery)
169 | }
170 |
171 | # ---------------------------------------------------------------------------------------------------------------------
172 | # Create the S3 Bucket Public Access Block Policy
173 | # All public access should be blocked per default
174 | # ---------------------------------------------------------------------------------------------------------------------
175 |
176 | resource "aws_s3_bucket_public_access_block" "bucket" {
177 | count = var.module_enabled ? 1 : 0
178 |
179 | bucket = local.bucket_id
180 |
181 | block_public_acls = var.block_public_acls
182 | block_public_policy = var.block_public_policy
183 | ignore_public_acls = var.ignore_public_acls
184 | restrict_public_buckets = var.restrict_public_buckets
185 |
186 | depends_on = [var.module_depends_on]
187 | }
188 |
189 | # ---------------------------------------------------------------------------------------------------------------------
190 | # Attach a Policy to the S3 Bucket to control:
191 | # - Cross account bucket actions
192 | # - Cross account object actions
193 | # - Cloudfront origin access identity access
194 | # ---------------------------------------------------------------------------------------------------------------------
195 |
196 | resource "aws_s3_bucket_policy" "bucket" {
197 | count = local.policy_enabled ? 1 : 0
198 |
199 | bucket = local.bucket_id
200 |
201 | # remove whitespaces by decoding and encoding again to suppress terrform output whitespace cahnges
202 | policy = try(jsonencode(jsondecode(data.aws_iam_policy_document.bucket[0].json)), null)
203 |
204 | depends_on = [
205 | var.module_depends_on,
206 | aws_s3_bucket_public_access_block.bucket,
207 | ]
208 | }
209 |
210 | data "aws_iam_policy_document" "bucket" {
211 | count = local.policy_enabled ? 1 : 0
212 |
213 | source_json = var.policy
214 |
215 | dynamic "statement" {
216 | for_each = local.cross_account_bucket_actions_enabled ? [1] : []
217 |
218 | content {
219 | actions = var.cross_account_bucket_actions
220 | resources = [local.bucket_arn]
221 |
222 | principals {
223 | type = "AWS"
224 | identifiers = var.cross_account_identifiers
225 | }
226 | }
227 | }
228 |
229 | dynamic "statement" {
230 | for_each = local.cross_account_object_actions_enabled ? [1] : []
231 |
232 | content {
233 | actions = var.cross_account_object_actions
234 | resources = ["${local.bucket_arn}/*"]
235 |
236 | principals {
237 | type = "AWS"
238 | identifiers = var.cross_account_identifiers
239 | }
240 | }
241 | }
242 |
243 | dynamic "statement" {
244 | for_each = local.cross_account_object_actions_with_forced_acl_enabled ? [1] : []
245 |
246 | content {
247 | actions = var.cross_account_object_actions_with_forced_acl
248 | resources = ["${local.bucket_arn}/*"]
249 |
250 | principals {
251 | type = "AWS"
252 | identifiers = var.cross_account_identifiers
253 | }
254 |
255 | dynamic "condition" {
256 | for_each = length(var.cross_account_forced_acls) == 0 ? [] : [1]
257 |
258 | content {
259 | test = "StringEquals"
260 | variable = "s3:x-amz-acl"
261 | values = var.cross_account_forced_acls
262 | }
263 | }
264 | }
265 | }
266 |
267 | dynamic "statement" {
268 | for_each = local.origin_access_identities_enabled ? [{
269 | actions = ["s3:GetObject"]
270 | resources = ["${local.bucket_arn}/*"]
271 | }, {
272 | actions = ["s3:ListBucket"]
273 | resources = [local.bucket_arn]
274 |
275 | }] : []
276 | content {
277 | actions = statement.value.actions
278 | resources = statement.value.resources
279 |
280 | principals {
281 | type = "AWS"
282 | identifiers = local.oai_identities
283 | }
284 | }
285 | }
286 |
287 | dynamic "statement" {
288 | for_each = local.elb_log_delivery ? [1] : []
289 |
290 | content {
291 | actions = ["s3:PutObject"]
292 | resources = ["${local.bucket_arn}/*"]
293 |
294 | principals {
295 | type = "AWS"
296 | identifiers = sort(local.elb_accounts)
297 | }
298 | }
299 | }
300 | }
301 |
302 | locals {
303 | oai_identities = concat(
304 | var.origin_access_identities,
305 | aws_cloudfront_origin_access_identity.oai.*.iam_arn
306 | )
307 | }
308 |
309 | resource "aws_cloudfront_origin_access_identity" "oai" {
310 | count = var.module_enabled && var.create_origin_access_identity ? 1 : 0
311 |
312 | comment = format("%s S3 buckets Origin Access Identity to be accessed from CloudFront", local.bucket_id)
313 |
314 | depends_on = [var.module_depends_on]
315 | }
316 |
317 | locals {
318 | elb_accounts = length(var.elb_regions) > 0 ? data.aws_elb_service_account.elbs.*.arn : [data.aws_elb_service_account.elb.arn]
319 | }
320 |
321 | data "aws_elb_service_account" "elb" {}
322 |
323 | data "aws_elb_service_account" "elbs" {
324 | count = length(var.elb_regions)
325 |
326 | region = var.elb_regions[count.index]
327 | }
328 |
329 | # ---------------------------------------------------------------------------------------------------------------------
330 | # Create S3 Access Points
331 | # ---------------------------------------------------------------------------------------------------------------------
332 | locals {
333 | aps = { for idx, ap in var.access_points : ap.name => idx }
334 | }
335 |
336 | resource "aws_s3_access_point" "ap" {
337 | for_each = var.module_enabled ? local.aps : {}
338 |
339 | bucket = local.bucket_id
340 | name = var.access_points[each.value].name
341 |
342 | # optional values
343 | account_id = try(var.access_points[each.value].account_id, null)
344 | policy = try(var.access_points[each.value].policy, null)
345 |
346 | # optional but block all public access by default
347 | public_access_block_configuration {
348 | block_public_acls = try(var.access_points[each.value].block_public_acls, true)
349 | block_public_policy = try(var.access_points[each.value].block_public_policy, true)
350 | ignore_public_acls = try(var.access_points[each.value].ignore_public_acls, true)
351 | restrict_public_buckets = try(var.access_points[each.value].restrict_public_buckets, true)
352 | }
353 |
354 | dynamic "vpc_configuration" {
355 | for_each = try([var.access_points[each.value].vpc_id], [])
356 |
357 | content {
358 | vpc_id = vpc_configuration.each.value
359 | }
360 | }
361 |
362 | depends_on = [var.module_depends_on]
363 | }
364 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [
](https://mineiros.io/?ref=terraform-aws-s3-bucket)
2 |
3 | [](https://github.com/mineiros-io/terraform-aws-s3-bucket/actions)
4 | [](https://github.com/mineiros-io/terraform-aws-s3-bucket/releases)
5 | [](https://github.com/hashicorp/terraform/releases)
6 | [](https://github.com/terraform-providers/terraform-provider-aws/releases)
7 | [](https://mineiros.io/slack)
8 |
9 | # terraform-aws-s3-bucket
10 |
11 | A [Terraform] base module for creating a secure [AWS S3-Bucket].
12 |
13 | ***This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above
14 | and is compatible with the terraform AWS provider v3 as well as v2.0 and above.***
15 |
16 |
17 | - [Module Features](#module-features)
18 | - [Getting Started](#getting-started)
19 | - [Module Argument Reference](#module-argument-reference)
20 | - [Bucket Configuration](#bucket-configuration)
21 | - [Extended Resource Configuration](#extended-resource-configuration)
22 | - [S3 Access Points](#s3-access-points)
23 | - [S3 bucket-level Public Access Block Configuration](#s3-bucket-level-public-access-block-configuration)
24 | - [Cross Account Access Configuration](#cross-account-access-configuration)
25 | - [Cloudfront Origin Access Identity Access](#cloudfront-origin-access-identity-access)
26 | - [ELB Log Delivery](#elb-log-delivery)
27 | - [Module Configuration](#module-configuration)
28 | - [Module Outputs](#module-outputs)
29 | - [External Documentation](#external-documentation)
30 | - [AWS Documentation S3](#aws-documentation-s3)
31 | - [Terraform AWS Provider Documentation](#terraform-aws-provider-documentation)
32 | - [Module Versioning](#module-versioning)
33 | - [Backwards compatibility in `0.0.z` and `0.y.z` version](#backwards-compatibility-in-00z-and-0yz-version)
34 | - [About Mineiros](#about-mineiros)
35 | - [Reporting Issues](#reporting-issues)
36 | - [Contributing](#contributing)
37 | - [Makefile Targets](#makefile-targets)
38 | - [License](#license)
39 |
40 | ## Module Features
41 |
42 | In contrast to the plain `aws_s3_bucket` resource this module creates secure
43 | buckets by default. While all security features can be disabled as needed, best practices
44 | are pre-configured.
45 |
46 | In addition to security, easy cross-account access can be granted to the objects
47 | of the bucket enforcing `bucket-owner-full-control` ACL for objects created by other accounts.
48 |
49 | - **Default Security Settings**:
50 | Bucket public access blocking all set to `true` by default,
51 | Server-Side-Encryption (SSE) at rest `enabled` by default (AES256),
52 | Bucket ACL defaults to canned `private` ACL
53 |
54 | - **Standard S3 Features**:
55 | Server-Side-Encryption (SSE) enabled by default,
56 | Versioning,
57 | Bucket Logging,
58 | Lifecycle Rules,
59 | Request Payer,
60 | Cross-Origin Resource Sharing (CORS),
61 | Acceleration Status,
62 | Bucket Policy,
63 | Tags
64 |
65 | - **Extended S3 Features**:
66 | Bucket Public Access Blocking,
67 | S3 Access Points
68 |
69 | - **Additional Features**:
70 | Cross-Account access policy with forced `bucket-owner-full-control` ACL for direct access,
71 | Create Cloudfront Origin Access Identity (OAI) and grant read-only access,
72 | Grant read-only access to existing Cloudfront Origin Access Identity (OAI),
73 | Allow ELB log delivery
74 |
75 | - *Features not yet implemented*:
76 | Enforce Encryption via a policy that blocks unencrypted uploads,
77 | ACL policy grants (aws-provider >= 2.52.0),
78 | Amazon S3 Analytics (aws-provider >= 2.49.0),
79 | Replication Configuration,
80 | Website Configuration,
81 | S3 Object Locking,
82 | Bucket Notifications,
83 | Bucket Metrics,
84 | Bucket Inventory,
85 | Generate Cross-Account role for OAI enabled buckets if desired,
86 | Generate KMS key to encrypt objects at rest if desired
87 |
88 | ## Getting Started
89 |
90 | Most basic usage creating a random named secure AWS bucket.
91 |
92 | ```hcl
93 | module "bucket" {
94 | source = "mineiros-io/s3-bucket/aws"
95 | version = "~> 0.6.0"
96 | }
97 | ```
98 |
99 | Advanced usage as found in [examples/secure-s3-bucket/main.tf] setting all required and optional arguments to their default values.
100 |
101 | ## Module Argument Reference
102 |
103 | See [variables.tf] and [examples/] for details and use-cases.
104 |
105 | ### Bucket Configuration
106 |
107 | - [**`bucket`**](#var-bucket): *(Optional `string`)*
108 |
109 | The name of the bucket. If omitted, Terraform will assign a random, unique name. Forces new resource.
110 |
111 | - [**`bucket_prefix`**](#var-bucket_prefix): *(Optional `string`)*
112 |
113 | Creates a unique bucket name beginning with the specified prefix. Conflicts with `bucket`. Forces new resource.
114 |
115 | - [**`acl`**](#var-acl): *(Optional `string`)*
116 |
117 | The canned ACL to apply.
118 |
119 | Default is `"private"`.
120 |
121 | - [**`policy`**](#var-policy): *(Optional `string`)*
122 |
123 | A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy. For more information about building AWS IAM policy documents with Terraform, see the [AWS IAM Policy Document Guide].
124 |
125 | Default is `null`.
126 |
127 | - [**`tags`**](#var-tags): *(Optional `map(string)`)*
128 |
129 | A mapping of tags to assign to the bucket.
130 |
131 | Default is `{}`.
132 |
133 | - [**`force_destroy`**](#var-force_destroy): *(Optional `bool`)*
134 |
135 | A boolean that indicates all objects (including any locked objects) should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable.
136 |
137 | Default is `false`.
138 |
139 | - [**`acceleration_status`**](#var-acceleration_status): *(Optional `string`)*
140 |
141 | Sets the accelerate configuration of an existing bucket. Can be `Enabled` or `Suspended`.
142 |
143 | - [**`request_payer`**](#var-request_payer): *(Optional `string`)*
144 |
145 | Specifies who should bear the cost of Amazon S3 data transfer. Can be either `BucketOwner` or `Requester`.
146 | By default, the owner of the S3 bucket would incur the costs of any data transfer.
147 | See [Requester Pays Buckets developer guide] for more information.
148 |
149 | Default is `"BucketOwner"`.
150 |
151 | - [**`cors_rule`**](#var-cors_rule): *(Optional `object(cors)`)*
152 |
153 | Specifying settings for Cross-Origin Resource Sharing (CORS) (documented below).
154 |
155 | Default is `{}`.
156 |
157 | The `cors` object accepts the following attributes:
158 |
159 | - [**`allowed_headers`**](#attr-cors_rule-allowed_headers): *(Optional `list(string)`)*
160 |
161 | Specifies which headers are allowed.
162 |
163 | Default is `[]`.
164 |
165 | - [**`allowed_methods`**](#attr-cors_rule-allowed_methods): *(**Required** `list(string)`)*
166 |
167 | Specifies which methods are allowed. Can be `GET`, `PUT`, `POST`, `DELETE` or `HEAD`.
168 |
169 | - [**`allowed_origins`**](#attr-cors_rule-allowed_origins): *(**Required** `list(string)`)*
170 |
171 | Specifies which origins are allowed.
172 |
173 | - [**`expose_headers`**](#attr-cors_rule-expose_headers): *(Optional `list(string)`)*
174 |
175 | Specifies expose header in the response.
176 |
177 | Default is `[]`.
178 |
179 | - [**`max_age_seconds`**](#attr-cors_rule-max_age_seconds): *(Optional `number`)*
180 |
181 | Specifies time in seconds that browser can cache the response for a preflight request.
182 |
183 | - [**`versioning`**](#var-versioning): *(Optional `bool`)*
184 |
185 | Can also be of type `object`. When set to `true` versioning will be enabled. Specifies Versioning Configuration when passed as an object (documented below).
186 |
187 | Default is `false`.
188 |
189 | The object accepts the following attributes:
190 |
191 | - [**`enabled`**](#attr-versioning-enabled): *(Optional `bool`)*
192 |
193 | Once you version-enable a bucket, it can never return to an unversioned state.
194 | You can, however, suspend versioning on that bucket.
195 |
196 | - [**`mfa_delete`**](#attr-versioning-mfa_delete): *(Optional `bool`)*
197 |
198 | Enable MFA delete for either change: the versioning state of your bucket or
199 | permanently delete an object version.
200 |
201 | Default is `false`.
202 |
203 | - [**`logging`**](#var-logging): *(Optional `map(string)`)*
204 |
205 | Specifying a configuration for logging access logs (documented below).
206 |
207 | Default is `{}`.
208 |
209 | Each `` object in the map accepts the following attributes:
210 |
211 | - [**`target_bucket`**](#attr-logging-target_bucket): *(**Required** `string`)*
212 |
213 | The name of the bucket that will receive the log objects.
214 |
215 | - [**`target_prefix`**](#attr-logging-target_prefix): *(Optional `string`)*
216 |
217 | To specify a key prefix for log objects.
218 |
219 | - [**`apply_server_side_encryption_by_default`**](#var-apply_server_side_encryption_by_default): *(Optional `map(string)`)*
220 |
221 | Specifying the server side encryption to apply to objects at rest (documented below).
222 | Default is to use `AES256` encryption.
223 |
224 | Each `` object in the map accepts the following attributes:
225 |
226 | - [**`sse_algorithm`**](#attr-apply_server_side_encryption_by_default-sse_algorithm): *(Optional `string`)*
227 |
228 | The server-side encryption algorithm to use. Valid values are `AES256` and `aws:kms`. Default applies when `kms_master_key_id` is specified, else `AES256`
229 |
230 | Default is `"aws:kms"`.
231 |
232 | - [**`kms_master_key_id`**](#attr-apply_server_side_encryption_by_default-kms_master_key_id): *(Optional `string`)*
233 |
234 | The AWS KMS master key ID used for the SSE-KMS encryption. The default `aws/s3` AWS KMS master key is used if this element is absent while the sse_algorithm is `aws:kms`.
235 |
236 | Default is `"null"`.
237 |
238 | - [**`lifecycle_rules`**](#var-lifecycle_rules): *(Optional `list(lifecycle_rule)`)*
239 |
240 | Specifying various rules specifying object lifecycle management (documented below).
241 |
242 | Default is `[]`.
243 |
244 | Each `lifecycle_rule` object in the list accepts the following attributes:
245 |
246 | - [**`id`**](#attr-lifecycle_rules-id): *(Optional `string`)*
247 |
248 | Unique identifier for the rule.
249 |
250 | - [**`prefix`**](#attr-lifecycle_rules-prefix): *(Optional `string`)*
251 |
252 | Object key prefix identifying one or more objects to which the rule applies.
253 |
254 | - [**`tags`**](#attr-lifecycle_rules-tags): *(Optional `map(string)`)*
255 |
256 | Specifies object tags key and value.
257 |
258 | - [**`enabled`**](#attr-lifecycle_rules-enabled): *(**Required** `bool`)*
259 |
260 | Specifies lifecycle rule status.
261 |
262 | - [**`abort_incomplete_multipart_upload_days`**](#attr-lifecycle_rules-abort_incomplete_multipart_upload_days): *(Optional `number`)*
263 |
264 | Specifies the number of days after initiating a multipart upload when the multipart upload must be completed.
265 |
266 | - [**`expiration`**](#attr-lifecycle_rules-expiration): *(Optional `object(expiration)`)*
267 |
268 | Specifies a period in the object's expire (documented below).
269 |
270 | The `expiration` object accepts the following attributes:
271 |
272 | - [**`date`**](#attr-lifecycle_rules-expiration-date): *(Optional `string`)*
273 |
274 | Specifies the date after which you want the corresponding action to take effect.
275 |
276 | - [**`days`**](#attr-lifecycle_rules-expiration-days): *(Optional `string`)*
277 |
278 | Specifies the number of days after object creation when the specific rule action takes effect.
279 |
280 | - [**`expired_object_delete_marker`**](#attr-lifecycle_rules-expiration-expired_object_delete_marker): *(Optional `bool`)*
281 |
282 | On a versioned bucket (versioning-enabled or versioning-suspended bucket), you can add this element in the lifecycle configuration to direct Amazon S3 to delete expired object delete markers.
283 |
284 | - [**`transition`**](#attr-lifecycle_rules-transition): *(Optional `object(transition)`)*
285 |
286 | Specifies a period in the object's transitions (documented below).
287 |
288 | The `transition` object accepts the following attributes:
289 |
290 | - [**`date`**](#attr-lifecycle_rules-transition-date): *(Optional `string`)*
291 |
292 | Specifies the date after which you want the corresponding action to take effect.
293 |
294 | - [**`days`**](#attr-lifecycle_rules-transition-days): *(Optional `number`)*
295 |
296 | Specifies the number of days after object creation when the specific rule action takes effect.
297 |
298 | - [**`storage_class`**](#attr-lifecycle_rules-transition-storage_class): *(**Required** `string`)*
299 |
300 | Specifies the Amazon S3 storage class to which you want the object to transition.
301 | Can be `ONEZONE_IA`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER`, or `DEEP_ARCHIVE`.
302 |
303 | - [**`noncurrent_version_expiration`**](#attr-lifecycle_rules-noncurrent_version_expiration): *(Optional `object(noncurrent_version_expiration)`)*
304 |
305 | Specifies when noncurrent object versions expire (documented below).
306 |
307 | The `noncurrent_version_expiration` object accepts the following attributes:
308 |
309 | - [**`days`**](#attr-lifecycle_rules-noncurrent_version_expiration-days): *(**Required** `number`)*
310 |
311 | Specifies the number of days an object's noncurrent object versions expire.
312 |
313 | - [**`noncurrent_version_transition`**](#attr-lifecycle_rules-noncurrent_version_transition): *(Optional `object(noncurrent_version_transition)`)*
314 |
315 | Specifies when noncurrent object versions transitions (documented below).
316 | At least one of `expiration`, `transition`, `noncurrent_version_expiration`, `noncurrent_version_transition` must be specified.
317 |
318 | The `noncurrent_version_transition` object accepts the following attributes:
319 |
320 | - [**`days`**](#attr-lifecycle_rules-noncurrent_version_transition-days): *(**Required** `number`)*
321 |
322 | Specifies the number of days an object's noncurrent object versions expire.
323 |
324 | - [**`storage_class`**](#attr-lifecycle_rules-noncurrent_version_transition-storage_class): *(**Required** `string`)*
325 |
326 | Specifies the Amazon S3 storage class to which you want the noncurrent versions object to transition.
327 | Can be `ONEZONE_IA`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER`, or `DEEP_ARCHIVE`.
328 |
329 | ### Extended Resource Configuration
330 |
331 | #### S3 Access Points
332 |
333 | - [**`access_points`**](#var-access_points): *(Optional `list(access_point)`)*
334 |
335 | Amazon S3 Access Points simplify managing data access at scale for shared datasets in S3.
336 | Access points are named network endpoints that are attached to buckets that
337 | you can use to perform S3 object operations, such as `GetObject` and `PutObject`.
338 | Each access point has distinct permissions and network controls that S3 applies
339 | for any request that is made through that access point.
340 | Each access point enforces a customized access point policy that works in
341 | conjunction with the bucket policy that is attached to the underlying bucket.
342 | You can configure any access point to accept requests only from a
343 | virtual private cloud (VPC) to restrict Amazon S3 data access to a private network.
344 | You can also configure custom block public access settings for each access point.
345 |
346 | Default is `[]`.
347 |
348 | Each `access_point` object in the list accepts the following attributes:
349 |
350 | - [**`name`**](#attr-access_points-name): *(**Required** `string`)*
351 |
352 | The name you want to assign to this access point.
353 |
354 | - [**`account_id`**](#attr-access_points-account_id): *(Optional `string`)*
355 |
356 | The AWS account ID for the owner of the bucket for which you want to create an access point.
357 | Defaults to automatically determined account ID of the Terraform AWS provider.
358 |
359 | - [**`policy`**](#attr-access_points-policy): *(Optional `string`)*
360 |
361 | A valid JSON document that specifies the policy that you want to apply to this access point.
362 |
363 | - [**`vpc_id`**](#attr-access_points-vpc_id): *(Optional `string`)*
364 |
365 | If set, this access point will only allow connections from the specified VPC ID.
366 |
367 | - [**`block_public_acls`**](#attr-access_points-block_public_acls): *(Optional `bool`)*
368 |
369 | Whether Amazon S3 should block public ACLs for this bucket.
370 | Enabling this setting does not affect existing policies or ACLs.
371 |
372 | Default is `true`.
373 |
374 | - [**`block_public_policy`**](#attr-access_points-block_public_policy): *(Optional `bool`)*
375 |
376 | Whether Amazon S3 should block public bucket policies for this bucket.
377 | Enabling this setting does not affect the existing bucket policy.
378 | If `true`:
379 | - Reject calls to `PUT Bucket policy` if the specified bucket policy allows public access.
380 |
381 | Default is `true`.
382 |
383 | - [**`ignore_public_acls`**](#attr-access_points-ignore_public_acls): *(Optional `bool`)*
384 |
385 | Whether Amazon S3 should ignore public ACLs for this bucket.
386 | Enabling this setting does not affect the persistence of any existing ACLs and
387 | doesn't prevent new public ACLs from being set.
388 | If `true`:
389 | - Ignore public ACLs on this bucket and any objects that it contains.
390 |
391 | Default is `true`.
392 |
393 | - [**`restrict_public_buckets`**](#attr-access_points-restrict_public_buckets): *(Optional `bool`)*
394 |
395 | Whether Amazon S3 should restrict public bucket policies for this bucket.
396 | Enabling this setting does not affect the previously stored bucket policy,
397 | except that public and cross-account access within the public bucket policy,
398 | including non-public delegation to specific accounts, is blocked.
399 | If `true`:
400 | - Only the bucket owner and AWS Services can access this buckets if it has a public policy.
401 |
402 | Default is `true`.
403 |
404 | #### S3 bucket-level Public Access Block Configuration
405 |
406 | - [**`block_public_acls`**](#var-block_public_acls): *(Optional `bool`)*
407 |
408 | Whether Amazon S3 should block public ACLs for this bucket.
409 | Enabling this setting does not affect existing policies or ACLs.
410 | If `true`:
411 | - `PUT Bucket acl` and `PUT Object acl` calls will fail if the specified ACL allows public access.
412 | - `PUT Object` calls will fail if the request includes an object ACL.
413 |
414 | Default is `true`.
415 |
416 | - [**`block_public_policy`**](#var-block_public_policy): *(Optional `bool`)*
417 |
418 | Whether Amazon S3 should block public bucket policies for this bucket.
419 | Enabling this setting does not affect the existing bucket policy.
420 | If `true`:
421 | - Reject calls to `PUT Bucket policy` if the specified bucket policy allows public access.
422 |
423 | Default is `true`.
424 |
425 | - [**`ignore_public_acls`**](#var-ignore_public_acls): *(Optional `bool`)*
426 |
427 | Whether Amazon S3 should ignore public ACLs for this bucket.
428 | Enabling this setting does not affect the persistence of any existing ACLs and
429 | doesn't prevent new public ACLs from being set.
430 | If `true`:
431 | - Ignore public ACLs on this bucket and any objects that it contains.
432 |
433 | Default is `true`.
434 |
435 | - [**`restrict_public_buckets`**](#var-restrict_public_buckets): *(Optional `bool`)*
436 |
437 | Whether Amazon S3 should restrict public bucket policies for this bucket.
438 | Enabling this setting does not affect the previously stored bucket policy,
439 | except that public and cross-account access within the public bucket policy,
440 | including non-public delegation to specific accounts, is blocked.
441 | If `true`:
442 | - Only the bucket owner and AWS Services can access this buckets if it has a public policy.
443 |
444 | Default is `true`.
445 |
446 | #### Cross Account Access Configuration
447 |
448 | - [**`cross_account_identifiers`**](#var-cross_account_identifiers): *(Optional `list(string)`)*
449 |
450 | Specifies identifiers that should be granted cross account access to.
451 | If this list is empty Cross Account Access is not configured and all other
452 | options in this category are ignored.
453 |
454 | Default is `[]`.
455 |
456 | - [**`cross_account_bucket_actions`**](#var-cross_account_bucket_actions): *(Optional `list(string)`)*
457 |
458 | Specifies actions on the bucket to grant from cross account.
459 |
460 | Default is `["s3:ListBucket"]`.
461 |
462 | - [**`cross_account_object_actions`**](#var-cross_account_object_actions): *(Optional `list(string)`)*
463 |
464 | Specifies actions on bucket objects to grant from cross account.
465 |
466 | Default is `["s3:GetObject"]`.
467 |
468 | - [**`cross_account_object_actions_with_forced_acl`**](#var-cross_account_object_actions_with_forced_acl): *(Optional `list(string)`)*
469 |
470 | Specifies actions on bucket objects to grant only with foreced ACL from cross account.
471 |
472 | Default is `["s3:PutObject","s3:PutObjectAcl"]`.
473 |
474 | - [**`cross_account_forced_acls`**](#var-cross_account_forced_acls): *(Optional `list(string)`)*
475 |
476 | Specifies ACLs to force on new objects for cross account access.
477 |
478 | Default is `["bucket-owner-full-control"]`.
479 |
480 | #### Cloudfront Origin Access Identity Access
481 |
482 | - [**`create_origin_access_identity`**](#var-create_origin_access_identity): *(Optional `bool`)*
483 |
484 | Specifies whether to create and origin access identity and grant it access to read
485 | from the bucket. This can be used to grant a Cloudfront Distribution access to
486 | bucket objects when specifying this bucket as an origin.
487 | The Cloudfront Distribution must be in the same account.
488 | For cross account access create the OAI in the account of the cloudfront distribution and use
489 | `origin_acesss_identities` attribute to enable access.
490 | **Attention:** Objects shared that way need
491 | to be owned by the account the bucket belongs to and can not be owned by other accounts
492 | (e.g. when uploaded through cross-account-access).
493 |
494 | Default is `false`.
495 |
496 | - [**`origin_acesss_identities`**](#var-origin_acesss_identities): *(Optional `list(string)`)*
497 |
498 | Specify a list of Cloudfront OAIs to grant read-only access to.
499 | If in addition a new origin access identity is created via the `create_origin_access_identity`
500 | attribute, all identities will be granted access.
501 | **Attention:** Objects shared that way need
502 | to be owned by the account the bucket belongs to and can not be owned by other accounts
503 | (e.g. when uploaded through cross-account-access).
504 |
505 | Default is `[]`.
506 |
507 | #### ELB Log Delivery
508 |
509 | - [**`elb_log_delivery`**](#var-elb_log_delivery): *(Optional `bool`)*
510 |
511 | Allow delivery of logs from Elastic Loadbalancers (ELB).
512 |
513 | - [**`elb_regions`**](#var-elb_regions): *(Optional `list(string)`)*
514 |
515 | The names of the region whose AWS ELB account IDs are desired.
516 | Default is the region from the AWS provider configuration.
517 |
518 | Default is `[]`.
519 |
520 | ### Module Configuration
521 |
522 | - [**`module_enabled`**](#var-module_enabled): *(Optional `bool`)*
523 |
524 | Specifies whether resources in the module will be created.
525 |
526 | Default is `true`.
527 |
528 | - [**`module_tags`**](#var-module_tags): *(Optional `map(string)`)*
529 |
530 | A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be
531 | overwritten by resource-specific tags.
532 |
533 | Default is `{}`.
534 |
535 | - [**`module_depends_on`**](#var-module_depends_on): *(Optional `list(any)`)*
536 |
537 | A list of dependencies. Any object can be _assigned_ to this list to define a hidden external dependency.
538 |
539 | ## Module Outputs
540 |
541 | The following attributes are exported by the module:
542 |
543 | - [**`module_enabled`**](#output-module_enabled): *(`bool`)*
544 |
545 | Whether this module is enabled.
546 |
547 | - [**`bucket`**](#output-bucket): *(`object(bucket)`)*
548 |
549 | All bucket attributes as returned by the `aws_s3_bucket` resource
550 | containing all arguments as specified above and the other attributes as
551 | specified below.
552 |
553 | - [**`id`**](#output-id): *(`string`)*
554 |
555 | The name of the bucket.
556 |
557 | - [**`arn`**](#output-arn): *(`string`)*
558 |
559 | The ARN of the bucket. Will be of format `arn:aws:s3:::bucketname`.
560 |
561 | - [**`bucket_domain_name`**](#output-bucket_domain_name): *(`string`)*
562 |
563 | The bucket domain name. Will be of format `bucketname.s3.amazonaws.com`.
564 |
565 | - [**`bucket_regional_domain_name`**](#output-bucket_regional_domain_name): *(`string`)*
566 |
567 | The bucket region-specific domain name. The bucket domain name including
568 | the region name, please refer here for format. Note: The AWS CloudFront
569 | allows specifying S3 region-specific endpoint when creating S3 origin,
570 | it will prevent redirect issues from CloudFront to S3 Origin URL.
571 |
572 | - [**`hosted_zone_id`**](#output-hosted_zone_id): *(`string`)*
573 |
574 | The Route 53 Hosted Zone ID for this bucket's region.
575 |
576 | - [**`region`**](#output-region): *(`string`)*
577 |
578 | The AWS region this bucket resides in.
579 |
580 | - [**`bucket_policy`**](#output-bucket_policy): *(`object(bucket_policy)`)*
581 |
582 | All bucket policy object attributes as returned by the `s3_bucket_policy`
583 | resource.
584 |
585 | - [**`origin_access_identity`**](#output-origin_access_identity): *(`object(origin_access_identity)`)*
586 |
587 | All cloudfront origin access identity object attributes as returned by
588 | the `aws_cloudfront_origin_access_identity` resource.
589 |
590 | - [**`access_point`**](#output-access_point): *(`list(access_point)`)*
591 |
592 | A list of `aws_s3_access_point` objects keyed by the `name` attribute.
593 |
594 | ## External Documentation
595 |
596 | ### AWS Documentation S3
597 |
598 | - Access Points: https://docs.aws.amazon.com/AmazonS3/latest/dev/access-points.html
599 | - Default Encryption: https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html
600 | - Optimizing Performance: https://docs.aws.amazon.com/AmazonS3/latest/dev/optimizing-performance.html
601 | - Requester Pays Bucket: https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html
602 | - Security: https://docs.aws.amazon.com/AmazonS3/latest/dev/security.html
603 |
604 | ### Terraform AWS Provider Documentation
605 |
606 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
607 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_access_point
608 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy
609 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_object
610 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block
611 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_identity
612 |
613 | ## Module Versioning
614 |
615 | This Module follows the principles of [Semantic Versioning (SemVer)].
616 |
617 | Given a version number `MAJOR.MINOR.PATCH`, we increment the:
618 |
619 | 1. `MAJOR` version when we make incompatible changes,
620 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and
621 | 3. `PATCH` version when we make backwards compatible bug fixes.
622 |
623 | ### Backwards compatibility in `0.0.z` and `0.y.z` version
624 |
625 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development)
626 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release)
627 |
628 | ## About Mineiros
629 |
630 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany
631 | that solves development, automation and security challenges in cloud infrastructure.
632 |
633 | Our vision is to massively reduce time and overhead for teams to manage and
634 | deploy production-grade and secure cloud infrastructure.
635 |
636 | We offer commercial support for all of our modules and encourage you to reach out
637 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our
638 | [Community Slack channel][slack].
639 |
640 | ## Reporting Issues
641 |
642 | We use GitHub [Issues] to track community reported issues and missing features.
643 |
644 | ## Contributing
645 |
646 | Contributions are always encouraged and welcome! For the process of accepting changes, we use
647 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines].
648 |
649 | ## Makefile Targets
650 |
651 | This repository comes with a handy [Makefile].
652 | Run `make help` to see details on each available target.
653 |
654 | ## License
655 |
656 | [![license][badge-license]][apache20]
657 |
658 | This module is licensed under the Apache License Version 2.0, January 2004.
659 | Please see [LICENSE] for full details.
660 |
661 | Copyright © 2020-2022 [Mineiros GmbH][homepage]
662 |
663 |
664 |
665 |
666 | [homepage]: https://mineiros.io/?ref=terraform-aws-s3-bucket
667 | [hello@mineiros.io]: mailto:hello@mineiros.io
668 | [badge-build]: https://github.com/mineiros-io/terraform-aws-s3-bucket/workflows/CI/CD%20Pipeline/badge.svg
669 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-s3-bucket.svg?label=latest&sort=semver
670 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg
671 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform
672 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack
673 | [badge-tf-aws]: https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform
674 | [releases-aws-provider]: https://github.com/terraform-providers/terraform-provider-aws/releases
675 | [build-status]: https://github.com/mineiros-io/terraform-aws-s3-bucket/actions
676 | [releases-github]: https://github.com/mineiros-io/terraform-aws-s3-bucket/releases
677 | [releases-terraform]: https://github.com/hashicorp/terraform/releases
678 | [apache20]: https://opensource.org/licenses/Apache-2.0
679 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg
680 | [Terraform]: https://www.terraform.io
681 | [AWS S3-Bucket]: https://aws.amazon.com/s3/
682 | [Semantic Versioning (SemVer)]: https://semver.org/
683 | [AWS IAM Policy Document Guide]: https://learn.hashicorp.com/terraform/aws/iam-policy
684 | [Requester Pays Buckets developer guide]: https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html
685 | [examples/secure-s3-bucket/main.tf]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/examples/secure-s3-bucket/main.tf
686 | [variables.tf]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/variables.tf
687 | [examples/]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/examples
688 | [Issues]: https://github.com/mineiros-io/terraform-aws-s3-bucket/issues
689 | [LICENSE]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/LICENSE
690 | [Makefile]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/Makefile
691 | [Pull Requests]: https://github.com/mineiros-io/terraform-aws-s3-bucket/pulls
692 | [Contribution Guidelines]: https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/CONTRIBUTING.md
693 |
--------------------------------------------------------------------------------
/README.tfdoc.hcl:
--------------------------------------------------------------------------------
1 | header {
2 | image = "https://raw.githubusercontent.com/mineiros-io/brand/3bffd30e8bdbbde32c143e2650b2faa55f1df3ea/mineiros-primary-logo.svg"
3 | url = "https://mineiros.io/?ref=terraform-aws-s3-bucket"
4 |
5 | badge "build" {
6 | image = "https://github.com/mineiros-io/terraform-aws-s3-bucket/workflows/CI/CD%20Pipeline/badge.svg"
7 | url = "https://github.com/mineiros-io/terraform-aws-s3-bucket/actions"
8 | text = "Build Status"
9 | }
10 |
11 | badge "semver" {
12 | image = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-s3-bucket.svg?label=latest&sort=semver"
13 | url = "https://github.com/mineiros-io/terraform-aws-s3-bucket/releases"
14 | text = "GitHub tag (latest SemVer)"
15 | }
16 |
17 | badge "terraform" {
18 | image = "https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform"
19 | url = "https://github.com/hashicorp/terraform/releases"
20 | text = "Terraform Version"
21 | }
22 |
23 | badge "tf-aws-provider" {
24 | image = "https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform"
25 | url = "https://github.com/terraform-providers/terraform-provider-aws/releases"
26 | text = "AWS Provider Version"
27 | }
28 |
29 | badge "slack" {
30 | image = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack"
31 | url = "https://mineiros.io/slack"
32 | text = "Join Slack"
33 | }
34 | }
35 |
36 | section {
37 | title = "terraform-aws-s3-bucket"
38 | toc = true
39 | content = <<-END
40 | A [Terraform] base module for creating a secure [AWS S3-Bucket].
41 |
42 | ***This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above
43 | and is compatible with the terraform AWS provider v3 as well as v2.0 and above.***
44 | END
45 |
46 | section {
47 | title = "Module Features"
48 | content = <<-END
49 | In contrast to the plain `aws_s3_bucket` resource this module creates secure
50 | buckets by default. While all security features can be disabled as needed, best practices
51 | are pre-configured.
52 |
53 | In addition to security, easy cross-account access can be granted to the objects
54 | of the bucket enforcing `bucket-owner-full-control` ACL for objects created by other accounts.
55 |
56 | - **Default Security Settings**:
57 | Bucket public access blocking all set to `true` by default,
58 | Server-Side-Encryption (SSE) at rest `enabled` by default (AES256),
59 | Bucket ACL defaults to canned `private` ACL
60 |
61 | - **Standard S3 Features**:
62 | Server-Side-Encryption (SSE) enabled by default,
63 | Versioning,
64 | Bucket Logging,
65 | Lifecycle Rules,
66 | Request Payer,
67 | Cross-Origin Resource Sharing (CORS),
68 | Acceleration Status,
69 | Bucket Policy,
70 | Tags
71 |
72 | - **Extended S3 Features**:
73 | Bucket Public Access Blocking,
74 | S3 Access Points
75 |
76 | - **Additional Features**:
77 | Cross-Account access policy with forced `bucket-owner-full-control` ACL for direct access,
78 | Create Cloudfront Origin Access Identity (OAI) and grant read-only access,
79 | Grant read-only access to existing Cloudfront Origin Access Identity (OAI),
80 | Allow ELB log delivery
81 |
82 | - *Features not yet implemented*:
83 | Enforce Encryption via a policy that blocks unencrypted uploads,
84 | ACL policy grants (aws-provider >= 2.52.0),
85 | Amazon S3 Analytics (aws-provider >= 2.49.0),
86 | Replication Configuration,
87 | Website Configuration,
88 | S3 Object Locking,
89 | Bucket Notifications,
90 | Bucket Metrics,
91 | Bucket Inventory,
92 | Generate Cross-Account role for OAI enabled buckets if desired,
93 | Generate KMS key to encrypt objects at rest if desired
94 | END
95 | }
96 |
97 | section {
98 | title = "Getting Started"
99 | content = <<-END
100 | Most basic usage creating a random named secure AWS bucket.
101 |
102 | ```hcl
103 | module "bucket" {
104 | source = "mineiros-io/s3-bucket/aws"
105 | version = "~> 0.6.0"
106 | }
107 | ```
108 |
109 | Advanced usage as found in [examples/secure-s3-bucket/main.tf] setting all required and optional arguments to their default values.
110 | END
111 | }
112 |
113 | section {
114 | title = "Module Argument Reference"
115 | content = <<-END
116 | See [variables.tf] and [examples/] for details and use-cases.
117 | END
118 |
119 | section {
120 | title = "Bucket Configuration"
121 |
122 | variable "bucket" {
123 | type = string
124 | description = <<-END
125 | The name of the bucket. If omitted, Terraform will assign a random, unique name. Forces new resource.
126 | END
127 | }
128 |
129 | variable "bucket_prefix" {
130 | type = string
131 | description = <<-END
132 | Creates a unique bucket name beginning with the specified prefix. Conflicts with `bucket`. Forces new resource.
133 | END
134 | }
135 |
136 | variable "acl" {
137 | type = string
138 | default = "private"
139 | description = <<-END
140 | The canned ACL to apply.
141 | END
142 | }
143 |
144 | variable "policy" {
145 | type = string
146 | default = null
147 | description = <<-END
148 | A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy. For more information about building AWS IAM policy documents with Terraform, see the [AWS IAM Policy Document Guide].
149 | END
150 | }
151 |
152 | variable "tags" {
153 | type = map(string)
154 | default = {}
155 | description = <<-END
156 | A mapping of tags to assign to the bucket.
157 | END
158 | }
159 |
160 | variable "force_destroy" {
161 | type = bool
162 | default = false
163 | description = <<-END
164 | A boolean that indicates all objects (including any locked objects) should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable.
165 | END
166 | }
167 |
168 | variable "acceleration_status" {
169 | type = string
170 | description = <<-END
171 | Sets the accelerate configuration of an existing bucket. Can be `Enabled` or `Suspended`.
172 | END
173 | }
174 |
175 | variable "request_payer" {
176 | type = string
177 | default = "BucketOwner"
178 | description = <<-END
179 | Specifies who should bear the cost of Amazon S3 data transfer. Can be either `BucketOwner` or `Requester`.
180 | By default, the owner of the S3 bucket would incur the costs of any data transfer.
181 | See [Requester Pays Buckets developer guide] for more information.
182 | END
183 | }
184 |
185 | variable "cors_rule" {
186 | type = object(cors)
187 | default = {}
188 | description = <<-END
189 | Specifying settings for Cross-Origin Resource Sharing (CORS) (documented below).
190 | END
191 |
192 | attribute "allowed_headers" {
193 | type = list(string)
194 | default = []
195 | description = <<-END
196 | Specifies which headers are allowed.
197 | END
198 | }
199 |
200 | attribute "allowed_methods" {
201 | required = true
202 | type = list(string)
203 | description = <<-END
204 | Specifies which methods are allowed. Can be `GET`, `PUT`, `POST`, `DELETE` or `HEAD`.
205 | END
206 | }
207 |
208 | attribute "allowed_origins" {
209 | required = true
210 | type = list(string)
211 | description = <<-END
212 | Specifies which origins are allowed.
213 | END
214 | }
215 |
216 | attribute "expose_headers" {
217 | type = list(string)
218 | default = []
219 | description = <<-END
220 | Specifies expose header in the response.
221 | END
222 | }
223 |
224 | attribute "max_age_seconds" {
225 | type = number
226 | description = <<-END
227 | Specifies time in seconds that browser can cache the response for a preflight request.
228 | END
229 | }
230 | }
231 |
232 | variable "versioning" {
233 | type = bool
234 | default = false
235 | description = <<-END
236 | Can also be of type `object`. When set to `true` versioning will be enabled. Specifies Versioning Configuration when passed as an object (documented below).
237 | END
238 |
239 | attribute "enabled" {
240 | type = bool
241 | description = <<-END
242 | Once you version-enable a bucket, it can never return to an unversioned state.
243 | You can, however, suspend versioning on that bucket.
244 | END
245 | }
246 |
247 | attribute "mfa_delete" {
248 | type = bool
249 | default = false
250 | description = <<-END
251 | Enable MFA delete for either change: the versioning state of your bucket or
252 | permanently delete an object version.
253 | END
254 | }
255 | }
256 |
257 | variable "logging" {
258 | type = map(string)
259 | default = {}
260 | description = <<-END
261 | Specifying a configuration for logging access logs (documented below).
262 | END
263 |
264 | attribute "target_bucket" {
265 | required = true
266 | type = string
267 | description = <<-END
268 | The name of the bucket that will receive the log objects.
269 | END
270 | }
271 |
272 | attribute "target_prefix" {
273 | type = string
274 | description = <<-END
275 | To specify a key prefix for log objects.
276 | END
277 | }
278 | }
279 |
280 | variable "apply_server_side_encryption_by_default" {
281 | type = map(string)
282 | description = <<-END
283 | Specifying the server side encryption to apply to objects at rest (documented below).
284 | Default is to use `AES256` encryption.
285 | END
286 |
287 | attribute "sse_algorithm" {
288 | type = string
289 | default = "aws:kms"
290 | description = <<-END
291 | The server-side encryption algorithm to use. Valid values are `AES256` and `aws:kms`. Default applies when `kms_master_key_id` is specified, else `AES256`
292 | END
293 | }
294 |
295 | attribute "kms_master_key_id" {
296 | type = string
297 | default = "null"
298 | description = <<-END
299 | The AWS KMS master key ID used for the SSE-KMS encryption. The default `aws/s3` AWS KMS master key is used if this element is absent while the sse_algorithm is `aws:kms`.
300 | END
301 | }
302 | }
303 |
304 | variable "lifecycle_rules" {
305 | type = list(lifecycle_rule)
306 | default = []
307 | description = <<-END
308 | Specifying various rules specifying object lifecycle management (documented below).
309 | END
310 |
311 | attribute "id" {
312 | type = string
313 | description = <<-END
314 | Unique identifier for the rule.
315 | END
316 | }
317 |
318 | attribute "prefix" {
319 | type = string
320 | description = <<-END
321 | Object key prefix identifying one or more objects to which the rule applies.
322 | END
323 | }
324 |
325 | attribute "tags" {
326 | type = map(string)
327 | description = <<-END
328 | Specifies object tags key and value.
329 | END
330 | }
331 |
332 | attribute "enabled" {
333 | required = true
334 | type = bool
335 | description = <<-END
336 | Specifies lifecycle rule status.
337 | END
338 | }
339 |
340 | attribute "abort_incomplete_multipart_upload_days" {
341 | type = number
342 | description = <<-END
343 | Specifies the number of days after initiating a multipart upload when the multipart upload must be completed.
344 | END
345 | }
346 |
347 | attribute "expiration" {
348 | type = object(expiration)
349 | description = <<-END
350 | Specifies a period in the object's expire (documented below).
351 | END
352 |
353 | attribute "date" {
354 | type = string
355 | description = <<-END
356 | Specifies the date after which you want the corresponding action to take effect.
357 | END
358 | }
359 |
360 | attribute "days" {
361 | type = string
362 | description = <<-END
363 | Specifies the number of days after object creation when the specific rule action takes effect.
364 | END
365 | }
366 |
367 | attribute "expired_object_delete_marker" {
368 | type = bool
369 | description = <<-END
370 | On a versioned bucket (versioning-enabled or versioning-suspended bucket), you can add this element in the lifecycle configuration to direct Amazon S3 to delete expired object delete markers.
371 | END
372 | }
373 | }
374 |
375 | attribute "transition" {
376 | type = object(transition)
377 | description = <<-END
378 | Specifies a period in the object's transitions (documented below).
379 | END
380 |
381 | attribute "date" {
382 | type = string
383 | description = <<-END
384 | Specifies the date after which you want the corresponding action to take effect.
385 | END
386 | }
387 |
388 | attribute "days" {
389 | type = number
390 | description = <<-END
391 | Specifies the number of days after object creation when the specific rule action takes effect.
392 | END
393 | }
394 |
395 | attribute "storage_class" {
396 | required = true
397 | type = string
398 | description = <<-END
399 | Specifies the Amazon S3 storage class to which you want the object to transition.
400 | Can be `ONEZONE_IA`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER`, or `DEEP_ARCHIVE`.
401 | END
402 | }
403 | }
404 |
405 | attribute "noncurrent_version_expiration" {
406 | type = object(noncurrent_version_expiration)
407 | description = <<-END
408 | Specifies when noncurrent object versions expire (documented below).
409 | END
410 |
411 | attribute "days" {
412 | required = true
413 | type = number
414 | description = <<-END
415 | Specifies the number of days an object's noncurrent object versions expire.
416 | END
417 | }
418 | }
419 |
420 | attribute "noncurrent_version_transition" {
421 | type = object(noncurrent_version_transition)
422 | description = <<-END
423 | Specifies when noncurrent object versions transitions (documented below).
424 | At least one of `expiration`, `transition`, `noncurrent_version_expiration`, `noncurrent_version_transition` must be specified.
425 | END
426 |
427 | attribute "days" {
428 | required = true
429 | type = number
430 | description = <<-END
431 | Specifies the number of days an object's noncurrent object versions expire.
432 | END
433 | }
434 |
435 | attribute "storage_class" {
436 | required = true
437 | type = string
438 | description = <<-END
439 | Specifies the Amazon S3 storage class to which you want the noncurrent versions object to transition.
440 | Can be `ONEZONE_IA`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER`, or `DEEP_ARCHIVE`.
441 | END
442 | }
443 | }
444 | }
445 | }
446 |
447 | section {
448 | title = "Extended Resource Configuration"
449 |
450 | section {
451 | title = "S3 Access Points"
452 |
453 | variable "access_points" {
454 | type = list(access_point)
455 | default = []
456 | description = <<-END
457 | Amazon S3 Access Points simplify managing data access at scale for shared datasets in S3.
458 | Access points are named network endpoints that are attached to buckets that
459 | you can use to perform S3 object operations, such as `GetObject` and `PutObject`.
460 | Each access point has distinct permissions and network controls that S3 applies
461 | for any request that is made through that access point.
462 | Each access point enforces a customized access point policy that works in
463 | conjunction with the bucket policy that is attached to the underlying bucket.
464 | You can configure any access point to accept requests only from a
465 | virtual private cloud (VPC) to restrict Amazon S3 data access to a private network.
466 | You can also configure custom block public access settings for each access point.
467 | END
468 |
469 | attribute "name" {
470 | required = true
471 | type = string
472 | description = <<-END
473 | The name you want to assign to this access point.
474 | END
475 | }
476 |
477 | attribute "account_id" {
478 | type = string
479 | description = <<-END
480 | The AWS account ID for the owner of the bucket for which you want to create an access point.
481 | Defaults to automatically determined account ID of the Terraform AWS provider.
482 | END
483 | }
484 |
485 | attribute "policy" {
486 | type = string
487 | description = <<-END
488 | A valid JSON document that specifies the policy that you want to apply to this access point.
489 | END
490 | }
491 |
492 | attribute "vpc_id" {
493 | type = string
494 | description = <<-END
495 | If set, this access point will only allow connections from the specified VPC ID.
496 | END
497 | }
498 |
499 | attribute "block_public_acls" {
500 | type = bool
501 | default = true
502 | description = <<-END
503 | Whether Amazon S3 should block public ACLs for this bucket.
504 | Enabling this setting does not affect existing policies or ACLs.
505 | END
506 | }
507 |
508 | attribute "block_public_policy" {
509 | type = bool
510 | default = true
511 | description = <<-END
512 | Whether Amazon S3 should block public bucket policies for this bucket.
513 | Enabling this setting does not affect the existing bucket policy.
514 | If `true`:
515 | - Reject calls to `PUT Bucket policy` if the specified bucket policy allows public access.
516 | END
517 | }
518 |
519 | attribute "ignore_public_acls" {
520 | type = bool
521 | default = true
522 | description = <<-END
523 | Whether Amazon S3 should ignore public ACLs for this bucket.
524 | Enabling this setting does not affect the persistence of any existing ACLs and
525 | doesn't prevent new public ACLs from being set.
526 | If `true`:
527 | - Ignore public ACLs on this bucket and any objects that it contains.
528 | END
529 | }
530 |
531 | attribute "restrict_public_buckets" {
532 | type = bool
533 | default = true
534 | description = <<-END
535 | Whether Amazon S3 should restrict public bucket policies for this bucket.
536 | Enabling this setting does not affect the previously stored bucket policy,
537 | except that public and cross-account access within the public bucket policy,
538 | including non-public delegation to specific accounts, is blocked.
539 | If `true`:
540 | - Only the bucket owner and AWS Services can access this buckets if it has a public policy.
541 | END
542 | }
543 | }
544 | }
545 |
546 | section {
547 | title = "S3 bucket-level Public Access Block Configuration"
548 |
549 | variable "block_public_acls" {
550 | type = bool
551 | default = true
552 | description = <<-END
553 | Whether Amazon S3 should block public ACLs for this bucket.
554 | Enabling this setting does not affect existing policies or ACLs.
555 | If `true`:
556 | - `PUT Bucket acl` and `PUT Object acl` calls will fail if the specified ACL allows public access.
557 | - `PUT Object` calls will fail if the request includes an object ACL.
558 | END
559 | }
560 |
561 | variable "block_public_policy" {
562 | type = bool
563 | default = true
564 | description = <<-END
565 | Whether Amazon S3 should block public bucket policies for this bucket.
566 | Enabling this setting does not affect the existing bucket policy.
567 | If `true`:
568 | - Reject calls to `PUT Bucket policy` if the specified bucket policy allows public access.
569 | END
570 | }
571 |
572 | variable "ignore_public_acls" {
573 | type = bool
574 | default = true
575 | description = <<-END
576 | Whether Amazon S3 should ignore public ACLs for this bucket.
577 | Enabling this setting does not affect the persistence of any existing ACLs and
578 | doesn't prevent new public ACLs from being set.
579 | If `true`:
580 | - Ignore public ACLs on this bucket and any objects that it contains.
581 | END
582 | }
583 |
584 | variable "restrict_public_buckets" {
585 | type = bool
586 | default = true
587 | description = <<-END
588 | Whether Amazon S3 should restrict public bucket policies for this bucket.
589 | Enabling this setting does not affect the previously stored bucket policy,
590 | except that public and cross-account access within the public bucket policy,
591 | including non-public delegation to specific accounts, is blocked.
592 | If `true`:
593 | - Only the bucket owner and AWS Services can access this buckets if it has a public policy.
594 | END
595 | }
596 | }
597 |
598 | section {
599 | title = "Cross Account Access Configuration"
600 |
601 | variable "cross_account_identifiers" {
602 | type = list(string)
603 | default = []
604 | description = <<-END
605 | Specifies identifiers that should be granted cross account access to.
606 | If this list is empty Cross Account Access is not configured and all other
607 | options in this category are ignored.
608 | END
609 | }
610 |
611 | variable "cross_account_bucket_actions" {
612 | type = list(string)
613 | default = ["s3:ListBucket"]
614 | description = <<-END
615 | Specifies actions on the bucket to grant from cross account.
616 | END
617 | }
618 |
619 | variable "cross_account_object_actions" {
620 | type = list(string)
621 | default = ["s3:GetObject"]
622 | description = <<-END
623 | Specifies actions on bucket objects to grant from cross account.
624 | END
625 | }
626 |
627 | variable "cross_account_object_actions_with_forced_acl" {
628 | type = list(string)
629 | default = ["s3:PutObject", "s3:PutObjectAcl"]
630 | description = <<-END
631 | Specifies actions on bucket objects to grant only with foreced ACL from cross account.
632 | END
633 | }
634 |
635 | variable "cross_account_forced_acls" {
636 | type = list(string)
637 | default = ["bucket-owner-full-control"]
638 | description = <<-END
639 | Specifies ACLs to force on new objects for cross account access.
640 | END
641 | }
642 | }
643 |
644 | section {
645 | title = "Cloudfront Origin Access Identity Access"
646 |
647 | variable "create_origin_access_identity" {
648 | type = bool
649 | default = false
650 | description = <<-END
651 | Specifies whether to create and origin access identity and grant it access to read
652 | from the bucket. This can be used to grant a Cloudfront Distribution access to
653 | bucket objects when specifying this bucket as an origin.
654 | The Cloudfront Distribution must be in the same account.
655 | For cross account access create the OAI in the account of the cloudfront distribution and use
656 | `origin_acesss_identities` attribute to enable access.
657 | **Attention:** Objects shared that way need
658 | to be owned by the account the bucket belongs to and can not be owned by other accounts
659 | (e.g. when uploaded through cross-account-access).
660 | END
661 | }
662 |
663 | variable "origin_acesss_identities" {
664 | type = list(string)
665 | default = []
666 | description = <<-END
667 | Specify a list of Cloudfront OAIs to grant read-only access to.
668 | If in addition a new origin access identity is created via the `create_origin_access_identity`
669 | attribute, all identities will be granted access.
670 | **Attention:** Objects shared that way need
671 | to be owned by the account the bucket belongs to and can not be owned by other accounts
672 | (e.g. when uploaded through cross-account-access).
673 | END
674 | }
675 | }
676 |
677 | section {
678 | title = "ELB Log Delivery"
679 |
680 | variable "elb_log_delivery" {
681 | type = bool
682 | description = <<-END
683 | Allow delivery of logs from Elastic Loadbalancers (ELB).
684 | END
685 | }
686 |
687 | variable "elb_regions" {
688 | type = list(string)
689 | default = []
690 | description = <<-END
691 | The names of the region whose AWS ELB account IDs are desired.
692 | Default is the region from the AWS provider configuration.
693 | END
694 | }
695 | }
696 | }
697 |
698 | section {
699 | title = "Module Configuration"
700 |
701 | variable "module_enabled" {
702 | type = bool
703 | default = true
704 | description = <<-END
705 | Specifies whether resources in the module will be created.
706 | END
707 | }
708 |
709 | variable "module_tags" {
710 | type = map(string)
711 | default = {}
712 | description = <<-END
713 | A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be
714 | overwritten by resource-specific tags.
715 | END
716 | }
717 |
718 | variable "module_depends_on" {
719 | type = list(any)
720 | description = <<-END
721 | A list of dependencies. Any object can be _assigned_ to this list to define a hidden external dependency.
722 | END
723 | }
724 | }
725 |
726 | }
727 |
728 | section {
729 | title = "Module Outputs"
730 | content = <<-END
731 | The following attributes are exported by the module:
732 | END
733 |
734 | output "module_enabled" {
735 | type = bool
736 | description = <<-END
737 | Whether this module is enabled.
738 | END
739 | }
740 |
741 | output "bucket" {
742 | type = object(bucket)
743 | description = <<-END
744 | All bucket attributes as returned by the `aws_s3_bucket` resource
745 | containing all arguments as specified above and the other attributes as
746 | specified below.
747 | END
748 | }
749 |
750 | output "id" {
751 | type = string
752 | description = <<-END
753 | The name of the bucket.
754 | END
755 | }
756 |
757 | output "arn" {
758 | type = string
759 | description = <<-END
760 | The ARN of the bucket. Will be of format `arn:aws:s3:::bucketname`.
761 | END
762 | }
763 |
764 | output "bucket_domain_name" {
765 | type = string
766 | description = <<-END
767 | The bucket domain name. Will be of format `bucketname.s3.amazonaws.com`.
768 | END
769 | }
770 |
771 | output "bucket_regional_domain_name" {
772 | type = string
773 | description = <<-END
774 | The bucket region-specific domain name. The bucket domain name including
775 | the region name, please refer here for format. Note: The AWS CloudFront
776 | allows specifying S3 region-specific endpoint when creating S3 origin,
777 | it will prevent redirect issues from CloudFront to S3 Origin URL.
778 | END
779 | }
780 |
781 | output "hosted_zone_id" {
782 | type = string
783 | description = <<-END
784 | The Route 53 Hosted Zone ID for this bucket's region.
785 | END
786 | }
787 |
788 | output "region" {
789 | type = string
790 | description = <<-END
791 | The AWS region this bucket resides in.
792 | END
793 | }
794 |
795 | output "bucket_policy" {
796 | type = object(bucket_policy)
797 | description = <<-END
798 | All bucket policy object attributes as returned by the `s3_bucket_policy`
799 | resource.
800 | END
801 | }
802 |
803 | output "origin_access_identity" {
804 | type = object(origin_access_identity)
805 | description = <<-END
806 | All cloudfront origin access identity object attributes as returned by
807 | the `aws_cloudfront_origin_access_identity` resource.
808 | END
809 | }
810 |
811 | output "access_point" {
812 | type = list(access_point)
813 | description = <<-END
814 | A list of `aws_s3_access_point` objects keyed by the `name` attribute.
815 | END
816 | }
817 | }
818 |
819 | section {
820 | title = "External Documentation"
821 |
822 | section {
823 | title = "AWS Documentation S3"
824 | content = <<-END
825 | - Access Points: https://docs.aws.amazon.com/AmazonS3/latest/dev/access-points.html
826 | - Default Encryption: https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html
827 | - Optimizing Performance: https://docs.aws.amazon.com/AmazonS3/latest/dev/optimizing-performance.html
828 | - Requester Pays Bucket: https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html
829 | - Security: https://docs.aws.amazon.com/AmazonS3/latest/dev/security.html
830 | END
831 | }
832 |
833 | section {
834 | title = "Terraform AWS Provider Documentation"
835 | content = <<-END
836 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
837 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_access_point
838 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy
839 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_object
840 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block
841 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_identity
842 | END
843 | }
844 | }
845 |
846 | section {
847 | title = "Module Versioning"
848 | content = <<-END
849 | This Module follows the principles of [Semantic Versioning (SemVer)].
850 |
851 | Given a version number `MAJOR.MINOR.PATCH`, we increment the:
852 |
853 | 1. `MAJOR` version when we make incompatible changes,
854 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and
855 | 3. `PATCH` version when we make backwards compatible bug fixes.
856 | END
857 |
858 | section {
859 | title = "Backwards compatibility in `0.0.z` and `0.y.z` version"
860 | content = <<-END
861 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development)
862 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release)
863 | END
864 | }
865 | }
866 |
867 | section {
868 | title = "About Mineiros"
869 | content = <<-END
870 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany
871 | that solves development, automation and security challenges in cloud infrastructure.
872 |
873 | Our vision is to massively reduce time and overhead for teams to manage and
874 | deploy production-grade and secure cloud infrastructure.
875 |
876 | We offer commercial support for all of our modules and encourage you to reach out
877 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our
878 | [Community Slack channel][slack].
879 | END
880 | }
881 |
882 | section {
883 | title = "Reporting Issues"
884 | content = <<-END
885 | We use GitHub [Issues] to track community reported issues and missing features.
886 | END
887 | }
888 |
889 | section {
890 | title = "Contributing"
891 | content = <<-END
892 | Contributions are always encouraged and welcome! For the process of accepting changes, we use
893 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines].
894 | END
895 | }
896 |
897 | section {
898 | title = "Makefile Targets"
899 | content = <<-END
900 | This repository comes with a handy [Makefile].
901 | Run `make help` to see details on each available target.
902 | END
903 | }
904 |
905 | section {
906 | title = "License"
907 | content = <<-END
908 | [![license][badge-license]][apache20]
909 |
910 | This module is licensed under the Apache License Version 2.0, January 2004.
911 | Please see [LICENSE] for full details.
912 |
913 | Copyright © 2020-2022 [Mineiros GmbH][homepage]
914 | END
915 | }
916 | }
917 |
918 | references {
919 | ref "homepage" {
920 | value = "https://mineiros.io/?ref=terraform-aws-s3-bucket"
921 | }
922 | ref "hello@mineiros.io" {
923 | value = "mailto:hello@mineiros.io"
924 | }
925 | ref "badge-build" {
926 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/workflows/CI/CD%20Pipeline/badge.svg"
927 | }
928 | ref "badge-semver" {
929 | value = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-s3-bucket.svg?label=latest&sort=semver"
930 | }
931 | ref "badge-license" {
932 | value = "https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg"
933 | }
934 | ref "badge-terraform" {
935 | value = "https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform"
936 | }
937 | ref "badge-slack" {
938 | value = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack"
939 | }
940 | ref "badge-tf-aws" {
941 | value = "https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform"
942 | }
943 | ref "releases-aws-provider" {
944 | value = "https://github.com/terraform-providers/terraform-provider-aws/releases"
945 | }
946 | ref "build-status" {
947 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/actions"
948 | }
949 | ref "releases-github" {
950 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/releases"
951 | }
952 | ref "releases-terraform" {
953 | value = "https://github.com/hashicorp/terraform/releases"
954 | }
955 | ref "apache20" {
956 | value = "https://opensource.org/licenses/Apache-2.0"
957 | }
958 | ref "slack" {
959 | value = "https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg"
960 | }
961 | ref "Terraform" {
962 | value = "https://www.terraform.io"
963 | }
964 | ref "AWS S3-Bucket" {
965 | value = "https://aws.amazon.com/s3/"
966 | }
967 | ref "Semantic Versioning (SemVer)" {
968 | value = "https://semver.org/"
969 | }
970 | ref "AWS IAM Policy Document Guide" {
971 | value = "https://learn.hashicorp.com/terraform/aws/iam-policy"
972 | }
973 | ref "Requester Pays Buckets developer guide" {
974 | value = "https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html"
975 | }
976 | ref "examples/secure-s3-bucket/main.tf" {
977 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/examples/secure-s3-bucket/main.tf"
978 | }
979 | ref "variables.tf" {
980 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/variables.tf"
981 | }
982 | ref "examples/" {
983 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/examples"
984 | }
985 | ref "Issues" {
986 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/issues"
987 | }
988 | ref "LICENSE" {
989 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/LICENSE"
990 | }
991 | ref "Makefile" {
992 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/Makefile"
993 | }
994 | ref "Pull Requests" {
995 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/pulls"
996 | }
997 | ref "Contribution Guidelines" {
998 | value = "https://github.com/mineiros-io/terraform-aws-s3-bucket/blob/master/CONTRIBUTING.md"
999 | }
1000 | }
1001 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
8 | cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
9 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
10 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
11 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
12 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
13 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
14 | github.com/Azure/azure-sdk-for-go v32.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
15 | github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
16 | github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
17 | github.com/Azure/azure-sdk-for-go v38.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
18 | github.com/Azure/azure-sdk-for-go v46.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
19 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
20 | github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
21 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
22 | github.com/Azure/go-autorest/autorest v0.9.1/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
23 | github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
24 | github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
25 | github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
26 | github.com/Azure/go-autorest/autorest v0.11.5/go.mod h1:foo3aIXRQ90zFve3r0QiDsrjGDUwWhKl0ZOQy1CT14k=
27 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
28 | github.com/Azure/go-autorest/autorest/adal v0.6.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
29 | github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
30 | github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
31 | github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
32 | github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
33 | github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
34 | github.com/Azure/go-autorest/autorest/azure/auth v0.3.0/go.mod h1:CI4BQYBct8NS7BXNBBX+RchsFsUu5+oz+OSyR/ZIi7U=
35 | github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
36 | github.com/Azure/go-autorest/autorest/azure/auth v0.5.1/go.mod h1:ea90/jvmnAwDrSooLH4sRIehEPtG/EPUXavDh31MnA4=
37 | github.com/Azure/go-autorest/autorest/azure/cli v0.3.0/go.mod h1:rNYMNAefZMRowqCV0cVhr/YDW5dD7afFq9nXAXL4ykE=
38 | github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
39 | github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s=
40 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
41 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
42 | github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
43 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
44 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
45 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
46 | github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
47 | github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
48 | github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
49 | github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
50 | github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
51 | github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
52 | github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
53 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
54 | github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
55 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
56 | github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
57 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
58 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
59 | github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
60 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
61 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
62 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
63 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
64 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
65 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
66 | github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
67 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
68 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
69 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
70 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
71 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
72 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
73 | github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0=
74 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
75 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
76 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
77 | github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
78 | github.com/aws/aws-sdk-go v1.23.8 h1:G/azJoBN0pnhB3B+0eeC4yyVFYIIad6bbzg6wwtImqk=
79 | github.com/aws/aws-sdk-go v1.23.8/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
80 | github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU=
81 | github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
82 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
83 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
84 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
85 | github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
86 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
87 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
88 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
89 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
90 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
91 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
92 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
93 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
94 | github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
95 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
96 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
97 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
98 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
99 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
100 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
101 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
102 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
103 | github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
104 | github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
105 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
106 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
107 | github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
108 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
109 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
110 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
111 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
112 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
113 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
114 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
115 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
116 | github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
117 | github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
118 | github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
119 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
120 | github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
121 | github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
122 | github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
123 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
124 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
125 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
126 | github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
127 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
128 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
129 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
130 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
131 | github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
132 | github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
133 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
134 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
135 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
136 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
137 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
138 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
139 | github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
140 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
141 | github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
142 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
143 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
144 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
145 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
146 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
147 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU=
148 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
149 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
150 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
151 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
152 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
153 | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
154 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
155 | github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
156 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
157 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
158 | github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
159 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
160 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
161 | github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
162 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
163 | github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
164 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
165 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
166 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
167 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
168 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
169 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
170 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
171 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
172 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
173 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
174 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
175 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
176 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
177 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
178 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
179 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
180 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
181 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
182 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
183 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
184 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
185 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
186 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
187 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
188 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
189 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
190 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
191 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
192 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
193 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
194 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
195 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
196 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
197 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
198 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
199 | github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk=
200 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
201 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
202 | github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
203 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
204 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
205 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
206 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
207 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
208 | github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c h1:jWtZjFEUE/Bz0IeIhqCnyZ3HG6KRXSntXe4SjtuTH7c=
209 | github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
210 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
211 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
212 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
213 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
214 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
215 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
216 | github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
217 | github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
218 | github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
219 | github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
220 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
221 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
222 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
223 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
224 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
225 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
226 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
227 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
228 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
229 | github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
230 | github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
231 | github.com/gruntwork-io/gruntwork-cli v0.5.1/go.mod h1:IBX21bESC1/LGoV7jhXKUnTQTZgQ6dYRsoj/VqxUSZQ=
232 | github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00=
233 | github.com/gruntwork-io/terratest v0.23.0 h1:JmGeqO0r5zRLAV55T67NEmPZArz9lN3RKd0moAKhIT4=
234 | github.com/gruntwork-io/terratest v0.23.0/go.mod h1:+fVff0FQYuRzCF3LKpKF9ac+4w384LDcwLZt7O/KmEE=
235 | github.com/gruntwork-io/terratest v0.28.2 h1:M9CMfS/5unIawxYlz55eRDWH16AH522OAJcUc+zsKv4=
236 | github.com/gruntwork-io/terratest v0.28.2/go.mod h1:lTntpr4gGDzb2YEQ1GTjC5G/xw9ixMwxGmZkPCk1O0A=
237 | github.com/gruntwork-io/terratest v0.28.5 h1:B3Cd45sc18V0Ieaw9JrIl/U27c2mPdwc0pOAF3hGMn4=
238 | github.com/gruntwork-io/terratest v0.28.5/go.mod h1:lTntpr4gGDzb2YEQ1GTjC5G/xw9ixMwxGmZkPCk1O0A=
239 | github.com/gruntwork-io/terratest v0.30.0 h1:1USVQG4Rg7Fp5WLuTjgU6kt+o7GM0ZcllYcsKXGv7nI=
240 | github.com/gruntwork-io/terratest v0.30.0/go.mod h1:7dNmTD2zDKUEVqfmvcUU5c9mZi+986mcXNzhzqPYPg8=
241 | github.com/gruntwork-io/terratest v0.34.0 h1:zlDNwYHkjCavF2NWawbEdwEaUJnkyqXCI3P5B0Z3mdM=
242 | github.com/gruntwork-io/terratest v0.34.0/go.mod h1:IBb+b5b7p34oZLfpz/ZADyn8TSKeWSBu+vQMmNeePLE=
243 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
244 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
245 | github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
246 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
247 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
248 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
249 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
250 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
251 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
252 | github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY=
253 | github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
254 | github.com/hashicorp/terraform-json v0.9.0 h1:WE7+Wt93W93feOiCligElSyS0tlDzwZUtJuDGIBr8zg=
255 | github.com/hashicorp/terraform-json v0.9.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE=
256 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
257 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
258 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
259 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
260 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
261 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=
262 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
263 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
264 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
265 | github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
266 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
267 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
268 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
269 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
270 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
271 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
272 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
273 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
274 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
275 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
276 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
277 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
278 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
279 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
280 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
281 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
282 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
283 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
284 | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
285 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
286 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
287 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
288 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
289 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
290 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
291 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
292 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
293 | github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
294 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
295 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
296 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
297 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
298 | github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
299 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
300 | github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
301 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
302 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
303 | github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
304 | github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
305 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
306 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
307 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
308 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
309 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
310 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
311 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
312 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
313 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
314 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
315 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
316 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
317 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
318 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
319 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
320 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
321 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
322 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
323 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
324 | github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
325 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
326 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
327 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
328 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
329 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
330 | github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
331 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
332 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
333 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
334 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
335 | github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
336 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
337 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
338 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
339 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
340 | github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
341 | github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
342 | github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
343 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
344 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
345 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
346 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
347 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
348 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
349 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
350 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
351 | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
352 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
353 | github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
354 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
355 | github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
356 | github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
357 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
358 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
359 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
360 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
361 | github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
362 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
363 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
364 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
365 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
366 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
367 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
368 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
369 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
370 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
371 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
372 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
373 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
374 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
375 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
376 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
377 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
378 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
379 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
380 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
381 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
382 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
383 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
384 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
385 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
386 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
387 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
388 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
389 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
390 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
391 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
392 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
393 | github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
394 | github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
395 | github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
396 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
397 | github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
398 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
399 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
400 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
401 | github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
402 | github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
403 | github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
404 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
405 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
406 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
407 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
408 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
409 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
410 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
411 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
412 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
413 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
414 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
415 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
416 | golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
417 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
418 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
419 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
420 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
421 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
422 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
423 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
424 | golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
425 | golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
426 | golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
427 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
428 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
429 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
430 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
431 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
432 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
433 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
434 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
435 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
436 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
437 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
438 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
439 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
440 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
441 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
442 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
443 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
444 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
445 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
446 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
447 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
448 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
449 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
450 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
451 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
452 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
453 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
454 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
455 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
456 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
457 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
458 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
459 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
460 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
461 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
462 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
463 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
464 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
465 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
466 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
467 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
468 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
469 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
470 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
471 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
472 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
473 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
474 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
475 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
476 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
477 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
478 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
479 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
480 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
481 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
482 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
483 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
484 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
485 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
486 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
487 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
488 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
489 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
490 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
491 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
492 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
493 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
494 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
495 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
496 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
497 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
498 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
499 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
500 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
501 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
502 | golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
503 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
504 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
505 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
506 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
507 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
508 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
509 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
510 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
511 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
512 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
513 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
514 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
515 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
516 | golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
517 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
518 | golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 h1:Hynbrlo6LbYI3H1IqXpkVDOcX/3HiPdhVEuyj5a59RM=
519 | golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
520 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
521 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
522 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA=
523 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
524 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
525 | golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
526 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
527 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
528 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
529 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
530 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
531 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
532 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
533 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
534 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
535 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
536 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
537 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
538 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
539 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
540 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
541 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
542 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
543 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
544 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
545 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
546 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
547 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
548 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
549 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
550 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
551 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
552 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
553 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
554 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
555 | golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
556 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
557 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
558 | golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
559 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
560 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
561 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
562 | golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
563 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
564 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
565 | golang.org/x/tools v0.0.0-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
566 | golang.org/x/tools v0.0.0-20201110201400-7099162a900a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
567 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
568 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
569 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
570 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
571 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
572 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
573 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
574 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
575 | google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
576 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
577 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
578 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
579 | google.golang.org/api v0.9.1-0.20190821000710-329ecc3c9c34/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
580 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
581 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
582 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
583 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
584 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
585 | google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
586 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
587 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
588 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
589 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
590 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
591 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
592 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
593 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
594 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
595 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
596 | google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
597 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
598 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
599 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
600 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
601 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
602 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
603 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
604 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
605 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
606 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
607 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
608 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
609 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
610 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
611 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
612 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
613 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
614 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
615 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
616 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
617 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
618 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
619 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
620 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
621 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
622 | gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
623 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
624 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
625 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
626 | gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
627 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
628 | gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
629 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
630 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
631 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
632 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
633 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
634 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
635 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
636 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
637 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
638 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
639 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
640 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
641 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
642 | k8s.io/api v0.0.0-20181110191121-a33c8200050f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
643 | k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
644 | k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
645 | k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs=
646 | k8s.io/apimachinery v0.0.0-20190704094520-6f131bee5e2c/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
647 | k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
648 | k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
649 | k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
650 | k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg=
651 | k8s.io/client-go v0.0.0-20190704095228-386e588352a4/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
652 | k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
653 | k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
654 | k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM=
655 | k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE=
656 | k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
657 | k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
658 | k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
659 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
660 | k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
661 | k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
662 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
663 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
664 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
665 | k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
666 | k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
667 | k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
668 | k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
669 | k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
670 | k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8=
671 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
672 | k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
673 | k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
674 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
675 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
676 | modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
677 | modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
678 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
679 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
680 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
681 | sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
682 | sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
683 | sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
684 | sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
685 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
686 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
687 |
--------------------------------------------------------------------------------