├── .github ├── CODEOWNERS └── workflows │ └── main.yml ├── examples ├── user-pool-with-default-settings │ ├── outputs.tf │ ├── main.tf │ └── README.md ├── complete │ ├── outputs.tf │ ├── main.tf │ └── README.md └── README.md ├── versions.tf ├── .pre-commit-config.yaml ├── resource-server.tf ├── test ├── unit_disabled_test.go ├── unit_complete_test.go ├── unit_minimal_test.go ├── unit-disabled │ └── main.tf ├── unit-minimal │ └── main.tf ├── README.md └── unit-complete │ └── main.tf ├── .gitignore ├── .golangci.yml ├── outputs.tf ├── go.mod ├── CONTRIBUTING.md ├── Makefile ├── CHANGELOG.md ├── LICENSE ├── main.tf ├── variables.tf ├── README.md └── README.tfdoc.hcl /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mariux @mineiros-io/terraform-service-catalog 2 | -------------------------------------------------------------------------------- /examples/user-pool-with-default-settings/outputs.tf: -------------------------------------------------------------------------------- 1 | output "user_pool" { 2 | description = "The full `aws_cognito_user_pool` object." 3 | value = module.cognito_user_pool.user_pool 4 | } 5 | -------------------------------------------------------------------------------- /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 = ">= 3.50, < 5.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 | -------------------------------------------------------------------------------- /resource-server.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cognito_resource_server" "resource_server" { 2 | for_each = var.module_enabled ? { for resource in var.resource_servers : resource.identifier => resource } : {} 3 | identifier = each.value.identifier 4 | name = try(each.value.name, null) 5 | user_pool_id = aws_cognito_user_pool.user_pool[0].id 6 | 7 | dynamic "scope" { 8 | for_each = try(each.value.scopes, []) 9 | 10 | content { 11 | scope_name = scope.value.scope_name 12 | scope_description = scope.value.scope_description 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | output "user_pool" { 2 | description = "All outputs exposed by the module." 3 | value = merge(module.cognito_user_pool, { client_secrets = null }) 4 | } 5 | 6 | output "clients" { 7 | description = "All Cognito User Pool Client resources associated with the Cognito User Pool." 8 | value = { for client in module.cognito_user_pool.clients : client.name => merge(client, { client_secret = null }) } 9 | } 10 | 11 | output "client_secrets" { 12 | description = "The secrets of all created Cognito User Pool Client resources." 13 | value = module.cognito_user_pool.client_secrets 14 | sensitive = true 15 | } 16 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /examples/user-pool-with-default-settings/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # DEPLOY A COGNITO USER POOL 3 | # This example deploys a Cognito User Pool with default settings that are 4 | # defined in the variables.tf file of this module. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | # ------------------------------------------------------------------------------ 8 | # PROVIDER CONFIGURATION 9 | # ------------------------------------------------------------------------------ 10 | 11 | provider "aws" { 12 | region = "us-east-1" 13 | } 14 | 15 | # ------------------------------------------------------------------------------ 16 | # THE COGNITO USER POOL WITH DEFAULT SETTINGS 17 | # ------------------------------------------------------------------------------ 18 | 19 | module "cognito_user_pool" { 20 | source = "mineiros-io/cognito-user-pool/aws" 21 | version = "~> 0.9.0" 22 | 23 | name = "example-userpool" 24 | } 25 | -------------------------------------------------------------------------------- /test/unit_disabled_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestUnitDisabled(t *testing.T) { 11 | t.Parallel() 12 | 13 | terraformOptions := &terraform.Options{ 14 | TerraformDir: "unit-disabled", 15 | Vars: map[string]interface{}{ 16 | "aws_region": "us-east-1", 17 | }, 18 | Upgrade: true, 19 | } 20 | 21 | defer terraform.Destroy(t, terraformOptions) 22 | 23 | terraform.InitAndPlan(t, terraformOptions) 24 | stdout := terraform.ApplyAndIdempotent(t, terraformOptions) 25 | 26 | resourceCount := terraform.GetResourceCount(t, stdout) 27 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 28 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 29 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ files 2 | .idea_modules 3 | *.iml 4 | *.iws 5 | *.ipr 6 | .idea/ 7 | build/ 8 | */build/ 9 | out/ 10 | 11 | # macOS files 12 | .history 13 | .DS_Store 14 | 15 | # Local .terraform directories 16 | **/.terraform/* 17 | 18 | # .tfstate files 19 | *.tfstate 20 | *.tfstate.* 21 | 22 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 23 | # .tfvars files are managed as part of configuration and so should be included in 24 | # version control. 25 | # 26 | # example.tfvars 27 | 28 | # Ignore override files as they are usually used to override resources locally and so 29 | # are not checked in 30 | override.tf 31 | override.tf.json 32 | *_override.tf 33 | *_override.tf.json 34 | 35 | # Include override files you do wish to add to version control using negated pattern 36 | # 37 | # !example_override.tf 38 | 39 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 40 | # example: *tfplan* 41 | *.tfplan 42 | 43 | # Go best practices dictate that libraries should not include the vendor directory 44 | vendor 45 | 46 | # Terratest directory used to store temporary data 47 | .test-data 48 | 49 | # Terraform crash log files 50 | crash.log 51 | -------------------------------------------------------------------------------- /test/unit_complete_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | ) 8 | 9 | func TestUnitComplete(t *testing.T) { 10 | t.Parallel() 11 | 12 | terraformOptions := &terraform.Options{ 13 | TerraformDir: "unit-complete", 14 | Vars: map[string]interface{}{ 15 | "aws_region": "us-east-1", 16 | }, 17 | Upgrade: true, 18 | } 19 | 20 | defer terraform.Destroy(t, terraformOptions) 21 | 22 | terraform.InitAndPlan(t, terraformOptions) 23 | terraform.ApplyAndIdempotent(t, terraformOptions) 24 | 25 | // Replace ApplyAndIdempotent() check with below code if provider and terraform report output changes that 26 | // can not be prevented due to some bugs in this feature 27 | 28 | // terraform.Apply(t, terraformOptions) 29 | 30 | // stdout := terraform.Plan(t, terraformOptions) 31 | 32 | // resourceCount := terraform.GetResourceCount(t, stdout) 33 | // assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 34 | // assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 35 | // assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 36 | } 37 | -------------------------------------------------------------------------------- /test/unit_minimal_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | ) 8 | 9 | func TestUnitMinimal(t *testing.T) { 10 | t.Parallel() 11 | 12 | terraformOptions := &terraform.Options{ 13 | TerraformDir: "unit-minimal", 14 | Vars: map[string]interface{}{ 15 | "aws_region": "us-east-1", 16 | }, 17 | Upgrade: true, 18 | } 19 | 20 | defer terraform.Destroy(t, terraformOptions) 21 | 22 | terraform.InitAndPlan(t, terraformOptions) 23 | terraform.ApplyAndIdempotent(t, terraformOptions) 24 | 25 | // Replace ApplyAndIdempotent() check with below code if provider and terraform report output changes that 26 | // can not be prevented due to some bugs in this feature 27 | 28 | // terraform.Apply(t, terraformOptions) 29 | 30 | // stdout := terraform.Plan(t, terraformOptions) 31 | 32 | // resourceCount := terraform.GetResourceCount(t, stdout) 33 | // assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 34 | // assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 35 | // assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 36 | } 37 | -------------------------------------------------------------------------------- /test/unit-disabled/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # EMPTY FEATURES (DISABLED) UNIT TEST 3 | # This module tests an empty set of features. 4 | # The purpose is to verify no resources are created when the module is disabled. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Optional) The AWS region in which all resources will be created." 9 | type = string 10 | default = "us-east-1" 11 | } 12 | 13 | terraform { 14 | required_providers { 15 | aws = { 16 | source = "hashicorp/aws" 17 | version = "~> 4.0" 18 | } 19 | } 20 | } 21 | 22 | provider "aws" { 23 | region = var.aws_region 24 | } 25 | 26 | # DO NOT RENAME MODULE NAME 27 | module "test" { 28 | source = "../.." 29 | 30 | name = "example-cognito-user-pool" 31 | 32 | module_enabled = false 33 | 34 | # add all required arguments 35 | 36 | # add all optional arguments that create additional resources 37 | } 38 | 39 | # outputs generate non-idempotent terraform plans so we disable them for now unless we need them. 40 | # output "all" { 41 | # description = "All outputs of the module." 42 | # value = module.test 43 | # } 44 | -------------------------------------------------------------------------------- /test/unit-minimal/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # MINIMAL FEATURES UNIT TEST 3 | # This module tests a minimal set of features. 4 | # The purpose is to test all defaults for optional arguments and just provide the required arguments. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Optional) The AWS region in which all resources will be created." 9 | type = string 10 | default = "us-east-1" 11 | } 12 | 13 | terraform { 14 | required_providers { 15 | aws = { 16 | source = "hashicorp/aws" 17 | # always test with exact version to catch unsupported blocks/arguments early 18 | # this should match the minimal version in versions.tf 19 | version = "3.50.0" 20 | } 21 | } 22 | } 23 | 24 | provider "aws" { 25 | region = var.aws_region 26 | } 27 | 28 | # DO NOT RENAME MODULE NAME 29 | module "test" { 30 | source = "../.." 31 | 32 | name = "example-cognito-user-pool" 33 | 34 | # add only required arguments and no optional arguments 35 | } 36 | 37 | # outputs generate non-idempotent terraform plans so we disable them for now unless we need them. 38 | # output "all" { 39 | # description = "All outputs of the module." 40 | # value = module.test 41 | # } 42 | -------------------------------------------------------------------------------- /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 | - [complete/] Deploy a Cognito User Pool with custom settings. 11 | - [user-pool-with-default-settings/] Deploy a Cognito User Pool with custom settings. 12 | 13 | 14 | [complete/]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/complete 15 | [user-pool-with-default-settings/]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/user-pool-with-default-settings 16 | 17 | [homepage]: https://mineiros.io/?ref=terraform-aws-cognito-user-pool 18 | 19 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 20 | [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 21 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 22 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-cognito-user-pool.svg?label=latest&sort=semver 23 | 24 | [releases-github]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/releases 25 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 26 | [apache20]: https://opensource.org/licenses/Apache-2.0 27 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 28 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------------------------------------------------- 2 | # GOLANG LINTER RULES 3 | # ---------------------------------------------------------------------------------------------------------------------- 4 | 5 | # configure golangci-lint 6 | # see https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml 7 | issues: 8 | exclude-rules: 9 | - path: _test\.go 10 | linters: 11 | - dupl 12 | - gosec 13 | - goconst 14 | linters: 15 | enable: 16 | - bodyclose 17 | - deadcode 18 | - depguard 19 | - dupl 20 | - errcheck 21 | - gocritic 22 | - gofmt 23 | - goconst 24 | - goimports 25 | - gosec 26 | - gosimple 27 | - revive 28 | - govet 29 | - ineffassign 30 | - interfacer 31 | - misspell 32 | - nakedret 33 | - prealloc 34 | - staticcheck 35 | - structcheck 36 | - stylecheck 37 | - typecheck 38 | - unconvert 39 | - unparam 40 | - unused 41 | - varcheck 42 | - whitespace 43 | 44 | linters-settings: 45 | errcheck: 46 | # report about assignment of errors to blank identifier: `num, _ := strcnv.Atoi(numStr)`; 47 | # default is false: such cases aren't reported by default. 48 | check-blank: true 49 | ignore: fmt:.*,[rR]ead|[wW]rite|[cC]lose,io:Copy 50 | govet: 51 | # report about shadowed variables 52 | check-shadowing: true 53 | gocyclo: 54 | # minimal code complexity to report, 30 by default 55 | min-complexity: 15 56 | maligned: 57 | # print struct with more effective memory layout or not, false by default 58 | suggest-new: true 59 | gofmt: 60 | # simplify code: gofmt with `-s` option, true by default 61 | simplify: true 62 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # OUTPUT CALCULATED VARIABLES (prefer full objects) 3 | # ------------------------------------------------------------------------------ 4 | 5 | # ------------------------------------------------------------------------------ 6 | # OUTPUT ALL RESOURCES AS FULL OBJECTS 7 | # ------------------------------------------------------------------------------ 8 | 9 | # fix tf13 output diff 10 | locals { 11 | user_pool = try(aws_cognito_user_pool.user_pool[0], {}) 12 | 13 | o_user_pool_tags = try(local.user_pool.tags, {}) 14 | 15 | o_user_pool = var.module_enabled ? merge(local.user_pool, { 16 | tags = local.o_user_pool_tags != null ? local.user_pool.tags : {} 17 | }) : null 18 | } 19 | 20 | 21 | output "user_pool" { 22 | description = "The full `aws_cognito_user_pool` object." 23 | value = local.o_user_pool 24 | } 25 | 26 | output "domain" { 27 | description = "The full `aws_cognito_user_pool` object." 28 | value = try(aws_cognito_user_pool_domain.domain[0], null) 29 | } 30 | 31 | output "clients" { 32 | description = "All Cognito User Pool Client resources associated with the Cognito User Pool." 33 | value = { for client in aws_cognito_user_pool_client.client : client.name => merge(client, { client_secret = null }) } 34 | } 35 | 36 | output "client_secrets" { 37 | description = "The secrets of all created Cognito User Pool Client resources." 38 | value = { for client in aws_cognito_user_pool_client.client : client.name => client.client_secret } 39 | sensitive = true 40 | } 41 | 42 | # ------------------------------------------------------------------------------ 43 | # OUTPUT ALL INPUT VARIABLES 44 | # ------------------------------------------------------------------------------ 45 | 46 | # ------------------------------------------------------------------------------ 47 | # OUTPUT MODULE CONFIGURATION 48 | # ------------------------------------------------------------------------------ 49 | 50 | output "module_enabled" { 51 | description = "Whether the module is enabled" 52 | value = var.module_enabled 53 | } 54 | -------------------------------------------------------------------------------- /examples/user-pool-with-default-settings/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 | # What this example shows 8 | 9 | The code in [main.tf] 10 | shows how to deploy a Cognito User Pool with default settings that are 11 | defined in the [variables.tf] file of this module. 12 | 13 | ```hcl 14 | module "cognito_user_pool" { 15 | source = "mineiros-io/cognito-user-pool/aws" 16 | version = "~> 0.8.0" 17 | 18 | name = "example-userpool" 19 | } 20 | ``` 21 | 22 | ## Running the example 23 | 24 | ### Cloning the repository 25 | 26 | ```bash 27 | git clone https://github.com/mineiros-io/terraform-aws-cognito-user-pool.git 28 | cd terraform-aws-cognito-user-pool/examples/user-pool-with-default-settings 29 | ``` 30 | 31 | ### Initializing Terraform 32 | 33 | Run `terraform init` to initialize the example and download providers and the module. 34 | 35 | ### Planning the example 36 | 37 | Run `terraform plan` to see a plan of the changes. 38 | 39 | ### Applying the example 40 | 41 | Run `terraform apply` to create the resources. 42 | You will see a plan of the changes and Terraform will prompt you for approval to actually apply the changes. 43 | 44 | ### Destroying the example 45 | 46 | Run `terraform destroy` to destroy all resources again. 47 | 48 | 49 | 50 | [main.tf]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/tree/master/examples/user-pool-with-default-settings/main.tf 51 | [variables.tf]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/tree/master/variables.tf 52 | 53 | [homepage]: https://mineiros.io/?ref=terraform-aws-cognito-user-pool 54 | 55 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 56 | [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 57 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 58 | 59 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 60 | [apache20]: https://opensource.org/licenses/Apache-2.0 61 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 62 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mineiros-io/terraform-aws-cognito-user-pool 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gruntwork-io/terratest v0.40.0 7 | github.com/stretchr/testify v1.7.0 8 | ) 9 | 10 | require ( 11 | cloud.google.com/go v0.83.0 // indirect 12 | cloud.google.com/go/storage v1.10.0 // indirect 13 | github.com/agext/levenshtein v1.2.3 // indirect 14 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 15 | github.com/aws/aws-sdk-go v1.40.56 // indirect 16 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect 19 | github.com/golang/protobuf v1.5.2 // indirect 20 | github.com/golang/snappy v0.0.3 // indirect 21 | github.com/googleapis/gax-go/v2 v2.0.5 // indirect 22 | github.com/hashicorp/errwrap v1.0.0 // indirect 23 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 24 | github.com/hashicorp/go-getter v1.5.9 // indirect 25 | github.com/hashicorp/go-multierror v1.1.0 // indirect 26 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 27 | github.com/hashicorp/go-version v1.3.0 // indirect 28 | github.com/hashicorp/hcl/v2 v2.9.1 // indirect 29 | github.com/hashicorp/terraform-json v0.13.0 // indirect 30 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect 31 | github.com/jmespath/go-jmespath v0.4.0 // indirect 32 | github.com/jstemmer/go-junit-report v0.9.1 // indirect 33 | github.com/klauspost/compress v1.13.0 // indirect 34 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect 35 | github.com/mitchellh/go-homedir v1.1.0 // indirect 36 | github.com/mitchellh/go-testing-interface v1.0.0 // indirect 37 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 38 | github.com/pmezard/go-difflib v1.0.0 // indirect 39 | github.com/tmccombs/hcl2json v0.3.3 // indirect 40 | github.com/ulikunitz/xz v0.5.8 // indirect 41 | github.com/zclconf/go-cty v1.9.1 // indirect 42 | go.opencensus.io v0.23.0 // indirect 43 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect 44 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect 45 | golang.org/x/mod v0.4.2 // indirect 46 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect 47 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect 48 | golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect 49 | golang.org/x/text v0.3.6 // indirect 50 | golang.org/x/tools v0.1.2 // indirect 51 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 52 | google.golang.org/api v0.47.0 // indirect 53 | google.golang.org/appengine v1.6.7 // indirect 54 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect 55 | google.golang.org/grpc v1.38.0 // indirect 56 | google.golang.org/protobuf v1.26.0 // indirect 57 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 58 | ) 59 | -------------------------------------------------------------------------------- /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 docker-run-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-cognito-user-pool/blob/main/Makefile 67 | [testdirectory]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/tree/main/test 68 | [homepage]: https://mineiros.io/?ref=terraform-aws-cognito-user-pool 69 | [terratest]: https://github.com/gruntwork-io/terratest 70 | [package testing]: https://golang.org/pkg/testing/ 71 | [docker]: https://docs.docker.com/get-started/ 72 | [go]: https://golang.org/ 73 | [terraform]: https://www.terraform.io/downloads.html 74 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 75 | [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 76 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 77 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 78 | [apache20]: https://opensource.org/licenses/Apache-2.0 79 | [slack]: https://mineiros.io/slack 80 | -------------------------------------------------------------------------------- /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-cognito-user-pool/pulls 81 | [pre-commit-file]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/.pre-commit-config.yaml 82 | [Github Flow]: https://guides.github.com/introduction/flow/ 83 | [CODEOWNERS]: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 84 | [Fork]: https://help.github.com/en/github/getting-started-with-github/fork-a-repo 85 | [create a new branch]: https://guides.github.com/introduction/flow/ 86 | [Readme Driven Development]: https://tom.preston-werner.com/2010/08/23/readme-driven-development.html 87 | [commit]: https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project 88 | [create a pull request]: https://help.github.com/articles/creating-a-pull-request/ 89 | [Semantic Versioning (SemVer)]: https://semver.org/ 90 | [Test Driven Development]: https://en.wikipedia.org/wiki/Test-driven_development 91 | -------------------------------------------------------------------------------- /examples/complete/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # DEPLOY A COGNITO USER POOL 3 | # This example deploys a Cognito User Pool with customized settings. 4 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | 6 | # ------------------------------------------------------------------------------ 7 | # PROVIDER CONFIGURATION 8 | # ------------------------------------------------------------------------------ 9 | 10 | provider "aws" { 11 | region = "us-east-1" 12 | } 13 | 14 | # ------------------------------------------------------------------------------ 15 | # THE COGNITO USER POOL WITH CUSTOM SETTINGS 16 | # ------------------------------------------------------------------------------ 17 | 18 | module "cognito_user_pool" { 19 | source = "mineiros-io/cognito-user-pool/aws" 20 | version = "~> 0.9.0" 21 | 22 | name = "complete-example-userpool" 23 | 24 | # We allow the public to create user profiles 25 | allow_admin_create_user_only = false 26 | 27 | enable_username_case_sensitivity = false 28 | advanced_security_mode = "ENFORCED" 29 | 30 | alias_attributes = [ 31 | "email", 32 | "phone_number", 33 | "preferred_username", 34 | ] 35 | 36 | auto_verified_attributes = [ 37 | "email" 38 | ] 39 | 40 | account_recovery_mechanisms = [ 41 | { 42 | name = "verified_email" 43 | priority = 1 44 | }, 45 | { 46 | name = "verified_phone_number" 47 | priority = 2 48 | } 49 | ] 50 | 51 | # If invited by an admin 52 | invite_email_subject = "You've been invited to Mineiros.io" 53 | invite_email_message = "Hi {username}, your temporary password is '{####}'." 54 | invite_sms_message = "Hi {username}, your temporary password is '{####}'." 55 | 56 | domain = "mineiros-dev" 57 | default_email_option = "CONFIRM_WITH_LINK" 58 | email_subject_by_link = "Your Verification Link" 59 | email_message_by_link = "Please click the link below to verify your email address. {##Verify Email##}." 60 | sms_message = "Your verification code is {####}." 61 | 62 | challenge_required_on_new_device = true 63 | user_device_tracking = "USER_OPT_IN" 64 | 65 | # These paramters can be used to configure SES for emails 66 | # email_sending_account = "DEVELOPER" 67 | # email_reply_to_address = "support@mineiros.io" 68 | # email_from_address = "noreply@mineiros.io" 69 | # email_source_arn = "arn:aws:ses:us-east-1:999999999999:identity" 70 | 71 | # Require MFA 72 | mfa_configuration = "ON" 73 | allow_software_mfa_token = true 74 | 75 | password_minimum_length = 40 76 | password_require_lowercase = true 77 | password_require_numbers = true 78 | password_require_uppercase = true 79 | password_require_symbols = true 80 | 81 | temporary_password_validity_days = 3 82 | 83 | schema_attributes = [ 84 | { 85 | name = "gender", # overwrites the default attribute 'gender' 86 | type = "String" 87 | required = true 88 | min_length = 1 89 | max_length = 2048 90 | }, 91 | { 92 | name = "alternative_name" 93 | type = "String" 94 | developer_only_attribute = false, 95 | mutable = true, 96 | required = false, 97 | min_length = 0, 98 | max_length = 2048 99 | }, 100 | { 101 | name = "friends_count" 102 | type = "Number" 103 | min_value = 0, 104 | max_value = 100 105 | }, 106 | { 107 | name = "is_active" 108 | type = "Boolean" 109 | 110 | }, 111 | { 112 | name = "last_seen" 113 | type = "DateTime" 114 | } 115 | ] 116 | 117 | clients = [ 118 | { 119 | name = "android-mobile-client" 120 | read_attributes = ["email", "email_verified", "preferred_username"] 121 | allowed_oauth_scopes = ["email", "openid"] 122 | allowed_oauth_flows = ["implicit"] 123 | callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 124 | default_redirect_uri = "https://mineiros.io/callback" 125 | generate_secret = true 126 | } 127 | ] 128 | 129 | tags = { 130 | environment = "Dev" 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /examples/complete/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 | # What this example shows 8 | 9 | The code in [main.tf] 10 | shows how to deploy a Cognito User Pool with custom settings. 11 | 12 | ```hcl 13 | module "cognito_user_pool" { 14 | source = "mineiros-io/cognito-user-pool/aws" 15 | version = "~> 0.9.0" 16 | 17 | name = "complete-example-userpool" 18 | 19 | # We allow the public to create user profiles 20 | allow_admin_create_user_only = false 21 | 22 | enable_username_case_sensitivity = false 23 | advanced_security_mode = "ENFORCED" 24 | 25 | alias_attributes = [ 26 | "email", 27 | "phone_number", 28 | "preferred_username", 29 | ] 30 | 31 | auto_verified_attributes = [ 32 | "email" 33 | ] 34 | 35 | # If invited by an admin 36 | invite_email_subject = "You've been invited to Mineiros.io" 37 | invite_email_message = "Hi {username}, your temporary password is '{####}'." 38 | invite_sms_message = "Hi {username}, your temporary password is '{####}'." 39 | 40 | default_email_option = "CONFIRM_WITH_LINK" 41 | email_subject_by_link = "Your Verification Link" 42 | email_message_by_link = "Please click the link below to verify your email address. {##Verify Email##}." 43 | sms_message = "Your verification code is {####}." 44 | 45 | challenge_required_on_new_device = true 46 | user_device_tracking = "USER_OPT_IN" 47 | 48 | # These paramters can be used to configure SES for emails 49 | # ... 50 | 51 | # Require MFA 52 | mfa_configuration = "ON" 53 | allow_software_mfa_token = true 54 | 55 | password_minimum_length = 40 56 | password_require_lowercase = true 57 | password_require_numbers = true 58 | password_require_uppercase = true 59 | password_require_symbols = true 60 | 61 | temporary_password_validity_days = 3 62 | 63 | schema_attributes = [ 64 | { 65 | name = "gender", # overwrites the default attribute 'gender' 66 | type = "String" 67 | required = true 68 | min_length = 1 69 | max_length = 2048 70 | }, 71 | { 72 | name = "alternative_name" 73 | type = "String" 74 | developer_only_attribute = false, 75 | mutable = true, 76 | required = false, 77 | min_length = 0, 78 | max_length = 2048 79 | }, 80 | { 81 | name = "friends_count" 82 | type = "Number" 83 | min_value = 0, 84 | max_value = 100 85 | }, 86 | { 87 | name = "is_active" 88 | type = "Boolean" 89 | 90 | }, 91 | { 92 | name = "last_seen" 93 | type = "DateTime" 94 | } 95 | ] 96 | 97 | clients = [ 98 | { 99 | name = "android-mobile-client" 100 | read_attributes = ["email", "email_verified", "preferred_username"] 101 | allowed_oauth_scopes = ["email", "openid"] 102 | allowed_oauth_flows = ["implicit"] 103 | callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 104 | default_redirect_uri = "https://mineiros.io/callback" 105 | generate_secret = true 106 | } 107 | ] 108 | 109 | tags = { 110 | environment = "Dev" 111 | } 112 | } 113 | ``` 114 | 115 | ## Running the example 116 | 117 | ### Cloning the repository 118 | 119 | ```bash 120 | git clone https://github.com/mineiros-io/terraform-aws-cognito-user-pool.git 121 | cd terraform-aws-cognito-user-pool/examples/complete 122 | ``` 123 | 124 | ### Initializing Terraform 125 | 126 | Run `terraform init` to initialize the example and download providers and the module. 127 | 128 | ### Planning the example 129 | 130 | Run `terraform plan` to see a plan of the changes. 131 | 132 | ### Applying the example 133 | 134 | Run `terraform apply` to create the resources. 135 | You will see a plan of the changes and Terraform will prompt you for approval to actually apply the changes. 136 | 137 | ### Destroying the example 138 | 139 | Run `terraform destroy` to destroy all resources again. 140 | 141 | 142 | 143 | [main.tf]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/tree/master/examples/complete/main.tf 144 | 145 | [homepage]: https://mineiros.io/?ref=terraform-aws-cognito-user-pool 146 | 147 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 148 | [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 149 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 150 | 151 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 152 | [apache20]: https://opensource.org/licenses/Apache-2.0 153 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 154 | -------------------------------------------------------------------------------- /test/unit-complete/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # COMPLETE FEATURES UNIT TEST 3 | # This module tests a complete set of most/all non-exclusive features 4 | # The purpose is to activate everything the module offers, but trying to keep execution time and costs minimal. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Optional) The AWS region in which all resources will be created." 9 | type = string 10 | default = "us-east-1" 11 | } 12 | 13 | terraform { 14 | required_providers { 15 | aws = { 16 | source = "hashicorp/aws" 17 | version = "~> 4.0" 18 | } 19 | } 20 | } 21 | 22 | provider "aws" { 23 | region = var.aws_region 24 | } 25 | 26 | # DO NOT RENAME MODULE NAME 27 | module "test" { 28 | source = "../.." 29 | 30 | module_enabled = true 31 | 32 | # add all required arguments 33 | name = "example-cognito-user-pool" 34 | 35 | # add all optional arguments that create additional resources 36 | clients = [ 37 | { 38 | name = "android-mobile-client" 39 | read_attributes = ["email", "email_verified", "preferred_username"] 40 | allowed_oauth_scopes = ["email", "openid"] 41 | allowed_oauth_flows = ["implicit"] 42 | callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 43 | default_redirect_uri = "https://mineiros.io/callback" 44 | generate_secret = true 45 | } 46 | ] 47 | 48 | resource_servers = [ 49 | { 50 | identifier = "https://api.resourceserver.com" 51 | name = "API" 52 | scopes = [ 53 | { 54 | scope_name = "users:read", 55 | scope_description = "Read user data" 56 | }, 57 | { 58 | scope_name = "users:write" 59 | scope_description = "Write user data" 60 | } 61 | ] 62 | } 63 | ] 64 | 65 | # add most/all other optional arguments 66 | 67 | enable_username_case_sensitivity = false 68 | advanced_security_mode = "ENFORCED" 69 | 70 | alias_attributes = [ 71 | "email", 72 | "phone_number", 73 | "preferred_username", 74 | ] 75 | 76 | auto_verified_attributes = [ 77 | "email" 78 | ] 79 | 80 | account_recovery_mechanisms = [ 81 | { 82 | name = "verified_email" 83 | priority = 1 84 | }, 85 | { 86 | name = "verified_phone_number" 87 | priority = 2 88 | } 89 | ] 90 | 91 | # If invited by an admin 92 | invite_email_subject = "You've been invited to Mineiros.io" 93 | invite_email_message = "Hi {username}, your temporary password is '{####}'." 94 | invite_sms_message = "Hi {username}, your temporary password is '{####}'." 95 | 96 | # domain = "mineiros-dev" 97 | default_email_option = "CONFIRM_WITH_LINK" 98 | email_subject_by_link = "Your Verification Link" 99 | email_message_by_link = "Please click the link below to verify your email address. {##Verify Email##}." 100 | sms_message = "Your verification code is {####}." 101 | 102 | challenge_required_on_new_device = true 103 | user_device_tracking = "USER_OPT_IN" 104 | 105 | # These paramters can be used to configure SES for emails 106 | # email_sending_account = "DEVELOPER" 107 | # email_reply_to_address = "support@mineiros.io" 108 | # email_from_address = "noreply@mineiros.io" 109 | # email_source_arn = "arn:aws:ses:us-east-1:999999999999:identity" 110 | 111 | # Require MFA 112 | mfa_configuration = "ON" 113 | allow_software_mfa_token = true 114 | 115 | password_minimum_length = 40 116 | password_require_lowercase = true 117 | password_require_numbers = true 118 | password_require_uppercase = true 119 | password_require_symbols = true 120 | 121 | temporary_password_validity_days = 3 122 | 123 | schema_attributes = [ 124 | { 125 | name = "gender", # overwrites the default attribute 'gender' 126 | type = "String" 127 | required = true 128 | min_length = 1 129 | max_length = 2048 130 | }, 131 | { 132 | name = "alternative_name" 133 | type = "String" 134 | developer_only_attribute = false, 135 | mutable = true, 136 | required = false, 137 | min_length = 0, 138 | max_length = 2048 139 | }, 140 | { 141 | name = "friends_count" 142 | type = "Number" 143 | min_value = 0, 144 | max_value = 100 145 | }, 146 | { 147 | name = "is_active" 148 | type = "Boolean" 149 | 150 | }, 151 | { 152 | name = "last_seen" 153 | type = "DateTime" 154 | } 155 | ] 156 | 157 | default_client_token_validity_units = { 158 | refresh_token = "hours" 159 | access_token = "hours" 160 | id_token = "hours" 161 | } 162 | 163 | tags = { 164 | Team = "Unknown" 165 | } 166 | 167 | module_tags = { 168 | Environment = "unknown" 169 | } 170 | 171 | module_depends_on = ["nothing"] 172 | } 173 | 174 | # outputs generate non-idempotent terraform plans so we disable them for now unless we need them. 175 | # output "all" { 176 | # description = "All outputs of the module." 177 | # value = module.test 178 | # } 179 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Set default shell to bash 2 | SHELL := /bin/bash -o pipefail 3 | 4 | BUILD_TOOLS_VERSION ?= v0.14.3 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 GOOGLE_CREDENTIALS is defined, we are likely running inside a GCP provider 63 | # module. To enable GCP authentication inside the docker container, we inject 64 | # the relevant environment variables (service-account key file). 65 | ifdef GOOGLE_CREDENTIALS 66 | DOCKER_GCP_FLAGS += -e GOOGLE_CREDENTIALS 67 | endif 68 | 69 | # If GITHUB_OWNER is defined, we are likely running inside a GitHub provider 70 | # module. To enable GitHub authentication inside the docker container, 71 | # we inject the relevant environment variables. 72 | ifdef GITHUB_OWNER 73 | DOCKER_GITHUB_FLAGS += -e GITHUB_TOKEN 74 | DOCKER_GITHUB_FLAGS += -e GITHUB_OWNER 75 | endif 76 | 77 | .PHONY: default 78 | default: help 79 | 80 | # Not exposed as a callable target by `make help`, since this is a one-time shot to simplify the development of this module. 81 | .PHONY: template/adjust 82 | template/adjust: FILTER = -path ./.git -prune -a -type f -o -type f -not -name Makefile 83 | template/adjust: 84 | @find . $(FILTER) -exec sed -i -e "s,terraform-module-template,$${PWD##*/},g" {} \; 85 | 86 | ## Run pre-commit hooks inside a build-tools docker container. 87 | .PHONY: test/pre-commit 88 | test/pre-commit: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 89 | test/pre-commit: 90 | $(call docker-run,pre-commit run -a) 91 | 92 | ## Run all Go tests inside a build-tools docker container. This is complementary to running 'go test ./test/...'. 93 | .PHONY: test/unit-tests 94 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 95 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_GITHUB_FLAGS} 96 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_AWS_FLAGS} 97 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_GCP_FLAGS} 98 | test/unit-tests: DOCKER_FLAGS += $(shell env | grep ^TF_VAR_ | cut -d = -f 1 | xargs -i printf ' -e {}') 99 | test/unit-tests: DOCKER_FLAGS += -e TF_DATA_DIR=.terratest 100 | test/unit-tests: TEST ?= "TestUnit" 101 | test/unit-tests: 102 | @echo "${YELLOW}[TEST] ${GREEN}Start Running Go Tests in Docker Container.${RESET}" 103 | $(call go-test,./test -run $(TEST)) 104 | 105 | ## Generate README.md with Terradoc 106 | .PHONY: terradoc 107 | terradoc: 108 | $(call quiet-command,terradoc -o README.md README.tfdoc.hcl) 109 | 110 | ## Clean up cache and temporary files 111 | .PHONY: clean 112 | clean: 113 | $(call rm-command,.terraform) 114 | $(call rm-command,.terraform.lock.hcl) 115 | $(call rm-command,*.tfplan) 116 | $(call rm-command,*/*/.terraform) 117 | $(call rm-command,*/*/*.tfplan) 118 | $(call rm-command,*/*/.terraform.lock.hcl) 119 | 120 | ## Display help for all targets 121 | .PHONY: help 122 | help: 123 | @awk '/^.PHONY: / { \ 124 | msg = match(lastLine, /^## /); \ 125 | if (msg) { \ 126 | cmd = substr($$0, 9, 100); \ 127 | msg = substr(lastLine, 4, 1000); \ 128 | printf " ${GREEN}%-30s${RESET} %s\n", cmd, msg; \ 129 | } \ 130 | } \ 131 | { lastLine = $$0 }' $(MAKEFILE_LIST) 132 | 133 | # Define helper functions 134 | DOCKER_FLAGS += ${DOCKER_RUN_FLAGS} 135 | DOCKER_RUN_CMD = docker run ${DOCKER_FLAGS} ${BUILD_TOOLS_DOCKER_IMAGE} 136 | 137 | quiet-command = $(if ${V},${1},$(if ${2},@echo ${2} && ${1}, @${1})) 138 | docker-run = $(call quiet-command,${DOCKER_RUN_CMD} ${1} | cat,"${YELLOW}[DOCKER RUN] ${GREEN}${1}${RESET}") 139 | go-test = $(call quiet-command,${DOCKER_RUN_CMD} go test -v -count 1 -timeout 45m -parallel 128 ${1} | cat,"${YELLOW}[TEST] ${GREEN}${1}${RESET}") 140 | rm-command = $(call quiet-command,rm -rf ${1},"${YELLOW}[CLEAN] ${GREEN}${1}${RESET}") 141 | -------------------------------------------------------------------------------- /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.9.2] 11 | 12 | ### Added 13 | 14 | - Added support for AWS provider `v4.x` 15 | 16 | ## [0.9.1] 17 | 18 | ### Added 19 | 20 | - Add support for `module_tags` 21 | - Implement support for resource servers through the 22 | `aws_cognito_resource_server` resource 23 | 24 | ## [0.9.0] 25 | 26 | ### BREAKING 27 | 28 | - Minimum version of the aws provider has been bumped to `3.50.0` to ensure 29 | support for the `enable_token_revocation` in the `aws_cognito_user_pool_client` 30 | resource. 31 | 32 | ### Fixed 33 | 34 | - Fixed implementation of `token_validity_units` block. 35 | 36 | ## [0.8.0] 37 | 38 | ### BREAKING 39 | 40 | - Minimum version of the aws provider has been bumped to `3.32.0` to enable 41 | support for `token_validity_units` 42 | 43 | ### Added 44 | 45 | - Add support `token_validity_units` 46 | 47 | ## [0.7.0] 48 | 49 | ### Added 50 | 51 | - Add support for Terraform `v1.x` 52 | 53 | ## [0.6.0] 54 | 55 | ### Added 56 | 57 | - Add support for Terraform `v0.15` 58 | 59 | ## [0.5.0] 60 | 61 | ### Added 62 | 63 | - Add support for `account_recovery_mechanisms` 64 | 65 | ### Removed 66 | 67 | - BREAKING CHANGE: Drop support for Terraform AWS Provider version `v2` 68 | 69 | ## [0.4.1] - 2021-02-08 70 | 71 | ### Fixed 72 | 73 | - Fixed examples to use new variable `user_device_tracking` instead of `device_only_remembered_on_user_prompt` 74 | 75 | ## [0.4.0] - 2020-12-09 76 | 77 | ### Changed 78 | 79 | - Add support for Terraform v0.14 80 | 81 | ## [0.3.0] - 2020-11-25 82 | 83 | ### Changes 84 | 85 | - Add argument `user_device_tracking` to set device tracking to `OFF`, `ALWAYS` or `USER_OPT_IN` 86 | - BREAKING CHANGE: Remove argument `device_only_remembered_on_user_prompt`. Replaced by `user_device_tracking`. 87 | Default behavior did not change. How to migrate: 88 | - `device_only_remembered_on_user_prompt=true`: Set `user_device_tracking='USER_OPT_IN'` 89 | - `device_only_remembered_on_user_prompt=false`: Set `user_device_tracking='ALWAYS'` 90 | - `device_only_remembered_on_user_prompt=null`: Set `user_device_tracking='OFF'` 91 | 92 | ### Fixes 93 | 94 | - Allow to cleanly turn off user device tracking by setting new variable `user_device_tracking` to `OFF`. [#23](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/issues/23) 95 | - The type of the clients output is a map of objects instead of a list. 96 | 97 | ## [0.2.0] - 2020-08-13 98 | 99 | ### Changed 100 | 101 | - Add support for Terraform `v0.13` 102 | - Prepared support for Terraform `v0.14` 103 | 104 | ## [0.1.4] - 2020-08-13 105 | 106 | ### Added 107 | 108 | - Add support for `username_attributes` argument. 109 | 110 | ## [0.1.3] - 2020-08-10 111 | 112 | ### Added 113 | 114 | - Add unit test coverage for the `aws_cognito_user_pool_domain` resource. 115 | 116 | ### Changed 117 | 118 | - Enable `markdown-link-check` pre-commit hook. 119 | 120 | ### Fixed 121 | 122 | - Fixes recreation of resources on multiple apply runs. 123 | - Fix non-idempotent number schema attributes. 124 | 125 | ## [0.1.2] - 2020-08-05 126 | 127 | ### Added 128 | 129 | - Add support for `aws_cognito_user_pool_domain`. 130 | 131 | ## [0.1.1] - 2020-08-04 132 | 133 | ### Fixed 134 | 135 | - Fix email subject for admin invites. 136 | - Fix example documentation to point to terraform registry. 137 | - Fix `string_attribute_constraints` default values for string attributes to prevent non-idempotent plan. 138 | 139 | ### Added 140 | 141 | - Add test to validate idempotency after apply. 142 | 143 | ## [0.1.0] - 2020-08-03 144 | 145 | ### Changed 146 | 147 | - Add support for terraform aws provider `v3` 148 | - Update test to test against `v3` aws provider 149 | - Update test dependencies to use `v3` capable module versions 150 | 151 | ## [0.0.1] - 2020-06-27 152 | 153 | ### Added 154 | 155 | - Implement support for `aws_cognito_user_pool` resource. 156 | - Implement support for `aws_cognito_user_pool_client` resource. 157 | - Document the usage of the module in README.md. 158 | - Document the usage of examples. 159 | - Add unit tests for basic use cases. 160 | 161 | [unreleased]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.9.2...HEAD 162 | [0.9.2]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.9.1...v0.9.2 163 | [0.9.1]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.9.0...v0.9.1 164 | [0.9.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.8.0...v0.9.0 165 | [0.8.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.7.0...v0.8.0 166 | [0.7.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.6.0...v0.7.0 167 | [0.6.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.5.0...v0.6.0 168 | [0.5.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.4.1...v0.5.0 169 | [0.4.1]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.4.0...v0.4.1 170 | [0.4.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.3.0...v0.4.0 171 | [0.3.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.2.0...v0.3.0 172 | [0.2.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.1.4...v0.2.0 173 | [0.1.4]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.1.3...v0.1.4 174 | [0.1.3]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.1.2...v0.1.3 175 | [0.1.2]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.1.1...v0.1.2 176 | [0.1.1]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.1.0...v0.1.1 177 | [0.1.0]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/compare/v0.0.1...v0.1.0 178 | [0.0.1]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/releases/tag/v0.0.1 179 | -------------------------------------------------------------------------------- /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] 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 | # DEPLOY A COGNITO USER POOL 3 | # This module deploys a Amazon Web Servics (AWS) Cognito User Pool Service. 4 | # Cognito user pools are used for authentication and act as identity provider. 5 | # With a user pool, your app users can sign in through the user pool or 6 | # federate through a third-party identity provider (idP). For more information 7 | # please see: 8 | # https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html 9 | # ------------------------------------------------------------------------------ 10 | 11 | locals { 12 | alias_attributes = var.alias_attributes == null && var.username_attributes == null ? [ 13 | "email", 14 | "preferred_username", 15 | ] : null 16 | } 17 | 18 | resource "aws_cognito_user_pool" "user_pool" { 19 | count = var.module_enabled ? 1 : 0 20 | 21 | name = var.name 22 | alias_attributes = var.alias_attributes != null ? var.alias_attributes : local.alias_attributes 23 | username_attributes = var.username_attributes 24 | auto_verified_attributes = var.auto_verified_attributes 25 | 26 | sms_authentication_message = var.sms_authentication_message 27 | 28 | mfa_configuration = var.mfa_configuration 29 | 30 | password_policy { 31 | minimum_length = var.password_minimum_length 32 | require_lowercase = var.password_require_lowercase 33 | require_numbers = var.password_require_numbers 34 | require_symbols = var.password_require_symbols 35 | require_uppercase = var.password_require_uppercase 36 | temporary_password_validity_days = var.temporary_password_validity_days 37 | } 38 | 39 | dynamic "account_recovery_setting" { 40 | for_each = length(var.account_recovery_mechanisms) > 0 ? [true] : [] 41 | 42 | content { 43 | dynamic "recovery_mechanism" { 44 | for_each = var.account_recovery_mechanisms 45 | iterator = recovery 46 | 47 | content { 48 | name = recovery.value.name 49 | priority = recovery.value.priority 50 | } 51 | } 52 | } 53 | } 54 | 55 | dynamic "device_configuration" { 56 | for_each = contains(["ALWAYS", "USER_OPT_IN"], upper(var.user_device_tracking)) ? [true] : [] 57 | 58 | content { 59 | device_only_remembered_on_user_prompt = var.user_device_tracking == "USER_OPT_IN" 60 | challenge_required_on_new_device = var.challenge_required_on_new_device 61 | } 62 | } 63 | 64 | dynamic "software_token_mfa_configuration" { 65 | for_each = var.allow_software_mfa_token ? [true] : [] 66 | 67 | content { 68 | enabled = true 69 | } 70 | } 71 | 72 | username_configuration { 73 | case_sensitive = var.enable_username_case_sensitivity 74 | } 75 | 76 | email_configuration { 77 | email_sending_account = var.email_sending_account 78 | reply_to_email_address = var.email_reply_to_address 79 | source_arn = var.email_source_arn 80 | from_email_address = var.email_from_address 81 | } 82 | 83 | # The configuration for AdminCreateUser 84 | # https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html. 85 | admin_create_user_config { 86 | allow_admin_create_user_only = var.allow_admin_create_user_only 87 | 88 | invite_message_template { 89 | email_subject = var.invite_email_subject 90 | email_message = var.invite_email_message 91 | sms_message = var.invite_sms_message 92 | } 93 | } 94 | 95 | dynamic "schema" { 96 | for_each = var.schema_attributes 97 | iterator = attribute 98 | 99 | content { 100 | name = attribute.value.name 101 | required = try(attribute.value.required, false) 102 | attribute_data_type = attribute.value.type 103 | developer_only_attribute = try(attribute.value.developer_only_attribute, false) 104 | mutable = try(attribute.value.mutable, true) 105 | 106 | dynamic "number_attribute_constraints" { 107 | for_each = attribute.value.type == "Number" ? [true] : [] 108 | 109 | content { 110 | min_value = lookup(attribute.value, "min_value", null) 111 | max_value = lookup(attribute.value, "max_value", null) 112 | } 113 | } 114 | 115 | dynamic "string_attribute_constraints" { 116 | for_each = attribute.value.type == "String" ? [true] : [] 117 | 118 | content { 119 | min_length = lookup(attribute.value, "min_length", 0) 120 | max_length = lookup(attribute.value, "max_length", 2048) 121 | } 122 | } 123 | 124 | } 125 | } 126 | 127 | dynamic "lambda_config" { 128 | for_each = try(coalesce( 129 | var.lambda_create_auth_challenge, 130 | var.lambda_custom_message, 131 | var.lambda_define_auth_challenge, 132 | var.lambda_post_authentication, 133 | var.lambda_post_confirmation, 134 | var.lambda_pre_authentication, 135 | var.lambda_pre_sign_up, 136 | var.lambda_pre_token_generation, 137 | var.lambda_user_migration, 138 | var.lambda_verify_auth_challenge_response 139 | ), null) == null ? [] : [true] 140 | 141 | content { 142 | create_auth_challenge = var.lambda_create_auth_challenge 143 | custom_message = var.lambda_custom_message 144 | define_auth_challenge = var.lambda_define_auth_challenge 145 | post_authentication = var.lambda_post_authentication 146 | post_confirmation = var.lambda_post_confirmation 147 | pre_authentication = var.lambda_pre_authentication 148 | pre_sign_up = var.lambda_pre_sign_up 149 | pre_token_generation = var.lambda_pre_token_generation 150 | user_migration = var.lambda_user_migration 151 | verify_auth_challenge_response = var.lambda_verify_auth_challenge_response 152 | } 153 | } 154 | 155 | # Configuration block for Short Message Service (SMS) settings. 156 | # These settings apply to SMS user verification and SMS Multi-Factor Authentication (MFA). 157 | # Due to Cognito API restrictions, the SMS configuration cannot be removed without recreating the Cognito User Pool. 158 | # For user data safety, this resource will ignore the removal of this configuration by disabling drift detection. 159 | # To force resource recreation after this configuration has been applied, see the taint command. 160 | dynamic "sms_configuration" { 161 | for_each = var.sms_configuration != null ? [var.sms_configuration] : [] 162 | 163 | content { 164 | external_id = lookup(var.sms_configuration, "external_id", null) 165 | sns_caller_arn = lookup(var.sms_configuration, "sns_caller_arn", null) 166 | } 167 | } 168 | 169 | # Advanced Security Features 170 | # Note: Additional pricing applies for Amazon Cognito advanced security features. For details please see: 171 | # https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-advanced-security.html 172 | user_pool_add_ons { 173 | advanced_security_mode = var.advanced_security_mode 174 | } 175 | 176 | verification_message_template { 177 | default_email_option = var.default_email_option 178 | email_subject = var.email_subject 179 | email_message = var.email_message 180 | email_subject_by_link = var.email_subject_by_link 181 | email_message_by_link = var.email_message_by_link 182 | sms_message = var.sms_message 183 | } 184 | 185 | tags = merge(var.module_tags, var.tags) 186 | depends_on = [var.module_depends_on] 187 | } 188 | 189 | locals { 190 | clients = { 191 | for client in var.clients : replace(lower(client.name), "/[^a-z0-9]/", "-") => { 192 | allowed_oauth_flows = lookup(client, "allowed_oauth_flows", var.default_client_allowed_oauth_flows) 193 | allowed_oauth_flows_user_pool_client = lookup(client, "allowed_oauth_flows_user_pool_client", var.default_client_allowed_oauth_flows_user_pool_client) 194 | allowed_oauth_scopes = lookup(client, "allowed_oauth_scopes", var.default_client_allowed_oauth_scopes) 195 | callback_urls = lookup(client, "callback_urls", var.default_client_callback_urls) 196 | default_redirect_uri = lookup(client, "default_redirect_uri", var.default_client_default_redirect_uri) 197 | explicit_auth_flows = lookup(client, "explicit_auth_flows", var.default_client_explicit_auth_flows) 198 | generate_secret = lookup(client, "generate_secret", var.default_client_generate_secret) 199 | logout_urls = lookup(client, "logout_urls", var.default_client_logout_urls) 200 | read_attributes = lookup(client, "read_attributes", var.default_client_read_attributes) 201 | refresh_token_validity = lookup(client, "refresh_token_validity", var.default_client_refresh_token_validity) 202 | supported_identity_providers = lookup(client, "supported_identity_providers", var.default_client_supported_identity_providers) 203 | prevent_user_existence_errors = lookup(client, "prevent_user_existence_errors", var.default_client_prevent_user_existence_errors) 204 | write_attributes = lookup(client, "write_attributes", var.default_client_write_attributes) 205 | access_token_validity = lookup(client, "access_token_validity", var.default_client_access_token_validity) 206 | id_token_validity = lookup(client, "id_token_validity", var.default_client_id_token_validity) 207 | token_validity_units = lookup(client, "token_validity_units", var.default_client_token_validity_units) 208 | enable_token_revocation = lookup(client, "enable_token_revocation", var.default_client_enable_token_revocation) 209 | } 210 | } 211 | } 212 | 213 | resource "aws_cognito_user_pool_client" "client" { 214 | for_each = var.module_enabled ? local.clients : {} 215 | 216 | name = each.key 217 | 218 | allowed_oauth_flows = each.value.allowed_oauth_flows 219 | allowed_oauth_flows_user_pool_client = each.value.allowed_oauth_flows_user_pool_client 220 | allowed_oauth_scopes = each.value.allowed_oauth_scopes 221 | callback_urls = each.value.callback_urls 222 | default_redirect_uri = each.value.default_redirect_uri 223 | explicit_auth_flows = each.value.explicit_auth_flows 224 | generate_secret = each.value.generate_secret 225 | logout_urls = each.value.logout_urls 226 | read_attributes = each.value.read_attributes 227 | refresh_token_validity = each.value.refresh_token_validity 228 | supported_identity_providers = each.value.supported_identity_providers 229 | prevent_user_existence_errors = each.value.prevent_user_existence_errors 230 | user_pool_id = aws_cognito_user_pool.user_pool[0].id 231 | write_attributes = each.value.write_attributes 232 | access_token_validity = each.value.access_token_validity 233 | id_token_validity = each.value.id_token_validity 234 | 235 | dynamic "token_validity_units" { 236 | for_each = each.value.token_validity_units != null ? [each.value.token_validity_units] : [] 237 | 238 | content { 239 | refresh_token = try(token_validity_units.value.refresh_token, null) 240 | access_token = try(token_validity_units.value.access_token, null) 241 | id_token = try(token_validity_units.value.id_token, null) 242 | } 243 | } 244 | 245 | enable_token_revocation = each.value.enable_token_revocation 246 | 247 | depends_on = [ 248 | aws_cognito_resource_server.resource_server 249 | ] 250 | } 251 | 252 | resource "aws_cognito_user_pool_domain" "domain" { 253 | count = var.module_enabled && var.domain != null ? 1 : 0 254 | 255 | domain = var.domain 256 | certificate_arn = var.certificate_arn 257 | user_pool_id = aws_cognito_user_pool.user_pool[0].id 258 | } 259 | -------------------------------------------------------------------------------- /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 PARAMETERS 11 | # These variables must be set when using this module. 12 | # ------------------------------------------------------------------------------ 13 | 14 | variable "name" { 15 | type = string 16 | description = "(Required) The name of the user pool." 17 | } 18 | 19 | # ------------------------------------------------------------------------------ 20 | # OPTIONAL PARAMETERS 21 | # These variables have defaults, but may be overridden. 22 | # ------------------------------------------------------------------------------ 23 | 24 | variable "advanced_security_mode" { 25 | type = string 26 | description = "(Optional) The mode for advanced security, must be one of `OFF`, `AUDIT` or `ENFORCED`. Additional pricing applies for Amazon Cognito advanced security features. For details see https://aws.amazon.com/cognito/pricing/" 27 | default = "OFF" 28 | } 29 | 30 | variable "alias_attributes" { 31 | type = set(string) 32 | description = "(Optional) Attributes supported as an alias for this user pool. Possible values: 'phone_number', 'email', or 'preferred_username'. Conflicts with username_attributes." 33 | default = null 34 | } 35 | 36 | variable "username_attributes" { 37 | type = set(string) 38 | description = "(Optional) Specifies whether email addresses or phone numbers can be specified as usernames when a user signs up. Conflicts with alias_attributes." 39 | default = null 40 | } 41 | 42 | variable "allow_admin_create_user_only" { 43 | type = bool 44 | description = "(Optional) Set to True if only the administrator is allowed to create user profiles. Set to False if users can sign themselves up via an app." 45 | default = true 46 | } 47 | 48 | variable "resource_servers" { 49 | description = "(Optional) A list of objects with resource server definitions." 50 | type = any 51 | 52 | # Declare resource servers and associated custom scopes 53 | # For details please see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server 54 | # 55 | # Example: 56 | # 57 | # resource_servers = [ 58 | # { 59 | # identifier = "https://api.resourceserver.com" 60 | # name = "API" 61 | # scopes = [ 62 | # { 63 | # scope_name = "users:read" 64 | # scope_description = "Read user data" 65 | # }, 66 | # { 67 | # scope_name = "users:write" 68 | # scope_description = "Write user data" 69 | # } 70 | # ] 71 | # } 72 | # ] 73 | 74 | default = [] 75 | } 76 | 77 | variable "clients" { 78 | description = "(Optional) A list of objects with the clients definitions." 79 | type = any 80 | 81 | # A list of clients that follow the normal schema defined by the provider. 82 | # For details please see https://www.terraform.io/docs/providers/aws/r/cognito_user_pool_client.html 83 | # 84 | # Example: 85 | # 86 | # clients = [ 87 | # { 88 | # name = "android-mobile-client" 89 | # read_attributes = ["email", "email_verified", "preferred_username"] 90 | # allowed_oauth_scopes = ["email", "openid"] 91 | # allowed_oauth_flows = ["implicit"] 92 | # callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 93 | # default_redirect_uri = "https://mineiros.io/callback" 94 | # generate_secret = true 95 | # } 96 | # ] 97 | 98 | default = [] 99 | } 100 | 101 | variable "domain" { 102 | description = "(Optional) Type a domain prefix to use for the sign-up and sign-in pages that are hosted by Amazon Cognito, e.g. 'https://{YOUR_PREFIX}.auth.eu-west-1.amazoncognito.com'. The prefix must be unique across the selected AWS Region. Domain names can only contain lower-case letters, numbers, and hyphens." 103 | type = string 104 | default = null 105 | } 106 | 107 | variable "certificate_arn" { 108 | description = "(Optional) The ARN of an ISSUED ACM certificate in us-east-1 for a custom domain." 109 | type = string 110 | default = null 111 | } 112 | 113 | variable "default_client_allowed_oauth_flows" { 114 | description = "(Optional) List of allowed OAuth flows. Possible flows are 'code', 'implicit', and 'client_credentials'." 115 | type = list(string) 116 | default = null 117 | } 118 | 119 | variable "default_client_allowed_oauth_flows_user_pool_client" { 120 | description = "(Optional) Whether the client is allowed to follow the OAuth protocol when interacting with Cognito User Pools." 121 | type = bool 122 | default = null 123 | } 124 | 125 | variable "default_client_allowed_oauth_scopes" { 126 | description = "(Optional) List of allowed OAuth scopes. Possible values are 'phone', 'email', 'openid', 'profile', and 'aws.cognito.signin.user.admin'." 127 | type = list(string) 128 | default = null 129 | } 130 | 131 | variable "default_client_callback_urls" { 132 | description = "(Optional) List of allowed callback URLs for the identity providers." 133 | type = list(string) 134 | default = null 135 | } 136 | 137 | variable "default_client_default_redirect_uri" { 138 | description = "(Optional) The default redirect URI. Must be in the list of callback URLs." 139 | type = string 140 | default = null 141 | } 142 | 143 | variable "default_client_explicit_auth_flows" { 144 | description = "(Optional) List of authentication flows. Possible values are 'ADMIN_NO_SRP_AUTH', 'CUSTOM_AUTH_FLOW_ONLY', 'USER_PASSWORD_AUTH', 'ALLOW_ADMIN_USER_PASSWORD_AUTH', 'ALLOW_CUSTOM_AUTH', 'ALLOW_USER_PASSWORD_AUTH', 'ALLOW_USER_SRP_AUTH', and 'ALLOW_REFRESH_TOKEN_AUTH'." 145 | type = list(string) 146 | default = null 147 | } 148 | 149 | variable "default_client_generate_secret" { 150 | description = "(Optional) Boolean flag for generating an application secret." 151 | type = bool 152 | default = null 153 | } 154 | 155 | variable "default_client_logout_urls" { 156 | description = "(Optional) List of allowed logout URLs for the identity providers." 157 | type = list(string) 158 | default = null 159 | } 160 | 161 | 162 | variable "default_client_read_attributes" { 163 | description = "(Optional) List of Cognito User Pool attributes the application client can read from." 164 | type = list(string) 165 | default = null 166 | } 167 | 168 | variable "default_client_refresh_token_validity" { 169 | description = "(Optional) The time limit in days refresh tokens are valid for." 170 | type = number 171 | default = 30 172 | } 173 | 174 | variable "default_client_prevent_user_existence_errors" { 175 | description = "(Optional) Choose which errors and responses are returned by Cognito APIs during authentication, account confirmation, and password recovery when the user does not exist in the Cognito User Pool. When set to 'ENABLED' and the user does not exist, authentication returns an error indicating either the username or password was incorrect, and account confirmation and password recovery return a response indicating a code was sent to a simulated destination. When set to 'LEGACY', those APIs will return a 'UserNotFoundException' exception if the user does not exist in the Cognito User Pool." 176 | type = string 177 | default = null 178 | } 179 | 180 | variable "default_client_supported_identity_providers" { 181 | description = "(Optional) List of provider names for the identity providers that are supported on this client." 182 | type = list(string) 183 | default = null 184 | } 185 | 186 | variable "default_client_write_attributes" { 187 | description = "(Optional) List of Cognito User Pool attributes the application client can write to." 188 | type = list(string) 189 | default = null 190 | } 191 | 192 | variable "default_client_access_token_validity" { 193 | description = "(Optional) Time limit, between 5 minutes and 1 day, after which the access token is no longer valid and cannot be used. This value will be overridden if you have entered a value in 'default_client_token_validity_units'." 194 | type = number 195 | default = null 196 | } 197 | 198 | variable "default_client_id_token_validity" { 199 | description = "(Optional) Time limit, between 5 minutes and 1 day, after which the ID token is no longer valid and cannot be used. This value will be overridden if you have entered a value in 'default_client_token_validity_units'." 200 | type = number 201 | default = null 202 | } 203 | 204 | variable "default_client_token_validity_units" { 205 | description = "(Optional) Configuration block for units in which the validity times are represented in." 206 | # type = object({ 207 | # refresh_token = optional(string) 208 | # access_token = optional(string) 209 | # id_token = optional(string) 210 | # }) 211 | type = any 212 | default = null 213 | 214 | # Example: 215 | # 216 | # default_client_token_validity_units = { 217 | # refresh_token = "days" 218 | # access_token = "minutes" 219 | # id_token = "minutes" 220 | # } 221 | } 222 | 223 | variable "default_client_enable_token_revocation" { 224 | description = "(Optional) Enables or disables token revocation." 225 | type = bool 226 | default = null 227 | } 228 | 229 | variable "invite_email_subject" { 230 | type = string 231 | description = "(Optional) The subject for email messages." 232 | default = "Your new account." 233 | } 234 | 235 | variable "invite_email_message" { 236 | type = string 237 | description = "(Optional) The message template for email messages. Must contain {username} and {####} placeholders, for username and temporary password, respectively." 238 | default = "Your username is {username} and your temporary password is '{####}'." 239 | } 240 | 241 | variable "invite_sms_message" { 242 | type = string 243 | description = "(Optional) The message template for SMS messages. Must contain {username} and {####} placeholders, for username and temporary password, respectively." 244 | default = "Your username is {username} and your temporary password is '{####}'." 245 | } 246 | 247 | variable "auto_verified_attributes" { 248 | type = set(string) 249 | description = "(Optional) The attributes to be auto-verified. Possible values: 'email', 'phone_number'." 250 | default = [ 251 | "email" 252 | ] 253 | } 254 | 255 | variable "account_recovery_mechanisms" { 256 | type = any 257 | description = "(Optional) A list of recovery_mechanisms which are defined by a `name` and its `priority`. Valid values for `name` are veri fied_email, verified_phone_number, and admin_only." 258 | 259 | # Example: 260 | # 261 | # account_recovery_setting_recovery_mechanisms = [ 262 | # { 263 | # name = "verified_email" 264 | # priority = 1 265 | # }, 266 | # { 267 | # name = "verified_phone_number" 268 | # priority = 2 269 | # } 270 | # ] 271 | 272 | default = [] 273 | } 274 | 275 | 276 | variable "challenge_required_on_new_device" { 277 | type = bool 278 | description = "(Optional) Indicates whether a challenge is required on a new device. Only applicable to a new device." 279 | default = true 280 | } 281 | 282 | variable "user_device_tracking" { 283 | type = string 284 | description = "(Optional) Configure tracking of user devices. Set to 'OFF' to disable tracking, 'ALWAYS' to track all devices or 'USER_OPT_IN' to only track when user opts in." 285 | default = "USER_OPT_IN" 286 | } 287 | 288 | variable "enable_username_case_sensitivity" { 289 | type = bool 290 | description = "(Optional) Specifies whether username case sensitivity will be applied for all users in the user pool through Cognito APIs." 291 | default = false 292 | } 293 | 294 | variable "email_sending_account" { 295 | type = string 296 | description = "(Optional) The email delivery method to use. 'COGNITO_DEFAULT' for the default email functionality built into Cognito or 'DEVELOPER' to use your Amazon SES configuration." 297 | default = "COGNITO_DEFAULT" 298 | } 299 | 300 | variable "email_reply_to_address" { 301 | type = string 302 | description = "(Optional) - The REPLY-TO email address." 303 | default = null 304 | } 305 | 306 | variable "email_source_arn" { 307 | type = string 308 | description = "(Optional) - The ARN of the email source." 309 | default = null 310 | } 311 | 312 | variable "email_from_address" { 313 | type = string 314 | description = "(Optional) - Sender’s email address or sender’s name with their email address (e.g. 'john@smith.com' or 'John Smith ')." 315 | default = null 316 | } 317 | 318 | variable "mfa_configuration" { 319 | type = string 320 | description = "Multi-Factor Authentication (MFA) configuration for the User Pool. Valid values: 'ON', 'OFF' or 'OPTIONAL'. 'ON' and 'OPTIONAL' require at least one of 'sms_configuration' or 'software_token_mfa_configuration' to be configured." 321 | default = "OPTIONAL" 322 | } 323 | 324 | variable "password_minimum_length" { 325 | type = number 326 | description = "(Optional) The minimum length of the password policy that you have set." 327 | default = 20 328 | } 329 | 330 | variable "password_require_lowercase" { 331 | type = bool 332 | description = "(Optional) Whether you have required users to use at least one lowercase letter in their password." 333 | default = true 334 | } 335 | 336 | variable "password_require_numbers" { 337 | type = bool 338 | description = "(Optional) Whether you have required users to use at least one number in their password." 339 | default = true 340 | } 341 | 342 | variable "password_require_symbols" { 343 | type = bool 344 | description = "(Optional) Whether you have required users to use at least one symbol in their password." 345 | default = true 346 | } 347 | 348 | variable "password_require_uppercase" { 349 | type = bool 350 | description = "(Optional) Whether you have required users to use at least one uppercase letter in their password." 351 | default = true 352 | } 353 | 354 | variable "temporary_password_validity_days" { 355 | type = number 356 | description = "(Optional) In the password policy you have set, refers to the number of days a temporary password is valid. If the user does not sign-in during this time, their password will need to be reset by an administrator." 357 | default = 1 358 | } 359 | 360 | variable "allow_software_mfa_token" { 361 | description = "(Optional) Boolean whether to enable software token Multi-Factor (MFA) tokens, such as Time-based One-Time Password (TOTP). To disable software token MFA when 'sms_configuration' is not present, the 'mfa_configuration' argument must be set to OFF and the 'software_token_mfa_configuration' configuration block must be fully removed." 362 | type = bool 363 | default = true 364 | } 365 | 366 | variable "sms_authentication_message" { 367 | type = string 368 | description = "(Optional) A string representing the SMS authentication message. The message must contain the {####} placeholder, which will be replaced with the authentication code." 369 | default = "Your temporary password is {####}." 370 | } 371 | 372 | variable "lambda_create_auth_challenge" { 373 | type = string 374 | description = "(Optional) The ARN of an AWS Lambda creating an authentication challenge." 375 | default = null 376 | } 377 | 378 | variable "lambda_custom_message" { 379 | type = string 380 | description = "(Optional) The ARN of a custom message AWS Lambda trigger." 381 | default = null 382 | } 383 | 384 | variable "lambda_define_auth_challenge" { 385 | type = string 386 | description = "(Optional) The ARN of an AWS Lambda that defines the authentication challenge." 387 | default = null 388 | } 389 | 390 | variable "lambda_post_authentication" { 391 | type = string 392 | description = "(Optional) The ARN of a post-authentication AWS Lambda trigger." 393 | default = null 394 | } 395 | 396 | variable "lambda_post_confirmation" { 397 | type = string 398 | description = "(Optional) The ARN of a post-confirmation AWS Lambda trigger." 399 | default = null 400 | } 401 | 402 | variable "lambda_pre_authentication" { 403 | type = string 404 | description = "(Optional) The ARN of a pre-authentication AWS Lambda trigger." 405 | default = null 406 | } 407 | 408 | variable "lambda_pre_sign_up" { 409 | type = string 410 | description = "(Optional) The ARN of a pre-registration AWS Lambda trigger." 411 | default = null 412 | } 413 | 414 | variable "lambda_pre_token_generation" { 415 | type = string 416 | description = "(Optional) The ARN of an AWS Lambda that allows customization of identity token claims before token generation." 417 | default = null 418 | } 419 | 420 | variable "lambda_user_migration" { 421 | type = string 422 | description = "(Optional) The ARN of the user migration AWS Lambda config type." 423 | default = null 424 | } 425 | 426 | variable "lambda_verify_auth_challenge_response" { 427 | type = string 428 | description = "(Optional) The ARN of an AWS Lambda that verifies the authentication challenge response." 429 | default = null 430 | } 431 | 432 | variable "schema_attributes" { 433 | description = "(Optional) A list of schema attributes of a user pool. You can add a maximum of 25 custom attributes." 434 | type = any 435 | 436 | # Example: 437 | # 438 | # schema_attributes = [ 439 | # { 440 | # name = "alternative_name" 441 | # type = "String" 442 | # developer_only_attribute = false, 443 | # mutable = true, 444 | # required = false, 445 | # min_length = 0, 446 | # max_length = 2048 447 | # }, 448 | # { 449 | # name = "friends_count" 450 | # type = "Number" 451 | # min_value = 0, 452 | # max_value = 100 453 | # 454 | # }, 455 | # { 456 | # 457 | # name = "is_active" 458 | # type = "Boolean" 459 | # 460 | # }, 461 | # { 462 | # name = "last_seen" 463 | # type = "DateTime" 464 | # 465 | # } 466 | # ] 467 | 468 | default = [] 469 | } 470 | 471 | variable "sms_configuration" { 472 | description = "(Optional) The `sms_configuration` with the `external_id` parameter used in iam role trust relationships and the `sns_caller_arn` parameter to set he arn of the amazon sns caller. this is usually the iam role that you've given cognito permission to assume." 473 | type = object({ 474 | # The external ID used in IAM role trust relationships. For more information about using external IDs, see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html 475 | external_id = string 476 | # The ARN of the Amazon SNS caller. This is usually the IAM role that you've given Cognito permission to assume. 477 | sns_caller_arn = string 478 | }) 479 | default = null 480 | } 481 | 482 | variable "default_email_option" { 483 | type = string 484 | description = "(Optional) The default email option. Must be either `CONFIRM_WITH_CODE` or `CONFIRM_WITH_LINK`." 485 | default = "CONFIRM_WITH_CODE" 486 | } 487 | 488 | variable "email_message" { 489 | type = string 490 | description = "(Optional) The email message template. Must contain the {####} placeholder." 491 | default = "Your verification code is {####}." 492 | } 493 | 494 | variable "email_message_by_link" { 495 | type = string 496 | description = "(Optional) The email message template for sending a confirmation link to the user, it must contain the {##Any Text##} placeholder." 497 | default = "Please click the link below to verify your email address. {##Verify Email##}." 498 | } 499 | 500 | variable "email_subject" { 501 | type = string 502 | description = "(Optional) The subject line for the email message template." 503 | default = "Your Verification Code" 504 | } 505 | 506 | variable "email_subject_by_link" { 507 | type = string 508 | description = "(Optional) The subject line for the email message template for sending a confirmation link to the user." 509 | default = "Your Verification Link" 510 | } 511 | 512 | variable "sms_message" { 513 | type = string 514 | description = "(Optional) The SMS message template. Must contain the {####} placeholder, which will be replaced with the verification code. Can also contain the {username} placeholder which will be replaced with the username." 515 | default = "Your verification code is {####}." 516 | } 517 | 518 | variable "tags" { 519 | type = map(string) 520 | description = "(Optional) A mapping of tags to assign to the resource." 521 | 522 | # 523 | # Example: 524 | # 525 | # tags = { 526 | # CreatedAt = "2020-02-07", 527 | # Alice = "Bob 528 | # } 529 | # 530 | 531 | default = {} 532 | } 533 | 534 | # ------------------------------------------------------------------------------ 535 | # OPTIONAL MODULE CONFIGURATION PARAMETERS 536 | # These variables are used to configure the module. 537 | # ------------------------------------------------------------------------------ 538 | 539 | variable "module_enabled" { 540 | type = bool 541 | description = "(Optional) Whether to create resources within the module or not." 542 | default = true 543 | } 544 | 545 | variable "module_tags" { 546 | type = map(string) 547 | 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." 548 | default = {} 549 | } 550 | 551 | variable "module_depends_on" { 552 | type = any 553 | description = "(Optional) A list of external resources the module depends_on." 554 | default = [] 555 | } 556 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://mineiros.io/?ref=terraform-aws-cognito-user-pool) 2 | 3 | [![Build Status](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/workflows/CI/CD%20Pipeline/badge.svg)](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/actions) 4 | [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-cognito-user-pool.svg?label=latest&sort=semver)](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/releases) 5 | [![Terraform Version](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)](https://github.com/hashicorp/terraform/releases) 6 | [![AWS Provider Version](https://img.shields.io/badge/AWS-3.50+-F8991D.svg?logo=terraform)](https://github.com/terraform-providers/terraform-provider-aws/releases) 7 | [![Join Slack](https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack)](https://mineiros.io/slack) 8 | 9 | # terraform-aws-cognito-user-pool 10 | 11 | A [Terraform] module for deploying and managing 12 | [Cognito User Pools] 13 | on [Amazon Web Services (AWS)][AWS]. 14 | 15 | *This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above 16 | and is compatible with the Terraform AWS provider v3.50 and above. 17 | 18 | 19 | - [Module Features](#module-features) 20 | - [Getting Started](#getting-started) 21 | - [Module Argument Reference](#module-argument-reference) 22 | - [Top-level Arguments](#top-level-arguments) 23 | - [Module Configuration](#module-configuration) 24 | - [Cognito User Pool](#cognito-user-pool) 25 | - [Cognito User Pool Domain](#cognito-user-pool-domain) 26 | - [Cognito User Pool Resource Servers](#cognito-user-pool-resource-servers) 27 | - [Cognito User Pool Clients](#cognito-user-pool-clients) 28 | - [Cognito User Pool Clients Default Values](#cognito-user-pool-clients-default-values) 29 | - [Module Outputs](#module-outputs) 30 | - [External Documentation](#external-documentation) 31 | - [AWS Documentation](#aws-documentation) 32 | - [Terraform AWS Provider Documentation](#terraform-aws-provider-documentation) 33 | - [Module Versioning](#module-versioning) 34 | - [Backwards compatibility in `0.0.z` and `0.y.z` version](#backwards-compatibility-in-00z-and-0yz-version) 35 | - [About Mineiros](#about-mineiros) 36 | - [Reporting Issues](#reporting-issues) 37 | - [Contributing](#contributing) 38 | - [Makefile Targets](#makefile-targets) 39 | - [License](#license) 40 | 41 | ## Module Features 42 | 43 | In contrast to the plain [`cognito_user_pool`](https://www.terraform.io/docs/providers/aws/r/cognito_user_pool.html) 44 | resource this module has a more secure level of default settings. 45 | 46 | While all settings can be customized as needed, best practices are 47 | pre-configured. 48 | 49 | - **Default Security Settings**: 50 | Per default, only administrators are allowed to create user profiles by 51 | setting `allow_admin_create_user_only` to `true`. This module comes with a 52 | strong default password policy. 53 | 54 | **Standard Cognito Features**: 55 | Create a Cognito User Pool with pre-configured best practices. 56 | Create Cognito User Pool Clients. 57 | Create a Cognito User Pool Domain. 58 | Create Cognito User Pool Resource Servers as associated scopes. 59 | 60 | - *Features not yet implemented*: 61 | [`cognito_user_group`](https://www.terraform.io/docs/providers/aws/r/cognito_user_group.html) 62 | 63 | ## Getting Started 64 | 65 | Most basic usage just setting required arguments: 66 | 67 | ```hcl 68 | module "terraform-aws-cognito-user-pool" { 69 | source = "mineiros-io/cognito-user-pool/aws" 70 | version = "~> 0.9.0" 71 | 72 | name = "application-userpool" 73 | } 74 | ``` 75 | 76 | Advanced usage as found in 77 | [examples/complete/main.tf](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/complete/main.tf) 78 | setting all required and optional arguments to their default values. 79 | 80 | ## Module Argument Reference 81 | 82 | See 83 | [variables.tf](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/variables.tf) 84 | and 85 | [examples/](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples) 86 | for details and use-cases. 87 | 88 | ### Top-level Arguments 89 | 90 | #### Module Configuration 91 | 92 | - [**`module_enabled`**](#var-module_enabled): *(Optional `bool`)* 93 | 94 | Specifies whether resources in the module will be created. 95 | 96 | Default is `true`. 97 | 98 | - [**`module_tags`**](#var-module_tags): *(Optional `map(string)`)* 99 | 100 | 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. 101 | 102 | Default is `{}`. 103 | 104 | Example: 105 | 106 | ```hcl 107 | module_tags = { 108 | environment = "staging" 109 | team = "platform" 110 | } 111 | ``` 112 | 113 | - [**`module_depends_on`**](#var-module_depends_on): *(Optional `list(dependency)`)* 114 | 115 | A list of dependencies. Any object can be _assigned_ to this list to define a hidden external dependency. 116 | 117 | Example: 118 | 119 | ```hcl 120 | module_depends_on = [ 121 | aws_vpc.vpc 122 | ] 123 | ``` 124 | 125 | #### Cognito User Pool 126 | 127 | - [**`name`**](#var-name): *(**Required** `string`)* 128 | 129 | The name of the user pool. Forces new resource. 130 | 131 | - [**`advanced_security_mode`**](#var-advanced_security_mode): *(Optional `string`)* 132 | 133 | The mode for advanced security, must be one of `OFF`, `AUDIT` or `ENFORCED`. Additional pricing applies for Amazon Cognito advanced security features. For details see https://aws.amazon.com/cognito/pricing/. 134 | 135 | Default is `"OFF"`. 136 | 137 | - [**`alias_attributes`**](#var-alias_attributes): *(Optional `set(string)`)* 138 | 139 | Attributes supported as an alias for this user pool. Possible values: `phone_number`, `email`, or `preferred_username`. Conflicts with `username_attributes`. Default applies if `username_attributes` is not set. 140 | 141 | - [**`username_attributes`**](#var-username_attributes): *(Optional `set(string)`)* 142 | 143 | Specifies whether `email` addresse or `phone_number` can be specified as usernames when a user signs up. Conflicts with `alias_attributes`. 144 | Default is to use `alias_attributes`. 145 | 146 | - [**`allow_admin_create_user_only`**](#var-allow_admin_create_user_only): *(Optional `bool`)* 147 | 148 | Set to True if only the administrator is allowed to create user profiles. Set to False if users can sign themselves up via an app. 149 | 150 | Default is `true`. 151 | 152 | - [**`invite_email_subject`**](#var-invite_email_subject): *(Optional `string`)* 153 | 154 | The message template for email messages. 155 | 156 | Default is `"Your new account."`. 157 | 158 | - [**`invite_email_message`**](#var-invite_email_message): *(Optional `string`)* 159 | 160 | The message template for email messages. Must contain `{username}` and `{####}` placeholders, for username and temporary password, respectively. 161 | 162 | Default is `"Your username is {username} and your temporary password is ' {####}'"`. 163 | 164 | - [**`invite_sms_message`**](#var-invite_sms_message): *(Optional `string`)* 165 | 166 | The message template for SMS messages. Must contain `{username}` and `{####}` placeholders, for username and temporary password, respectively. 167 | 168 | Default is `"Your username is {username} and your temporary password is ' {####}'."`. 169 | 170 | - [**`auto_verified_attributes`**](#var-auto_verified_attributes): *(Optional `set(string)`)* 171 | 172 | The attributes to be auto-verified. Possible values: `email`, `phone_number`. 173 | 174 | Default is `["email"]`. 175 | 176 | - [**`user_device_tracking`**](#var-user_device_tracking): *(Optional `string`)* 177 | 178 | Configure tracking of user devices. Set to `OFF` to disable tracking, `ALWAYS` to track all devices or `USER_OPT_IN` to only track when user opts in. 179 | 180 | Default is `"USER_OPT_IN"`. 181 | 182 | - [**`challenge_required_on_new_device`**](#var-challenge_required_on_new_device): *(Optional `bool`)* 183 | 184 | Indicates whether a challenge is required on a new device. Only applicable to a new device. Only applied when `user_device_tracking` is enabled. 185 | 186 | Default is `true`. 187 | 188 | - [**`enable_username_case_sensitivity`**](#var-enable_username_case_sensitivity): *(Optional `bool`)* 189 | 190 | Specifies whether username case sensitivity will be applied to all users in the user pool through Cognito APIs. 191 | 192 | Default is `false`. 193 | 194 | - [**`email_sending_account`**](#var-email_sending_account): *(Optional `string`)* 195 | 196 | The email delivery method to use. `COGNITO_DEFAULT` for the default email functionality built into Cognito or `DEVELOPER` to use your Amazon SES configuration. 197 | 198 | Default is `"COGNITO_DEFAULT"`. 199 | 200 | - [**`email_reply_to_address`**](#var-email_reply_to_address): *(Optional `string`)* 201 | 202 | The REPLY-TO email address. 203 | 204 | - [**`email_source_arn`**](#var-email_source_arn): *(Optional `string`)* 205 | 206 | The ARN of the email source. 207 | 208 | - [**`email_from_address`**](#var-email_from_address): *(Optional `string`)* 209 | 210 | Sender’s email address or sender’s name with their email address (e.g. 'john@smith.com' or 'John Smith '). 211 | 212 | - [**`mfa_configuration`**](#var-mfa_configuration): *(Optional `string`)* 213 | 214 | Multi-Factor Authentication (MFA) configuration for the User Pool. Valid values: `ON`, `OFF` or `OPTIONAL`. `ON` and `OPTIONAL` require at least one of `sms_configuration` or `software_token_mfa_configuration` to be configured. 215 | 216 | Default is `"OPTIONAL"`. 217 | 218 | - [**`password_minimum_length`**](#var-password_minimum_length): *(Optional `number`)* 219 | 220 | The minimum length of the password policy that you have set. 221 | 222 | Default is `20`. 223 | 224 | - [**`password_require_lowercase`**](#var-password_require_lowercase): *(Optional `bool`)* 225 | 226 | Whether you have required users to use at least one lowercase letter in their password. 227 | 228 | Default is `true`. 229 | 230 | - [**`password_require_numbers`**](#var-password_require_numbers): *(Optional `bool`)* 231 | 232 | Whether you have required users to use at least one number in their password. 233 | 234 | Default is `true`. 235 | 236 | - [**`password_require_symbols`**](#var-password_require_symbols): *(Optional `bool`)* 237 | 238 | Whether you have required users to use at least one symbol in their password. 239 | 240 | Default is `true`. 241 | 242 | - [**`password_require_uppercase`**](#var-password_require_uppercase): *(Optional `bool`)* 243 | 244 | Whether you have required users to use at least one uppercase letter in their password. 245 | 246 | Default is `true`. 247 | 248 | - [**`temporary_password_validity_days`**](#var-temporary_password_validity_days): *(Optional `number`)* 249 | 250 | In the password policy you have set, refers to the number of days a temporary password is valid. If the user does not sign in during this time, their password will need to be reset by an administrator. 251 | 252 | Default is `1`. 253 | 254 | - [**`allow_software_mfa_token`**](#var-allow_software_mfa_token): *(Optional `bool`)* 255 | 256 | Boolean whether to enable software token Multi-Factor Authentication (MFA) tokens, such as Time-Based One-Time Password (TOTP). To disable software token MFA when `sms_configuration` is not present, the `mfa_configuration` argument must be set to `OFF` and the `software_token_mfa_configuration` configuration block must be fully removed. 257 | 258 | Default is `true`. 259 | 260 | - [**`sms_authentication_message`**](#var-sms_authentication_message): *(Optional `string`)* 261 | 262 | A string representing the SMS authentication message. The message must contain the `{####}` placeholder, which will be replaced with the authentication code. 263 | 264 | Default is `"Your temporary password is {####}."`. 265 | 266 | - [**`lambda_create_auth_challenge`**](#var-lambda_create_auth_challenge): *(Optional `string`)* 267 | 268 | The ARN of an AWS Lambda creating an authentication challenge. 269 | 270 | - [**`lambda_custom_message`**](#var-lambda_custom_message): *(Optional `string`)* 271 | 272 | The ARN of a custom message AWS Lambda trigger. 273 | 274 | - [**`lambda_define_auth_challenge`**](#var-lambda_define_auth_challenge): *(Optional `string`)* 275 | 276 | The ARN of an AWS Lambda that defines the authentication challenge. 277 | 278 | - [**`lambda_post_authentication`**](#var-lambda_post_authentication): *(Optional `string`)* 279 | 280 | The ARN of an AWS Lambda that defines the authentication challenge. 281 | 282 | - [**`lambda_post_confirmation`**](#var-lambda_post_confirmation): *(Optional `string`)* 283 | 284 | The ARN of a post-confirmation AWS Lambda trigger. 285 | 286 | - [**`lambda_pre_authentication`**](#var-lambda_pre_authentication): *(Optional `string`)* 287 | 288 | The ARN of a pre-authentication AWS Lambda trigger. 289 | 290 | - [**`lambda_pre_sign_up`**](#var-lambda_pre_sign_up): *(Optional `string`)* 291 | 292 | The ARN of a pre-registration AWS Lambda trigger. 293 | 294 | - [**`lambda_pre_token_generation`**](#var-lambda_pre_token_generation): *(Optional `string`)* 295 | 296 | The ARN of an AWS Lambda that allows customization of identity token claims before token generation. 297 | 298 | - [**`lambda_user_migration`**](#var-lambda_user_migration): *(Optional `string`)* 299 | 300 | The ARN of he user migration AWS Lambda config type. 301 | 302 | - [**`lambda_verify_auth_challenge_response`**](#var-lambda_verify_auth_challenge_response): *(Optional `string`)* 303 | 304 | The ARN of an AWS Lambda that verifies the authentication challenge response. 305 | 306 | Default is `"true"`. 307 | 308 | - [**`schema_attributes`**](#var-schema_attributes): *(Optional `list(schema_attribute)`)* 309 | 310 | A list of schema attributes of a user pool. You can add a maximum of 25 custom attributes. Please note that only default attributes can be marked as required. 311 | Also an attribute cannot be switched between required and not required after a user pool has been created. 312 | For details please see the [attributes docs]. 313 | 314 | Default is `[]`. 315 | 316 | Example: 317 | 318 | ```hcl 319 | schema_attributes = [ 320 | { 321 | name = "gender", # overwrites the default attribute 'gender' 322 | type = "String" 323 | required = true # required can only be set for default attributes 324 | }, 325 | { 326 | name = "alternative_name" 327 | type = "String" 328 | min_length = 0, 329 | max_length = 2048 330 | }, 331 | { 332 | name = "friends_count" 333 | type = "Number" 334 | min_value = 0, 335 | max_value = 100 336 | }, 337 | { 338 | name = "is_active" 339 | type = "Boolean" 340 | }, 341 | { 342 | name = "last_seen" 343 | type = "DateTime" 344 | } 345 | ] 346 | ``` 347 | 348 | - [**`account_recovery_mechanisms`**](#var-account_recovery_mechanisms): *(Optional `list(account_recovery_mechanism)`)* 349 | 350 | A list of recovery_mechanisms to be inserted inside `account_recovery_setting`. 351 | 352 | Default is `[]`. 353 | 354 | Example: 355 | 356 | ```hcl 357 | account_recovery_mechanisms = [ 358 | { 359 | name = "verified_email" 360 | priority = 1 361 | }, 362 | { 363 | name = "verified_phone_number" 364 | priority = 2 365 | } 366 | ] 367 | ``` 368 | 369 | Each `account_recovery_mechanism` object in the list accepts the following attributes: 370 | 371 | - [**`name`**](#attr-account_recovery_mechanisms-name): *(**Required** `string`)* 372 | 373 | Recovery method for a user. Can be of the following: verified_email, verified_phone_number, and admin_only. 374 | 375 | - [**`priority`**](#attr-account_recovery_mechanisms-priority): *(**Required** `string`)* 376 | 377 | Positive integer specifying priority of a method with 1 being the highest priority. 378 | 379 | - [**`sms_configuration`**](#var-sms_configuration): *(Optional `object(sms_configuration)`)* 380 | 381 | The `sms_configuration` with the `external_id` parameter used in IAM role trust relationships and the `sns_caller_arn` parameter to set the ARN of the Amazon SNS caller. This is usually the IAM role that you have given AWS Cognito permission to assume. 382 | 383 | The `sms_configuration` object accepts the following attributes: 384 | 385 | - [**`external_id`**](#attr-sms_configuration-external_id): *(**Required** `string`)* 386 | 387 | External ID used in IAM role trust relationships. 388 | 389 | - [**`sns_caller_arn`**](#attr-sms_configuration-sns_caller_arn): *(**Required** `string`)* 390 | 391 | ARN of the Amazon SNS caller. This is usually the IAM role that you've given Cognito permission to assume. 392 | 393 | - [**`default_email_option`**](#var-default_email_option): *(Optional `string`)* 394 | 395 | The default email option. Must be either `CONFIRM_WITH_CODE` or `CONFIRM_WITH_LINK`. 396 | 397 | Default is `"CONFIRM_WITH_CODE"`. 398 | 399 | - [**`email_message`**](#var-email_message): *(Optional `string`)* 400 | 401 | The email message template. Must contain the `{####}` placeholder. 402 | 403 | Default is `"Your verification code is {####}."`. 404 | 405 | - [**`email_message_by_link`**](#var-email_message_by_link): *(Optional `string`)* 406 | 407 | The email message template for sending a confirmation link to the user, it must contain the `{##Any Text##}` placeholder. 408 | 409 | Default is `"Please click the link below to verify your email address.{##Verify Email##}."`. 410 | 411 | - [**`email_subject`**](#var-email_subject): *(Optional `string`)* 412 | 413 | The subject line for the email message template. 414 | 415 | Default is `"Your Verification Code"`. 416 | 417 | - [**`email_subject_by_link`**](#var-email_subject_by_link): *(Optional `string`)* 418 | 419 | The subject line for the email message template for sending a confirmation link to the user. 420 | 421 | Default is `"Your Verifiction Link"`. 422 | 423 | - [**`sms_message`**](#var-sms_message): *(Optional `string`)* 424 | 425 | The SMS message template. Must contain the `{####}` placeholder, which will be replaced with the verification code. Can also contain the `{username}` placeholder which will be replaced with the username. 426 | 427 | Default is `"Your verification code is {####}."`. 428 | 429 | - [**`tags`**](#var-tags): *(Optional `map(string)`)* 430 | 431 | A mapping of tags to assign to the resource. 432 | 433 | Default is `{}`. 434 | 435 | Example: 436 | 437 | ```hcl 438 | tags = { 439 | CreatedAt = "2020-02-07", 440 | Alice = "Bob" 441 | } 442 | ``` 443 | 444 | #### Cognito User Pool Domain 445 | 446 | - [**`domain`**](#var-domain): *(Optional `string`)* 447 | 448 | The domain name that should be used. Can be set to a FQDN or prefix. 449 | If no FQDN and `certificate_arn` are set, the domain prefix will be used for the sign-up and sign-in pages that are hosted by Amazon Cognito, 450 | e.g. `https://{YOUR_PREFIX}.auth.eu-west-1.amazoncognito.com`. 451 | The prefix must be unique across the selected AWS Region. 452 | Domain names can only contain lower-case letters, numbers, and hyphens. 453 | 454 | - [**`certificate_arn`**](#var-certificate_arn): *(Optional `string`)* 455 | 456 | The ARN of an ISSUED ACM certificate in us-east-1 for a custom domain. 457 | 458 | #### Cognito User Pool Resource Servers 459 | 460 | - [**`resource_servers`**](#var-resource_servers): *(Optional `list(resource_server)`)* 461 | 462 | A list of objects with resource server declarations. 463 | 464 | Default is `[]`. 465 | 466 | Example: 467 | 468 | ```hcl 469 | resource_servers = [ 470 | { 471 | identifier = "https://api.resourceserver.com" 472 | name = "API" 473 | scopes = [ 474 | { 475 | scope_name = "users:read" 476 | scope_description = "Read user data" 477 | }, 478 | { 479 | scope_name = "users:write" 480 | scope_description = "Write user data" 481 | } 482 | ] 483 | } 484 | ] 485 | ``` 486 | 487 | Each `resource_server` object in the list accepts the following attributes: 488 | 489 | - [**`identifier`**](#attr-resource_servers-identifier): *(**Required** `string`)* 490 | 491 | An identifier for the resource server. 492 | 493 | - [**`name`**](#attr-resource_servers-name): *(**Required** `string`)* 494 | 495 | A name for the resource server. 496 | 497 | - [**`scope`**](#attr-resource_servers-scope): *(Optional `list(scope)`)* 498 | 499 | A list of Authorization Scope. 500 | 501 | Each `scope` object in the list accepts the following attributes: 502 | 503 | - [**`scope_name`**](#attr-resource_servers-scope-scope_name): *(**Required** `string`)* 504 | 505 | The scope name. 506 | 507 | - [**`scope_description`**](#attr-resource_servers-scope-scope_description): *(**Required** `string`)* 508 | 509 | The scope description. 510 | 511 | #### Cognito User Pool Clients 512 | 513 | - [**`clients`**](#var-clients): *(Optional `list(client)`)* 514 | 515 | A list of objects with the clients definitions. 516 | 517 | Default is `[]`. 518 | 519 | Example: 520 | 521 | ```hcl 522 | clients = [ 523 | { 524 | name = "android-mobile-client" 525 | read_attributes = ["email", "email_verified", "preferred_username"] 526 | allowed_oauth_scopes = ["email", "openid"] 527 | allowed_oauth_flows = ["implicit"] 528 | callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 529 | default_redirect_uri = "https://mineiros.io/callback" 530 | generate_secret = true 531 | } 532 | ] 533 | ``` 534 | 535 | Each `client` object in the list accepts the following attributes: 536 | 537 | - [**`name`**](#attr-clients-name): *(**Required** `string`)* 538 | 539 | Name of the application client. 540 | 541 | - [**`user_pool_id`**](#attr-clients-user_pool_id): *(Optional `string`)* 542 | 543 | Name of the application client. 544 | 545 | - [**`access_token_validity`**](#attr-clients-access_token_validity): *(Optional `number`)* 546 | 547 | Time limit, between 5 minutes and 1 day, after which the access token is no longer valid and cannot be used. This value will be overridden if you have entered a value in token_validity_units. 548 | 549 | - [**`allowed_oauth_flows_user_pool_client`**](#attr-clients-allowed_oauth_flows_user_pool_client): *(Optional `bool`)* 550 | 551 | Whether the client is allowed to follow the OAuth protocol when interacting with Cognito user pools. 552 | 553 | - [**`allowed_oauth_flows`**](#attr-clients-allowed_oauth_flows): *(Optional `set(string)`)* 554 | 555 | List of allowed OAuth flows (code, implicit, client_credentials). 556 | 557 | - [**`allowed_oauth_scopes`**](#attr-clients-allowed_oauth_scopes): *(Optional `set(string)`)* 558 | 559 | List of allowed OAuth scopes (phone, email, openid, profile, and aws.cognito.signin.user.admin). 560 | 561 | - [**`analytics_configuration`**](#attr-clients-analytics_configuration): *(Optional `object(analytics_configuration)`)* 562 | 563 | Configuration block for Amazon Pinpoint analytics for collecting metrics for this user pool. 564 | 565 | The `analytics_configuration` object accepts the following attributes: 566 | 567 | - [**`application_arn`**](#attr-clients-analytics_configuration-application_arn): *(Optional `string`)* 568 | 569 | Application ARN for an Amazon Pinpoint application. Conflicts with external_id and role_arn. 570 | 571 | - [**`application_id`**](#attr-clients-analytics_configuration-application_id): *(Optional `string`)* 572 | 573 | Application ID for an Amazon Pinpoint application. 574 | 575 | - [**`external_id`**](#attr-clients-analytics_configuration-external_id): *(Optional `string`)* 576 | 577 | ID for the Analytics Configuration. Conflicts with application_arn. Application ID for an Amazon Pinpoint application. 578 | 579 | - [**`role_arn`**](#attr-clients-analytics_configuration-role_arn): *(Optional `string`)* 580 | 581 | ARN of an IAM role that authorizes Amazon Cognito to publish events to Amazon Pinpoint analytics. Conflicts with application_arn. 582 | 583 | - [**`user_data_shared`**](#attr-clients-analytics_configuration-user_data_shared): *(Optional `bool`)* 584 | 585 | If set to true, Amazon Cognito will include user data in the events it publishes to Amazon Pinpoint analytics. 586 | 587 | - [**`callback_urls`**](#attr-clients-callback_urls): *(Optional `set(string)`)* 588 | 589 | List of allowed callback URLs for the identity providers. 590 | 591 | - [**`default_redirect_uri`**](#attr-clients-default_redirect_uri): *(Optional `string`)* 592 | 593 | Default redirect URI. Must be in the list of callback URLs. 594 | 595 | - [**`enable_token_revocation`**](#attr-clients-enable_token_revocation): *(Optional `bool`)* 596 | 597 | Enables or disables token revocation. 598 | 599 | - [**`explicit_auth_flows`**](#attr-clients-explicit_auth_flows): *(Optional `set(string)`)* 600 | 601 | List of authentication flows (ADMIN_NO_SRP_AUTH, CUSTOM_AUTH_FLOW_ONLY, USER_PASSWORD_AUTH, ALLOW_ADMIN_USER_PASSWORD_AUTH, ALLOW_CUSTOM_AUTH, ALLOW_USER_PASSWORD_AUTH, ALLOW_USER_SRP_AUTH, ALLOW_REFRESH_TOKEN_AUTH). 602 | 603 | - [**`generate_secret`**](#attr-clients-generate_secret): *(Optional `bool`)* 604 | 605 | Should an application secret be generated. 606 | 607 | - [**`id_token_validity`**](#attr-clients-id_token_validity): *(Optional `number`)* 608 | 609 | Time limit, between 5 minutes and 1 day, after which the ID token is no longer valid and cannot be used. This value will be overridden if you have entered a value in token_validity_units. 610 | 611 | - [**`logout_urls`**](#attr-clients-logout_urls): *(Optional `set(string)`)* 612 | 613 | List of allowed logout URLs for the identity providers. 614 | 615 | - [**`prevent_user_existence_errors`**](#attr-clients-prevent_user_existence_errors): *(Optional `string`)* 616 | 617 | Choose which errors and responses are returned by Cognito APIs during authentication, account confirmation, and password recovery when the user does not exist in the user pool. When set to ENABLED and the user does not exist, authentication returns an error indicating either the username or password was incorrect, and account confirmation and password recovery return a response indicating a code was sent to a simulated destination. When set to LEGACY, those APIs will return a UserNotFoundException exception if the user does not exist in the user pool. 618 | 619 | - [**`read_attributes`**](#attr-clients-read_attributes): *(Optional `set(string)`)* 620 | 621 | List of user pool attributes the application client can read from. 622 | 623 | - [**`refresh_token_validity`**](#attr-clients-refresh_token_validity): *(Optional `number`)* 624 | 625 | Time limit in days refresh tokens are valid for. 626 | 627 | - [**`supported_identity_providers`**](#attr-clients-supported_identity_providers): *(Optional `set(string)`)* 628 | 629 | List of provider names for the identity providers that are supported on this client. Uses the provider_name attribute of aws_cognito_identity_provider resource(s), or the equivalent string(s). 630 | 631 | - [**`token_validity_units`**](#attr-clients-token_validity_units): *(Optional `object(token_validity_units)`)* 632 | 633 | Configuration block for units in which the validity times are represented in. 634 | 635 | The `token_validity_units` object accepts the following attributes: 636 | 637 | - [**`access_token`**](#attr-clients-token_validity_units-access_token): *(Optional `string`)* 638 | 639 | Time unit in for the value in access_token_validity, defaults to hours. 640 | 641 | Default is `"hours"`. 642 | 643 | - [**`id_token`**](#attr-clients-token_validity_units-id_token): *(Optional `string`)* 644 | 645 | Time unit in for the value in id_token_validity, defaults to hours. 646 | 647 | Default is `"hours"`. 648 | 649 | - [**`refresh_token`**](#attr-clients-token_validity_units-refresh_token): *(Optional `string`)* 650 | 651 | Time unit in for the value in refresh_token_validity, defaults to days. 652 | 653 | Default is `"days"`. 654 | 655 | - [**`write_attributes`**](#attr-clients-write_attributes): *(Optional `set(string)`)* 656 | 657 | List of user pool attributes the application client can write to. 658 | 659 | #### Cognito User Pool Clients Default Values 660 | 661 | The following variables can be used for setting default settings among various clients defined through the `clients` variable. This helps you to quickly issue several clients that implement the same settings, e.g. like so: 662 | 663 | ```hcl 664 | clients = [ 665 | { name = "ios" }, 666 | { name = "android" }, 667 | { name = "web" }, 668 | ] 669 | 670 | default_client_read_attributes = ["email", "email_verified", "preferred_username"] 671 | default_client_allowed_oauth_scopes = ["email", "openid"] 672 | default_client_allowed_oauth_flows = ["implicit"] 673 | default_client_callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 674 | default_client_default_redirect_uri = "https://mineiros.io/callback" 675 | default_client_generate_secret = true 676 | default_client_refresh_token_validity = 45 677 | 678 | default_client_supported_identity_providers = null 679 | default_client_logout_urls = null 680 | default_client_allowed_oauth_flows_user_pool_client = null 681 | default_client_write_attributes = null 682 | default_client_explicit_auth_flows = null 683 | default_client_prevent_user_existence_errors = null 684 | default_client_access_token_validity = null 685 | default_client_id_token_validity = null 686 | default_client_token_validity_units = null 687 | default_client_enable_token_revocation = null 688 | ``` 689 | 690 | - [**`default_client_callback_urls`**](#var-default_client_callback_urls): *(Optional `list(string)`)* 691 | 692 | List of allowed callback URLs for the identity providers. 693 | 694 | - [**`default_client_default_redirect_uri`**](#var-default_client_default_redirect_uri): *(Optional `string`)* 695 | 696 | The default redirect URI. Must be in the list of callback URLs. 697 | 698 | - [**`default_client_read_attributes`**](#var-default_client_read_attributes): *(Optional `list(string)`)* 699 | 700 | List of Cognito User Pool attributes the application client can read from. 701 | 702 | - [**`default_client_refresh_token_validity`**](#var-default_client_refresh_token_validity): *(Optional `number`)* 703 | 704 | The time limit in days refresh tokens are valid for. 705 | 706 | Default is `30`. 707 | 708 | - [**`default_client_supported_identity_providers`**](#var-default_client_supported_identity_providers): *(Optional `list(string)`)* 709 | 710 | List of provider names for the identity providers that are supported on this client. 711 | 712 | - [**`default_client_allowed_oauth_scopes`**](#var-default_client_allowed_oauth_scopes): *(Optional `list(string)`)* 713 | 714 | List of allowed OAuth scopes. Possible values are `phone`, `email`, `openid`, `profile`, and `aws.cognito.signin.user.admin`. 715 | 716 | - [**`default_client_logout_urls`**](#var-default_client_logout_urls): *(Optional `list(string)`)* 717 | 718 | List of allowed logout URLs for the identity providers. 719 | 720 | - [**`default_client_allowed_oauth_flows_user_pool_client`**](#var-default_client_allowed_oauth_flows_user_pool_client): *(Optional `bool`)* 721 | 722 | Whether the client is allowed to follow the OAuth protocol when interacting with Cognito User Pools. 723 | 724 | - [**`default_client_generate_secret`**](#var-default_client_generate_secret): *(Optional `bool`)* 725 | 726 | Boolean flag for generating an application secret. 727 | 728 | - [**`default_client_allowed_oauth_flows`**](#var-default_client_allowed_oauth_flows): *(Optional `list(string)`)* 729 | 730 | List of allowed OAuth flows. Possible flows are `code`, `implicit`, and `client_credentials`. 731 | 732 | - [**`default_client_write_attributes`**](#var-default_client_write_attributes): *(Optional `list(string)`)* 733 | 734 | List of Cognito User Pool attributes the application client can write to. 735 | 736 | - [**`default_client_explicit_auth_flows`**](#var-default_client_explicit_auth_flows): *(Optional `list(string)`)* 737 | 738 | List of authentication flows. Possible values are `ADMIN_NO_SRP_AUTH`, `CUSTOM_AUTH_FLOW_ONLY`, `USER_PASSWORD_AUTH`, `ALLOW_ADMIN_USER_PASSWORD_AUTH`, `ALLOW_CUSTOM_AUTH`, `ALLOW_USER_PASSWORD_AUTH`, `ALLOW_USER_SRP_AUTH`, and `ALLOW_REFRESH_TOKEN_AUTH`. 739 | 740 | - [**`default_client_prevent_user_existence_errors`**](#var-default_client_prevent_user_existence_errors): *(Optional `string`)* 741 | 742 | Choose which errors and responses are returned by Cognito APIs during authentication, account confirmation, and password recovery when the user does not exist in the Cognito User Pool. When set to `ENABLED` and the user does not exist, authentication returns an error indicating either the username or password was incorrect, and account confirmation and password recovery return a response indicating a code was sent to a simulated destination. When set to `LEGACY`, those APIs will return a `UserNotFoundException` exception if the user does not exist in the Cognito User Pool. 743 | 744 | - [**`default_client_access_token_validity`**](#var-default_client_access_token_validity): *(Optional `number`)* 745 | 746 | Time limit, between 5 minutes and 1 day, after which the access token is no longer valid and cannot be used. 747 | This value will be overridden if you have entered a value in 'default_client_token_validity_units'. 748 | 749 | - [**`default_client_id_token_validity`**](#var-default_client_id_token_validity): *(Optional `number`)* 750 | 751 | Time limit, between 5 minutes and 1 day, after which the ID token is no longer valid and cannot be used. 752 | This value will be overridden if you have entered a value in 'default_client_token_validity_units'. 753 | 754 | - [**`default_client_token_validity_units`**](#var-default_client_token_validity_units): *(Optional `number`)* 755 | 756 | Configuration block for units in which the validity times are represented in. 757 | 758 | - [**`default_client_enable_token_revocation`**](#var-default_client_enable_token_revocation): *(Optional `bool`)* 759 | 760 | Enables or disables token revocation. 761 | 762 | ## Module Outputs 763 | 764 | The following attributes are exported by the module: 765 | 766 | - [**`user_pool`**](#output-user_pool): *(`object(user_pool)`)* 767 | 768 | The `cognito_user_pool` object. 769 | 770 | - [**`domain`**](#output-domain): *(`object(domain)`)* 771 | 772 | The full `aws_cognito_user_pool` object. 773 | 774 | - [**`clients`**](#output-clients): *(`map(client)`)* 775 | 776 | A map of `cognito_user_pool_client` objects. The map is keyed by the 777 | `name` of the created clients. Client secrets are filtered out of this 778 | map and are available through the `client_secrets` output variable and 779 | flagged as sensitive. 780 | 781 | - [**`client_secrets`**](#output-client_secrets): *(`map(client_secret)`)* 782 | 783 | A sensitive map of client secrets for all created 784 | `cognito_user_pool_client` resources. The map is keyed by the `name` of 785 | the created clients. 786 | 787 | - [**`module_enabled`**](#output-module_enabled): *(`bool`)* 788 | 789 | Whether this module is enabled. 790 | 791 | ## External Documentation 792 | 793 | ### AWS Documentation 794 | 795 | - https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html 796 | - https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html 797 | 798 | ### Terraform AWS Provider Documentation 799 | 800 | - User Pool - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool 801 | - User Pool Client - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client 802 | - User Pool Domain - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain 803 | - Resource Server - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server 804 | 805 | ## Module Versioning 806 | 807 | This Module follows the principles of [Semantic Versioning (SemVer)]. 808 | 809 | Given a version number `MAJOR.MINOR.PATCH`, we increment the: 810 | 811 | 1. `MAJOR` version when we make incompatible changes, 812 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and 813 | 3. `PATCH` version when we make backwards compatible bug fixes. 814 | 815 | ### Backwards compatibility in `0.0.z` and `0.y.z` version 816 | 817 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) 818 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) 819 | 820 | ## About Mineiros 821 | 822 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany 823 | that solves development, automation and security challenges in cloud infrastructure. 824 | 825 | Our vision is to massively reduce time and overhead for teams to manage and 826 | deploy production-grade and secure cloud infrastructure. 827 | 828 | We offer commercial support for all of our modules and encourage you to reach out 829 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our 830 | [Community Slack channel][slack]. 831 | 832 | ## Reporting Issues 833 | 834 | We use GitHub [Issues] to track community reported issues and missing features. 835 | 836 | ## Contributing 837 | 838 | Contributions are always encouraged and welcome! For the process of accepting changes, we use 839 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines]. 840 | 841 | ## Makefile Targets 842 | 843 | This repository comes with a handy [Makefile]. 844 | Run `make help` to see details on each available target. 845 | 846 | ## License 847 | 848 | [![license][badge-license]][apache20] 849 | 850 | This module is licensed under the Apache License Version 2.0, January 2004. 851 | Please see [LICENSE] for full details. 852 | 853 | Copyright © 2020-2022 [Mineiros GmbH][homepage] 854 | 855 | 856 | 857 | 858 | [homepage]: https://mineiros.io/?ref=terraform-aws-cognito-user-pool 859 | [mineiros-library]: https://www.mineiros.io/solutions/terraform-library 860 | [mineiros-pricing]: https://www.mineiros.io/solutions/terraform-library#pricing 861 | [hello@mineiros.io]: mailto:hello@mineiros.io 862 | [badge-build]: https://github.com/mineiros-io/terraform-aws-lambda-function/workflows/CI/CD%20Pipeline/badge.svg 863 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-cognito-user-pool.svg?label=latest&sort=semver 864 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 865 | [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 866 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 867 | [build-status]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/actions 868 | [badge-tf-aws]: https://img.shields.io/badge/AWS-3.19+-F8991D.svg?logo=terraform 869 | [releases-aws-provider]: https://github.com/terraform-providers/terraform-provider-aws/releases 870 | [releases-github]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/releases 871 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 872 | [apache20]: https://opensource.org/licenses/Apache-2.0 873 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 874 | [Terraform]: https://www.terraform.io 875 | [AWS]: https://aws.amazon.com/ 876 | [Semantic Versioning (SemVer)]: https://semver.org/ 877 | [examples/example/main.tf]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/example/main.tf 878 | [variables.tf]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/variables.tf 879 | [examples/]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples 880 | [Issues]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/issues 881 | [LICENSE]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/LICENSE 882 | [Makefile]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/Makefile 883 | [Pull Requests]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/pulls 884 | [Contribution Guidelines]: https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/CONTRIBUTING.md 885 | [Cognito User Pools]: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html 886 | [attributes docs]: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html 887 | [Terraform AWS Cognito User Pool Client Docs]: https://www.terraform.io/docs/providers/aws/r/cognito_user_pool_client.html 888 | [Terraform AWS Cognito Resource Server Docs]: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server 889 | -------------------------------------------------------------------------------- /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-cognito-user-pool" 4 | 5 | badge "build" { 6 | image = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/workflows/CI/CD%20Pipeline/badge.svg" 7 | url = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/actions" 8 | text = "Build Status" 9 | } 10 | 11 | badge "semver" { 12 | image = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-cognito-user-pool.svg?label=latest&sort=semver" 13 | url = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/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.50+-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-cognito-user-pool" 38 | toc = true 39 | content = <<-END 40 | A [Terraform] module for deploying and managing 41 | [Cognito User Pools] 42 | on [Amazon Web Services (AWS)][AWS]. 43 | 44 | *This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above 45 | and is compatible with the Terraform AWS provider v3.50 and above. 46 | END 47 | 48 | section { 49 | title = "Module Features" 50 | content = <<-END 51 | In contrast to the plain [`cognito_user_pool`](https://www.terraform.io/docs/providers/aws/r/cognito_user_pool.html) 52 | resource this module has a more secure level of default settings. 53 | 54 | While all settings can be customized as needed, best practices are 55 | pre-configured. 56 | 57 | - **Default Security Settings**: 58 | Per default, only administrators are allowed to create user profiles by 59 | setting `allow_admin_create_user_only` to `true`. This module comes with a 60 | strong default password policy. 61 | 62 | **Standard Cognito Features**: 63 | Create a Cognito User Pool with pre-configured best practices. 64 | Create Cognito User Pool Clients. 65 | Create a Cognito User Pool Domain. 66 | Create Cognito User Pool Resource Servers as associated scopes. 67 | 68 | - *Features not yet implemented*: 69 | [`cognito_user_group`](https://www.terraform.io/docs/providers/aws/r/cognito_user_group.html) 70 | END 71 | } 72 | 73 | section { 74 | title = "Getting Started" 75 | content = <<-END 76 | Most basic usage just setting required arguments: 77 | 78 | ```hcl 79 | module "terraform-aws-cognito-user-pool" { 80 | source = "mineiros-io/cognito-user-pool/aws" 81 | version = "~> 0.9.0" 82 | 83 | name = "application-userpool" 84 | } 85 | ``` 86 | 87 | Advanced usage as found in 88 | [examples/complete/main.tf](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/complete/main.tf) 89 | setting all required and optional arguments to their default values. 90 | END 91 | } 92 | 93 | section { 94 | title = "Module Argument Reference" 95 | content = <<-END 96 | See 97 | [variables.tf](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/variables.tf) 98 | and 99 | [examples/](https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples) 100 | for details and use-cases. 101 | END 102 | 103 | section { 104 | title = "Top-level Arguments" 105 | 106 | section { 107 | title = "Module Configuration" 108 | 109 | variable "module_enabled" { 110 | type = bool 111 | default = true 112 | description = <<-END 113 | Specifies whether resources in the module will be created. 114 | END 115 | } 116 | 117 | variable "module_tags" { 118 | type = map(string) 119 | default = {} 120 | description = <<-END 121 | 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. 122 | END 123 | readme_example = <<-END 124 | module_tags = { 125 | environment = "staging" 126 | team = "platform" 127 | } 128 | END 129 | } 130 | 131 | variable "module_depends_on" { 132 | type = list(dependency) 133 | description = <<-END 134 | A list of dependencies. Any object can be _assigned_ to this list to define a hidden external dependency. 135 | END 136 | readme_example = <<-END 137 | module_depends_on = [ 138 | aws_vpc.vpc 139 | ] 140 | END 141 | } 142 | } 143 | 144 | section { 145 | title = "Cognito User Pool" 146 | 147 | variable "name" { 148 | required = true 149 | type = string 150 | description = <<-END 151 | The name of the user pool. Forces new resource. 152 | END 153 | } 154 | 155 | variable "advanced_security_mode" { 156 | type = string 157 | default = "OFF" 158 | description = <<-END 159 | The mode for advanced security, must be one of `OFF`, `AUDIT` or `ENFORCED`. Additional pricing applies for Amazon Cognito advanced security features. For details see https://aws.amazon.com/cognito/pricing/. 160 | END 161 | } 162 | 163 | variable "alias_attributes" { 164 | type = set(string) 165 | description = <<-END 166 | Attributes supported as an alias for this user pool. Possible values: `phone_number`, `email`, or `preferred_username`. Conflicts with `username_attributes`. Default applies if `username_attributes` is not set. 167 | END 168 | } 169 | 170 | variable "username_attributes" { 171 | type = set(string) 172 | description = <<-END 173 | Specifies whether `email` addresse or `phone_number` can be specified as usernames when a user signs up. Conflicts with `alias_attributes`. 174 | Default is to use `alias_attributes`. 175 | END 176 | } 177 | 178 | variable "allow_admin_create_user_only" { 179 | type = bool 180 | default = true 181 | description = <<-END 182 | Set to True if only the administrator is allowed to create user profiles. Set to False if users can sign themselves up via an app. 183 | END 184 | } 185 | 186 | variable "invite_email_subject" { 187 | type = string 188 | default = "Your new account." 189 | description = <<-END 190 | The message template for email messages. 191 | END 192 | } 193 | 194 | variable "invite_email_message" { 195 | type = string 196 | default = "Your username is {username} and your temporary password is ' {####}'" 197 | description = <<-END 198 | The message template for email messages. Must contain `{username}` and `{####}` placeholders, for username and temporary password, respectively. 199 | END 200 | } 201 | 202 | variable "invite_sms_message" { 203 | type = string 204 | default = "Your username is {username} and your temporary password is ' {####}'." 205 | description = <<-END 206 | The message template for SMS messages. Must contain `{username}` and `{####}` placeholders, for username and temporary password, respectively. 207 | END 208 | } 209 | 210 | variable "auto_verified_attributes" { 211 | type = set(string) 212 | default = ["email"] 213 | description = <<-END 214 | The attributes to be auto-verified. Possible values: `email`, `phone_number`. 215 | END 216 | } 217 | 218 | variable "user_device_tracking" { 219 | type = string 220 | default = "USER_OPT_IN" 221 | description = <<-END 222 | Configure tracking of user devices. Set to `OFF` to disable tracking, `ALWAYS` to track all devices or `USER_OPT_IN` to only track when user opts in. 223 | END 224 | } 225 | 226 | variable "challenge_required_on_new_device" { 227 | type = bool 228 | default = true 229 | description = <<-END 230 | Indicates whether a challenge is required on a new device. Only applicable to a new device. Only applied when `user_device_tracking` is enabled. 231 | END 232 | } 233 | 234 | variable "enable_username_case_sensitivity" { 235 | type = bool 236 | default = false 237 | description = <<-END 238 | Specifies whether username case sensitivity will be applied to all users in the user pool through Cognito APIs. 239 | END 240 | } 241 | 242 | variable "email_sending_account" { 243 | type = string 244 | default = "COGNITO_DEFAULT" 245 | description = <<-END 246 | The email delivery method to use. `COGNITO_DEFAULT` for the default email functionality built into Cognito or `DEVELOPER` to use your Amazon SES configuration. 247 | END 248 | } 249 | 250 | variable "email_reply_to_address" { 251 | type = string 252 | description = <<-END 253 | The REPLY-TO email address. 254 | END 255 | } 256 | 257 | variable "email_source_arn" { 258 | type = string 259 | description = <<-END 260 | The ARN of the email source. 261 | END 262 | } 263 | 264 | variable "email_from_address" { 265 | type = string 266 | description = <<-END 267 | Sender’s email address or sender’s name with their email address (e.g. 'john@smith.com' or 'John Smith '). 268 | END 269 | } 270 | 271 | variable "mfa_configuration" { 272 | type = string 273 | default = "OPTIONAL" 274 | description = <<-END 275 | Multi-Factor Authentication (MFA) configuration for the User Pool. Valid values: `ON`, `OFF` or `OPTIONAL`. `ON` and `OPTIONAL` require at least one of `sms_configuration` or `software_token_mfa_configuration` to be configured. 276 | END 277 | } 278 | 279 | variable "password_minimum_length" { 280 | type = number 281 | default = 20 282 | description = <<-END 283 | The minimum length of the password policy that you have set. 284 | END 285 | } 286 | 287 | variable "password_require_lowercase" { 288 | type = bool 289 | default = true 290 | description = <<-END 291 | Whether you have required users to use at least one lowercase letter in their password. 292 | END 293 | } 294 | 295 | variable "password_require_numbers" { 296 | type = bool 297 | default = true 298 | description = <<-END 299 | Whether you have required users to use at least one number in their password. 300 | END 301 | } 302 | 303 | variable "password_require_symbols" { 304 | type = bool 305 | default = true 306 | description = <<-END 307 | Whether you have required users to use at least one symbol in their password. 308 | END 309 | } 310 | 311 | variable "password_require_uppercase" { 312 | type = bool 313 | default = true 314 | description = <<-END 315 | Whether you have required users to use at least one uppercase letter in their password. 316 | END 317 | } 318 | 319 | variable "temporary_password_validity_days" { 320 | type = number 321 | default = 1 322 | description = <<-END 323 | In the password policy you have set, refers to the number of days a temporary password is valid. If the user does not sign in during this time, their password will need to be reset by an administrator. 324 | END 325 | } 326 | 327 | variable "allow_software_mfa_token" { 328 | type = bool 329 | default = true 330 | description = <<-END 331 | Boolean whether to enable software token Multi-Factor Authentication (MFA) tokens, such as Time-Based One-Time Password (TOTP). To disable software token MFA when `sms_configuration` is not present, the `mfa_configuration` argument must be set to `OFF` and the `software_token_mfa_configuration` configuration block must be fully removed. 332 | END 333 | } 334 | 335 | variable "sms_authentication_message" { 336 | type = string 337 | default = "Your temporary password is {####}." 338 | description = <<-END 339 | A string representing the SMS authentication message. The message must contain the `{####}` placeholder, which will be replaced with the authentication code. 340 | END 341 | } 342 | 343 | variable "lambda_create_auth_challenge" { 344 | type = string 345 | description = <<-END 346 | The ARN of an AWS Lambda creating an authentication challenge. 347 | END 348 | } 349 | 350 | variable "lambda_custom_message" { 351 | type = string 352 | description = <<-END 353 | The ARN of a custom message AWS Lambda trigger. 354 | END 355 | } 356 | 357 | variable "lambda_define_auth_challenge" { 358 | type = string 359 | description = <<-END 360 | The ARN of an AWS Lambda that defines the authentication challenge. 361 | END 362 | } 363 | 364 | variable "lambda_post_authentication" { 365 | type = string 366 | description = <<-END 367 | The ARN of an AWS Lambda that defines the authentication challenge. 368 | END 369 | } 370 | 371 | variable "lambda_post_confirmation" { 372 | type = string 373 | description = <<-END 374 | The ARN of a post-confirmation AWS Lambda trigger. 375 | END 376 | } 377 | 378 | variable "lambda_pre_authentication" { 379 | type = string 380 | description = <<-END 381 | The ARN of a pre-authentication AWS Lambda trigger. 382 | END 383 | } 384 | 385 | variable "lambda_pre_sign_up" { 386 | type = string 387 | description = <<-END 388 | The ARN of a pre-registration AWS Lambda trigger. 389 | END 390 | } 391 | 392 | variable "lambda_pre_token_generation" { 393 | type = string 394 | description = <<-END 395 | The ARN of an AWS Lambda that allows customization of identity token claims before token generation. 396 | END 397 | } 398 | 399 | variable "lambda_user_migration" { 400 | type = string 401 | description = <<-END 402 | The ARN of he user migration AWS Lambda config type. 403 | END 404 | } 405 | 406 | variable "lambda_verify_auth_challenge_response" { 407 | type = string 408 | default = "true" 409 | description = <<-END 410 | The ARN of an AWS Lambda that verifies the authentication challenge response. 411 | END 412 | } 413 | 414 | variable "schema_attributes" { 415 | type = list(schema_attribute) 416 | default = [] 417 | description = <<-END 418 | A list of schema attributes of a user pool. You can add a maximum of 25 custom attributes. Please note that only default attributes can be marked as required. 419 | Also an attribute cannot be switched between required and not required after a user pool has been created. 420 | For details please see the [attributes docs]. 421 | END 422 | readme_example = <<-END 423 | schema_attributes = [ 424 | { 425 | name = "gender", # overwrites the default attribute 'gender' 426 | type = "String" 427 | required = true # required can only be set for default attributes 428 | }, 429 | { 430 | name = "alternative_name" 431 | type = "String" 432 | min_length = 0, 433 | max_length = 2048 434 | }, 435 | { 436 | name = "friends_count" 437 | type = "Number" 438 | min_value = 0, 439 | max_value = 100 440 | }, 441 | { 442 | name = "is_active" 443 | type = "Boolean" 444 | }, 445 | { 446 | name = "last_seen" 447 | type = "DateTime" 448 | } 449 | ] 450 | END 451 | } 452 | 453 | variable "account_recovery_mechanisms" { 454 | type = list(account_recovery_mechanism) 455 | default = [] 456 | description = <<-END 457 | A list of recovery_mechanisms to be inserted inside `account_recovery_setting`. 458 | END 459 | readme_example = <<-END 460 | account_recovery_mechanisms = [ 461 | { 462 | name = "verified_email" 463 | priority = 1 464 | }, 465 | { 466 | name = "verified_phone_number" 467 | priority = 2 468 | } 469 | ] 470 | END 471 | 472 | attribute "name" { 473 | required = true 474 | type = string 475 | description = <<-END 476 | Recovery method for a user. Can be of the following: verified_email, verified_phone_number, and admin_only. 477 | END 478 | } 479 | 480 | attribute "priority" { 481 | required = true 482 | type = string 483 | description = <<-END 484 | Positive integer specifying priority of a method with 1 being the highest priority. 485 | END 486 | } 487 | } 488 | 489 | variable "sms_configuration" { 490 | type = object(sms_configuration) 491 | description = <<-END 492 | The `sms_configuration` with the `external_id` parameter used in IAM role trust relationships and the `sns_caller_arn` parameter to set the ARN of the Amazon SNS caller. This is usually the IAM role that you have given AWS Cognito permission to assume. 493 | END 494 | 495 | attribute "external_id" { 496 | required = true 497 | type = string 498 | description = <<-END 499 | External ID used in IAM role trust relationships. 500 | END 501 | } 502 | 503 | attribute "sns_caller_arn" { 504 | required = true 505 | type = string 506 | description = <<-END 507 | ARN of the Amazon SNS caller. This is usually the IAM role that you've given Cognito permission to assume. 508 | END 509 | } 510 | } 511 | 512 | variable "default_email_option" { 513 | type = string 514 | default = "CONFIRM_WITH_CODE" 515 | description = <<-END 516 | The default email option. Must be either `CONFIRM_WITH_CODE` or `CONFIRM_WITH_LINK`. 517 | END 518 | } 519 | 520 | variable "email_message" { 521 | type = string 522 | default = "Your verification code is {####}." 523 | description = <<-END 524 | The email message template. Must contain the `{####}` placeholder. 525 | END 526 | } 527 | 528 | variable "email_message_by_link" { 529 | type = string 530 | default = "Please click the link below to verify your email address.{##Verify Email##}." 531 | description = <<-END 532 | The email message template for sending a confirmation link to the user, it must contain the `{##Any Text##}` placeholder. 533 | END 534 | } 535 | 536 | variable "email_subject" { 537 | type = string 538 | default = "Your Verification Code" 539 | description = <<-END 540 | The subject line for the email message template. 541 | END 542 | } 543 | 544 | variable "email_subject_by_link" { 545 | type = string 546 | default = "Your Verifiction Link" 547 | description = <<-END 548 | The subject line for the email message template for sending a confirmation link to the user. 549 | END 550 | } 551 | 552 | variable "sms_message" { 553 | type = string 554 | default = "Your verification code is {####}." 555 | description = <<-END 556 | The SMS message template. Must contain the `{####}` placeholder, which will be replaced with the verification code. Can also contain the `{username}` placeholder which will be replaced with the username. 557 | END 558 | } 559 | 560 | variable "tags" { 561 | type = map(string) 562 | default = {} 563 | description = <<-END 564 | A mapping of tags to assign to the resource. 565 | END 566 | readme_example = <<-END 567 | tags = { 568 | CreatedAt = "2020-02-07", 569 | Alice = "Bob" 570 | } 571 | END 572 | } 573 | } 574 | 575 | section { 576 | title = "Cognito User Pool Domain" 577 | 578 | variable "domain" { 579 | type = string 580 | description = <<-END 581 | The domain name that should be used. Can be set to a FQDN or prefix. 582 | If no FQDN and `certificate_arn` are set, the domain prefix will be used for the sign-up and sign-in pages that are hosted by Amazon Cognito, 583 | e.g. `https://{YOUR_PREFIX}.auth.eu-west-1.amazoncognito.com`. 584 | The prefix must be unique across the selected AWS Region. 585 | Domain names can only contain lower-case letters, numbers, and hyphens. 586 | END 587 | } 588 | 589 | variable "certificate_arn" { 590 | type = string 591 | description = <<-END 592 | The ARN of an ISSUED ACM certificate in us-east-1 for a custom domain. 593 | END 594 | } 595 | } 596 | 597 | section { 598 | title = "Cognito User Pool Resource Servers" 599 | 600 | variable "resource_servers" { 601 | type = list(resource_server) 602 | default = [] 603 | description = <<-END 604 | A list of objects with resource server declarations. 605 | END 606 | readme_example = <<-END 607 | resource_servers = [ 608 | { 609 | identifier = "https://api.resourceserver.com" 610 | name = "API" 611 | scopes = [ 612 | { 613 | scope_name = "users:read" 614 | scope_description = "Read user data" 615 | }, 616 | { 617 | scope_name = "users:write" 618 | scope_description = "Write user data" 619 | } 620 | ] 621 | } 622 | ] 623 | END 624 | 625 | attribute "identifier" { 626 | required = true 627 | type = string 628 | description = <<-END 629 | An identifier for the resource server. 630 | END 631 | } 632 | 633 | attribute "name" { 634 | required = true 635 | type = string 636 | description = <<-END 637 | A name for the resource server. 638 | END 639 | } 640 | 641 | attribute "scope" { 642 | type = list(scope) 643 | description = <<-END 644 | A list of Authorization Scope. 645 | END 646 | 647 | attribute "scope_name" { 648 | required = true 649 | type = string 650 | description = <<-END 651 | The scope name. 652 | END 653 | } 654 | 655 | attribute "scope_description" { 656 | required = true 657 | type = string 658 | description = <<-END 659 | The scope description. 660 | END 661 | } 662 | } 663 | } 664 | } 665 | 666 | section { 667 | title = "Cognito User Pool Clients" 668 | 669 | variable "clients" { 670 | type = list(client) 671 | default = [] 672 | description = <<-END 673 | A list of objects with the clients definitions. 674 | END 675 | readme_example = <<-END 676 | clients = [ 677 | { 678 | name = "android-mobile-client" 679 | read_attributes = ["email", "email_verified", "preferred_username"] 680 | allowed_oauth_scopes = ["email", "openid"] 681 | allowed_oauth_flows = ["implicit"] 682 | callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 683 | default_redirect_uri = "https://mineiros.io/callback" 684 | generate_secret = true 685 | } 686 | ] 687 | END 688 | 689 | attribute "name" { 690 | required = true 691 | type = string 692 | description = <<-END 693 | Name of the application client. 694 | END 695 | } 696 | 697 | attribute "user_pool_id" { 698 | type = string 699 | description = <<-END 700 | Name of the application client. 701 | END 702 | } 703 | 704 | attribute "access_token_validity" { 705 | type = number 706 | description = <<-END 707 | Time limit, between 5 minutes and 1 day, after which the access token is no longer valid and cannot be used. This value will be overridden if you have entered a value in token_validity_units. 708 | END 709 | } 710 | 711 | attribute "allowed_oauth_flows_user_pool_client" { 712 | type = bool 713 | description = <<-END 714 | Whether the client is allowed to follow the OAuth protocol when interacting with Cognito user pools. 715 | END 716 | } 717 | 718 | attribute "allowed_oauth_flows" { 719 | type = set(string) 720 | description = <<-END 721 | List of allowed OAuth flows (code, implicit, client_credentials). 722 | END 723 | } 724 | 725 | attribute "allowed_oauth_scopes" { 726 | type = set(string) 727 | description = <<-END 728 | List of allowed OAuth scopes (phone, email, openid, profile, and aws.cognito.signin.user.admin). 729 | END 730 | } 731 | 732 | attribute "analytics_configuration" { 733 | type = object(analytics_configuration) 734 | description = <<-END 735 | Configuration block for Amazon Pinpoint analytics for collecting metrics for this user pool. 736 | END 737 | 738 | attribute "application_arn" { 739 | type = string 740 | description = <<-END 741 | Application ARN for an Amazon Pinpoint application. Conflicts with external_id and role_arn. 742 | END 743 | } 744 | 745 | attribute "application_id" { 746 | type = string 747 | description = <<-END 748 | Application ID for an Amazon Pinpoint application. 749 | END 750 | } 751 | 752 | attribute "external_id" { 753 | type = string 754 | description = <<-END 755 | ID for the Analytics Configuration. Conflicts with application_arn. Application ID for an Amazon Pinpoint application. 756 | END 757 | } 758 | 759 | attribute "role_arn" { 760 | type = string 761 | description = <<-END 762 | ARN of an IAM role that authorizes Amazon Cognito to publish events to Amazon Pinpoint analytics. Conflicts with application_arn. 763 | END 764 | } 765 | 766 | attribute "user_data_shared" { 767 | type = bool 768 | description = <<-END 769 | If set to true, Amazon Cognito will include user data in the events it publishes to Amazon Pinpoint analytics. 770 | END 771 | } 772 | } 773 | 774 | attribute "callback_urls" { 775 | type = set(string) 776 | description = <<-END 777 | List of allowed callback URLs for the identity providers. 778 | END 779 | } 780 | 781 | attribute "default_redirect_uri" { 782 | type = string 783 | description = <<-END 784 | Default redirect URI. Must be in the list of callback URLs. 785 | END 786 | } 787 | 788 | attribute "enable_token_revocation" { 789 | type = bool 790 | description = <<-END 791 | Enables or disables token revocation. 792 | END 793 | } 794 | 795 | attribute "explicit_auth_flows" { 796 | type = set(string) 797 | description = <<-END 798 | List of authentication flows (ADMIN_NO_SRP_AUTH, CUSTOM_AUTH_FLOW_ONLY, USER_PASSWORD_AUTH, ALLOW_ADMIN_USER_PASSWORD_AUTH, ALLOW_CUSTOM_AUTH, ALLOW_USER_PASSWORD_AUTH, ALLOW_USER_SRP_AUTH, ALLOW_REFRESH_TOKEN_AUTH). 799 | END 800 | } 801 | 802 | attribute "generate_secret" { 803 | type = bool 804 | description = <<-END 805 | Should an application secret be generated. 806 | END 807 | } 808 | 809 | attribute "id_token_validity" { 810 | type = number 811 | description = <<-END 812 | Time limit, between 5 minutes and 1 day, after which the ID token is no longer valid and cannot be used. This value will be overridden if you have entered a value in token_validity_units. 813 | END 814 | } 815 | 816 | attribute "logout_urls" { 817 | type = set(string) 818 | description = <<-END 819 | List of allowed logout URLs for the identity providers. 820 | END 821 | } 822 | 823 | attribute "prevent_user_existence_errors" { 824 | type = string 825 | description = <<-END 826 | Choose which errors and responses are returned by Cognito APIs during authentication, account confirmation, and password recovery when the user does not exist in the user pool. When set to ENABLED and the user does not exist, authentication returns an error indicating either the username or password was incorrect, and account confirmation and password recovery return a response indicating a code was sent to a simulated destination. When set to LEGACY, those APIs will return a UserNotFoundException exception if the user does not exist in the user pool. 827 | END 828 | } 829 | 830 | attribute "read_attributes" { 831 | type = set(string) 832 | description = <<-END 833 | List of user pool attributes the application client can read from. 834 | END 835 | } 836 | 837 | attribute "refresh_token_validity" { 838 | type = number 839 | description = <<-END 840 | Time limit in days refresh tokens are valid for. 841 | END 842 | } 843 | 844 | attribute "supported_identity_providers" { 845 | type = set(string) 846 | description = <<-END 847 | List of provider names for the identity providers that are supported on this client. Uses the provider_name attribute of aws_cognito_identity_provider resource(s), or the equivalent string(s). 848 | END 849 | } 850 | 851 | attribute "token_validity_units" { 852 | type = object(token_validity_units) 853 | description = <<-END 854 | Configuration block for units in which the validity times are represented in. 855 | END 856 | 857 | attribute "access_token" { 858 | type = string 859 | default = "hours" 860 | description = <<-END 861 | Time unit in for the value in access_token_validity, defaults to hours. 862 | END 863 | } 864 | 865 | attribute "id_token" { 866 | type = string 867 | default = "hours" 868 | description = <<-END 869 | Time unit in for the value in id_token_validity, defaults to hours. 870 | END 871 | } 872 | 873 | attribute "refresh_token" { 874 | type = string 875 | default = "days" 876 | description = <<-END 877 | Time unit in for the value in refresh_token_validity, defaults to days. 878 | END 879 | } 880 | } 881 | 882 | attribute "write_attributes" { 883 | type = set(string) 884 | description = <<-END 885 | List of user pool attributes the application client can write to. 886 | END 887 | } 888 | } 889 | } 890 | 891 | section { 892 | title = "Cognito User Pool Clients Default Values" 893 | content = <<-END 894 | The following variables can be used for setting default settings among various clients defined through the `clients` variable. This helps you to quickly issue several clients that implement the same settings, e.g. like so: 895 | 896 | ```hcl 897 | clients = [ 898 | { name = "ios" }, 899 | { name = "android" }, 900 | { name = "web" }, 901 | ] 902 | 903 | default_client_read_attributes = ["email", "email_verified", "preferred_username"] 904 | default_client_allowed_oauth_scopes = ["email", "openid"] 905 | default_client_allowed_oauth_flows = ["implicit"] 906 | default_client_callback_urls = ["https://mineiros.io/callback", "https://mineiros.io/anothercallback"] 907 | default_client_default_redirect_uri = "https://mineiros.io/callback" 908 | default_client_generate_secret = true 909 | default_client_refresh_token_validity = 45 910 | 911 | default_client_supported_identity_providers = null 912 | default_client_logout_urls = null 913 | default_client_allowed_oauth_flows_user_pool_client = null 914 | default_client_write_attributes = null 915 | default_client_explicit_auth_flows = null 916 | default_client_prevent_user_existence_errors = null 917 | default_client_access_token_validity = null 918 | default_client_id_token_validity = null 919 | default_client_token_validity_units = null 920 | default_client_enable_token_revocation = null 921 | ``` 922 | END 923 | 924 | variable "default_client_callback_urls" { 925 | type = list(string) 926 | description = <<-END 927 | List of allowed callback URLs for the identity providers. 928 | END 929 | } 930 | 931 | variable "default_client_default_redirect_uri" { 932 | type = string 933 | description = <<-END 934 | The default redirect URI. Must be in the list of callback URLs. 935 | END 936 | } 937 | 938 | variable "default_client_read_attributes" { 939 | type = list(string) 940 | description = <<-END 941 | List of Cognito User Pool attributes the application client can read from. 942 | END 943 | } 944 | 945 | variable "default_client_refresh_token_validity" { 946 | type = number 947 | description = <<-END 948 | The time limit in days refresh tokens are valid for. 949 | END 950 | default = 30 951 | } 952 | 953 | variable "default_client_supported_identity_providers" { 954 | type = list(string) 955 | description = <<-END 956 | List of provider names for the identity providers that are supported on this client. 957 | END 958 | } 959 | 960 | variable "default_client_allowed_oauth_scopes" { 961 | type = list(string) 962 | description = <<-END 963 | List of allowed OAuth scopes. Possible values are `phone`, `email`, `openid`, `profile`, and `aws.cognito.signin.user.admin`. 964 | END 965 | } 966 | 967 | variable "default_client_logout_urls" { 968 | type = list(string) 969 | description = <<-END 970 | List of allowed logout URLs for the identity providers. 971 | END 972 | } 973 | 974 | variable "default_client_allowed_oauth_flows_user_pool_client" { 975 | type = bool 976 | description = <<-END 977 | Whether the client is allowed to follow the OAuth protocol when interacting with Cognito User Pools. 978 | END 979 | } 980 | 981 | variable "default_client_generate_secret" { 982 | type = bool 983 | description = <<-END 984 | Boolean flag for generating an application secret. 985 | END 986 | } 987 | 988 | variable "default_client_allowed_oauth_flows" { 989 | type = list(string) 990 | description = <<-END 991 | List of allowed OAuth flows. Possible flows are `code`, `implicit`, and `client_credentials`. 992 | END 993 | } 994 | 995 | variable "default_client_write_attributes" { 996 | type = list(string) 997 | description = <<-END 998 | List of Cognito User Pool attributes the application client can write to. 999 | END 1000 | } 1001 | 1002 | variable "default_client_explicit_auth_flows" { 1003 | type = list(string) 1004 | description = <<-END 1005 | List of authentication flows. Possible values are `ADMIN_NO_SRP_AUTH`, `CUSTOM_AUTH_FLOW_ONLY`, `USER_PASSWORD_AUTH`, `ALLOW_ADMIN_USER_PASSWORD_AUTH`, `ALLOW_CUSTOM_AUTH`, `ALLOW_USER_PASSWORD_AUTH`, `ALLOW_USER_SRP_AUTH`, and `ALLOW_REFRESH_TOKEN_AUTH`. 1006 | END 1007 | } 1008 | 1009 | variable "default_client_prevent_user_existence_errors" { 1010 | type = string 1011 | description = <<-END 1012 | Choose which errors and responses are returned by Cognito APIs during authentication, account confirmation, and password recovery when the user does not exist in the Cognito User Pool. When set to `ENABLED` and the user does not exist, authentication returns an error indicating either the username or password was incorrect, and account confirmation and password recovery return a response indicating a code was sent to a simulated destination. When set to `LEGACY`, those APIs will return a `UserNotFoundException` exception if the user does not exist in the Cognito User Pool. 1013 | END 1014 | } 1015 | 1016 | variable "default_client_access_token_validity" { 1017 | type = number 1018 | description = <<-END 1019 | Time limit, between 5 minutes and 1 day, after which the access token is no longer valid and cannot be used. 1020 | This value will be overridden if you have entered a value in 'default_client_token_validity_units'. 1021 | END 1022 | } 1023 | 1024 | variable "default_client_id_token_validity" { 1025 | type = number 1026 | description = <<-END 1027 | Time limit, between 5 minutes and 1 day, after which the ID token is no longer valid and cannot be used. 1028 | This value will be overridden if you have entered a value in 'default_client_token_validity_units'. 1029 | END 1030 | } 1031 | 1032 | variable "default_client_token_validity_units" { 1033 | type = number 1034 | description = <<-END 1035 | Configuration block for units in which the validity times are represented in. 1036 | END 1037 | } 1038 | 1039 | variable "default_client_enable_token_revocation" { 1040 | type = bool 1041 | description = <<-END 1042 | Enables or disables token revocation. 1043 | END 1044 | } 1045 | } 1046 | } 1047 | } 1048 | 1049 | section { 1050 | title = "Module Outputs" 1051 | content = <<-END 1052 | The following attributes are exported by the module: 1053 | END 1054 | 1055 | output "user_pool" { 1056 | type = object(user_pool) 1057 | description = <<-END 1058 | The `cognito_user_pool` object. 1059 | END 1060 | } 1061 | 1062 | output "domain" { 1063 | type = object(domain) 1064 | description = <<-END 1065 | The full `aws_cognito_user_pool` object. 1066 | END 1067 | } 1068 | 1069 | output "clients" { 1070 | type = map(client) 1071 | description = <<-END 1072 | A map of `cognito_user_pool_client` objects. The map is keyed by the 1073 | `name` of the created clients. Client secrets are filtered out of this 1074 | map and are available through the `client_secrets` output variable and 1075 | flagged as sensitive. 1076 | END 1077 | } 1078 | 1079 | output "client_secrets" { 1080 | type = map(client_secret) 1081 | description = <<-END 1082 | A sensitive map of client secrets for all created 1083 | `cognito_user_pool_client` resources. The map is keyed by the `name` of 1084 | the created clients. 1085 | END 1086 | } 1087 | 1088 | output "module_enabled" { 1089 | type = bool 1090 | description = <<-END 1091 | Whether this module is enabled. 1092 | END 1093 | } 1094 | } 1095 | 1096 | section { 1097 | title = "External Documentation" 1098 | 1099 | section { 1100 | title = "AWS Documentation" 1101 | 1102 | content = <<-END 1103 | - https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html 1104 | - https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html 1105 | END 1106 | } 1107 | 1108 | section { 1109 | title = "Terraform AWS Provider Documentation" 1110 | 1111 | content = <<-END 1112 | - User Pool - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool 1113 | - User Pool Client - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client 1114 | - User Pool Domain - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain 1115 | - Resource Server - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server 1116 | END 1117 | } 1118 | } 1119 | 1120 | section { 1121 | title = "Module Versioning" 1122 | content = <<-END 1123 | This Module follows the principles of [Semantic Versioning (SemVer)]. 1124 | 1125 | Given a version number `MAJOR.MINOR.PATCH`, we increment the: 1126 | 1127 | 1. `MAJOR` version when we make incompatible changes, 1128 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and 1129 | 3. `PATCH` version when we make backwards compatible bug fixes. 1130 | END 1131 | 1132 | section { 1133 | title = "Backwards compatibility in `0.0.z` and `0.y.z` version" 1134 | content = <<-END 1135 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) 1136 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) 1137 | END 1138 | } 1139 | } 1140 | 1141 | section { 1142 | title = "About Mineiros" 1143 | content = <<-END 1144 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany 1145 | that solves development, automation and security challenges in cloud infrastructure. 1146 | 1147 | Our vision is to massively reduce time and overhead for teams to manage and 1148 | deploy production-grade and secure cloud infrastructure. 1149 | 1150 | We offer commercial support for all of our modules and encourage you to reach out 1151 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our 1152 | [Community Slack channel][slack]. 1153 | END 1154 | } 1155 | 1156 | section { 1157 | title = "Reporting Issues" 1158 | content = <<-END 1159 | We use GitHub [Issues] to track community reported issues and missing features. 1160 | END 1161 | } 1162 | 1163 | section { 1164 | title = "Contributing" 1165 | content = <<-END 1166 | Contributions are always encouraged and welcome! For the process of accepting changes, we use 1167 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines]. 1168 | END 1169 | } 1170 | 1171 | section { 1172 | title = "Makefile Targets" 1173 | content = <<-END 1174 | This repository comes with a handy [Makefile]. 1175 | Run `make help` to see details on each available target. 1176 | END 1177 | } 1178 | 1179 | section { 1180 | title = "License" 1181 | content = <<-END 1182 | [![license][badge-license]][apache20] 1183 | 1184 | This module is licensed under the Apache License Version 2.0, January 2004. 1185 | Please see [LICENSE] for full details. 1186 | 1187 | Copyright © 2020-2022 [Mineiros GmbH][homepage] 1188 | END 1189 | } 1190 | } 1191 | 1192 | references { 1193 | ref "homepage" { 1194 | value = "https://mineiros.io/?ref=terraform-aws-cognito-user-pool" 1195 | } 1196 | ref "mineiros-library" { 1197 | value = "https://www.mineiros.io/solutions/terraform-library" 1198 | } 1199 | ref "mineiros-pricing" { 1200 | value = "https://www.mineiros.io/solutions/terraform-library#pricing" 1201 | } 1202 | ref "hello@mineiros.io" { 1203 | value = "mailto:hello@mineiros.io" 1204 | } 1205 | ref "badge-build" { 1206 | value = "https://github.com/mineiros-io/terraform-aws-lambda-function/workflows/CI/CD%20Pipeline/badge.svg" 1207 | } 1208 | ref "badge-semver" { 1209 | value = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-cognito-user-pool.svg?label=latest&sort=semver" 1210 | } 1211 | ref "badge-license" { 1212 | value = "https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg" 1213 | } 1214 | ref "badge-terraform" { 1215 | 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" 1216 | } 1217 | ref "badge-slack" { 1218 | value = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack" 1219 | } 1220 | ref "build-status" { 1221 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/actions" 1222 | } 1223 | ref "badge-tf-aws" { 1224 | value = "https://img.shields.io/badge/AWS-3.19+-F8991D.svg?logo=terraform" 1225 | } 1226 | ref "releases-aws-provider" { 1227 | value = "https://github.com/terraform-providers/terraform-provider-aws/releases" 1228 | } 1229 | ref "releases-github" { 1230 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/releases" 1231 | } 1232 | ref "releases-terraform" { 1233 | value = "https://github.com/hashicorp/terraform/releases" 1234 | } 1235 | ref "apache20" { 1236 | value = "https://opensource.org/licenses/Apache-2.0" 1237 | } 1238 | ref "slack" { 1239 | value = "https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg" 1240 | } 1241 | ref "Terraform" { 1242 | value = "https://www.terraform.io" 1243 | } 1244 | ref "AWS" { 1245 | value = "https://aws.amazon.com/" 1246 | } 1247 | ref "Semantic Versioning (SemVer)" { 1248 | value = "https://semver.org/" 1249 | } 1250 | ref "examples/example/main.tf" { 1251 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples/example/main.tf" 1252 | } 1253 | ref "variables.tf" { 1254 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/variables.tf" 1255 | } 1256 | ref "examples/" { 1257 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/examples" 1258 | } 1259 | ref "Issues" { 1260 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/issues" 1261 | } 1262 | ref "LICENSE" { 1263 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/LICENSE" 1264 | } 1265 | ref "Makefile" { 1266 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/Makefile" 1267 | } 1268 | ref "Pull Requests" { 1269 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/pulls" 1270 | } 1271 | ref "Contribution Guidelines" { 1272 | value = "https://github.com/mineiros-io/terraform-aws-cognito-user-pool/blob/master/CONTRIBUTING.md" 1273 | } 1274 | ref "Cognito User Pools" { 1275 | value = "https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html" 1276 | } 1277 | ref "attributes docs" { 1278 | value = "https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html" 1279 | } 1280 | ref "Terraform AWS Cognito User Pool Client Docs" { 1281 | value = "https://www.terraform.io/docs/providers/aws/r/cognito_user_pool_client.html" 1282 | } 1283 | ref "Terraform AWS Cognito Resource Server Docs" { 1284 | value = "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server" 1285 | } 1286 | } 1287 | --------------------------------------------------------------------------------