diff --git a/cmd/zz_gen_cmd_dnshelp.go b/cmd/zz_gen_cmd_dnshelp.go index 6ba64ffa..14440f7a 100644 --- a/cmd/zz_gen_cmd_dnshelp.go +++ b/cmd/zz_gen_cmd_dnshelp.go @@ -213,6 +213,7 @@ func displayDNSHelp(name string) error { ew.writeln(`Credentials:`) ew.writeln(` - "AZURE_CLIENT_ID": Client ID`) ew.writeln(` - "AZURE_CLIENT_SECRET": Client secret`) + ew.writeln(` - "AZURE_ENVIRONMENT": Azure environment, one of: public, usgovernment, german, and china`) ew.writeln(` - "AZURE_RESOURCE_GROUP": Resource group`) ew.writeln(` - "AZURE_SUBSCRIPTION_ID": Subscription ID`) ew.writeln(` - "AZURE_TENANT_ID": Tenant ID`) diff --git a/docs/content/dns/zz_gen_azure.md b/docs/content/dns/zz_gen_azure.md index 70abe1a9..4c4dcf7b 100644 --- a/docs/content/dns/zz_gen_azure.md +++ b/docs/content/dns/zz_gen_azure.md @@ -31,6 +31,7 @@ _Please contribute by adding a CLI example._ |-----------------------|-------------| | `AZURE_CLIENT_ID` | Client ID | | `AZURE_CLIENT_SECRET` | Client secret | +| `AZURE_ENVIRONMENT` | Azure environment, one of: public, usgovernment, german, and china | | `AZURE_RESOURCE_GROUP` | Resource group | | `AZURE_SUBSCRIPTION_ID` | Subscription ID | | `AZURE_TENANT_ID` | Tenant ID | diff --git a/providers/dns/azure/azure.go b/providers/dns/azure/azure.go index 0995dcf1..5ed5d063 100644 --- a/providers/dns/azure/azure.go +++ b/providers/dns/azure/azure.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns" "github.com/Azure/go-autorest/autorest" + aazure "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/azure/auth" "github.com/Azure/go-autorest/autorest/to" "github.com/go-acme/lego/v3/challenge/dns01" @@ -25,6 +26,7 @@ const defaultMetadataEndpoint = "http://169.254.169.254" const ( envNamespace = "AZURE_" + EnvEnvironment = envNamespace + "ENVIRONMENT" EnvMetadataEndpoint = envNamespace + "METADATA_ENDPOINT" EnvSubscriptionID = envNamespace + "SUBSCRIPTION_ID" EnvResourceGroup = envNamespace + "RESOURCE_GROUP" @@ -47,7 +49,9 @@ type Config struct { SubscriptionID string ResourceGroup string - MetadataEndpoint string + MetadataEndpoint string + ResourceManagerEndpoint string + ActiveDirectoryEndpoint string PropagationTimeout time.Duration PollingInterval time.Duration @@ -58,10 +62,12 @@ type Config struct { // NewDefaultConfig returns a default configuration for the DNSProvider. func NewDefaultConfig() *Config { return &Config{ - TTL: env.GetOrDefaultInt(EnvTTL, 60), - PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), - PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, 2*time.Second), - MetadataEndpoint: env.GetOrFile(EnvMetadataEndpoint), + TTL: env.GetOrDefaultInt(EnvTTL, 60), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, 2*time.Second), + MetadataEndpoint: env.GetOrFile(EnvMetadataEndpoint), + ResourceManagerEndpoint: aazure.PublicCloud.ResourceManagerEndpoint, + ActiveDirectoryEndpoint: aazure.PublicCloud.ActiveDirectoryEndpoint, } } @@ -73,12 +79,34 @@ type DNSProvider struct { // NewDNSProvider returns a DNSProvider instance configured for azure. // Credentials can be passed in the environment variables: -// AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP +// AZURE_ENVIRONMENT, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, +// AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP // If the credentials are _not_ set via the environment, // then it will attempt to get a bearer token via the instance metadata service. // see: https://github.com/Azure/go-autorest/blob/v10.14.0/autorest/azure/auth/auth.go#L38-L42 func NewDNSProvider() (*DNSProvider, error) { config := NewDefaultConfig() + + environmentName := env.GetOrFile(EnvEnvironment) + if environmentName != "" { + var environment aazure.Environment + switch environmentName { + case "china": + environment = aazure.ChinaCloud + case "german": + environment = aazure.GermanCloud + case "public": + environment = aazure.PublicCloud + case "usgovernment": + environment = aazure.USGovernmentCloud + default: + return nil, fmt.Errorf("azure: unknown environment %s", environmentName) + } + + config.ResourceManagerEndpoint = environment.ResourceManagerEndpoint + config.ActiveDirectoryEndpoint = environment.ActiveDirectoryEndpoint + } + config.SubscriptionID = env.GetOrFile(EnvSubscriptionID) config.ResourceGroup = env.GetOrFile(EnvResourceGroup) config.ClientSecret = env.GetOrFile(EnvClientSecret) @@ -146,7 +174,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("azure: %w", err) } - rsc := dns.NewRecordSetsClient(d.config.SubscriptionID) + rsc := dns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) @@ -202,7 +230,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { } relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) - rsc := dns.NewRecordSetsClient(d.config.SubscriptionID) + rsc := dns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer _, err = rsc.Delete(ctx, d.config.ResourceGroup, zone, relative, dns.TXT, "") @@ -219,7 +247,7 @@ func (d *DNSProvider) getHostedZoneID(ctx context.Context, fqdn string) (string, return "", err } - dc := dns.NewZonesClient(d.config.SubscriptionID) + dc := dns.NewZonesClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) dc.Authorizer = d.authorizer zone, err := dc.Get(ctx, d.config.ResourceGroup, dns01.UnFqdn(authZone)) @@ -238,7 +266,13 @@ func toRelativeRecord(domain, zone string) string { func getAuthorizer(config *Config) (autorest.Authorizer, error) { if config.ClientID != "" && config.ClientSecret != "" && config.TenantID != "" { - credentialsConfig := auth.NewClientCredentialsConfig(config.ClientID, config.ClientSecret, config.TenantID) + credentialsConfig := auth.ClientCredentialsConfig{ + ClientID: config.ClientID, + ClientSecret: config.ClientSecret, + TenantID: config.TenantID, + Resource: config.ResourceManagerEndpoint, + AADEndpoint: config.ActiveDirectoryEndpoint, + } spToken, err := credentialsConfig.ServicePrincipalToken() if err != nil { @@ -249,6 +283,7 @@ func getAuthorizer(config *Config) (autorest.Authorizer, error) { return autorest.NewBearerAuthorizer(spToken), nil } + return auth.NewAuthorizerFromEnvironment() } diff --git a/providers/dns/azure/azure.toml b/providers/dns/azure/azure.toml index b28bcbd9..c8336115 100644 --- a/providers/dns/azure/azure.toml +++ b/providers/dns/azure/azure.toml @@ -8,6 +8,7 @@ Example = '''''' [Configuration] [Configuration.Credentials] + AZURE_ENVIRONMENT = "Azure environment, one of: public, usgovernment, german, and china" AZURE_CLIENT_ID = "Client ID" AZURE_CLIENT_SECRET = "Client secret" AZURE_SUBSCRIPTION_ID = "Subscription ID" diff --git a/providers/dns/azure/azure_test.go b/providers/dns/azure/azure_test.go index 38cc9371..01dcb129 100644 --- a/providers/dns/azure/azure_test.go +++ b/providers/dns/azure/azure_test.go @@ -13,6 +13,7 @@ import ( const envDomain = envNamespace + "DOMAIN" var envTest = tester.NewEnvTest( + EnvEnvironment, EnvClientID, EnvClientSecret, EnvSubscriptionID,