diff --git a/go.mod b/go.mod index ef02a9b24c..895e73e184 100644 --- a/go.mod +++ b/go.mod @@ -187,3 +187,5 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/ovh/go-ovh => github.com/ldez/go-ovh v1.4.2-0.20240621144634-e57d43b43c1c diff --git a/go.sum b/go.sum index 4dfcc8148c..eaa6738379 100644 --- a/go.sum +++ b/go.sum @@ -409,6 +409,8 @@ github.com/labbsr0x/goh v1.0.1 h1:97aBJkDjpyBZGPbQuOK5/gHcSFbcr5aRsq3RSRJFpPk= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A= github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/ldez/go-ovh v1.4.2-0.20240621144634-e57d43b43c1c h1:R+W37CyFOLz4xF2M3TRz/xflvvrJGMihgKNbajqrPYw= +github.com/ldez/go-ovh v1.4.2-0.20240621144634-e57d43b43c1c/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= @@ -526,8 +528,6 @@ github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:Ff github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/oracle/oci-go-sdk/v65 v65.63.1 h1:dYL7sk9L1+C9LCmoq+zjPMNteuJJfk54YExq/4pV9xQ= github.com/oracle/oci-go-sdk/v65 v65.63.1/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0= -github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI= -github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= diff --git a/providers/dns/ovh/ovh.go b/providers/dns/ovh/ovh.go index edc3e6e305..c7bfccebcd 100644 --- a/providers/dns/ovh/ovh.go +++ b/providers/dns/ovh/ovh.go @@ -102,9 +102,23 @@ type DNSProvider struct { // Credentials must be passed in the environment variables: // OVH_ENDPOINT (must be either "ovh-eu" or "ovh-ca"), OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY. func NewDNSProvider() (*DNSProvider, error) { - config, err := createConfigFromEnvVars() - if err != nil { - return nil, fmt.Errorf("ovh: %w", err) + config := NewDefaultConfig() + + // https://github.com/ovh/go-ovh/blob/6817886d12a8c5650794b28da635af9fcdfd1162/ovh/configuration.go#L105 + config.APIEndpoint = env.GetOrDefaultString(EnvEndpoint, "ovh-eu") + + config.ApplicationKey = env.GetOrFile(EnvApplicationKey) + config.ApplicationSecret = env.GetOrFile(EnvApplicationSecret) + config.ConsumerKey = env.GetOrFile(EnvConsumerKey) + + clientID := env.GetOrFile(EnvClientID) + clientSecret := env.GetOrFile(EnvClientSecret) + + if clientID != "" || clientSecret != "" { + config.OAuth2Config = &OAuth2Config{ + ClientID: clientID, + ClientSecret: clientSecret, + } } return NewDNSProviderConfig(config) @@ -222,94 +236,29 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func createConfigFromEnvVars() (*Config, error) { - firstAppKeyEnvVar := findFirstValuedEnvVar(EnvApplicationKey, EnvApplicationSecret, EnvConsumerKey) - firstOAuth2EnvVar := findFirstValuedEnvVar(EnvClientID, EnvClientSecret) - - if firstAppKeyEnvVar != "" && firstOAuth2EnvVar != "" { - return nil, fmt.Errorf("can't use both %s and %s at the same time", firstAppKeyEnvVar, firstOAuth2EnvVar) - } - - config := NewDefaultConfig() - - if firstOAuth2EnvVar != "" { - values, err := env.Get(EnvEndpoint, EnvClientID, EnvClientSecret) - if err != nil { - return nil, err - } - - config.APIEndpoint = values[EnvEndpoint] - config.OAuth2Config = &OAuth2Config{ - ClientID: values[EnvClientID], - ClientSecret: values[EnvClientSecret], - } - - return config, nil - } - - values, err := env.Get(EnvEndpoint, EnvApplicationKey, EnvApplicationSecret, EnvConsumerKey) - if err != nil { - return nil, err - } - - config.APIEndpoint = values[EnvEndpoint] - - config.ApplicationKey = values[EnvApplicationKey] - config.ApplicationSecret = values[EnvApplicationSecret] - config.ConsumerKey = values[EnvConsumerKey] - - return config, nil -} - -func findFirstValuedEnvVar(envVars ...string) string { - for _, envVar := range envVars { - if env.GetOrFile(envVar) != "" { - return envVar - } - } - - return "" -} - +// Inspired by: +// - NewClient: https://github.com/ovh/go-ovh/blob/6817886d12a8c5650794b28da635af9fcdfd1162/ovh/ovh.go#L103 +// - NewOAuth2Client: https://github.com/ovh/go-ovh/blob/6817886d12a8c5650794b28da635af9fcdfd1162/ovh/ovh.go#L132 func newClient(config *Config) (*ovh.Client, error) { - if config.OAuth2Config == nil { - return newClientApplicationKey(config) + client := ovh.Client{ + AppKey: config.ApplicationKey, + AppSecret: config.ApplicationSecret, + ConsumerKey: config.ConsumerKey, + Client: &http.Client{}, + Timeout: ovh.DefaultTimeout, + UserAgent: "go-acme/lego", } - return newClientOAuth2(config) -} - -func newClientApplicationKey(config *Config) (*ovh.Client, error) { - if config.APIEndpoint == "" || config.ApplicationKey == "" || config.ApplicationSecret == "" || config.ConsumerKey == "" { - return nil, errors.New("credentials are missing") + if config.OAuth2Config != nil { + client.ClientID = config.OAuth2Config.ClientID + client.ClientSecret = config.OAuth2Config.ClientSecret } - client, err := ovh.NewClient( - config.APIEndpoint, - config.ApplicationKey, - config.ApplicationSecret, - config.ConsumerKey, - ) + // Get and check the configuration + err := client.LoadConfig(config.APIEndpoint) if err != nil { return nil, fmt.Errorf("new client: %w", err) } - return client, nil -} - -func newClientOAuth2(config *Config) (*ovh.Client, error) { - if config.APIEndpoint == "" || config.OAuth2Config.ClientID == "" || config.OAuth2Config.ClientSecret == "" { - return nil, errors.New("credentials are missing") - } - - client, err := ovh.NewOAuth2Client( - config.APIEndpoint, - config.OAuth2Config.ClientID, - config.OAuth2Config.ClientSecret, - ) - if err != nil { - return nil, fmt.Errorf("new OAuth2 client: %w", err) - } - - return client, nil + return &client, nil } diff --git a/providers/dns/ovh/ovh_test.go b/providers/dns/ovh/ovh_test.go index cac88e90b8..bebce1e40e 100644 --- a/providers/dns/ovh/ovh_test.go +++ b/providers/dns/ovh/ovh_test.go @@ -34,16 +34,6 @@ func TestNewDNSProvider(t *testing.T) { EnvConsumerKey: "D", }, }, - { - desc: "application key: missing endpoint", - envVars: map[string]string{ - EnvEndpoint: "", - EnvApplicationKey: "B", - EnvApplicationSecret: "C", - EnvConsumerKey: "D", - }, - expected: "ovh: some credentials information are missing: OVH_ENDPOINT", - }, { desc: "application key: missing invalid endpoint", envVars: map[string]string{ @@ -62,7 +52,7 @@ func TestNewDNSProvider(t *testing.T) { EnvApplicationSecret: "C", EnvConsumerKey: "D", }, - expected: "ovh: some credentials information are missing: OVH_APPLICATION_KEY", + expected: "ovh: new client: invalid authentication config, both application_key and application_secret must be given", }, { desc: "application key: missing application secret", @@ -72,17 +62,7 @@ func TestNewDNSProvider(t *testing.T) { EnvApplicationSecret: "", EnvConsumerKey: "D", }, - expected: "ovh: some credentials information are missing: OVH_APPLICATION_SECRET", - }, - { - desc: "application key: missing consumer key", - envVars: map[string]string{ - EnvEndpoint: "ovh-eu", - EnvApplicationKey: "B", - EnvApplicationSecret: "C", - EnvConsumerKey: "", - }, - expected: "ovh: some credentials information are missing: OVH_CONSUMER_KEY", + expected: "ovh: new client: invalid authentication config, both application_key and application_secret must be given", }, { desc: "oauth2: success", @@ -99,7 +79,7 @@ func TestNewDNSProvider(t *testing.T) { EnvClientID: "E", EnvClientSecret: "", }, - expected: "ovh: some credentials information are missing: OVH_CLIENT_SECRET", + expected: "ovh: new client: invalid oauth2 config, both client_id and client_secret must be given", }, { desc: "oauth2: missing client ID", @@ -108,7 +88,7 @@ func TestNewDNSProvider(t *testing.T) { EnvClientID: "", EnvClientSecret: "F", }, - expected: "ovh: some credentials information are missing: OVH_CLIENT_ID", + expected: "ovh: new client: invalid oauth2 config, both client_id and client_secret must be given", }, { desc: "missing credentials", @@ -120,7 +100,7 @@ func TestNewDNSProvider(t *testing.T) { EnvClientID: "", EnvClientSecret: "", }, - expected: "ovh: some credentials information are missing: OVH_ENDPOINT,OVH_APPLICATION_KEY,OVH_APPLICATION_SECRET,OVH_CONSUMER_KEY", + expected: "ovh: new client: missing authentication information, you need to provide one of the following: application_key/application_secret, client_id/client_secret, or access_token", }, { desc: "mixed auth", @@ -132,7 +112,7 @@ func TestNewDNSProvider(t *testing.T) { EnvClientID: "E", EnvClientSecret: "F", }, - expected: "ovh: can't use both OVH_APPLICATION_KEY and OVH_CLIENT_ID at the same time", + expected: "ovh: can't use both authentication systems (ApplicationKey and OAuth2)", }, } @@ -182,7 +162,7 @@ func TestNewDNSProviderConfig(t *testing.T) { applicationKey: "B", applicationSecret: "C", consumerKey: "D", - expected: "ovh: credentials are missing", + expected: "ovh: new client: unknown endpoint '', consider checking 'Endpoints' list or using an URL", }, { desc: "application key: invalid api endpoint", @@ -198,7 +178,7 @@ func TestNewDNSProviderConfig(t *testing.T) { applicationKey: "", applicationSecret: "C", consumerKey: "D", - expected: "ovh: credentials are missing", + expected: "ovh: new client: invalid authentication config, both application_key and application_secret must be given", }, { desc: "application key: missing application secret", @@ -206,15 +186,7 @@ func TestNewDNSProviderConfig(t *testing.T) { applicationKey: "B", applicationSecret: "", consumerKey: "D", - expected: "ovh: credentials are missing", - }, - { - desc: "application key: missing consumer key", - apiEndpoint: "ovh-eu", - applicationKey: "B", - applicationSecret: "C", - consumerKey: "", - expected: "ovh: credentials are missing", + expected: "ovh: new client: invalid authentication config, both application_key and application_secret must be given", }, { desc: "oauth2: success", @@ -227,32 +199,32 @@ func TestNewDNSProviderConfig(t *testing.T) { apiEndpoint: "", clientID: "B", clientSecret: "C", - expected: "ovh: credentials are missing", + expected: "ovh: new client: unknown endpoint '', consider checking 'Endpoints' list or using an URL", }, { desc: "oauth2: invalid api endpoint", apiEndpoint: "foobar", clientID: "B", clientSecret: "C", - expected: "ovh: new OAuth2 client: unknown endpoint 'foobar', consider checking 'Endpoints' list or using an URL", + expected: "ovh: new client: unknown endpoint 'foobar', consider checking 'Endpoints' list or using an URL", }, { desc: "oauth2: missing client id", apiEndpoint: "ovh-eu", clientID: "", clientSecret: "C", - expected: "ovh: credentials are missing", + expected: "ovh: new client: invalid oauth2 config, both client_id and client_secret must be given", }, { desc: "oauth2: missing client secret", apiEndpoint: "ovh-eu", clientID: "B", clientSecret: "", - expected: "ovh: credentials are missing", + expected: "ovh: new client: invalid oauth2 config, both client_id and client_secret must be given", }, { desc: "missing credentials", - expected: "ovh: credentials are missing", + expected: "ovh: new client: missing authentication information, you need to provide one of the following: application_key/application_secret, client_id/client_secret, or access_token", }, { desc: "mixed auth",