From 4447b2a810d6d94d563a27fa61399d9dd8bf0d9a Mon Sep 17 00:00:00 2001 From: Charles Xu Date: Tue, 18 Apr 2023 15:11:08 -0700 Subject: [PATCH 1/2] cloudflare: support reading API token from file --- docs/tutorials/cloudflare.md | 2 ++ provider/cloudflare/cloudflare.go | 12 +++++++++++- provider/cloudflare/cloudflare_test.go | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/cloudflare.md b/docs/tutorials/cloudflare.md index 211dbf72c..79deffeff 100644 --- a/docs/tutorials/cloudflare.md +++ b/docs/tutorials/cloudflare.md @@ -20,6 +20,8 @@ Snippet from [Cloudflare - Getting Started](https://api.cloudflare.com/#getting- API Token will be preferred for authentication if `CF_API_TOKEN` environment variable is set. Otherwise `CF_API_KEY` and `CF_API_EMAIL` should be set to run ExternalDNS with Cloudflare. +You may provide the Cloudflare API token through a file by setting the +`CF_API_TOKEN="file:/path/to/token"`. When using API Token authentication, the token should be granted Zone `Read`, DNS `Edit` privileges, and access to `All zones`. diff --git a/provider/cloudflare/cloudflare.go b/provider/cloudflare/cloudflare.go index 0f7bdf0cc..3bfc12c0c 100644 --- a/provider/cloudflare/cloudflare.go +++ b/provider/cloudflare/cloudflare.go @@ -19,8 +19,10 @@ package cloudflare import ( "context" "fmt" + "io/ioutil" "os" "strconv" + "strings" cloudflare "github.com/cloudflare/cloudflare-go" log "github.com/sirupsen/logrus" @@ -155,7 +157,15 @@ func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter prov err error ) if os.Getenv("CF_API_TOKEN") != "" { - config, err = cloudflare.NewWithAPIToken(os.Getenv("CF_API_TOKEN")) + token := os.Getenv("CF_API_TOKEN") + if strings.HasPrefix(token, "file:") { + tokenBytes, err := ioutil.ReadFile(strings.TrimPrefix(token, "file:")) + if err != nil { + return nil, fmt.Errorf("failed to read CF_API_TOKEN from file: %v", err) + } + token = string(tokenBytes) + } + config, err = cloudflare.NewWithAPIToken(token) } else { config, err = cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL")) } diff --git a/provider/cloudflare/cloudflare_test.go b/provider/cloudflare/cloudflare_test.go index 3755c8c9b..6d1d47b40 100644 --- a/provider/cloudflare/cloudflare_test.go +++ b/provider/cloudflare/cloudflare_test.go @@ -677,6 +677,23 @@ func TestCloudflareProvider(t *testing.T) { if err != nil { t.Errorf("should not fail, %s", err) } + + _ = os.Unsetenv("CF_API_TOKEN") + tokenFile := "/tmp/cf_api_token" + if err := os.WriteFile(tokenFile, []byte("abc123def"), 0644); err != nil { + t.Errorf("failed to write token file, %s", err) + } + _ = os.Setenv("CF_API_TOKEN", tokenFile) + _, err = NewCloudFlareProvider( + endpoint.NewDomainFilter([]string{"bar.com"}), + provider.NewZoneIDFilter([]string{""}), + false, + true, + 5000) + if err != nil { + t.Errorf("should not fail, %s", err) + } + _ = os.Unsetenv("CF_API_TOKEN") _ = os.Setenv("CF_API_KEY", "xxxxxxxxxxxxxxxxx") _ = os.Setenv("CF_API_EMAIL", "test@test.com") @@ -689,6 +706,7 @@ func TestCloudflareProvider(t *testing.T) { if err != nil { t.Errorf("should not fail, %s", err) } + _ = os.Unsetenv("CF_API_KEY") _ = os.Unsetenv("CF_API_EMAIL") _, err = NewCloudFlareProvider( From f4c7466e40667f898589e927617f126eef575e67 Mon Sep 17 00:00:00 2001 From: Charles Xu Date: Mon, 24 Apr 2023 11:17:59 -0700 Subject: [PATCH 2/2] fix lint --- provider/cloudflare/cloudflare.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/provider/cloudflare/cloudflare.go b/provider/cloudflare/cloudflare.go index 3bfc12c0c..0623ca2a0 100644 --- a/provider/cloudflare/cloudflare.go +++ b/provider/cloudflare/cloudflare.go @@ -19,7 +19,6 @@ package cloudflare import ( "context" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -159,9 +158,9 @@ func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter prov if os.Getenv("CF_API_TOKEN") != "" { token := os.Getenv("CF_API_TOKEN") if strings.HasPrefix(token, "file:") { - tokenBytes, err := ioutil.ReadFile(strings.TrimPrefix(token, "file:")) + tokenBytes, err := os.ReadFile(strings.TrimPrefix(token, "file:")) if err != nil { - return nil, fmt.Errorf("failed to read CF_API_TOKEN from file: %v", err) + return nil, fmt.Errorf("failed to read CF_API_TOKEN from file: %w", err) } token = string(tokenBytes) }