hashicorp / terraform-provider-google

Terraform Provider for Google Cloud Platform
https://registry.terraform.io/providers/hashicorp/google/latest/docs
Mozilla Public License 2.0
2.25k stars 1.7k forks source link

Cloud DNS: Get IP for dns_policy #3753

Open MPV opened 5 years ago

MPV commented 5 years ago

Community Note

Description

Today when you create a private managed DNS zone (a dns_managed_zone with visibility = "private"), and want to use it from your hybrid/VPN environment, you'll want to add a DNS policy allowing this (a google_dns_policy with enable_inbound_forwarding = true).

After you've done this, when the policy is created, IP-address(es) are automatically created with "Inbound query forwarding IP(s)" (for each region/network).

I'd like to be able to output/refer to these new IPs in Terraform.

Today I can run something like this with the gcloud command to get these IP addresses:

$ gcloud compute addresses list --filter='purpose:DNS_RESOLVER'
NAME                             ADDRESS/RANGE  TYPE      PURPOSE       NETWORK  REGION         SUBNET                   STATUS
dns-forwarding-ahashhere         10.20.0.11     INTERNAL  DNS_RESOLVER           europe-north1  mynetwork-europe-north1  RESERVED
dns-forwarding-anotherhashhere   10.30.0.11     INTERNAL  DNS_RESOLVER           europe-west1   mynetwork-europe-west1   RESERVED

I imagine this could either be included as an optional return value of the google_dns_policy, or by adding type and/or purpose attributes to the google_compute_address data type, so that you can filter on those.

The former makes more sense in my head, since it would make it possible to depend on the google_dns_policy and the order of the dependency graph would sort out that the policy and it's accompanying IP addresses are created before you can use them in something dependent upon it.

New or Affected Resource(s)

References

MPV commented 5 years ago

Another idea:

Maybe it could be made possible to create/allocating the forwarding IPs beforehand using google_compute_address resources (with INTERNAL type and DNS_RESOLVER purpose)?

...and then you could just send those allocated IPs into the google_dns_policy as arguments.

bernadinm commented 4 years ago

I was also looking into this myself as well @MPV and it sounds like a decent workaround but the google_dns_policy doesn't have a function where you could set a pre-existing allocated IP.

https://www.terraform.io/docs/providers/google/r/dns_policy.html

There is ipv4_address but that is related to the alternative_name_server_config block which is not the intended function to this use case.

Omarimcblack commented 4 years ago

@MPV do you know if there has been any movement on this? or has anybody found a feasible alternative solution in the meantime?

65156 commented 3 years ago

Would be worth upping the priority on this, being able to ref those inbound forwarder ip's will be useful in a multicloud dns deployment, amongst other things.

upodroid commented 3 years ago

@danawillow Can we put this on the backlog? It is pending an upstream API change. There is no programmatic way of reliably linking the address and the dns policy.

https://issuetracker.google.com/issues/169585798

danawillow commented 3 years ago

Hi @upodroid, if this is a blocker for you and you have a Google-side contact (like a TAM or CE), you can ask them to file an issue against our team internally.

upodroid commented 3 years ago

Thanks, it is not blocking me but the the Cloud DNS Team need to fix the api before I can fix it in terraform.

65156 commented 3 years ago

Google DNS Team have advised that this is working as intended, are we able to get terraform to leverage the gcloud command (below) to retrieve this instead of relying on the underlining api?

see update: https://issuetracker.google.com/issues/169585798

gcloud compute addresses list --filter="purpose=DNS_RESOLVER" --format='csv[no-heading](address, subnetwork)'

danawillow commented 3 years ago

We can't shell out to gcloud from the provider, but it's possible for the provider to make the same API call that gcloud makes. I'll leave it up to the implementor to decide whether it makes more sense in a DNS resource or to add filtering capability to the address data source.

upodroid commented 3 years ago

It is doable. Google forgot to mention that a VPC can only be bound to a single dns policy.

  1. List all the subnets in a VPC.
  2. https://cloud.google.com/compute/docs/reference/rest/v1/addresses/aggregatedList make this call and in the filter supply all the subnet self links

I think it should be a separate datasource considering that the IPs will change when subnets are changed

rileykarson commented 3 years ago

The most likely solution to this is a case of https://github.com/hashicorp/terraform-provider-google/issues/8255 which isn't supported yet.

red8888 commented 3 years ago

is #8255 going to be the solution to this problem?

shebang89 commented 3 years ago

While we wait for a permanent solution (I like the #8255 suggestion), here's a quick and dirty fix:

Requirements:

Create the following script in your modules/yourmodule/scripts: get_dns_forwarder_ips.sh

#!/bin/bash

set -e

gcloud compute addresses list --filter='purpose="DNS_RESOLVER"' --format='json[no-heading](address, subnetwork)' | jq 'map({(.address): .subnetwork}) | add'

Execution of this script will output a map of ip:subnet pairs (I needed it like this, feel free to play with gcloud and jq filters anyway you like):

{
  "10.50.1.3": "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-project-vpc-subnet-europe-west1",
  "10.50.2.4": "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west2/subnetworks/my-project-vpc-subnet-europe-west2",
  "10.50.3.4": "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west3/subnetworks/my-project-vpc-subnet-europe-west3",
  "10.50.4.6": "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west6/subnetworks/my-project-vpc-subnet-europe-west6"
}

Now we use this script with external data source in your module's main.tf:

resource "google_dns_policy" "example-policy" {
  name                      = "example-policy"
  enable_inbound_forwarding = true

  networks {
    network_url = google_compute_network.network-1.id
  }
  networks {
    network_url = google_compute_network.network-2.id
  }
}

resource "google_compute_network" "network-1" {
  name                    = "network-1"
  auto_create_subnetworks = false
}

resource "google_compute_network" "network-2" {
  name                    = "network-2"
  auto_create_subnetworks = false
}

data "external" "dns_forwarder_ips" {
    program = [ "bash", "${path.module}/scripts/get_forwarder_ips.sh" ]
    depends_on = [
      google_dns_policy.example-policy
    ]
}

output "dns_forwarder_ips" {
    value = data.external.dns_forwarder_ips.result
}

Outputting data.external.dns_forwarder_ips.result will provide:

dns_forwarder_ips = tomap({
  "10.50.1.3" = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-project-vpc-subnet-europe-west1"
  "10.50.2.4" = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west2/subnetworks/my-project-vpc-subnet-europe-west2"
  "10.50.3.4" = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west3/subnetworks/my-project-vpc-subnet-europe-west3"
  "10.50.4.6" = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west6/subnetworks/my-project-vpc-subnet-europe-west6"
})
AarshDhokai commented 1 year ago

b/262524736

AarshDhokai commented 1 year ago
rileykarson commented 1 year ago

Implementing this as the google_compute_addresses plural datasource makes the most sense from our perspective- calling GCE APIs from the DNS resource itself would take additional permissions.