terraform-provider-aws: aws_elasticsearch_domain cognito_options cause Cycle Error
Community Note
- Please vote on this issue by adding a đ reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave â+1â or âme tooâ comments, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
Terraform Version
Terraform v0.11.7
- provider.aws v1.31.0
Affected Resource(s)
aws_elasticsearch_domain aws_cognito_user_pool aws_cognito_user_pool_client aws_cognito_identity_pool
Terraform Configuration Files
resource "aws_elasticsearch_domain" "elasticsearch-cognito" {
domain_name = "test-ovowebsite-${var.environment}"
elasticsearch_version = "6.2"
cluster_config {
instance_count = "${var.elasticsearch_instance_count}"
instance_type = "${var.elasticsearch_instance_type}"
zone_awareness_enabled = "${var.elasticsearch_zone_awareness}"
dedicated_master_enabled = "${var.elasticsearch_dedicated_master_enabled}"
dedicated_master_count = "${var.elasticsearch_master_count}"
dedicated_master_type = "${var.elasticsearch_master_type}"
}
access_policies = <<CONFIG
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["es:*"],
"Resource": "arn:aws:es:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:domain/test-ovowebsite-${var.environment}/*"
}
]
}
CONFIG
ebs_options {
ebs_enabled = true
volume_type = "gp2"
volume_size = "10"
}
encrypt_at_rest {
enabled = true
kms_key_id = "${aws_kms_key.es_key.id}"
}
snapshot_options {
automated_snapshot_start_hour = "${var.elasticsearch_snapshot_time}"
}
vpc_options {
subnet_ids = ["${aws_subnet.protected_subnet1.id}","${aws_subnet.protected_subnet2.id}"]
security_group_ids = ["${aws_security_group.elasticsearch.id}"]
}
cognito_options {
enabled = true
user_pool_id = "${aws_cognito_user_pool.kibana.id}"
identity_pool_id = "${aws_cognito_identity_pool.kibana.id}"
role_arn = "${aws_iam_role.CustomESCognitoAccess.arn}"
}
tags {
Name = "ovowebsite-${var.environment}"
Team = "${var.team}"
}
}
// cognito setup
// create user pool
resource "aws_cognito_user_pool" "kibana" {
name = "kibana user pool"
auto_verified_attributes = ["email"]
admin_create_user_config = {
allow_admin_create_user_only = false
}
schema {
attribute_data_type = "String"
name = "email"
required = true
}
alias_attributes = ["email"]
}
// set user pool domain
resource "aws_cognito_user_pool_domain" "kibana" {
domain = "ovo-kibana-login"
user_pool_id = "${aws_cognito_user_pool.kibana.id}"
}
// set user pool client
resource "aws_cognito_user_pool_client" "kibana" {
name = "elasticsearch"
user_pool_id = "${aws_cognito_user_pool.kibana.id}"
generate_secret = true
callback_urls = ["${aws_elasticsearch_domain.elasticsearch-cognito.kibana_endpoint}"]
logout_urls = ["${aws_elasticsearch_domain.elasticsearch-cognito.kibana_endpoint}"]
allowed_oauth_flows = ["code", "implicit"]
allowed_oauth_scopes = ["email", "openid"]
}
//create identity pool
resource "aws_cognito_identity_pool" "kibana" {
identity_pool_name = "kibana pool"
allow_unauthenticated_identities = false
cognito_identity_providers {
client_id = "${aws_cognito_user_pool_client.kibana.id}"
provider_name = "${aws_cognito_user_pool.kibana.endpoint}"
server_side_token_check = false
}
}
Debug Output
Cycle: module.common.aws_cognito_user_pool_client.kibana, module.common.aws_cognito_identity_pool.kibana, module.common.aws_elasticsearch_domain.elasticsearch-cognito
Expected Behavior
I need to create a user pool, identity pool and user client (with the Elasticsearch Kibana Endpoint as the callback_url) and create the elasticsearch resource. Then enable Elasticsearch Cognito with the user pool id and identity pool id.
Actual Behavior
Creates an Error: Cycle: module.common.aws_cognito_user_pool_client.kibana, module.common.aws_cognito_identity_pool.kibana, module.common.aws_elasticsearch_domain.elasticsearch-cognito
Steps to Reproduce
Create an âaws_cognito_user_poolâ resource Create an âaws_cognito_identity_poolâ resource with âcognito_identity_providersâ attribute Create an âaws_elasticsearch_domainâ resource with âcognito_optionsâ attribute Create an âaws_cognito_user_pool_clientâ resource with the elasticsearch kibana endpoint
Important Factoids
We require the kibana endpoint to redirect users to kibana after login.
I propose abstracting the cognito options for elasticsearch into its own resource. This would be the minimum required to get this working i believe.
It may also be work creating a new resource that can attach a new cognito identity provider?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 122
- Comments: 30 (2 by maintainers)
@bnr242003 What we ended up doing was using terraform to still manage our aws_elasticsearch_domain with Cognito enabled, together with our Cognito related resources (i.e. aws_cognito_user_pool, aws_cognito_user_pool_domain, aws_cognito_identity_provider, and aws_cognito_identity_pool).
After doing a
tf plan/apply, our pipeline will run apost-apply.shscript, which uses the AWS CLI to directly modify theUserPoolClientAWS automatically creates for you, in order to support our SAML identity provider.See this gist for an example of how that works. Obviously, your use case may be different: https://gist.github.com/jleskovar-tyro/051317370190394d551f8861fb760f68
If you use this approach, youâll need to be sure to add the appropriate
lifecycle.ignore_changesto any TF resources that are modified by thepost-apply.shscript, or AWS itself. In our case, we had to ignore changes tocognito_identity_providerson our TF-managedaws_cognito_identity_poolresource, as otherwise the nexttf plan/applywould revert theUserPoolClientAWS automatically creates and attaches for you. Hope that makes senseHi there. Putting aside the cyclic dependency issue you mention, my experience with ElasticSearch and cognito so far is that it simply isnât possible to have Terraform manage cognito with ElasticSearch. The problem Iâve been having is that enabling Cognito auth for ES results in AWS going rogue and creating its own application client on the user pool you specify, as well as adding this client as an auth provider on your identity pool. My current workaround is to use the AWS CLI to configure cognito, after using Terraform to enable cognito on the ElasticSearch domain. Doing this, youâll need to use âignore_changesâ on your identity pool to prevent TF from blowing away the AWS-managed app client
Any updates on this issue? Weâre experiencing this, Iâd rather not ignore changes on resources or use a script to make changes after tf apply as part of CI.
Iâm using the provisioner to set the callback urls, and the rest of the configuration, after the Elasticsearch domain is created. However, the proper solution (i.e. separate resource) would be highly appreciated.
It feels like the solution here would be to split out the
cognito_identity_providers {}block and replace it with acognito_identity_provider_associationresource that would work something like this:Similar kind of issue that was seen with security groups/IAM roles that necessitated a separate associative resource to prevent these kinds of annoying overlaps you canât control in a singular definition.
Hello,
as @jleskovar-tyro mentioned, when you enable cognito authentication on ES, AWS will automatically create a new cognito app client in the background.
This renders the app client you want created via Terraform to be used via ES useless, as the configuration on ES references the AWS created app client I think?
The only work around I can think of is to data source the app client that gets created via AWS.
But then this would require two deployments, as the app client cannot be data sourced until it is created, so you would have to comment out the âcognito_identity_providersâ block in the âaws_cognito_identity_poolâ resource first (and any roles attachment resources). Deploy to enable cognito authentication for kibana on ES. Then remove the commented out code (adding the data sourced app client to the configuration) and deploy again?
@jleskovar-tyro Still using the post install approach? Do you happen to have an example of the terraform code as well?
It does not seem like a working approach. When AWS Opensearch creates the app client in your User Pool it stores its client ID and secret, which it uses later during login process for the authentication redirect to Cognito User Pool. So Opensearch is locked to the app client it has created. And what happens if you clean up that original client app named
AmazonOpenSearchService-bla-blais that your Domain will be broken:And it seems there is no way to set ClientID and Client Secret through the Opensearch control API.
ah, this is not possible: https://www.terraform.io/docs/providers/aws/d/cognito_user_pool_client.html
Hi everyone. In the AWS documentation for Amazon OpenSearch (the AWS rebranding of Elastiseach), it states
From my understanding, in your
aws_cognito_identity_pool, you should be able to leave out thecognito_identity_providersand AWS will configure it. Note that you will have to ignore changes to that field usinglifecycle.ignore_changes.In the acceptance tests for
aws_elasticsearch_domainwe do the followingUnfortunately, this isnât well documented.
Does this address the problem for you?
I think this issue could be solved if terraform had a data source for Cognito client app (with support for regex filter on name) and an independent resource for adding Cognito identity providers to an existing identity pool.
Some quick solution will be appreciated. Please let me know if you need anymore clarifications.