mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 06:46:19 +08:00
GANDI: Adopt new Gandi v5 auth changes (#2726)
This commit is contained in:
parent
24b5c4b0e4
commit
663be6e268
|
@ -1,19 +1,31 @@
|
|||
`GANDI_V5` uses the v5 API and can act as a registrar provider
|
||||
or a DNS provider. It is only able to work with domains
|
||||
migrated to the new LiveDNS API, which should be all domains.
|
||||
API keys are assigned to particular users. Go to User Settings,
|
||||
"Manage the user account and security settings", the "Security"
|
||||
tab, then regenerate the "Production API key".
|
||||
|
||||
* API Documentation: https://api.gandi.net/docs
|
||||
* API Endpoint: https://api.gandi.net/
|
||||
* Sandbox API Documentation: https://api.sandbox.gandi.net/docs/
|
||||
* Sandbox API Endpoint: https://api.sandbox.gandi.net/
|
||||
|
||||
## Configuration
|
||||
|
||||
To use this provider, add an entry to `creds.json` with `TYPE` set to `GANDI_V5`
|
||||
along your Gandi.net API key. The [sharing_id](https://api.gandi.net/docs/reference/) is optional.
|
||||
along with other settings:
|
||||
|
||||
The `sharing_id` selects between different organizations which your account is
|
||||
* (mandatory, string) your Gandi.net access credentials (see below) - one of:
|
||||
* `token`: Personal Access Token (PAT)
|
||||
* `apikey` API Key (deprecated)
|
||||
* `apiurl`: (optional, string) the endpoint of the API. When empty or absent the production
|
||||
endpoint is used (default) ; you can use it to select the Sandbox API Endpoint instead.
|
||||
* `sharing_id`: (optional, string) let you scope to a specific organization. When empty or absent
|
||||
calls are not scoped to a specific organization.
|
||||
|
||||
When both `token` and `apikey` are defined, the priority is given to `token` which will
|
||||
be used for API communication (as if `apikey` was not set).
|
||||
See [the Authentication section](#authentication) for details on obtaining these credentials.
|
||||
|
||||
|
||||
The [sharing_id](https://api.gandi.net/docs/reference/#Sharing-ID) selects between different organizations which your account is
|
||||
a member of; to manage domains in multiple organizations, you can use multiple
|
||||
`creds.json` entries.
|
||||
|
||||
|
@ -33,13 +45,32 @@ Example:
|
|||
{
|
||||
"gandi": {
|
||||
"TYPE": "GANDI_V5",
|
||||
"apikey": "your-gandi-key",
|
||||
"token": "your-gandi-personal-access-token",
|
||||
"sharing_id": "your-sharing_id"
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
## Authentication
|
||||
|
||||
(Cf [official documentation of the API](https://api.gandi.net/docs/authentication/)
|
||||
The **Personal Access Token** (PAT) is configured in the [Account Settings of the
|
||||
Gandi Admin application](https://admin.gandi.net/organizations/account/pat), then
|
||||
click on "Create a token" button.
|
||||
Choose an organisation (if your account happens to have multiple ones).
|
||||
Then, choose a name (limited to 42 chars), an expiration date.
|
||||
You can choose to limit the scope to a select number of products (domain names).
|
||||
Finally, choose the permissions : the needed one is "Manage domain name technical configurations"
|
||||
(in French: "Gérer la configuration technique des domaines"), which automatically
|
||||
implies "See and renew domain names" (in French: "Voir et renouveler les domaines").
|
||||
You then have only one (1) chance to copy and save the token somewhere.
|
||||
|
||||
The **API Key** is the previous (deprecated) mechanism used to do api calls.
|
||||
To generate or delete your API key, go to User Settings,
|
||||
"Manage the user account and security settings", the "Authentication options"
|
||||
tab, then regenerate the "Production API key" under "Developer access"
|
||||
|
||||
## Metadata
|
||||
This provider does not recognize any special metadata fields unique to Gandi.
|
||||
|
||||
|
@ -80,7 +111,7 @@ If a domain does not exist in your Gandi account, DNSControl will *not* automati
|
|||
Error getting corrections: 401: The server could not verify that you authorized to access the document you requested. Either you supplied the wrong credentials (e.g., bad api key), or your access token has expired
|
||||
```
|
||||
|
||||
This is the error you'll see if your `apikey` in `creds.json` is wrong or invalid.
|
||||
This is the error you'll see if your `token` (or (deprecated) `apikey`) in `creds.json` is wrong or invalid.
|
||||
|
||||
#### Domain does not exist in profile
|
||||
|
||||
|
@ -97,3 +128,12 @@ If a `dnscontrol get-zones --format=nameonly CredId - all` returns nothing,
|
|||
this is usually because your `creds.json` information is pointing at an empty
|
||||
organization or no organization. The solution is to set `sharing_id` in
|
||||
`creds.json`.
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
### Debugging
|
||||
Set `GANDI_V5_DEBUG` environment variable to a [boolean-compatible](https://pkg.go.dev/strconv#ParseBool) value to dump all API calls made by this provider.
|
||||
|
||||
### Testing
|
||||
Set `apiurl` key to the endpoint url for the sandbox (https://api.sandbox.gandi.net/), along with corresponding `token` (or (deprecated) `apikey`) created in this sandbox environment (Cf https://api.sandbox.gandi.net/docs/sandbox/) to make all API calls against Gandi sandbox environment.
|
||||
|
|
|
@ -112,7 +112,8 @@
|
|||
"GANDI_V5": {
|
||||
"TYPE": "GANDI_V5",
|
||||
"apikey": "$GANDI_V5_APIKEY",
|
||||
"domain": "$GANDI_V5_DOMAIN"
|
||||
"domain": "$GANDI_V5_DOMAIN",
|
||||
"token": "$GANDI_V5_TOKEN"
|
||||
},
|
||||
"GCLOUD": {
|
||||
"TYPE": "GCLOUD",
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/v4/providers"
|
||||
"github.com/go-gandi/go-gandi"
|
||||
"github.com/go-gandi/go-gandi/config"
|
||||
"github.com/go-gandi/go-gandi/livedns"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
)
|
||||
|
||||
|
@ -72,8 +73,10 @@ var features = providers.DocumentationNotes{
|
|||
// gandiv5Provider is the gandiv5Provider handle used to store any client-related state.
|
||||
type gandiv5Provider struct {
|
||||
apikey string
|
||||
token string
|
||||
sharingid string
|
||||
debug bool
|
||||
apiurl string
|
||||
}
|
||||
|
||||
// newDsp generates a DNS Service Provider client handle.
|
||||
|
@ -90,10 +93,12 @@ func newReg(conf map[string]string) (providers.Registrar, error) {
|
|||
func newHelper(m map[string]string, _ json.RawMessage) (*gandiv5Provider, error) {
|
||||
api := &gandiv5Provider{}
|
||||
api.apikey = m["apikey"]
|
||||
if api.apikey == "" {
|
||||
return nil, fmt.Errorf("missing Gandi apikey")
|
||||
api.token = m["token"]
|
||||
if (api.apikey == "") && (api.token == "") {
|
||||
return nil, fmt.Errorf("missing Gandi personal access token (or apikey - deprecated)")
|
||||
}
|
||||
api.sharingid = m["sharing_id"]
|
||||
api.apiurl = m["apiurl"]
|
||||
debug, err := strconv.ParseBool(os.Getenv("GANDI_V5_DEBUG"))
|
||||
if err == nil {
|
||||
api.debug = debug
|
||||
|
@ -104,15 +109,24 @@ func newHelper(m map[string]string, _ json.RawMessage) (*gandiv5Provider, error)
|
|||
|
||||
// Section 3: Domain Service Provider (DSP) related functions
|
||||
|
||||
// newLiveDNSClient returns a client to the Gandi Domains API
|
||||
// It expects an API key, available from https://account.gandi.net/en/
|
||||
func newLiveDNSClient(client *gandiv5Provider) *livedns.LiveDNS {
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
PersonalAccessToken: client.token,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
APIURL: client.apiurl,
|
||||
})
|
||||
return g
|
||||
}
|
||||
|
||||
// // ListZones lists the zones on this account.
|
||||
// This no longer works. Until we can figure out why, we're removing this
|
||||
// feature for Gandi.
|
||||
// func (client *gandiv5Provider) ListZones() ([]string, error) {
|
||||
// g := gandi.NewLiveDNSClient(config.Config{
|
||||
// APIKey: client.apikey,
|
||||
// SharingID: client.sharingid,
|
||||
// Debug: client.debug,
|
||||
// })
|
||||
// g := newLiveDNSClient(client)
|
||||
|
||||
// listResp, err := g.ListDomains()
|
||||
// if err != nil {
|
||||
|
@ -133,11 +147,7 @@ func newHelper(m map[string]string, _ json.RawMessage) (*gandiv5Provider, error)
|
|||
// GetZoneRecords gathers the DNS records and converts them to
|
||||
// dnscontrol's format.
|
||||
func (client *gandiv5Provider) GetZoneRecords(domain string, meta map[string]string) (models.Records, error) {
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
})
|
||||
g := newLiveDNSClient(client)
|
||||
|
||||
// Get all the existing records:
|
||||
records, err := g.GetDomainRecords(domain)
|
||||
|
@ -200,11 +210,7 @@ func (client *gandiv5Provider) GetZoneRecordsCorrections(dc *models.DomainConfig
|
|||
|
||||
PrepDesiredRecords(dc)
|
||||
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
})
|
||||
g := newLiveDNSClient(client)
|
||||
|
||||
// Gandi is a "ByLabel" API with the odd exception that changes must be
|
||||
// done one label:rtype at a time.
|
||||
|
@ -301,11 +307,7 @@ func debugRecords(note string, recs []*models.RecordConfig) {
|
|||
|
||||
// GetNameservers returns a list of nameservers for domain.
|
||||
func (client *gandiv5Provider) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
})
|
||||
g := newLiveDNSClient(client)
|
||||
nameservers, err := g.GetDomainNS(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -316,9 +318,11 @@ func (client *gandiv5Provider) GetNameservers(domain string) ([]*models.Nameserv
|
|||
// GetRegistrarCorrections returns a list of corrections for this registrar.
|
||||
func (client *gandiv5Provider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
gd := gandi.NewDomainClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
APIKey: client.apikey,
|
||||
PersonalAccessToken: client.token,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
APIURL: client.apiurl,
|
||||
})
|
||||
|
||||
existingNs, err := gd.GetNameServers(dc.Name)
|
||||
|
|
Loading…
Reference in a new issue