Repository: certbot/certbot

Issue:
Support Google DNS Private Zones
## My operating system is (include version):
Ubuntu 18.04


## I installed Certbot with (certbot-auto, OS package manager, pip, etc):
Docker certbot/dns-google


## I ran this command and it produced this output:
```console
$ sudo docker run --rm -ti -v /etc/letsencrypt/:/etc/letsencrypt -v /var/lib/letsencrypt/:/var/lib/letsencrypt certbot/dns-google certonly  --test-cert --dns-google -n -d '*.privatesd.public.domain'
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-google, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for privatesd.public.domain
URL being requested: GET https://www.googleapis.com/discovery/v1/apis/dns/v1/rest
URL being requested: GET https://www.googleapis.com/dns/v1/projects/XXX/managedZones?alt=json&dnsName=privatesd.public.domain.
URL being requested: GET https://www.googleapis.com/dns/v1/projects/XXX/managedZones/XXX/rrsets?alt=json
URL being requested: POST https://www.googleapis.com/dns/v1/projects/XXX/managedZones/XXX/changes?alt=json
URL being requested: GET https://www.googleapis.com/dns/v1/projects/XXX/managedZones/XXX/changes/12?alt=json
Waiting 60 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges
URL being requested: GET https://www.googleapis.com/discovery/v1/apis/dns/v1/rest
URL being requested: GET https://www.googleapis.com/dns/v1/projects/XXX/managedZones?alt=json&dnsName=privatesd.public.domain.
URL being requested: GET https://www.googleapis.com/dns/v1/projects/XXX/managedZones/XXX/rrsets?alt=json
URL being requested: POST https://www.googleapis.com/dns/v1/projects/XXX/managedZones/XXX/changes?alt=json
Failed authorization procedure. privatesd.public.domain (dns-01): urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.privatesd.public.domain.

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: privatesd.public.domain.
   Type:   None
   Detail: DNS problem: NXDOMAIN looking up TXT for
   _acme-challenge.privatesd.public.domain
```

## Certbot's behavior differed from what I expected because:
Certbot Google DNS is using the wrong zone, the private instead of public zone. We have private zones (https://cloud.google.com/dns/docs/overview#concepts) to serve different DNS to some of the VPC networks. However, Certbot needs to use the public zone, otherwise the _acme-challenge entry it's added can't be seen by Letsencrypt servers.

While the first query (https://www.googleapis.com/dns/v1/projects/XXX/managedZones?alt=json&dnsName=privatesd.public.domain.) works, we need to look at the privateVisibilityConfig, as this is present in private zones. If it's a private zone, we need to continue our search for the correct managedZone (public.domain) until we find a public domain that matches.


Discussion:
I've not got a dev environment setup, but I imagine code something like this diff should solve this issue (totally untested)
```diff
diff --git a/certbot-dns-google/certbot_dns_google/dns_google.py b/certbot-dns-google/certbot_dns_google/dns_google.py
index 0b84dddb..c14af6f8 100644
--- a/certbot-dns-google/certbot_dns_google/dns_google.py
+++ b/certbot-dns-google/certbot_dns_google/dns_google.py
@@ -274,10 +274,11 @@ class _GoogleClient(object):
                 raise errors.PluginError('Encountered error finding managed zone: {0}'
                                          .format(e))
 
-            if len(zones) > 0:
-                zone_id = zones[0]['id']
-                logger.debug('Found id of %s for %s using name %s', zone_id, domain, zone_name)
-                return zone_id
+            for zone in zones:
+                zone_id = zone['id']
+                if 'privateVisibilityConfig' not in zone:
+                    logger.debug('Found id of %s for %s using name %s', zone_id, domain, zone_name)
+                    return zone_id
 
         raise errors.PluginError('Unable to determine managed zone for {0} using zone names: {1}.'
                                  .format(domain, zone_dns_name_guesses))
```
@timwsuqld, thanks for investigating and reporting this.

Would you be willing to make a pull request with your proposed fix above and suggest a way that we could confirm how well it works? 

Resolving patch:
diff --git a/certbot-dns-google/certbot_dns_google/dns_google.py b/certbot-dns-google/certbot_dns_google/dns_google.py
--- a/certbot-dns-google/certbot_dns_google/dns_google.py
+++ b/certbot-dns-google/certbot_dns_google/dns_google.py
@@ -274,10 +274,11 @@ def _find_managed_zone_id(self, domain):
                 raise errors.PluginError('Encountered error finding managed zone: {0}'
                                          .format(e))
 
-            if zones:
-                zone_id = zones[0]['id']
-                logger.debug('Found id of %s for %s using name %s', zone_id, domain, zone_name)
-                return zone_id
+            for zone in zones:
+                zone_id = zone['id']
+                if 'privateVisibilityConfig' not in zone:
+                    logger.debug('Found id of %s for %s using name %s', zone_id, domain, zone_name)
+                    return zone_id
 
         raise errors.PluginError('Unable to determine managed zone for {0} using zone names: {1}.'
                                  .format(domain, zone_dns_name_guesses))


Test patch: