diff --git a/docs/_providers/cloudflare.md b/docs/_providers/cloudflare.md index 5f3d6f278..c691c987d 100644 --- a/docs/_providers/cloudflare.md +++ b/docs/_providers/cloudflare.md @@ -11,7 +11,21 @@ jsId: CLOUDFLAREAPI * When using `SPF()` or the `SPF_BUILDER()` the records are converted to RecordType `TXT` as Cloudflare API fails otherwise. See more [here](https://github.com/StackExchange/dnscontrol/issues/446). ## Configuration -In the credentials file you must provide your Cloudflare API username and access token: +In the credentials file you must provide a [Cloudflare API token](https://dash.cloudflare.com/profile/api-tokens): + +{% highlight json %} +{ + "cloudflare": { + "apitoken": "your-cloudflare-api-token" + } +} +{% endhighlight %} + +Make sure the token has at least the right read zones and edit DNS records (i.e. `Zone → Zone → Read` and `Zone → DNS → Edit`); +checkout [Cloudflare's documentation](https://support.cloudflare.com/hc/en-us/articles/200167836-Managing-API-Tokens-and-Keys) for instructions on how to generate and configure permissions on API tokens. + + +Or you can provide your Cloudflare API username and access key instead, but it isn't recommended because those credentials give DNSControl access to the complete Cloudflare API rather: {% highlight json %} { @@ -27,8 +41,7 @@ If your Cloudflare account has access to multiple Cloudflare accounts, you can s {% highlight json %} { "cloudflare": { - "apikey": "...", - "apiuser": "...", + "apitoken": "...", "accountid": "your-cloudflare-account-id", "accountname": "your-cloudflare-account-name" } diff --git a/docs/getting-started.md b/docs/getting-started.md index 15cb1dca1..475215f32 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -66,8 +66,7 @@ If you are using other providers, you will likely need to make a `creds.json` fi {% highlight js %} { "cloudflare":{ // provider name to be used in dnsconfig.js - "apikey": "key", // API key - "apiuser": "username" // username for cloudflare + "apitoken": "token" // API token }, "namecom":{ // provider name to be used in dnsconfig.js "apikey": "key", // API Key @@ -259,4 +258,4 @@ If you are going to use this in production, we highly recommend the following: * Store the configuration files in Git. * Encrypt the `creds.json` file before storing it in Git. * Use a CI/CD tool like Jenkins to automatically push DNS changes. -* Join the DNSControl community. File [issues and PRs](https://github.com/StackExchange/dnscontrol). \ No newline at end of file +* Join the DNSControl community. File [issues and PRs](https://github.com/StackExchange/dnscontrol). diff --git a/providers/cloudflare/cloudflareProvider.go b/providers/cloudflare/cloudflareProvider.go index 85a789ab4..ba375997e 100644 --- a/providers/cloudflare/cloudflareProvider.go +++ b/providers/cloudflare/cloudflareProvider.go @@ -58,6 +58,7 @@ func init() { // CloudflareApi is the handle for API calls. type CloudflareApi struct { ApiKey string `json:"apikey"` + ApiToken string `json:apitoken` ApiUser string `json:"apiuser"` AccountID string `json:"accountid"` AccountName string `json:"accountname"` @@ -370,10 +371,13 @@ func (c *CloudflareApi) preprocessConfig(dc *models.DomainConfig) error { func newCloudflare(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) { api := &CloudflareApi{} - api.ApiUser, api.ApiKey = m["apiuser"], m["apikey"] + api.ApiUser, api.ApiKey, api.ApiToken = m["apiuser"], m["apikey"], m["apitoken"] // check api keys from creds json file - if api.ApiKey == "" || api.ApiUser == "" { - return nil, errors.Errorf("cloudflare apikey and apiuser must be provided") + if api.ApiToken == "" && (api.ApiKey == "" || api.ApiUser == "") { + return nil, errors.Errorf("if cloudflare apitoken is not set, apikey and apiuser must be provided") + } + if api.ApiToken != "" && (api.ApiKey != "" || api.ApiUser != "") { + return nil, errors.Errorf("if cloudflare apitoken is set, apikey and apiuser should not be provided") } // Check account data if set diff --git a/providers/cloudflare/rest.go b/providers/cloudflare/rest.go index 7cef0035d..5850c8c48 100644 --- a/providers/cloudflare/rest.go +++ b/providers/cloudflare/rest.go @@ -355,8 +355,12 @@ func handleActionResponse(resp *http.Response, err error) (id string, e error) { } func (c *CloudflareApi) setHeaders(req *http.Request) { - req.Header.Set("X-Auth-Key", c.ApiKey) - req.Header.Set("X-Auth-Email", c.ApiUser) + if len(c.ApiToken) > 0 { + req.Header.Set("Authorization", "Bearer "+c.ApiToken) + } else { + req.Header.Set("X-Auth-Key", c.ApiKey) + req.Header.Set("X-Auth-Email", c.ApiUser) + } } // generic get handler. makes request and unmarshalls response to given interface