diff --git a/pkg/issuer/acme/dns/akamai/akamai.go b/pkg/issuer/acme/dns/akamai/akamai.go index 31d7967b4..4496eca46 100644 --- a/pkg/issuer/acme/dns/akamai/akamai.go +++ b/pkg/issuer/acme/dns/akamai/akamai.go @@ -21,6 +21,7 @@ import ( // DNSProvider is an implementation of the acme.ChallengeProvider interface type DNSProvider struct { + dns01Nameservers []string // serviceConsumerDomain as issued by Akamai Luna Control Center. // The ServiceConsumerDomain is the base URL. serviceConsumerDomain string @@ -32,8 +33,9 @@ type DNSProvider struct { } // NewDNSProvider returns a DNSProvider instance configured for Akamai. -func NewDNSProvider(serviceConsumerDomain, clientToken, clientSecret, accessToken string) (*DNSProvider, error) { +func NewDNSProvider(serviceConsumerDomain, clientToken, clientSecret, accessToken string, dns01Nameservers []string) (*DNSProvider, error) { return &DNSProvider{ + dns01Nameservers, serviceConsumerDomain, NewEdgeGridAuth(clientToken, clientSecret, accessToken), http.DefaultTransport, @@ -58,7 +60,7 @@ func (a *DNSProvider) Timeout() (timeout, interval time.Duration) { // Present creates a TXT record to fulfil the dns-01 challenge func (a *DNSProvider) Present(domain, token, keyAuth string) error { - fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth) + fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth, a.dns01Nameservers) if err != nil { return err } @@ -68,7 +70,7 @@ func (a *DNSProvider) Present(domain, token, keyAuth string) error { // CleanUp removes the TXT record matching the specified parameters func (a *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, _, _, err := util.DNS01Record(domain, keyAuth) + fqdn, _, _, err := util.DNS01Record(domain, keyAuth, a.dns01Nameservers) if err != nil { return err } diff --git a/pkg/issuer/acme/dns/akamai/akamai_test.go b/pkg/issuer/acme/dns/akamai/akamai_test.go index a787d1398..171807a2c 100644 --- a/pkg/issuer/acme/dns/akamai/akamai_test.go +++ b/pkg/issuer/acme/dns/akamai/akamai_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" "github.com/stretchr/testify/assert" ) @@ -88,7 +89,7 @@ func (r httpResponder) RoundTrip(req *http.Request) (*http.Response, error) { } func TestPresent(t *testing.T) { - akamai, err := NewDNSProvider("akamai.example.com", "token", "secret", "access-token") + akamai, err := NewDNSProvider("akamai.example.com", "token", "secret", "access-token", util.RecursiveNameservers) assert.NoError(t, err) var response []byte @@ -103,7 +104,7 @@ func TestPresent(t *testing.T) { } func TestCleanUp(t *testing.T) { - akamai, err := NewDNSProvider("akamai.example.com", "token", "secret", "access-token") + akamai, err := NewDNSProvider("akamai.example.com", "token", "secret", "access-token", util.RecursiveNameservers) assert.NoError(t, err) var response []byte diff --git a/pkg/issuer/acme/dns/azuredns/azuredns.go b/pkg/issuer/acme/dns/azuredns/azuredns.go index 5c23dd3a0..6c689aebf 100644 --- a/pkg/issuer/acme/dns/azuredns/azuredns.go +++ b/pkg/issuer/acme/dns/azuredns/azuredns.go @@ -19,6 +19,7 @@ import ( // DNSProvider implements the util.ChallengeProvider interface type DNSProvider struct { + dns01Nameservers []string recordClient dns.RecordSetsClient zoneClient dns.ZonesClient resourceGroupName string @@ -28,7 +29,7 @@ type DNSProvider struct { // NewDNSProvider returns a DNSProvider instance configured for the Azure // DNS service. // Credentials are automatically detected from environment variables -func NewDNSProvider() (*DNSProvider, error) { +func NewDNSProvider(dns01Nameservers []string) (*DNSProvider, error) { clientID := os.Getenv("AZURE_CLIENT_ID") clientSecret := os.Getenv("AZURE_CLIENT_SECRET") @@ -37,12 +38,12 @@ func NewDNSProvider() (*DNSProvider, error) { resourceGroupName := ("AZURE_RESOURCE_GROUP") zoneName := ("AZURE_ZONE_NAME") - return NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName) + return NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName, dns01Nameservers) } // NewDNSProviderCredentials returns a DNSProvider instance configured for the Azure // DNS service using static credentials from its parameters -func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName string) (*DNSProvider, error) { +func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName string, dns01Nameservers []string) (*DNSProvider, error) { oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID) if err != nil { return nil, err @@ -60,6 +61,7 @@ func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, zc.Authorizer = autorest.NewBearerAuthorizer(spt) return &DNSProvider{ + dns01Nameservers: dns01Nameservers, recordClient: rc, zoneClient: zc, resourceGroupName: resourceGroupName, @@ -69,7 +71,7 @@ func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, // Present creates a TXT record using the specified parameters func (c *DNSProvider) Present(domain, token, keyAuth string) error { - fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth) + fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth, c.dns01Nameservers) if err != nil { return err } @@ -79,7 +81,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error { // CleanUp removes the TXT record matching the specified parameters func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, _, _, err := util.DNS01Record(domain, keyAuth) + fqdn, _, _, err := util.DNS01Record(domain, keyAuth, c.dns01Nameservers) if err != nil { return err } diff --git a/pkg/issuer/acme/dns/azuredns/azuredns_test.go b/pkg/issuer/acme/dns/azuredns/azuredns_test.go index 29f46ec4e..a82ab8bb6 100644 --- a/pkg/issuer/acme/dns/azuredns/azuredns_test.go +++ b/pkg/issuer/acme/dns/azuredns/azuredns_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" "github.com/stretchr/testify/assert" ) @@ -36,7 +37,7 @@ func TestLiveAzureDnsPresent(t *testing.T) { if !azureLiveTest { t.Skip("skipping live test") } - provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName) + provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) assert.NoError(t, err) err = provider.Present(azureDomain, "", "123d==") @@ -50,7 +51,7 @@ func TestLiveAzureDnsCleanUp(t *testing.T) { time.Sleep(time.Second * 5) - provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName) + provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) assert.NoError(t, err) err = provider.CleanUp(azureDomain, "", "123d==") diff --git a/pkg/issuer/acme/dns/clouddns/clouddns.go b/pkg/issuer/acme/dns/clouddns/clouddns.go index 4a9f2c23c..9be71d6fe 100644 --- a/pkg/issuer/acme/dns/clouddns/clouddns.go +++ b/pkg/issuer/acme/dns/clouddns/clouddns.go @@ -18,25 +18,26 @@ import ( // DNSProvider is an implementation of the DNSProvider interface. type DNSProvider struct { - project string - client *dns.Service + dns01Nameservers []string + project string + client *dns.Service } // NewDNSProvider returns a DNSProvider instance configured for Google Cloud // DNS. Project name must be passed in the environment variable: GCE_PROJECT. // A Service Account file can be passed in the environment variable: // GCE_SERVICE_ACCOUNT_FILE -func NewDNSProvider() (*DNSProvider, error) { +func NewDNSProvider(dns01Nameservers []string) (*DNSProvider, error) { project := os.Getenv("GCE_PROJECT") if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok { - return NewDNSProviderServiceAccount(project, saFile) + return NewDNSProviderServiceAccount(project, saFile, dns01Nameservers) } - return NewDNSProviderCredentials(project) + return NewDNSProviderCredentials(project, dns01Nameservers) } // NewDNSProviderCredentials uses the supplied credentials to return a // DNSProvider instance configured for Google Cloud DNS. -func NewDNSProviderCredentials(project string) (*DNSProvider, error) { +func NewDNSProviderCredentials(project string, dns01Nameservers []string) (*DNSProvider, error) { if project == "" { return nil, fmt.Errorf("Google Cloud project name missing") } @@ -50,14 +51,15 @@ func NewDNSProviderCredentials(project string) (*DNSProvider, error) { return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err) } return &DNSProvider{ - project: project, - client: svc, + project: project, + client: svc, + dns01Nameservers: dns01Nameservers, }, nil } // NewDNSProviderServiceAccount uses the supplied service account JSON file to // return a DNSProvider instance configured for Google Cloud DNS. -func NewDNSProviderServiceAccount(project string, saFile string) (*DNSProvider, error) { +func NewDNSProviderServiceAccount(project string, saFile string, dns01Nameservers []string) (*DNSProvider, error) { if project == "" { return nil, fmt.Errorf("Google Cloud project name missing") } @@ -69,12 +71,12 @@ func NewDNSProviderServiceAccount(project string, saFile string) (*DNSProvider, if err != nil { return nil, fmt.Errorf("Unable to read Service Account file: %v", err) } - return NewDNSProviderServiceAccountBytes(project, dat) + return NewDNSProviderServiceAccountBytes(project, dat, dns01Nameservers) } // NewDNSProviderServiceAccountBytes uses the supplied service account JSON // file data to return a DNSProvider instance configured for Google Cloud DNS. -func NewDNSProviderServiceAccountBytes(project string, saBytes []byte) (*DNSProvider, error) { +func NewDNSProviderServiceAccountBytes(project string, saBytes []byte, dns01Nameservers []string) (*DNSProvider, error) { if project == "" { return nil, fmt.Errorf("Google Cloud project name missing") } @@ -93,14 +95,15 @@ func NewDNSProviderServiceAccountBytes(project string, saBytes []byte) (*DNSProv return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err) } return &DNSProvider{ - project: project, - client: svc, + project: project, + client: svc, + dns01Nameservers: dns01Nameservers, }, nil } // Present creates a TXT record to fulfil the dns-01 challenge. func (c *DNSProvider) Present(domain, token, key string) error { - fqdn, value, ttl, err := util.DNS01Record(domain, key) + fqdn, value, ttl, err := util.DNS01Record(domain, key, c.dns01Nameservers) if err != nil { return err } @@ -150,7 +153,7 @@ func (c *DNSProvider) Present(domain, token, key string) error { // CleanUp removes the TXT record matching the specified parameters. func (c *DNSProvider) CleanUp(domain, token, key string) error { - fqdn, _, _, err := util.DNS01Record(domain, key) + fqdn, _, _, err := util.DNS01Record(domain, key, c.dns01Nameservers) if err != nil { return err } diff --git a/pkg/issuer/acme/dns/clouddns/clouddns_test.go b/pkg/issuer/acme/dns/clouddns/clouddns_test.go index d5ca763c6..34ff00ee7 100644 --- a/pkg/issuer/acme/dns/clouddns/clouddns_test.go +++ b/pkg/issuer/acme/dns/clouddns/clouddns_test.go @@ -9,6 +9,7 @@ import ( "golang.org/x/oauth2/google" "google.golang.org/api/dns/v1" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" "github.com/stretchr/testify/assert" ) @@ -36,7 +37,7 @@ func TestNewDNSProviderValid(t *testing.T) { t.Skip("skipping live test (requires credentials)") } os.Setenv("GCE_PROJECT", "") - _, err := NewDNSProviderCredentials("my-project") + _, err := NewDNSProviderCredentials("my-project", util.RecursiveNameservers) assert.NoError(t, err) restoreGCloudEnv() } @@ -46,14 +47,14 @@ func TestNewDNSProviderValidEnv(t *testing.T) { t.Skip("skipping live test (requires credentials)") } os.Setenv("GCE_PROJECT", "my-project") - _, err := NewDNSProvider() + _, err := NewDNSProvider(util.RecursiveNameservers) assert.NoError(t, err) restoreGCloudEnv() } func TestNewDNSProviderMissingCredErr(t *testing.T) { os.Setenv("GCE_PROJECT", "") - _, err := NewDNSProvider() + _, err := NewDNSProvider(util.RecursiveNameservers) assert.EqualError(t, err, "Google Cloud project name missing") restoreGCloudEnv() } @@ -63,7 +64,7 @@ func TestLiveGoogleCloudPresent(t *testing.T) { t.Skip("skipping live test") } - provider, err := NewDNSProviderCredentials(gcloudProject) + provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers) assert.NoError(t, err) err = provider.Present(gcloudDomain, "", "123d==") @@ -75,7 +76,7 @@ func TestLiveGoogleCloudPresentMultiple(t *testing.T) { t.Skip("skipping live test") } - provider, err := NewDNSProviderCredentials(gcloudProject) + provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers) assert.NoError(t, err) // Check that we're able to create multiple entries @@ -91,7 +92,7 @@ func TestLiveGoogleCloudCleanUp(t *testing.T) { time.Sleep(time.Second * 1) - provider, err := NewDNSProviderCredentials(gcloudProject) + provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers) assert.NoError(t, err) err = provider.CleanUp(gcloudDomain, "", "123d==") diff --git a/pkg/issuer/acme/dns/cloudflare/cloudflare.go b/pkg/issuer/acme/dns/cloudflare/cloudflare.go index ec79f0029..741c8f602 100644 --- a/pkg/issuer/acme/dns/cloudflare/cloudflare.go +++ b/pkg/issuer/acme/dns/cloudflare/cloudflare.go @@ -22,29 +22,31 @@ const CloudFlareAPIURL = "https://api.cloudflare.com/client/v4" // DNSProvider is an implementation of the acme.ChallengeProvider interface type DNSProvider struct { - authEmail string - authKey string + dns01Nameservers []string + authEmail string + authKey string } // NewDNSProvider returns a DNSProvider instance configured for cloudflare. // Credentials must be passed in the environment variables: CLOUDFLARE_EMAIL // and CLOUDFLARE_API_KEY. -func NewDNSProvider() (*DNSProvider, error) { +func NewDNSProvider(dns01Nameservers []string) (*DNSProvider, error) { email := os.Getenv("CLOUDFLARE_EMAIL") key := os.Getenv("CLOUDFLARE_API_KEY") - return NewDNSProviderCredentials(email, key) + return NewDNSProviderCredentials(email, key, dns01Nameservers) } // NewDNSProviderCredentials uses the supplied credentials to return a // DNSProvider instance configured for cloudflare. -func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) { +func NewDNSProviderCredentials(email, key string, dns01Nameservers []string) (*DNSProvider, error) { if email == "" || key == "" { return nil, fmt.Errorf("CloudFlare credentials missing") } return &DNSProvider{ - authEmail: email, - authKey: key, + authEmail: email, + authKey: key, + dns01Nameservers: dns01Nameservers, }, nil } @@ -56,7 +58,7 @@ func (c *DNSProvider) Timeout() (timeout, interval time.Duration) { // Present creates a TXT record to fulfil the dns-01 challenge func (c *DNSProvider) Present(domain, token, keyAuth string) error { - fqdn, value, _, err := util.DNS01Record(domain, keyAuth) + fqdn, value, _, err := util.DNS01Record(domain, keyAuth, c.dns01Nameservers) if err != nil { return err } @@ -105,7 +107,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error { // CleanUp removes the TXT record matching the specified parameters func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, _, _, err := util.DNS01Record(domain, keyAuth) + fqdn, _, _, err := util.DNS01Record(domain, keyAuth, c.dns01Nameservers) if err != nil { return err } diff --git a/pkg/issuer/acme/dns/cloudflare/cloudflare_test.go b/pkg/issuer/acme/dns/cloudflare/cloudflare_test.go index 19b5a40b9..e601c7d3a 100644 --- a/pkg/issuer/acme/dns/cloudflare/cloudflare_test.go +++ b/pkg/issuer/acme/dns/cloudflare/cloudflare_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" "github.com/stretchr/testify/assert" ) @@ -32,7 +33,7 @@ func restoreCloudFlareEnv() { func TestNewDNSProviderValid(t *testing.T) { os.Setenv("CLOUDFLARE_EMAIL", "") os.Setenv("CLOUDFLARE_API_KEY", "") - _, err := NewDNSProviderCredentials("123", "123") + _, err := NewDNSProviderCredentials("123", "123", util.RecursiveNameservers) assert.NoError(t, err) restoreCloudFlareEnv() } @@ -40,7 +41,7 @@ func TestNewDNSProviderValid(t *testing.T) { func TestNewDNSProviderValidEnv(t *testing.T) { os.Setenv("CLOUDFLARE_EMAIL", "test@example.com") os.Setenv("CLOUDFLARE_API_KEY", "123") - _, err := NewDNSProvider() + _, err := NewDNSProvider(util.RecursiveNameservers) assert.NoError(t, err) restoreCloudFlareEnv() } @@ -48,7 +49,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) { func TestNewDNSProviderMissingCredErr(t *testing.T) { os.Setenv("CLOUDFLARE_EMAIL", "") os.Setenv("CLOUDFLARE_API_KEY", "") - _, err := NewDNSProvider() + _, err := NewDNSProvider(util.RecursiveNameservers) assert.EqualError(t, err, "CloudFlare credentials missing") restoreCloudFlareEnv() } @@ -58,7 +59,7 @@ func TestCloudFlarePresent(t *testing.T) { t.Skip("skipping live test") } - provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey) + provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey, util.RecursiveNameservers) assert.NoError(t, err) err = provider.Present(cflareDomain, "", "123d==") @@ -72,7 +73,7 @@ func TestCloudFlareCleanUp(t *testing.T) { time.Sleep(time.Second * 2) - provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey) + provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey, util.RecursiveNameservers) assert.NoError(t, err) err = provider.CleanUp(cflareDomain, "", "123d==") diff --git a/pkg/issuer/acme/dns/dns.go b/pkg/issuer/acme/dns/dns.go index a8eb42d8e..901a7e6d3 100644 --- a/pkg/issuer/acme/dns/dns.go +++ b/pkg/issuer/acme/dns/dns.go @@ -34,10 +34,10 @@ type solver interface { // It is useful for mocking out a given provider since an alternate set of // constructors may be set. type dnsProviderConstructors struct { - cloudDNS func(project string, serviceAccount []byte) (*clouddns.DNSProvider, error) - cloudFlare func(email, apikey string) (*cloudflare.DNSProvider, error) - route53 func(accessKey, secretKey, hostedZoneID, region string, ambient bool) (*route53.DNSProvider, error) - azureDNS func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string) (*azuredns.DNSProvider, error) + cloudDNS func(project string, serviceAccount []byte, dns01Nameservers []string) (*clouddns.DNSProvider, error) + cloudFlare func(email, apikey string, dns01Nameservers []string) (*cloudflare.DNSProvider, error) + route53 func(accessKey, secretKey, hostedZoneID, region string, ambient bool, dns01Nameservers []string) (*route53.DNSProvider, error) + azureDNS func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error) } // Solver is a solver for the acme dns01 challenge. @@ -69,7 +69,7 @@ func (s *Solver) Present(ctx context.Context, issuer v1alpha1.GenericIssuer, _ * } func (s *Solver) Check(ch v1alpha1.ACMEOrderChallenge) (bool, error) { - fqdn, value, ttl, err := util.DNS01Record(ch.Domain, ch.Key) + fqdn, value, ttl, err := util.DNS01Record(ch.Domain, ch.Key, s.DNS01Nameservers) if err != nil { return false, err } @@ -147,7 +147,8 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider providerConfig.Akamai.ServiceConsumerDomain, string(clientToken), string(clientSecret), - string(accessToken)) + string(accessToken), + s.DNS01Nameservers) if err != nil { return nil, errors.Wrap(err, "error instantiating akamai challenge solver") } @@ -164,7 +165,7 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider return nil, fmt.Errorf("specfied key %q not found in secret %s/%s", saKey, saSecret.Namespace, saSecret.Name) } - impl, err = s.dnsProviderConstructors.cloudDNS(providerConfig.CloudDNS.Project, saBytes) + impl, err = s.dnsProviderConstructors.cloudDNS(providerConfig.CloudDNS.Project, saBytes, s.DNS01Nameservers) if err != nil { return nil, fmt.Errorf("error instantiating google clouddns challenge solver: %s", err) } @@ -177,7 +178,7 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider email := providerConfig.Cloudflare.Email apiKey := string(apiKeySecret.Data[providerConfig.Cloudflare.APIKey.Key]) - impl, err = s.dnsProviderConstructors.cloudFlare(email, apiKey) + impl, err = s.dnsProviderConstructors.cloudFlare(email, apiKey, s.DNS01Nameservers) if err != nil { return nil, fmt.Errorf("error instantiating cloudflare challenge solver: %s", err) } @@ -202,6 +203,7 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider providerConfig.Route53.HostedZoneID, providerConfig.Route53.Region, s.CanUseAmbientCredentials(issuer), + s.DNS01Nameservers, ) if err != nil { return nil, fmt.Errorf("error instantiating route53 challenge solver: %s", err) @@ -224,6 +226,7 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider providerConfig.AzureDNS.TenantID, providerConfig.AzureDNS.ResourceGroupName, providerConfig.AzureDNS.HostedZoneName, + s.DNS01Nameservers, ) default: return nil, fmt.Errorf("no dns provider config specified for provider %q", providerName) diff --git a/pkg/issuer/acme/dns/dns_test.go b/pkg/issuer/acme/dns/dns_test.go index 044f46930..eb7653560 100644 --- a/pkg/issuer/acme/dns/dns_test.go +++ b/pkg/issuer/acme/dns/dns_test.go @@ -12,6 +12,7 @@ import ( "github.com/jetstack/cert-manager/pkg/controller" "github.com/jetstack/cert-manager/pkg/controller/test" "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" ) func newIssuer(name, namespace string, configs []v1alpha1.ACMEIssuerDNS01Provider) *v1alpha1.Issuer { @@ -260,7 +261,7 @@ func TestRoute53TrimCreds(t *testing.T) { expectedR53Call := []fakeDNSProviderCall{ { name: "route53", - args: []interface{}{"test_with_spaces", "AKIENDINNEWLINE", "", "us-west-2", false}, + args: []interface{}{"test_with_spaces", "AKIENDINNEWLINE", "", "us-west-2", false, util.RecursiveNameservers}, }, } @@ -308,7 +309,7 @@ func TestRoute53AmbientCreds(t *testing.T) { result{ expectedCall: &fakeDNSProviderCall{ name: "route53", - args: []interface{}{"", "", "", "us-west-2", true}, + args: []interface{}{"", "", "", "us-west-2", true, util.RecursiveNameservers}, }, }, }, @@ -341,7 +342,7 @@ func TestRoute53AmbientCreds(t *testing.T) { result{ expectedCall: &fakeDNSProviderCall{ name: "route53", - args: []interface{}{"", "", "", "us-west-2", false}, + args: []interface{}{"", "", "", "us-west-2", false, util.RecursiveNameservers}, }, }, }, diff --git a/pkg/issuer/acme/dns/route53/route53.go b/pkg/issuer/acme/dns/route53/route53.go index 5a29687b5..fbad38406 100644 --- a/pkg/issuer/acme/dns/route53/route53.go +++ b/pkg/issuer/acme/dns/route53/route53.go @@ -28,8 +28,9 @@ const ( // DNSProvider implements the util.ChallengeProvider interface type DNSProvider struct { - client *route53.Route53 - hostedZoneID string + dns01Nameservers []string + client *route53.Route53 + hostedZoneID string } // customRetryer implements the client.Retryer interface by composing the @@ -57,7 +58,7 @@ func (d customRetryer) RetryRules(r *request.Request) time.Duration { // NewDNSProvider returns a DNSProvider instance configured for the AWS // Route 53 service using static credentials from its parameters or, if they're // unset and the 'ambient' option is set, credentials from the environment. -func NewDNSProvider(accessKeyID, secretAccessKey, hostedZoneID, region string, ambient bool) (*DNSProvider, error) { +func NewDNSProvider(accessKeyID, secretAccessKey, hostedZoneID, region string, ambient bool, dns01Nameservers []string) (*DNSProvider, error) { if accessKeyID == "" && secretAccessKey == "" { if !ambient { return nil, fmt.Errorf("unable to construct route53 provider: empty credentials; perhaps you meant to enable ambient credentials?") @@ -99,8 +100,9 @@ func NewDNSProvider(accessKeyID, secretAccessKey, hostedZoneID, region string, a client := route53.New(sess, config) return &DNSProvider{ - client: client, - hostedZoneID: hostedZoneID, + client: client, + hostedZoneID: hostedZoneID, + dns01Nameservers: dns01Nameservers, }, nil } @@ -112,7 +114,7 @@ func (*DNSProvider) Timeout() (timeout, interval time.Duration) { // Present creates a TXT record using the specified parameters func (r *DNSProvider) Present(domain, token, keyAuth string) error { - fqdn, value, _, err := util.DNS01Record(domain, keyAuth) + fqdn, value, _, err := util.DNS01Record(domain, keyAuth, r.dns01Nameservers) if err != nil { return err } @@ -123,7 +125,7 @@ func (r *DNSProvider) Present(domain, token, keyAuth string) error { // CleanUp removes the TXT record matching the specified parameters func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, value, _, err := util.DNS01Record(domain, keyAuth) + fqdn, value, _, err := util.DNS01Record(domain, keyAuth, r.dns01Nameservers) if err != nil { return err } diff --git a/pkg/issuer/acme/dns/route53/route53_test.go b/pkg/issuer/acme/dns/route53/route53_test.go index 9e1e116a9..6da0b2196 100644 --- a/pkg/issuer/acme/dns/route53/route53_test.go +++ b/pkg/issuer/acme/dns/route53/route53_test.go @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/route53" "github.com/stretchr/testify/assert" + + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" ) var ( @@ -40,7 +42,7 @@ func makeRoute53Provider(ts *httptest.Server) *DNSProvider { } client := route53.New(session.New(config)) - return &DNSProvider{client: client} + return &DNSProvider{client: client, dns01Nameservers: util.RecursiveNameservers} } func TestAmbientCredentialsFromEnv(t *testing.T) { @@ -49,7 +51,7 @@ func TestAmbientCredentialsFromEnv(t *testing.T) { os.Setenv("AWS_REGION", "us-east-1") defer restoreRoute53Env() - provider, err := NewDNSProvider("", "", "", "", true) + provider, err := NewDNSProvider("", "", "", "", true, util.RecursiveNameservers) assert.NoError(t, err, "Expected no error constructing DNSProvider") _, err = provider.client.Config.Credentials.Get() @@ -63,7 +65,7 @@ func TestNoCredentialsFromEnv(t *testing.T) { os.Setenv("AWS_REGION", "us-east-1") defer restoreRoute53Env() - _, err := NewDNSProvider("", "", "", "", false) + _, err := NewDNSProvider("", "", "", "", false, util.RecursiveNameservers) assert.Error(t, err, "Expected error constructing DNSProvider with no credentials and not ambient") } @@ -71,7 +73,7 @@ func TestAmbientRegionFromEnv(t *testing.T) { os.Setenv("AWS_REGION", "us-east-1") defer restoreRoute53Env() - provider, err := NewDNSProvider("", "", "", "", true) + provider, err := NewDNSProvider("", "", "", "", true, util.RecursiveNameservers) assert.NoError(t, err, "Expected no error constructing DNSProvider") assert.Equal(t, "us-east-1", *provider.client.Config.Region, "Expected Region to be set from environment") @@ -81,7 +83,7 @@ func TestNoRegionFromEnv(t *testing.T) { os.Setenv("AWS_REGION", "us-east-1") defer restoreRoute53Env() - provider, err := NewDNSProvider("marx", "swordfish", "", "", false) + provider, err := NewDNSProvider("marx", "swordfish", "", "", false, util.RecursiveNameservers) assert.NoError(t, err, "Expected no error constructing DNSProvider") assert.Equal(t, "", *provider.client.Config.Region, "Expected Region to not be set from environment") diff --git a/pkg/issuer/acme/dns/util/dns.go b/pkg/issuer/acme/dns/util/dns.go index 7fa730f7b..361eca00a 100644 --- a/pkg/issuer/acme/dns/util/dns.go +++ b/pkg/issuer/acme/dns/util/dns.go @@ -8,11 +8,11 @@ import ( // DNS01Record returns a DNS record which will fulfill the `dns-01` challenge // TODO: move this into a non-generic place by resolving import cycle in dns package -func DNS01Record(domain, value string) (string, string, int, error) { +func DNS01Record(domain, value string, nameservers []string) (string, string, int, error) { fqdn := fmt.Sprintf("_acme-challenge.%s.", domain) // Check if the domain has CNAME then return that - r, err := dnsQuery(fqdn, dns.TypeCNAME, RecursiveNameservers, true) + r, err := dnsQuery(fqdn, dns.TypeCNAME, nameservers, true) if err == nil && r.Rcode == dns.RcodeSuccess { fqdn = updateDomainWithCName(r, fqdn) } diff --git a/pkg/issuer/acme/dns/util/wait.go b/pkg/issuer/acme/dns/util/wait.go index e91ff1396..f9ec55d16 100644 --- a/pkg/issuer/acme/dns/util/wait.go +++ b/pkg/issuer/acme/dns/util/wait.go @@ -76,7 +76,7 @@ func checkDNSPropagation(fqdn, value string, nameservers []string) (bool, error) fqdn = updateDomainWithCName(r, fqdn) } - authoritativeNss, err := lookupNameservers(fqdn) + authoritativeNss, err := lookupNameservers(fqdn, nameservers) if err != nil { return false, err } @@ -147,15 +147,15 @@ func dnsQuery(fqdn string, rtype uint16, nameservers []string, recursive bool) ( } // lookupNameservers returns the authoritative nameservers for the given fqdn. -func lookupNameservers(fqdn string) ([]string, error) { +func lookupNameservers(fqdn string, nameservers []string) ([]string, error) { var authoritativeNss []string - zone, err := FindZoneByFqdn(fqdn, RecursiveNameservers) + zone, err := FindZoneByFqdn(fqdn, nameservers) if err != nil { return nil, fmt.Errorf("Could not determine the zone: %v", err) } - r, err := dnsQuery(zone, dns.TypeNS, RecursiveNameservers, true) + r, err := dnsQuery(zone, dns.TypeNS, nameservers, true) if err != nil { return nil, err } diff --git a/pkg/issuer/acme/dns/util/wait_test.go b/pkg/issuer/acme/dns/util/wait_test.go index 9fa25a46a..7187543e1 100644 --- a/pkg/issuer/acme/dns/util/wait_test.go +++ b/pkg/issuer/acme/dns/util/wait_test.go @@ -91,7 +91,7 @@ func TestPreCheckDNS(t *testing.T) { func TestLookupNameserversOK(t *testing.T) { for _, tt := range lookupNameserversTestsOK { - nss, err := lookupNameservers(tt.fqdn) + nss, err := lookupNameservers(tt.fqdn, RecursiveNameservers) if err != nil { t.Fatalf("#%s: got %q; want nil", tt.fqdn, err) } @@ -107,7 +107,7 @@ func TestLookupNameserversOK(t *testing.T) { func TestLookupNameserversErr(t *testing.T) { for _, tt := range lookupNameserversTestsErr { - _, err := lookupNameservers(tt.fqdn) + _, err := lookupNameservers(tt.fqdn, RecursiveNameservers) if err == nil { t.Fatalf("#%s: expected %q (error); got ", tt.fqdn, tt.error) } diff --git a/pkg/issuer/acme/dns/util_test.go b/pkg/issuer/acme/dns/util_test.go index 84239123c..584a3c42b 100644 --- a/pkg/issuer/acme/dns/util_test.go +++ b/pkg/issuer/acme/dns/util_test.go @@ -12,6 +12,7 @@ import ( "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/clouddns" "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare" "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/route53" + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" ) const ( @@ -118,23 +119,23 @@ func newFakeDNSProviders() *fakeDNSProviders { calls: []fakeDNSProviderCall{}, } f.constructors = dnsProviderConstructors{ - cloudDNS: func(project string, serviceAccount []byte) (*clouddns.DNSProvider, error) { - f.call("clouddns", project, serviceAccount) + cloudDNS: func(project string, serviceAccount []byte, dns01Nameservers []string) (*clouddns.DNSProvider, error) { + f.call("clouddns", project, serviceAccount, util.RecursiveNameservers) return nil, nil }, - cloudFlare: func(email, apikey string) (*cloudflare.DNSProvider, error) { - f.call("cloudflare", email, apikey) + cloudFlare: func(email, apikey string, dns01Nameservers []string) (*cloudflare.DNSProvider, error) { + f.call("cloudflare", email, apikey, util.RecursiveNameservers) if email == "" || apikey == "" { return nil, errors.New("invalid email or apikey") } return nil, nil }, - route53: func(accessKey, secretKey, hostedZoneID, region string, ambient bool) (*route53.DNSProvider, error) { - f.call("route53", accessKey, secretKey, hostedZoneID, region, ambient) + route53: func(accessKey, secretKey, hostedZoneID, region string, ambient bool, dns01Nameservers []string) (*route53.DNSProvider, error) { + f.call("route53", accessKey, secretKey, hostedZoneID, region, ambient, util.RecursiveNameservers) return nil, nil }, - azureDNS: func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string) (*azuredns.DNSProvider, error) { - f.call("azuredns", clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName) + azureDNS: func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error) { + f.call("azuredns", clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName, util.RecursiveNameservers) return nil, nil }, }