diff --git a/docs/generated/reference/output/reference/api-docs/index.html b/docs/generated/reference/output/reference/api-docs/index.html index efb0fad45..f19a28781 100755 --- a/docs/generated/reference/output/reference/api-docs/index.html +++ b/docs/generated/reference/output/reference/api-docs/index.html @@ -1133,6 +1133,10 @@ Appears In: +environment
string + + + hostedZoneName
string diff --git a/docs/tasks/issuers/setup-acme/dns01/azuredns.rst b/docs/tasks/issuers/setup-acme/dns01/azuredns.rst index c02c25e2e..22698bf87 100644 --- a/docs/tasks/issuers/setup-acme/dns01/azuredns.rst +++ b/docs/tasks/issuers/setup-acme/dns01/azuredns.rst @@ -64,3 +64,5 @@ You can configure the issuer like so: # ResourceGroup name where dns zone is provisioned resourceGroupName: AZURE_RESOURCE_GROUP hostedZoneName: AZURE_DNS_ZONE_NAME + # Azure Cloud Environment, default to AzurePublicCloud + environment: AZURE_ENVIRONMENT diff --git a/pkg/apis/certmanager/v1alpha1/types_issuer.go b/pkg/apis/certmanager/v1alpha1/types_issuer.go index 7ee8d6f97..b49338e91 100644 --- a/pkg/apis/certmanager/v1alpha1/types_issuer.go +++ b/pkg/apis/certmanager/v1alpha1/types_issuer.go @@ -479,6 +479,10 @@ type ACMEIssuerDNS01ProviderAzureDNS struct { // +optional HostedZoneName string `json:"hostedZoneName,omitempty"` + + // +kubebuilder:validation:Enum=,AzurePublicCloud,AzureChinaCloud,AzureGermanCloud,AzureUSGovernmentCloud + // +optional + Environment string `json:"environment,omitempty"` } // ACMEIssuerDNS01ProviderAcmeDNS is a structure containing the diff --git a/pkg/apis/certmanager/validation/issuer.go b/pkg/apis/certmanager/validation/issuer.go index d58131b74..1d3041547 100644 --- a/pkg/apis/certmanager/validation/issuer.go +++ b/pkg/apis/certmanager/validation/issuer.go @@ -268,6 +268,12 @@ func ValidateACMEIssuerDNS01Config(iss *v1alpha1.ACMEIssuerDNS01Config, fldPath if len(p.AzureDNS.ResourceGroupName) == 0 { el = append(el, field.Required(fldPath.Child("azuredns", "resourceGroupName"), "")) } + switch p.AzureDNS.Environment { + case "", "AzurePublicCloud", "AzureChinaCloud", "AzureGermanCloud", "AzureUSGovernmentCloud": + default: + el = append(el, field.Invalid(fldPath.Child("azuredns", "environment"), p.AzureDNS.Environment, + "must be either empty or one of AzurePublicCloud, AzureChinaCloud, AzureGermanCloud or AzureUSGovernmentCloud")) + } } } if p.CloudDNS != nil { diff --git a/pkg/apis/certmanager/validation/issuer_test.go b/pkg/apis/certmanager/validation/issuer_test.go index 28163798e..e3aacca3b 100644 --- a/pkg/apis/certmanager/validation/issuer_test.go +++ b/pkg/apis/certmanager/validation/issuer_test.go @@ -513,6 +513,26 @@ func TestValidateACMEIssuerDNS01Config(t *testing.T) { field.Required(providersPath.Index(0).Child("azuredns", "resourceGroupName"), ""), }, }, + "invalid azuredns environment": { + cfg: &v1alpha1.ACMEIssuerDNS01Config{ + Providers: []v1alpha1.ACMEIssuerDNS01Provider{ + { + Name: "a name", + AzureDNS: &v1alpha1.ACMEIssuerDNS01ProviderAzureDNS{Environment: "an env"}, + }, + }, + }, + errs: []*field.Error{ + field.Required(providersPath.Index(0).Child("azuredns", "clientSecretSecretRef", "name"), "secret name is required"), + field.Required(providersPath.Index(0).Child("azuredns", "clientSecretSecretRef", "key"), "secret key is required"), + field.Required(providersPath.Index(0).Child("azuredns", "clientID"), ""), + field.Required(providersPath.Index(0).Child("azuredns", "subscriptionID"), ""), + field.Required(providersPath.Index(0).Child("azuredns", "tenantID"), ""), + field.Required(providersPath.Index(0).Child("azuredns", "resourceGroupName"), ""), + field.Invalid(providersPath.Index(0).Child("azuredns", "environment"), "an env", + "must be either empty or one of AzurePublicCloud, AzureChinaCloud, AzureGermanCloud or AzureUSGovernmentCloud"), + }, + }, "missing akamai config": { cfg: &v1alpha1.ACMEIssuerDNS01Config{ Providers: []v1alpha1.ACMEIssuerDNS01Provider{ diff --git a/pkg/issuer/acme/dns/azuredns/azuredns.go b/pkg/issuer/acme/dns/azuredns/azuredns.go index 4f00a63f2..da781879a 100644 --- a/pkg/issuer/acme/dns/azuredns/azuredns.go +++ b/pkg/issuer/acme/dns/azuredns/azuredns.go @@ -46,27 +46,37 @@ func NewDNSProvider(dns01Nameservers []string) (*DNSProvider, error) { tenantID := os.Getenv("AZURE_TENANT_ID") resourceGroupName := ("AZURE_RESOURCE_GROUP") zoneName := ("AZURE_ZONE_NAME") + environment := ("AZURE_ENVIRONMENT") - return NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName, dns01Nameservers) + return NewDNSProviderCredentials(environment, 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, dns01Nameservers []string) (*DNSProvider, error) { - oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID) +func NewDNSProviderCredentials(environment, clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, zoneName string, dns01Nameservers []string) (*DNSProvider, error) { + env := azure.PublicCloud + if environment != "" { + var err error + env, err = azure.EnvironmentFromName(environment) + if err != nil { + return nil, err + } + } + + oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, tenantID) if err != nil { return nil, err } - spt, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, azure.PublicCloud.ResourceManagerEndpoint) + spt, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, env.ResourceManagerEndpoint) if err != nil { return nil, err } - rc := dns.NewRecordSetsClient(subscriptionID) + rc := dns.NewRecordSetsClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID) rc.Authorizer = autorest.NewBearerAuthorizer(spt) - zc := dns.NewZonesClient(subscriptionID) + zc := dns.NewZonesClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID) zc.Authorizer = autorest.NewBearerAuthorizer(spt) return &DNSProvider{ diff --git a/pkg/issuer/acme/dns/azuredns/azuredns_test.go b/pkg/issuer/acme/dns/azuredns/azuredns_test.go index 32275a882..122a637f2 100644 --- a/pkg/issuer/acme/dns/azuredns/azuredns_test.go +++ b/pkg/issuer/acme/dns/azuredns/azuredns_test.go @@ -45,7 +45,7 @@ func TestLiveAzureDnsPresent(t *testing.T) { if !azureLiveTest { t.Skip("skipping live test") } - provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) + provider, err := NewDNSProviderCredentials("", azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) assert.NoError(t, err) err = provider.Present(azureDomain, "_acme-challenge."+azureDomain+".", "123d==") @@ -59,9 +59,20 @@ func TestLiveAzureDnsCleanUp(t *testing.T) { time.Sleep(time.Second * 5) - provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) + provider, err := NewDNSProviderCredentials("", azureClientID, azureClientSecret, azuresubscriptionID, azureTenantID, azureResourceGroupName, azureHostedZoneName, util.RecursiveNameservers) assert.NoError(t, err) err = provider.CleanUp(azureDomain, "_acme-challenge."+azureDomain+".", "123d==") assert.NoError(t, err) } + +func TestInvalidAzureDns(t *testing.T) { + validEnv := []string{"", "AzurePublicCloud", "AzureChinaCloud", "AzureGermanCloud", "AzureUSGovernmentCloud"} + for _, env := range validEnv { + _, err := NewDNSProviderCredentials(env, "cid", "secret", "", "", "", "", util.RecursiveNameservers) + assert.NoError(t, err) + } + + _, err := NewDNSProviderCredentials("invalid env", "cid", "secret", "", "", "", "", util.RecursiveNameservers) + assert.Error(t, err) +} diff --git a/pkg/issuer/acme/dns/dns.go b/pkg/issuer/acme/dns/dns.go index ea8d8391e..724a0b08f 100644 --- a/pkg/issuer/acme/dns/dns.go +++ b/pkg/issuer/acme/dns/dns.go @@ -62,7 +62,7 @@ type dnsProviderConstructors struct { cloudDNS func(project string, serviceAccount []byte, dns01Nameservers []string, ambient bool) (*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, tenantID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error) + azureDNS func(environment, clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error) acmeDNS func(host string, accountJson []byte, dns01Nameservers []string) (*acmedns.DNSProvider, error) digitalOcean func(token string, dns01Nameservers []string) (*digitalocean.DNSProvider, error) } @@ -345,6 +345,7 @@ func (s *Solver) solverForChallenge(ctx context.Context, issuer v1alpha1.Generic } impl, err = s.dnsProviderConstructors.azureDNS( + providerConfig.AzureDNS.Environment, providerConfig.AzureDNS.ClientID, string(clientSecretBytes), providerConfig.AzureDNS.SubscriptionID, diff --git a/pkg/issuer/acme/dns/util_test.go b/pkg/issuer/acme/dns/util_test.go index fde1837ee..f841b1440 100644 --- a/pkg/issuer/acme/dns/util_test.go +++ b/pkg/issuer/acme/dns/util_test.go @@ -154,7 +154,7 @@ func newFakeDNSProviders() *fakeDNSProviders { f.call("route53", accessKey, secretKey, hostedZoneID, region, ambient, util.RecursiveNameservers) return nil, nil }, - azureDNS: func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error) { + azureDNS: func(environment, 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 },