mythicbeasts: fix token expiration (#1539)

This commit is contained in:
Ludovic Fernandez 2021-12-03 16:19:00 +01:00 committed by GitHub
parent 719341250f
commit 2b20b13fad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 13 deletions

View file

@ -9,6 +9,7 @@ import (
"net/http" "net/http"
"path" "path"
"strings" "strings"
"time"
) )
const ( const (
@ -25,6 +26,8 @@ type authResponse struct {
// The token type (must be 'bearer') // The token type (must be 'bearer')
TokenType string `json:"token_type"` TokenType string `json:"token_type"`
Deadline time.Time `json:"-"`
} }
type authResponseError struct { type authResponseError struct {
@ -61,14 +64,15 @@ type deleteTXTResponse struct {
// Logs into mythic beasts and acquires a bearer token for use in future API calls. // Logs into mythic beasts and acquires a bearer token for use in future API calls.
// https://www.mythic-beasts.com/support/api/auth#sec-obtaining-a-token // https://www.mythic-beasts.com/support/api/auth#sec-obtaining-a-token
func (d *DNSProvider) login() error { func (d *DNSProvider) login() error {
if d.token != "" { d.muToken.Lock()
defer d.muToken.Unlock()
if d.token != nil && time.Now().Before(d.token.Deadline) {
// Already authenticated, stop now // Already authenticated, stop now
return nil return nil
} }
reqBody := strings.NewReader("grant_type=client_credentials") req, err := http.NewRequest(http.MethodPost, d.config.AuthAPIEndpoint.String(), strings.NewReader("grant_type=client_credentials"))
req, err := http.NewRequest(http.MethodPost, d.config.AuthAPIEndpoint.String(), reqBody)
if err != nil { if err != nil {
return err return err
} }
@ -88,7 +92,7 @@ func (d *DNSProvider) login() error {
return fmt.Errorf("login: %w", err) return fmt.Errorf("login: %w", err)
} }
if resp.StatusCode != 200 { if resp.StatusCode != http.StatusOK {
if resp.StatusCode < 400 || resp.StatusCode > 499 { if resp.StatusCode < 400 || resp.StatusCode > 499 {
return fmt.Errorf("login: unknown error in auth API: %d", resp.StatusCode) return fmt.Errorf("login: unknown error in auth API: %d", resp.StatusCode)
} }
@ -113,7 +117,8 @@ func (d *DNSProvider) login() error {
return fmt.Errorf("login: received unexpected token type: %s", authResp.TokenType) return fmt.Errorf("login: received unexpected token type: %s", authResp.TokenType)
} }
d.token = authResp.Token authResp.Deadline = time.Now().Add(time.Duration(authResp.Lifetime) * time.Second)
d.token = &authResp
// Success // Success
return nil return nil
@ -121,7 +126,7 @@ func (d *DNSProvider) login() error {
// https://www.mythic-beasts.com/support/api/dnsv2#ep-get-zoneszonerecords // https://www.mythic-beasts.com/support/api/dnsv2#ep-get-zoneszonerecords
func (d *DNSProvider) createTXTRecord(zone, leaf, value string) error { func (d *DNSProvider) createTXTRecord(zone, leaf, value string) error {
if d.token == "" { if d.token == nil {
return fmt.Errorf("createTXTRecord: not logged in") return fmt.Errorf("createTXTRecord: not logged in")
} }
@ -149,7 +154,7 @@ func (d *DNSProvider) createTXTRecord(zone, leaf, value string) error {
return fmt.Errorf("createTXTRecord: %w", err) return fmt.Errorf("createTXTRecord: %w", err)
} }
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.token)) req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.token.Token))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
resp, err := d.config.HTTPClient.Do(req) resp, err := d.config.HTTPClient.Do(req)
@ -184,13 +189,13 @@ func (d *DNSProvider) createTXTRecord(zone, leaf, value string) error {
// https://www.mythic-beasts.com/support/api/dnsv2#ep-delete-zoneszonerecords // https://www.mythic-beasts.com/support/api/dnsv2#ep-delete-zoneszonerecords
func (d *DNSProvider) removeTXTRecord(zone, leaf, value string) error { func (d *DNSProvider) removeTXTRecord(zone, leaf, value string) error {
if d.token == "" { if d.token == nil {
return fmt.Errorf("removeTXTRecord: not logged in") return fmt.Errorf("removeTXTRecord: not logged in")
} }
endpoint, err := d.config.APIEndpoint.Parse(path.Join(d.config.APIEndpoint.Path, "zones", zone, "records", leaf, "TXT")) endpoint, err := d.config.APIEndpoint.Parse(path.Join(d.config.APIEndpoint.Path, "zones", zone, "records", leaf, "TXT"))
if err != nil { if err != nil {
return fmt.Errorf("createTXTRecord: failed to parse URL: %w", err) return fmt.Errorf("removeTXTRecord: failed to parse URL: %w", err)
} }
query := endpoint.Query() query := endpoint.Query()
@ -202,7 +207,7 @@ func (d *DNSProvider) removeTXTRecord(zone, leaf, value string) error {
return fmt.Errorf("removeTXTRecord: %w", err) return fmt.Errorf("removeTXTRecord: %w", err)
} }
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.token)) req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.token.Token))
resp, err := d.config.HTTPClient.Do(req) resp, err := d.config.HTTPClient.Do(req)
if err != nil { if err != nil {
@ -227,7 +232,7 @@ func (d *DNSProvider) removeTXTRecord(zone, leaf, value string) error {
} }
if deleteResp.Removed != 1 { if deleteResp.Removed != 1 {
return errors.New("deleteTXTRecord: did not add TXT record for some reason") return errors.New("removeTXTRecord: did not add TXT record for some reason")
} }
// Success // Success

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"sync"
"time" "time"
"github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/challenge/dns01"
@ -66,7 +67,10 @@ func NewDefaultConfig() (*Config, error) {
// DNSProvider implements the challenge.Provider interface. // DNSProvider implements the challenge.Provider interface.
type DNSProvider struct { type DNSProvider struct {
config *Config config *Config
token string
// token string
token *authResponse
muToken sync.Mutex
} }
// NewDNSProvider returns a DNSProvider instance configured for mythicbeasts DNSv2 API. // NewDNSProvider returns a DNSProvider instance configured for mythicbeasts DNSv2 API.