From 0f04639891f9d7e08e66a0c5179625fe09e5ee06 Mon Sep 17 00:00:00 2001 From: Markus Enander Date: Tue, 5 Jul 2022 21:53:51 +0200 Subject: [PATCH] Enable ADC for Gcloud provider (#1583) Fallback to using Application Default Credentials if no private_key is available in the creds.json-file. This allows usage with various short lived credentials, for example GCE-instances, gcloud auth application-default login, OIDC Workload Identity etc Co-authored-by: Tom Limoncelli --- docs/_providers/gcloud.md | 24 +++++++++++++++++++--- providers/gcloud/gcloudProvider.go | 32 ++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/docs/_providers/gcloud.md b/docs/_providers/gcloud.md index b53b6d2bb..f6a918762 100644 --- a/docs/_providers/gcloud.md +++ b/docs/_providers/gcloud.md @@ -9,10 +9,12 @@ jsId: GCLOUD ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `GCLOUD` -along with Google Cloud authentication values. +To use this provider, add an entry to `creds.json` with `TYPE` set to `GCLOUD`. -The provider requires a "Service Account Key" for your project. Newlines in the private key need to be replaced with `\n`. Copy the full JSON object into your `creds.json` like so: +For authentication you can either include a Service Account Key in the file or use Application Default Credentials (ADC) + +### Using a Service Account Key +Copy the full JSON object into your `creds.json`. Newlines in the private key need to be replaced with `\n`. Example: @@ -41,6 +43,22 @@ Example: See [the Activation section](#activation) for some tips on obtaining these credentials. +### Using Application Default Credentials +If you prefer to authenticate using ADC you only need to specify `project_id` in your creds.json file. + +Example: + +```json +{ + "gcloud": { + "TYPE": "GCLOUD", + "project_id": "mydnsproject" + } +} +``` + +**Note:** To use ADC, make sure to not add any `private_key` value to your configuration as that will prevent dnscontrol from attempting to use ADC. + ## Metadata This provider does not recognize any special metadata fields unique to google cloud dns. diff --git a/providers/gcloud/gcloudProvider.go b/providers/gcloud/gcloudProvider.go index dfec2207d..22c533072 100644 --- a/providers/gcloud/gcloudProvider.go +++ b/providers/gcloud/gcloudProvider.go @@ -4,11 +4,13 @@ import ( "context" "encoding/json" "fmt" - "github.com/StackExchange/dnscontrol/v3/pkg/printer" "log" + "net/http" "strings" "time" + "github.com/StackExchange/dnscontrol/v3/pkg/printer" + "google.golang.org/api/googleapi" "google.golang.org/api/option" @@ -66,19 +68,27 @@ func New(cfg map[string]string, metadata json.RawMessage) (providers.DNSServiceP // the key as downloaded is json encoded with literal "\n" instead of newlines. // in some cases (round-tripping through env vars) this tends to get messed up. // fix it if we find that. + + ctx := context.Background() + var hc *http.Client if key, ok := cfg["private_key"]; ok { cfg["private_key"] = strings.Replace(key, "\\n", "\n", -1) + raw, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + config, err := gauth.JWTConfigFromJSON(raw, "https://www.googleapis.com/auth/ndev.clouddns.readwrite") + if err != nil { + return nil, err + } + hc = config.Client(ctx) + } else { + var err error + hc, err = gauth.DefaultClient(ctx, "https://www.googleapis.com/auth/ndev.clouddns.readwrite") + if err != nil { + return nil, fmt.Errorf("No creds.json private_key found and ADC failed with:\n%s", err) + } } - raw, err := json.Marshal(cfg) - if err != nil { - return nil, err - } - config, err := gauth.JWTConfigFromJSON(raw, "https://www.googleapis.com/auth/ndev.clouddns.readwrite") - if err != nil { - return nil, err - } - ctx := context.Background() - hc := config.Client(ctx) // FIXME(tlim): Is it a problem that ctx is included with hc and in // the call to NewService? Seems redundant. dcli, err := gdns.NewService(ctx, option.WithHTTPClient(hc))