option to specify gcloud service account json by env as string (#776)

Added the option to provide the gcloud service account as a string via the environment variable `GCE_SERVICE_ACCOUNT` in addition to the already available option to specify a filepath to a keyfile `GCE_SERVICE_ACCOUNT_FILE`.
This commit is contained in:
Christopher Banck 2019-02-01 13:14:57 +01:00 committed by Ludovic Fernandez
parent 68568b7ded
commit 0e6e4807b1
3 changed files with 36 additions and 18 deletions

View file

@ -51,7 +51,7 @@ Here is an example bash command using the CloudFlare DNS provider:
fmt.Fprintln(w, "\tfastdns:\tAKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, AKAMAI_ACCESS_TOKEN")
fmt.Fprintln(w, "\tgandi:\tGANDI_API_KEY")
fmt.Fprintln(w, "\tgandiv5:\tGANDIV5_API_KEY")
fmt.Fprintln(w, "\tgcloud:\tGCE_PROJECT, 'Application Default Credentials', [GCE_SERVICE_ACCOUNT_FILE]")
fmt.Fprintln(w, "\tgcloud:\tGCE_PROJECT, 'Application Default Credentials', [GCE_SERVICE_ACCOUNT_FILE], [GCE_SERVICE_ACCOUNT]")
fmt.Fprintln(w, "\tglesys:\tGLESYS_API_USER, GLESYS_API_KEY")
fmt.Fprintln(w, "\tgodaddy:\tGODADDY_API_KEY, GODADDY_API_SECRET")
fmt.Fprintln(w, "\thostingde:\tHOSTINGDE_API_KEY, HOSTINGDE_ZONE_NAME")

View file

@ -7,7 +7,6 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
@ -53,11 +52,12 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for Google Cloud DNS.
// Project name must be passed in the environment variable: GCE_PROJECT.
// A Service Account file can be passed in the environment variable: GCE_SERVICE_ACCOUNT_FILE
// A Service Account can be passed in the environment variable: GCE_SERVICE_ACCOUNT
// or by specifying the keyfile location: GCE_SERVICE_ACCOUNT_FILE
func NewDNSProvider() (*DNSProvider, error) {
// Use a service account file if specified via environment variable.
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
return NewDNSProviderServiceAccount(saFile)
if saKey := env.GetOrFile("GCE_SERVICE_ACCOUNT"); len(saKey) > 0 {
return NewDNSProviderServiceAccountKey([]byte(saKey))
}
// Use default credentials.
@ -84,16 +84,11 @@ func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
return NewDNSProviderConfig(config)
}
// NewDNSProviderServiceAccount uses the supplied service account JSON file
// NewDNSProviderServiceAccountKey uses the supplied service account JSON
// to return a DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
if saFile == "" {
return nil, fmt.Errorf("googlecloud: Service Account file missing")
}
dat, err := ioutil.ReadFile(saFile)
if err != nil {
return nil, fmt.Errorf("googlecloud: unable to read Service Account file: %v", err)
func NewDNSProviderServiceAccountKey(saKey []byte) (*DNSProvider, error) {
if len(saKey) == 0 {
return nil, fmt.Errorf("googlecloud: Service Account is missing")
}
// If GCE_PROJECT is non-empty it overrides the project in the service
@ -104,14 +99,14 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
var datJSON struct {
ProjectID string `json:"project_id"`
}
err = json.Unmarshal(dat, &datJSON)
err := json.Unmarshal(saKey, &datJSON)
if err != nil || datJSON.ProjectID == "" {
return nil, fmt.Errorf("googlecloud: project ID not found in Google Cloud Service Account file")
}
project = datJSON.ProjectID
}
conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
conf, err := google.JWTConfigFromJSON(saKey, dns.NdevClouddnsReadwriteScope)
if err != nil {
return nil, fmt.Errorf("googlecloud: unable to acquire config: %v", err)
}
@ -124,6 +119,21 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
return NewDNSProviderConfig(config)
}
// NewDNSProviderServiceAccount uses the supplied service account JSON file
// to return a DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
if saFile == "" {
return nil, fmt.Errorf("googlecloud: Service Account file missing")
}
saKey, err := ioutil.ReadFile(saFile)
if err != nil {
return nil, fmt.Errorf("googlecloud: unable to read Service Account file: %v", err)
}
return NewDNSProviderServiceAccountKey(saKey)
}
// NewDNSProviderConfig return a DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {

View file

@ -19,7 +19,8 @@ import (
var envTest = tester.NewEnvTest(
"GCE_PROJECT",
"GCE_SERVICE_ACCOUNT_FILE",
"GOOGLE_APPLICATION_CREDENTIALS").
"GOOGLE_APPLICATION_CREDENTIALS",
"GCE_SERVICE_ACCOUNT").
WithDomain("GCE_DOMAIN").
WithLiveTestExtra(func() bool {
_, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
@ -51,12 +52,19 @@ func TestNewDNSProvider(t *testing.T) {
expected: "googlecloud: project name missing",
},
{
desc: "success",
desc: "success key file",
envVars: map[string]string{
"GCE_PROJECT": "",
"GCE_SERVICE_ACCOUNT_FILE": "fixtures/gce_account_service_file.json",
},
},
{
desc: "success key",
envVars: map[string]string{
"GCE_PROJECT": "",
"GCE_SERVICE_ACCOUNT": `{"project_id": "A","type": "service_account","client_email": "foo@bar.com","private_key_id": "pki","private_key": "pk","token_uri": "/token","client_secret": "secret","client_id": "C","refresh_token": "D"}`,
},
},
}
for _, test := range testCases {