Skip to content

Commit

Permalink
alidns: support ECS instance RAM role (#1462)
Browse files Browse the repository at this point in the history
  • Loading branch information
bestmike007 authored Aug 25, 2021
1 parent dc2b19e commit 99ba43f
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 19 deletions.
1 change: 1 addition & 0 deletions cmd/zz_gen_cmd_dnshelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func displayDNSHelp(name string) error {

ew.writeln(`Credentials:`)
ew.writeln(` - "ALICLOUD_ACCESS_KEY": Access key ID`)
ew.writeln(` - "ALICLOUD_RAM_ROLE": Your instance RAM role (https://www.alibabacloud.com/help/doc-detail/54579.htm)`)
ew.writeln(` - "ALICLOUD_SECRET_KEY": Access Key secret`)
ew.writeln(` - "ALICLOUD_SECURITY_TOKEN": STS Security Token (optional)`)
ew.writeln()
Expand Down
9 changes: 8 additions & 1 deletion docs/content/dns/zz_gen_alidns.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ Configuration for [Alibaba Cloud DNS](https://www.alibabacloud.com/product/dns).
Here is an example bash command using the Alibaba Cloud DNS provider:

```bash
# Setup using instance RAM role
ALICLOUD_RAM_ROLE=lego \
lego --email myemail@example.com --dns alidns --domains my.example.org run

# Or, using credentials
ALICLOUD_ACCESS_KEY=abcdefghijklmnopqrstuvwx \
ALICLOUD_SECRET_KEY=xxxxxxx \
ALICLOUD_SECRET_KEY=your-secret-key \
ALICLOUD_SECURITY_TOKEN=your-sts-token \
lego --email myemail@example.com --dns alidns --domains my.example.org run
```

Expand All @@ -34,6 +40,7 @@ lego --email myemail@example.com --dns alidns --domains my.example.org run
| Environment Variable Name | Description |
|-----------------------|-------------|
| `ALICLOUD_ACCESS_KEY` | Access key ID |
| `ALICLOUD_RAM_ROLE` | Your instance RAM role (https://www.alibabacloud.com/help/doc-detail/54579.htm) |
| `ALICLOUD_SECRET_KEY` | Access Key secret |
| `ALICLOUD_SECURITY_TOKEN` | STS Security Token (optional) |

Expand Down
37 changes: 24 additions & 13 deletions providers/dns/alidns/alidns.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const defaultRegionID = "cn-hangzhou"
const (
envNamespace = "ALICLOUD_"

EnvRAMRole = envNamespace + "RAM_ROLE"
EnvAccessKey = envNamespace + "ACCESS_KEY"
EnvSecretKey = envNamespace + "SECRET_KEY"
EnvSecurityToken = envNamespace + "SECURITY_TOKEN"
Expand All @@ -36,6 +37,7 @@ const (

// Config is used to configure the creation of the DNSProvider.
type Config struct {
RAMRole string
APIKey string
SecretKey string
SecurityToken string
Expand Down Expand Up @@ -63,18 +65,26 @@ type DNSProvider struct {
}

// NewDNSProvider returns a DNSProvider instance configured for Alibaba Cloud DNS.
// Credentials must be passed in the environment variables:
// - If you're using the instance RAM role, the RAM role environment variable must be passed in: ALICLOUD_RAM_ROLE.
// - Other than that, credentials must be passed in the environment variables:
// ALICLOUD_ACCESS_KEY, ALICLOUD_SECRET_KEY, and optionally ALICLOUD_SECURITY_TOKEN.
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvAccessKey, EnvSecretKey)
config := NewDefaultConfig()
config.RegionID = env.GetOrFile(EnvRegionID)

values, err := env.Get(EnvRAMRole)
if err == nil {
config.RAMRole = values[EnvRAMRole]
return NewDNSProviderConfig(config)
}

values, err = env.Get(EnvAccessKey, EnvSecretKey)
if err != nil {
return nil, fmt.Errorf("alicloud: %w", err)
}

config := NewDefaultConfig()
config.APIKey = values[EnvAccessKey]
config.SecretKey = values[EnvSecretKey]
config.RegionID = env.GetOrFile(EnvRegionID)
config.SecurityToken = env.GetOrFile(EnvSecurityToken)

return NewDNSProviderConfig(config)
Expand All @@ -86,23 +96,24 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, errors.New("alicloud: the configuration of the DNS provider is nil")
}

if config.APIKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("alicloud: credentials missing")
}

if config.RegionID == "" {
config.RegionID = defaultRegionID
}

conf := sdk.NewConfig().WithTimeout(config.HTTPTimeout)

var credential auth.Credential
if config.SecurityToken == "" {
credential = credentials.NewAccessKeyCredential(config.APIKey, config.SecretKey)
} else {
switch {
case config.RAMRole != "":
credential = credentials.NewEcsRamRoleCredential(config.RAMRole)
case config.APIKey != "" && config.SecretKey != "" && config.SecurityToken != "":
credential = credentials.NewStsTokenCredential(config.APIKey, config.SecretKey, config.SecurityToken)
case config.APIKey != "" && config.SecretKey != "":
credential = credentials.NewAccessKeyCredential(config.APIKey, config.SecretKey)
default:
return nil, fmt.Errorf("alicloud: ram role or credentials missing")
}

conf := sdk.NewConfig().WithTimeout(config.HTTPTimeout)

client, err := alidns.NewClientWithOptions(config.RegionID, conf, credential)
if err != nil {
return nil, fmt.Errorf("alicloud: credentials failed: %w", err)
Expand Down
9 changes: 8 additions & 1 deletion providers/dns/alidns/alidns.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ Code = "alidns"
Since = "v1.1.0"

Example = '''
# Setup using instance RAM role
ALICLOUD_RAM_ROLE=lego \
lego --email myemail@example.com --dns alidns --domains my.example.org run
# Or, using credentials
ALICLOUD_ACCESS_KEY=abcdefghijklmnopqrstuvwx \
ALICLOUD_SECRET_KEY=xxxxxxx \
ALICLOUD_SECRET_KEY=your-secret-key \
ALICLOUD_SECURITY_TOKEN=your-sts-token \
lego --email myemail@example.com --dns alidns --domains my.example.org run
'''

[Configuration]
[Configuration.Credentials]
ALICLOUD_RAM_ROLE = "Your instance RAM role (https://www.alibabacloud.com/help/doc-detail/54579.htm)"
ALICLOUD_ACCESS_KEY = "Access key ID"
ALICLOUD_SECRET_KEY = "Access Key secret"
ALICLOUD_SECURITY_TOKEN = "STS Security Token (optional)"
Expand Down
21 changes: 17 additions & 4 deletions providers/dns/alidns/alidns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const envDomain = envNamespace + "DOMAIN"

var envTest = tester.NewEnvTest(
EnvAccessKey,
EnvSecretKey).
EnvSecretKey,
EnvRAMRole).
WithDomain(envDomain)

func TestNewDNSProvider(t *testing.T) {
Expand All @@ -28,6 +29,12 @@ func TestNewDNSProvider(t *testing.T) {
EnvSecretKey: "456",
},
},
{
desc: "success (RAM role)",
envVars: map[string]string{
EnvRAMRole: "LegoInstanceRole",
},
},
{
desc: "missing credentials",
envVars: map[string]string{
Expand Down Expand Up @@ -78,6 +85,7 @@ func TestNewDNSProvider(t *testing.T) {
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
ramRole string
apiKey string
secretKey string
expected string
Expand All @@ -87,19 +95,23 @@ func TestNewDNSProviderConfig(t *testing.T) {
apiKey: "123",
secretKey: "456",
},
{
desc: "success",
ramRole: "LegoInstanceRole",
},
{
desc: "missing credentials",
expected: "alicloud: credentials missing",
expected: "alicloud: ram role or credentials missing",
},
{
desc: "missing api key",
secretKey: "456",
expected: "alicloud: credentials missing",
expected: "alicloud: ram role or credentials missing",
},
{
desc: "missing secret key",
apiKey: "123",
expected: "alicloud: credentials missing",
expected: "alicloud: ram role or credentials missing",
},
}

Expand All @@ -108,6 +120,7 @@ func TestNewDNSProviderConfig(t *testing.T) {
config := NewDefaultConfig()
config.APIKey = test.apiKey
config.SecretKey = test.secretKey
config.RAMRole = test.ramRole

p, err := NewDNSProviderConfig(config)

Expand Down

0 comments on commit 99ba43f

Please sign in to comment.