_This issue was originally opened by @rginev as hashicorp/terraform#10208. It was migrated here as part of the provider split. The original body of the issue is below._
Hey there,
Terraform does have route53_zone_association resource, but it works for private zones and VPCs in the same AWS account.
If you want to associate a VPC that you created with one AWS account with a private hosted zone that you created with a different account you had to ask AWS support to create authorisation manually.
Now they added an API for this. It would be great to have this implemented in terraform e.g. new resource.
Thanks in advance!
@RyanJarv I don't know if you've looked here since the provider split. Let me know if you want to help get a fix together for this.
Should only require the creation of an authorization resource against a specific zone, with parameter inputs for source vpc id and source vpc region.
Would love to see this implemented.
EDIT: Just realised how difficult this could end up being to implement. It seems to me that the Zone owner account has to create an authorisation, the VPC owner account then has to perform the association, but then subsequently does not have permission to describe the association. If you manually create an authorisation and then use terraform to create the association; the association will be created but the apply will fail and all subsequent plans and applies will fail because in order to refresh the resource, the zone must be described, but permission is not available to do so.
@josephholsten Hey sorry, yeah that would be awesome I've just been pretty busy and not sure when I'll have time to get back to this.
Worth mentioning this actually does work currently for creating authorizations but like @Zordrak pointed out the association resource can't describe route53 zone and fails currently. This is talked about a bit more at https://github.com/hashicorp/terraform/pull/12553
If we don't mind the association and authorization resource working together currently this could probably be merged with some added docs and a note on the issue.
Is anyone still interested in trying to get this feature out?
Went ahead and cleaned this up a bit and added documentation in https://github.com/terraform-providers/terraform-provider-aws/pull/2005. Last PR was before the repo split.
Awesome! this will be very useful! Thanks for the hard work!
Agreed. Fixing this would be very helpful. In the meantime I have used the AWS CLI to do the Route53 VPC association from a VPC sitting in one AWS account to a Route53 Hosted Zone sitting on different AWS account. Here are the steps: https://aws.amazon.com/premiumsupport/knowledge-center/private-hosted-zone-different-account/
There's a problem with the way the Route 53 API works when creating the association between a hosted zone created in one AWS account and a VPC created in a second AWS account.
This Terraform code (following the steps here, and based on this code)
provider "aws" {
// Zone creator's credentials.
}
provider "aws" {
alias = "bar"
// VPC creator's credentials.
access_key = "XXXXXXXXXXXXXXXXXXXX"
secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
resource "aws_vpc" "foo" {
cidr_block = "10.6.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
}
resource "aws_route53_zone" "foo" {
name = "example.com"
vpc_id = "${aws_vpc.foo.id}"
}
resource "aws_vpc" "bar" {
provider = "aws.bar"
cidr_block = "10.7.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
}
resource "aws_route53_zone_association_authorization" "foo" {
zone_id = "${aws_route53_zone.foo.id}"
vpc_id = "${aws_vpc.bar.id}"
}
resource "aws_route53_zone_association" "bar" {
provider = "aws.bar"
zone_id = "${aws_route53_zone_association_authorization.foo.zone_id}"
vpc_id = "${aws_vpc.bar.id}"
}
should create VPCs in two different AWS accounts and associate them both with a hosted zone created in the first AWS account. In fact it does exactly that, but an error is reported:
terraform apply
aws_vpc.bar: Creating...
assign_generated_ipv6_cidr_block: "" => "false"
cidr_block: "" => "10.7.0.0/16"
default_network_acl_id: "" => "<computed>"
default_route_table_id: "" => "<computed>"
default_security_group_id: "" => "<computed>"
dhcp_options_id: "" => "<computed>"
enable_classiclink: "" => "<computed>"
enable_classiclink_dns_support: "" => "<computed>"
enable_dns_hostnames: "" => "true"
enable_dns_support: "" => "true"
instance_tenancy: "" => "<computed>"
ipv6_association_id: "" => "<computed>"
ipv6_cidr_block: "" => "<computed>"
main_route_table_id: "" => "<computed>"
aws_vpc.foo: Creating...
assign_generated_ipv6_cidr_block: "" => "false"
cidr_block: "" => "10.6.0.0/16"
default_network_acl_id: "" => "<computed>"
default_route_table_id: "" => "<computed>"
default_security_group_id: "" => "<computed>"
dhcp_options_id: "" => "<computed>"
enable_classiclink: "" => "<computed>"
enable_classiclink_dns_support: "" => "<computed>"
enable_dns_hostnames: "" => "true"
enable_dns_support: "" => "true"
instance_tenancy: "" => "<computed>"
ipv6_association_id: "" => "<computed>"
ipv6_cidr_block: "" => "<computed>"
main_route_table_id: "" => "<computed>"
aws_vpc.bar: Creation complete after 6s (ID: vpc-951bcaec)
aws_vpc.foo: Creation complete after 5s (ID: vpc-b018c9c9)
aws_route53_zone.foo: Creating...
comment: "" => "Managed by Terraform"
force_destroy: "" => "false"
name: "" => "example.com"
name_servers.#: "" => "<computed>"
vpc_id: "" => "vpc-b018c9c9"
vpc_region: "" => "<computed>"
zone_id: "" => "<computed>"
aws_route53_zone.foo: Still creating... (10s elapsed)
aws_route53_zone.foo: Still creating... (20s elapsed)
aws_route53_zone.foo: Still creating... (30s elapsed)
aws_route53_zone.foo: Creation complete after 35s (ID: Z3UMIQBZQ9Y13C)
aws_route53_zone_association_authorization.foo: Creating...
vpc_id: "" => "vpc-951bcaec"
vpc_region: "" => "<computed>"
zone_id: "" => "Z3UMIQBZQ9Y13C"
aws_route53_zone_association_authorization.foo: Creation complete after 0s (ID: Z3UMIQBZQ9Y13C:vpc-951bcaec)
aws_route53_zone_association.bar: Creating...
vpc_id: "" => "vpc-951bcaec"
vpc_region: "" => "<computed>"
zone_id: "" => "Z3UMIQBZQ9Y13C"
aws_route53_zone_association.bar: Still creating... (10s elapsed)
aws_route53_zone_association.bar: Still creating... (20s elapsed)
aws_route53_zone_association.bar: Still creating... (30s elapsed)
Error applying plan:
1 error(s) occurred:
* aws_route53_zone_association.bar: 1 error(s) occurred:
* aws_route53_zone_association.bar: AccessDenied: User: arn:aws:iam::000000000000:user/kit is not authorized to access this resource
status code: 403, request id: c1f53cc1-f6fe-11e7-8456-41d8d6fcb1f8
Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.
and subsequent terraform plan
s get the same error:
terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
aws_vpc.bar: Refreshing state... (ID: vpc-951bcaec)
aws_vpc.foo: Refreshing state... (ID: vpc-b018c9c9)
aws_route53_zone.foo: Refreshing state... (ID: Z3UMIQBZQ9Y13C)
aws_route53_zone_association_authorization.foo: Refreshing state... (ID: Z3UMIQBZQ9Y13C:vpc-951bcaec)
aws_route53_zone_association.bar: Refreshing state... (ID: Z3UMIQBZQ9Y13C:vpc-951bcaec)
Error refreshing state: 1 error(s) occurred:
* aws_route53_zone_association.bar: 1 error(s) occurred:
* aws_route53_zone_association.bar: aws_route53_zone_association.bar: AccessDenied: User: arn:aws:iam::000000000000:user/kit is not authorized to access this resource
status code: 403, request id: 22ab1eca-f700-11e7-aa35-9bd7d0c4ca7d
The problem is with the code that run under the credentials of the associator (i.e. NOT the AWS account that created the hosted zone) that is reading the state of the zone association https://github.com/terraform-providers/terraform-provider-aws/blob/17a320b90f85a7e98e19f2b405d0526b640f4880/aws/resource_aws_route53_zone_association.go#L94-L95
As there is no AWS zone associated resource the zone itself is queried and this fails with the _AccessDenied_ error when called from the AWS account that didn't create the zone.
@ewbankkit Yeah, this is an issue with aws_route53_zone_association and is documented in my PR at https://github.com/terraform-providers/terraform-provider-aws/pull/2005/files#diff-f048cbf19e0fc509e5df5d05254f5bdbR13.
This was also the reason I held off on making that PR for a bit, some people where asking for it regardless, so short of a better fix I added a note on the issue (although looking at it now this should be added to the aws_route53_zone_association
doc as well). I'm sure this could be worked around somehow, however I didn't come up with anything that didn't feel hacky to me at the time.
The core of the issue is that you can not enumerate Route53 zones attached to a VPC, so the aws_route53_zone_association resource checks to see if the VPC is attached by using GetHostedZone on the Route53 zone which the account that needs to do the association doesn't usually have access to.
@RyanJarv
Hi, have you considered requiring a second provider for which to do the R53 api call with?
If it's not a TF coding anti-pattern / no-no I'd be happy with having to specifiy two providers to a resource. I'd expect the authorisation to be created at the same time as the association as the example above does, so the second provider should be available anyway.
A second idea I've had, but the answer doesn't seem obvious from the AssociateVPCWithHostedZone API reference, What error/response do you get when trying to associate an already associated VPC to a zone? Is the response suitable to be used in determining whether the VPC is already associated, rather than having to get the list of vpcs from the zone?
excuse my naivety if these are obvious no's! š
Cheers,
Josh
@JoshiiSinfield If I'm reading the above correctly then @ewbankkit has already tried doing this (hence the two provider "aws"
statements at the top of his TF code.
From using the aws cli, from memory, I think you do get a different message when the zone has already been associated.
@psyvision
Yes he has, except I was on about passing a second provider into the zone_association resource.
Something like this (assuming use of the rest of @ewbankkit's code)::
resource "aws_route53_zone_association" "bar" {
provider = "aws.bar"
r53_zone_provider = "aws"
zone_id = "${aws_route53_zone_association_authorization.foo.zone_id}"
vpc_id = "${aws_vpc.bar.id}"
}
That way you're explicitly giving the zone_association access to the R53 zone to call GetHostedZones.
I think I remember considering something like that at one point,
unsure if I just didnāt think it was possible or wasnāt sure how to
implement it.
If itās doable though seems like a pretty good work around. But I might
need to take a step back from this PR and would be great if some one is
able to take the lead here.
On Mon, Mar 12, 2018, at 4:19 AM, Josh Sinfiel
@psyvision[1]
Yes he has, except I was on about passing a second provider into the
zone_association resource.>
Something like this (assuming use of the rest of
@ewbankkit[2]'s code)::
resource "aws_route53_zone_association" "bar" { provider = "aws.bar"
r53_zone_provider = "aws" zone_id =
"${aws_route53_zone_association_authorization.foo.zone_id}" vpc_id =
"${aws_vpc.bar.id}" }ā You are receiving this because you were mentioned. Reply to this
email directly, view it on GitHub[3], or mute the thread[4].>
Links:
Related: #585 and #8593
Hey all, haven't got around to looking into this again yet but did want to leave this here, turn's out the API issue thing is also a bit of a security problem. I reported this to AWS security about two years ago when I was working on this originally but am unsure of any timeline on fixing it.
https://blog.ryanjarv.sh/2019/05/24/backdooring-route53-with-cross-account-dns.html
Hi everyone, we've decided that there isn't a way we're happy to do this currently within the API constraints. Please don't submit new PRs for the resource right now. I'm going to leave the ticket open as an upstream issue to reconsider if something changes.
For a workaround, you can use the cli instructions instead: https://aws.amazon.com/premiumsupport/knowledge-center/private-hosted-zone-different-account/
Hi, I see that you guys don't want to go forward with this PR because the API does not have a good way of allowing an account to view vpc associations on a route53 zone that it does not own. I think that there are still uses for this resource and see no reason why limitation in associations API should stop you from implementing the authorizations API. All the pieces are there. And who knows, maybe once people get their hands on this, the path to full cross account route53 associations managed by terraform will be more clear.
Hi, I was able to workaround this limitations using multiple data sources and resource. Please let me know if this would be accepted, as then I would need additional time for testing coverage.
@krogon the issue could have been worked around before, the problem has always been it's hacky at best. If you think you have a good solution though and have the code available somewhere I'd be happy to take a look at it.
Why not simply split it into two ressources with a delay feature? Would then be easy to specify a provider for the auth ressource and another for the association ressource? Its just lame we still need to do some CLI calls when 99% of the infrastructure is all in TF!!!
@ipnextgen my workaround for these types of things right now has been to use https://github.com/scottwinkler/terraform-provider-shell.
The terraform ends up being very simple. Here is an example for security hub invitations. Basically you invoke the resource and tell it what script to call.
resource "shell_script" "security_hub_membership" {
lifecycle_commands {
create = "./scripts/security_hub_invitation.sh create ${data.aws_caller_identity.security.account_id} ${local.account_info.id} ${local.account_info.email}"
read = "./scripts/security_hub_invitation.sh read ${data.aws_caller_identity.security.account_id} ${local.account_info.id}"
delete = "./scripts/security_hub_invitation.sh delete ${data.aws_caller_identity.security.account_id} ${local.account_info.id}"
}
working_directory = path.module
}
Then I have structured all my scripts like so
#!/usr/bin/env bash
set -e -x -o pipefail
## Goal: Provide a script that terraform shell provider can use to manage security hub invitations.
## Helpful function to assume a role and run an AWS command
## arguments:
## 1 -> account id
## 2..n -> aws cli arguments
function AWS_RUN_CMD_AS {
##Get temporary credentials for the account we were given
CREDENTIALS=$(aws sts assume-role --role-arn arn:aws:iam::$1:role/YourRoleName \
--role-session-name enable-security-hub)
##Setup the proper temp credentials and invoke the aws cli with the provided args
AWS_ACCESS_KEY_ID=$(echo $CREDENTIALS | jq -r '.Credentials.AccessKeyId') \
AWS_SECRET_ACCESS_KEY=$(echo $CREDENTIALS | jq -r '.Credentials.SecretAccessKey') \
AWS_SESSION_TOKEN=$(echo $CREDENTIALS | jq -r '.Credentials.SessionToken') \
aws "${@:2}"
}
## arguments:
## 1 -> Security account id
## 2 -> id of account to create membership for
## 3 -> email of account to create membership for
function create {
## implement create function
}
## arguments:
## 1 -> Security account id
## 2 -> account id to check status for
function read {
## implement read function
}
function update {
echo "Update is not implemented."
exit 6
}
## arguments:
## 1 -> Security account id
## 2 -> account id to delete membership
function delete {
##Implement delete function
}
case $1 in
create)
create "${@:2}"
;;
read)
read "${@:2}"
;;
update)
update "${@:2}"
;;
delete)
delete "${@:2}"
;;
*)
echo "Unrecognized command $1"
exit 5
;;
esac
I don't like to use the shell provider too much, but the main benefit here is that we get the normal CRUD operations. This allows us to do normal terraform things, whereas using the built in local-exec really only lets you create and delete (sort of).
Creating a script to run the CLI commands to create/read/delete route53 authorizations should be pretty straight forward. The json output from the read operation is made available in terraform like any other resource so this should fit pretty seamlessly into your existing setup.
@ipnextgen you are misunderstanding the issue.
To clarify, it has always been two separate pieces. The core issue is one of those pieces needs to essentially use two providers, as far as I am aware there is not a way to do this that maps well to how terraform is currently used. Breaking this apart into separate resources, I believe would mean having one responsible for half of the CRUD operations and the second for the other.. Maybe this is possible? I suppose? Honestly have no idea how this would work though. Iām happy to review any PRās related to this if you think youāve found a way to do this that makes sense.
Edit: Ok I guess I said this was technically possible before. I canāt remember what I was thinking then though. Iāll probably stop responding to this issue for now though.
Edit2: If anyone wants to work on this feature I might suggest looking into how the web console gets information on associated zones. From my understanding although this information isnāt available through the API from the non-hosted zone account it somehow is through the web console.
I just opened this up here #24286 in terraform repo, but didn't realize this was already here.
I would imagine this just needs 2 resources similar to how to setting up a peer connection works.
respectfully:
aws_vpc_peering_connection
aws_vpc_peering_connection_accepter
maybe:
aws_route53_zone_authorization (new resource) like mentioned above
aws_route53_zone_association
Currently you can accomplish this with the cli manually:
aws route53 create-vpc-association-authorization \
--hosted-zone-id ZAZAPAPAXAXAXAXAXA10 \
--vpc VPCRegion=us-east-1,VPCId=vpc-000bb00bb00bb00bb \
--profile profile_with_access_to_private_hosted_zone
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id ZAZAPAPAXAXAXAXAXA10 \
--vpc VPCRegion=us-east-1,VPCId=vpc-000bb00bb00bb00bb \
--profile profile_with_access_to_vpc_in_secondary_account
md5-983ba3afd84f66ba433b9753f00800f5
```sh
aws route53 disassociate-vpc-from-hosted-zone \
--hosted-zone-id ZAZAPAPAXAXAXAXAXA10 \
--vpc VPCRegion=us-east-1,VPCId=vpc-000bb00bb00bb00bb \
--profile profile_with_access_to_vpc_in_secondary_account
md5-5e3a484a75e2d6f8cafa05260518a9a5
module.associate_vpc_2_zone.aws_route53_zone_association.env: Creating...
module.associate_vpc_2_zone.aws_route53_zone_association.env: Still creating... [10s elapsed]
module.associate_vpc_2_zone.aws_route53_zone_association.env: Still creating... [20s elapsed]
module.associate_vpc_2_zone.aws_route53_zone_association.env: Still creating... [30s elapsed]
Error: AccessDenied: User: arn:aws:sts::333333333333:assumed-role/SomeRole/terraform is not authorized to access this resource
status code: 403, request id: ae42ae42-ae42-ae42-ae42-ae42ae42ae42
However, this results in successful association of the vpc to the zone.
@RyanJarv does any of this change your opinion on how this would be tackled?
@RyanJarv does any of this change your opinion on how this would be tackled?
I kinda forget what the issue is exactly every time I look at this post, so probably worth taking whatever I say here with a grain of salt.
The association needs to be run in the hosted zone account iirc, so the error is because this account canāt enumerate current associations. It can work but you start to run into cases where you donāt know the current state of stuff. It seems like this is still an issue I believe? If you wanted to only store state about associations locally that seems doable, Iām not sure I understand the impact of doing this though.
This doesnāt sound right, probably best to ignore me. Iāll try to look into this again soon though.
Edit: Quick update, I had that backwards I think. So authorization is done by the hosted zone account, association is done by the VPC account. Itās failing because terraform tries to figure out if a zone is associated or not first, but you canāt do that with the API, you donāt have permissions to read the zone. If that information was stored locally then you should be able to do this, but you canāt know the state of your account other then that (I think I keep getting confused about the terraform vs security part of this). So if you take out the read part of the CRUD stuff on the association resource this should work(?)
If the resource is ever managed outside of terraform you will run into issues though. Maybe this is OK, Iām not really sure. I think it was mostly decided we didnāt want to do that but maybe this part wasnāt clear before (actually pretty sure this wasnāt obvious before, I need to read this thread though).
You mentioned something about passing roles (on my phone so difficult to look rn) in your other post, if you could somehow grant access to read the zone and maybe include it in an example of how this should be used maybe that would work as well.
Edit2: The other part of this is AWS recommends removing the authorization after the association is complete. But tbh Iām not really sure I understand the reasoning for doing this, or why you wouldnāt want a VPC to be re-associated. I think itās probably okay to just make note of it though in the docs, I thought there was discussion somewhere on this in the thread but not seeing it now.
Let me know if I missed anything here.
@RyanJarv
So if you take out the read part of the CRUD stuff on the association resource this should work(?)
Are addressing the 403 error I put above? I believe so.
If the resource is ever managed outside of terraform you will run into issues though.
We are strictly speaking about just association of VPC-Account B to private hosted zone-Account A.. i think this is ok.
if you could somehow grant access to read the zone and maybe include it in an example of how
this should be used maybe that would work as well.
Without the idea of assuming more than 1 profile/alias within a resource/module (role-ception) this doesn't seem doable with terraform/aws. I question though how the above command works fine though specifying only one profile. Route53 and VPC's don't have the capability of a s3 bucket policy equivalent where you can grant access to IAM users/roles in different accounts.
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id ZAZAPAPAXAXAXAXAXA10 \
--vpc VPCRegion=us-east-1,VPCId=vpc-000bb00bb00bb00bb \
--profile profile_with_access_to_vpc_in_secondary_account
I mainly point to the cli commands that I reference above. Both manual cases for applying and destroying work perfect with just 1 profile being used with each command. I would imagine this translates to the API.. given it only has the inputs I provide.
When running the associate cli command again after it's already associated. I get this.
An error occurred (ConflictingDomainExists) when calling the AssociateVPCWithHostedZone operation: The VPC that you chose, vpc-00000000000 in region us-east-1, is already associated with another private hosted zone that has an overlapping name space, somedomain.com..
Meaning it does plenty fine knowing it's already associated. This coming from the profile of the account with the VPC that doesn't have direct access to the private hosted zone in the "route53" account.
The other part of this is AWS recommends removing the authorization after the association is complete. But tbh Iām not really sure I understand the reasoning for doing this, or why you wouldnāt want a VPC to be re-associated.
This is because after it is associated you no longer need it authorized. I think like you mention this can be noted in the docs.. and probably ignored.
I would like to point out.
Seems that this was first reported by @rginev on Nov 17, 2016 (roughly ~3.5 years ago)
https://github.com/hashicorp/terraform/issues/10208
Since then:
https://github.com/hashicorp/terraform/issues/11174 (closed -> ^10208)
https://github.com/hashicorp/terraform/issues/12804 (closed -> #617)
https://github.com/hashicorp/terraform/issues/20841 (closed no resolution)
https://github.com/hashicorp/terraform/issues/22780 (closed -> #9453)
https://github.com/hashicorp/terraform/issues/24286 (closed -> #384 here)
https://github.com/hashicorp/terraform/pull/12553 (@RyanJarv your PR)
https://github.com/terraform-providers/terraform-provider-aws/issues/384 (here)
https://github.com/terraform-providers/terraform-provider-aws/issues/585 (open)
https://github.com/terraform-providers/terraform-provider-aws/issues/617 (open)
https://github.com/terraform-providers/terraform-provider-aws/pull/2005 (closed no resolution)
https://github.com/terraform-providers/terraform-provider-aws/issues/7805 (closed no resolution)
https://github.com/terraform-providers/terraform-provider-aws/issues/7812 (closed -> #7805)
https://github.com/terraform-providers/terraform-provider-aws/issues/8593 (open)
https://github.com/terraform-providers/terraform-provider-aws/issues/9453 (open)
There's probably more I missed, I'm just trying to point out that this has been wanted for a while.
Both @ewbankkit @FransUrbo seem to have a lot of history with this and might be interested in this still?
@bflad (maintainer?)
This also came up in some research:
https://forums.aws.amazon.com/thread.jspa?threadID=271250
I thought a lot about this a while back and my conclusion was that capturing the behaviour of this API in a resource doesn't match the way that the AWS provider works - i.e. the interactions for a single resource are done under the single AWS identity configured in the resource.
One solution may be to create separate provider that contains this new resource and this new provider is configured with both AWS identities. The complexity would all be in the myriad options for configuring those identities for the underlying AWS SDK.
https://github.com/hashicorp/aws-sdk-go-base could contain some reusable parts.
@ewbankkit
the interactions for a single resource are done under the single AWS identity configured in the resource.
I'm not understanding the issue tbh.
looking over:
API_CreateVPCAssociationAuthorization
and
API_AssociateVPCWithHostedZone
Seems that this would only require a single aws identity per resource/api call/cli cmd.
I quote from the 2nd link.
Use the AWS account that created the private hosted zone to submit a
CreateVPCAssociationAuthorization request. Then use the account that created the VPC to submit
an AssociateVPCWithHostedZone request.
If a subnet in the VPC was shared with another account, you can use the account that the subnet
was shared with to submit an AssociateVPCWithHostedZone request. For more information about
sharing subnets, see Working with Shared VPCs.
Sounds like it follows suit with the commands I posted above. https://github.com/terraform-providers/terraform-provider-aws/issues/384#issuecomment-595276897
Would you be able to explain what the issue is exactly?
wanted to bump you on this @ewbankkit and maybe also @RyanJarv
Any thoughts on? this is kinda of a pain to manage when you have have many accounts utilizing a private hosted zone in another account.
Is anyone aware of any examples in terraform where the read part of CRUD is skipped, leaving other operations to depend only the data in the state file?
I'm running into the same issue and would love to see a solution, or at least some extra documentation that outlines this scenario before more people end up running it and finding this issue.
Alternatively, would it be possible to have an IAM policy that would allow the account with the VPC to list hosted zones on the account with the hosted zone as a workaround?
I'm running into this issue as well and I think anyone trying to make use of a private hosted zone across accounts with terraform is going to run into this issue. Managing multiple aws accounts is a very common use case in large companies and is what aws seems to recommend as an architecture within an organization. It's very disappointing to see this go unresolved for years.
just encountering this issue myself.
there are ways to address using resolver-endpoints (inbound at _phz-provider_, outbound at _phz-consumer_), but those endpoints are charged separately by aws and it would be great to avoid that extra charge with the "direct" phz <-> vpc association alternative.
per this knowledge-base article it shows how to accomplish the authorization via cli.
i can/will try myself, but figured i would pose the question to the experienced participants in this thread:
assuming that the __authorization__ part was done manually in the context of the _phz-provider_ account, would use of aws_route53_zone_association work in the context of the _phz-consumer_ account?
Hi all, I was looking into this again after @miketwenty1 pointed out that you can get the state of the aws_route53_zone_association
from the error messages returned after repeated calls to that API.
I put something together to test this out in https://github.com/terraform-providers/terraform-provider-aws/compare/master...RyanJarv:cross-account-hostedzone-association.
This is all just a test right now, so any thoughts here are appreciated. In that branch I'm using a cross_account attribute on the aws_route53_zone_association
resource to change the behavior of how the read and wait parts are done.
So in that branch if cross_account = true
:
This seems to work ok but at the moment but has the following issues:
aws_route53_zone_association
resource.I don't think the second is really an issue but wanted to mention it since it was brought up before.
For the first there might be able to handle through something like always show a change during plan and somehow indicate that it may not actually result in a change. This behavior could potentially be toggled via something like the cross_account option as well.
Mostly wanted to post this now to see if anyone has any opinions on this behavior in the branch I linked and any thoughts on handling drift.
@evandam
Alternatively, would it be possible to have an IAM policy that would allow the account with the VPC to list hosted zones on the account with the hosted zone as a workaround?
Using assumeRole yes, however terraform afik isn't designed to connect to multiple accounts in a single resource. If it was possible to do this without assumeRole this would be more feasible. I wasn't able to figure either of these options out though at least in a way that made sense.
@tony-kerz
assuming that the authorization part was done manually in the context of the phz-provider account, would use of aws_route53_zone_association work in the context of the phz-consumer account?
This would not work, for the most part aws_route53_zone_association is the problem. If you want to try the branch in my last post that may work for you (warning: have not done much testing on it).
We have encountered this issue as well. Trying to build an ephemeral organization that has DNS is turning out to be quite the challenge.
This... _bug_? Will become more and more pertinent to businesses that have spawned in the era of IAC as they grow to incorporate multi account architectures, at AWS's recommendation I might add!
I'm also keen to see a clean resolution to this issue and I understand this is a complex one to solve!
I've tried using a null_resource to call the CLI and do the association. The problem is that when you create the zone, you can't specify the other account VPC or you get an error, so after everything has run the first time and the VPC is associated with the zone, terraforms seeks to remove the VPC from the hosted zone. It's all pretty ugly to handle at the moment.
One semi "clean" way to handle this now is to create a public hosted zone and record which points to the private DNS. Like the resolver-endpoint solution above, it costs more to implement of course depending on choice of domain.
For anyone interested the way I ended up implementing was as follows:
# new private zone in account_a
resource "aws_route53_zone" "private" {
name = local.zone_name
tags = local.tags
}
# This is run in context of account_a which has the hosted zone
resource "null_resource" "associate_zone_to_account_b" {
triggers = {
always = timestamp()
}
provisioner "local-exec" {
command = "New-R53VPCAssociationAuthorization -HostedZoneId ${aws_route53_zone.private.id} -VPC_VPCId ${local.account_b_id} -VPC_VPCRegion ${var.account_b_region}"
interpreter = ["PowerShell", "-Command"]
}
}
# This is run in context of account_b which has the vpc - using STS
resource "null_resource" "associate_zone_to_account_b_authorise" {
triggers = {
resource_id = null_resource.associate_zone_to_account_b.id
}
provisioner "local-exec" {
command = ". ${path.module}\\R53HostedZoneAssociation.ps1 ; Register-HostedZoneWithOtherAccountVpc -VpcId ${local.account_b_id} -VpcRegion ${local.account_b_region} -HostedZoneId ${aws_route53_zone.private.id} -STSRole ${local.sts_role}"
interpreter = ["PowerShell", "-Command"]
}
}
Effect of the above is I can re-run this terraform and reach the same outcome of the zone being associated with account_b VPC. It's not pretty because on every run it removes the association then re-adds, but it works.
New-R53VPCAssociationAuthorization
calls the CreateVPCAssociationAuthorization API operation
Register-HostedZoneWithOtherAccountVpc
uses the provided role to authenticate against account_b and then calls the AssociateVPCWithHostedZone API operation.
You need to have a role with the appropriate permission that the script can assume.
@tdmalone great timing with that post - has someone taken ownership to bring this home after the years of requests and posts :)
Any chance this will get added into the provider anytime soon? The workarounds given uses local exec for aws cli and this is something we are trying very hard to avoid when using Terraform Enterprise. Also we are going into 100+ accounts now - and the less dependencies on externals the better :)
@arnvid Copying an update from Brian on the above PR:
Marking this for right after we complete our work for 3.0 in the next week or two, although review cycles might make it slightly after 3.1 for actual release. š
So, this is looking promising for pretty soon! š
Support for Route 53 cross-account VPC Associations via a new aws_route53_vpc_association_authorization
resource and updated aws_route53_zone_association
resource handling has been merged and will release with version 3.1.0 of the Terraform AWS Provider, likely later today. Thanks to @goakley and @RyanJarv for implementation. š
This has been released in version 3.1.0 of the Terraform AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.
For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template for triage. Thanks!
I'm going to lock this issue because it has been closed for _30 days_ ā³. This helps our maintainers find and focus on the active issues.
If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!
Most helpful comment
I would like to point out.
Seems that this was first reported by @rginev on Nov 17, 2016 (roughly ~3.5 years ago)
https://github.com/hashicorp/terraform/issues/10208
Since then:
https://github.com/hashicorp/terraform/issues/11174 (closed -> ^10208)
https://github.com/hashicorp/terraform/issues/12804 (closed -> #617)
https://github.com/hashicorp/terraform/issues/20841 (closed no resolution)
https://github.com/hashicorp/terraform/issues/22780 (closed -> #9453)
https://github.com/hashicorp/terraform/issues/24286 (closed -> #384 here)
https://github.com/hashicorp/terraform/pull/12553 (@RyanJarv your PR)
https://github.com/terraform-providers/terraform-provider-aws/issues/384 (here)
https://github.com/terraform-providers/terraform-provider-aws/issues/585 (open)
https://github.com/terraform-providers/terraform-provider-aws/issues/617 (open)
https://github.com/terraform-providers/terraform-provider-aws/pull/2005 (closed no resolution)
https://github.com/terraform-providers/terraform-provider-aws/issues/7805 (closed no resolution)
https://github.com/terraform-providers/terraform-provider-aws/issues/7812 (closed -> #7805)
https://github.com/terraform-providers/terraform-provider-aws/issues/8593 (open)
https://github.com/terraform-providers/terraform-provider-aws/issues/9453 (open)
There's probably more I missed, I'm just trying to point out that this has been wanted for a while.
Both @ewbankkit @FransUrbo seem to have a lot of history with this and might be interested in this still?
@bflad (maintainer?)
This also came up in some research:
https://forums.aws.amazon.com/thread.jspa?threadID=271250