Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support list aliyun dns record #25

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/configFile.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const defaultConfigFile = `# # lc (list cloud) 的云服务商配置文件
# # 访问凭证获取地址:https://ram.console.aliyun.com
# - provider: aliyun
# id: aliyun_default
# cloud_services: ecs,oss,rds,fc,domain
# cloud_services: ecs,oss,rds,fc,domain,dns
# access_key:
# secret_key:
# session_token:
Expand Down
28 changes: 28 additions & 0 deletions cmd/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ func (r *Runner) Enumerate() {
var Count int
for _, instance := range instances.GetItems() {
builder.Reset()
if instance.DNSRecord != "" {
Count++
builder.WriteString("DNSRecord: ")
builder.WriteString(instance.DNSRecord)
builder.WriteString(` `)
// 输出DNSName
if instance.DNSName != "" {
builder.WriteString("CNAME: ")
builder.WriteString(instance.DNSName)
builder.WriteRune('\n')
}
// 输出PublicIPv4
if instance.PublicIPv4 != "" {
builder.WriteString("PublicIPv4: ")
builder.WriteString(instance.PublicIPv4)
builder.WriteRune('\n')
}
// 输出PrivateIpv4
if instance.PrivateIpv4 != "" {
builder.WriteString("PrivateIPv4: ")
builder.WriteString(instance.PrivateIpv4)
builder.WriteRune('\n')
}
output.WriteString(builder.String())
gologger.Silent().Msgf("%s", builder.String())
continue
}

if instance.DNSName != "" {
Count++
builder.WriteString(instance.DNSName)
Expand Down
23 changes: 15 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ module github.com/wgpsec/lc
go 1.22.1

require (
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.9
github.com/alibabacloud-go/alidns-20150109/v4 v4.5.6
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10
github.com/alibabacloud-go/domain-20180129/v4 v4.2.0
github.com/alibabacloud-go/fc-20230330/v4 v4.1.3
github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12
github.com/alibabacloud-go/tea v1.2.2
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
github.com/aliyun/alibaba-cloud-sdk-go v1.62.712
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
Expand All @@ -27,14 +29,19 @@ require (

require (
github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
github.com/alibabacloud-go/debug v1.0.0 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect
github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 // indirect
github.com/alibabacloud-go/darabonba-string v1.0.2 // indirect
github.com/alibabacloud-go/debug v1.0.1 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
github.com/alibabacloud-go/tea v1.2.2 // indirect
github.com/alibabacloud-go/tea-utils v1.3.1 // indirect
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
github.com/aliyun/credentials-go v1.3.1 // indirect
github.com/aliyun/credentials-go v1.3.10 // indirect
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
Expand Down Expand Up @@ -67,14 +74,14 @@ require (
github.com/tidwall/gjson v1.14.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.13.0 // indirect
Expand Down
108 changes: 101 additions & 7 deletions go.sum

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions pkg/providers/aliyun/aliyun.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aliyun
import (
"context"
"fmt"
dns "github.com/alibabacloud-go/alidns-20150109/v4/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
domain "github.com/alibabacloud-go/domain-20180129/v4/client"
"github.com/alibabacloud-go/tea/tea"
Expand Down Expand Up @@ -30,6 +31,7 @@ type Provider struct {
fcRegions []FcRegion
cloudServices []string
identity *sts.GetCallerIdentityResponse
dnsClient *dns.Client
}

type providerConfig struct {
Expand All @@ -47,6 +49,7 @@ func New(options schema.OptionBlock, cs goflags.StringSlice) (*Provider, error)
rdsClient *rds.Client
stsClient *sts.Client
domainClient *domain.Client
dnsClient *dns.Client
err error

identity *sts.GetCallerIdentityResponse
Expand Down Expand Up @@ -182,17 +185,36 @@ func New(options schema.OptionBlock, cs goflags.StringSlice) (*Provider, error)
return nil, err
gologger.Debug().Msg("阿里云 Domain 客户端创建成功")
}

case "dns":
// domain client
credential := &openapi.Config{AccessKeyId: tea.String(accessKeyID), AccessKeySecret: tea.String(accessKeySecret),
SecurityToken: tea.String(sessionToken)}
domainClient, err = domain.NewClient(credential)
if err != nil {
return nil, err
gologger.Debug().Msg("阿里云 Domain 客户端创建成功")
}

// dns client
dnsClient, err = dns.NewClient(credential)
if err != nil {
return nil, err
gologger.Debug().Msg("阿里云 dns 客户端创建成功")
}
}
}
return &Provider{
provider: utils.Aliyun, id: id, config: config, identity: identity,
ossClient: ossClient, ecsRegions: ecsRegions, rdsRegions: rdsRegions, fcRegions: fcRegions, cloudServices: cloudServices,
domainClient: domainClient,
dnsClient: dnsClient,
}, nil
}

func (p *Provider) Resources(ctx context.Context, cs goflags.StringSlice) (*schema.Resources, error) {
finalList := schema.NewResources()
domainListForDNS := schema.NewResources()
for _, cloudService := range p.cloudServices {
switch cloudService {
case "ecs":
Expand Down Expand Up @@ -254,6 +276,32 @@ func (p *Provider) Resources(ctx context.Context, cs goflags.StringSlice) (*sche
}
gologger.Info().Msgf("获取到 %d 条阿里云 Domain 信息", len(domainList.GetItems()))
finalList.Merge(domainList)
domainListForDNS.Merge(domainList)
case "dns":
if len(domainListForDNS.GetItems()) <= 0 {
//dns
domainProvider := &domainProvider{id: p.id, provider: p.provider, domainClient: p.domainClient}
domainList, err := domainProvider.GetResource(ctx)
if err != nil {
return nil, err
}
gologger.Info().Msgf("获取到 %d 条阿里云 Domain 信息", len(domainList.GetItems()))
finalList.Merge(domainList)
domainListForDNS.Merge(domainList)
}

// dns
dnsProvider := &dnsProvider{id: p.id, provider: p.provider, dnsClient: p.dnsClient}
dnsList := schema.NewResources()
for _, item := range domainListForDNS.GetItems() {
tmpList, err := dnsProvider.GetResource(ctx, item.DNSName)
if err != nil {
return nil, err
}
finalList.Merge(tmpList)
dnsList.Merge(tmpList)
}
gologger.Info().Msgf("获取到 %d 条阿里云 dns 信息", len(dnsList.GetItems()))
}
}
return finalList, nil
Expand Down
91 changes: 91 additions & 0 deletions pkg/providers/aliyun/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package aliyun

import (
"context"
dns "github.com/alibabacloud-go/alidns-20150109/v4/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"github.com/projectdiscovery/gologger"
"github.com/wgpsec/lc/pkg/schema"
"net"
)

type dnsProvider struct {
id string
provider string
dnsClient *dns.Client
}

func (d *dnsProvider) GetResource(ctx context.Context, domain string) (*schema.Resources, error) {

var allRespResult []*dns.DescribeDomainRecordsResponseBodyDomainRecordsRecord
dnsList := schema.NewResources()
gologger.Debug().Msg("正在获取阿里云 DNS 资源信息")

pageNumber := int64(1)
pageSize := int64(100)
totalCount := int64(0)
runtime := &util.RuntimeOptions{}

for {
describeDomainRecordsRequest := &dns.DescribeDomainRecordsRequest{
DomainName: tea.String(domain),
PageNumber: tea.Int64(pageNumber),
PageSize: tea.Int64(pageSize),
}

response, err := d.dnsClient.DescribeDomainRecordsWithOptions(describeDomainRecordsRequest, runtime)
if err != nil {
return nil, err
}

// Append current page records to the result list
for _, item := range response.Body.DomainRecords.Record {
allRespResult = append(allRespResult, item)
}
totalCount = *response.Body.TotalCount

// Check if we have retrieved all records
if int64(len(allRespResult)) >= totalCount {
break
}

// Move to the next page
pageNumber++
}

// Add records to dnsList
for _, item := range allRespResult {
if item.RR != nil && item.DomainName != nil {
if *item.Type == "A" || *item.Type == "AAAA" || *item.Type == "CNAME" {
result := *item.RR + `.` + *item.DomainName
pub := ""
pri := ""
cname := ""

if net.ParseIP(*item.Value) != nil && isPrivateIP(net.ParseIP(*item.Value)) {
pri = *item.Value
} else if net.ParseIP(*item.Value) != nil && !isPrivateIP(net.ParseIP(*item.Value)) {
pub = *item.Value
} else {
cname = *item.Value
}

dnsList.Append(&schema.Resource{
ID: d.id,
Public: true,
DNSRecord: result,
DNSName: cname,
PublicIPv4: pub,
PrivateIpv4: pri,
Provider: d.provider,
})
}
}
}
return dnsList, nil
}

func isPrivateIP(ip net.IP) bool {
return ip.IsPrivate()
}
6 changes: 6 additions & 0 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type Resource struct {
PublicIPv4 string `json:"public_ipv4,omitempty"`
PrivateIpv4 string `json:"private_ipv4,omitempty"`
DNSName string `json:"dns_name,omitempty"`
DNSRecord string `json:"dns_record,omitempty"`
}

type Options []OptionBlock
Expand All @@ -59,6 +60,11 @@ func init() {

// Resources
func (r *Resources) appendResource(resource *Resource, uniqueMap *sync.Map) {
if _, ok := uniqueMap.Load(resource.DNSRecord + resource.DNSName + resource.PublicIPv4 + resource.PrivateIpv4); !ok && resource.DNSRecord != "" {
r.AppendItem(resource)
uniqueMap.Store(resource.DNSRecord+resource.DNSName+resource.PublicIPv4+resource.PrivateIpv4, struct{}{})
return
}
if _, ok := uniqueMap.Load(resource.DNSName); !ok && resource.DNSName != "" {
resourceType := validator.Identify(resource.DNSName)
r.appendResourceWithTypeAndMeta(resourceType, resource.DNSName, resource.ID, resource.Provider)
Expand Down
2 changes: 1 addition & 1 deletion pkg/schema/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type Validator struct {
func NewValidator() (*Validator, error) {
validator := &Validator{}
// regex from: https://github.com/asaskevich/govalidator
validator.rxDNSName = regexp.MustCompile(`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`)
validator.rxDNSName = regexp.MustCompile(`^(\*\.)?([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`)

err := validator.appendIPv4Ranges(ipv4PrivateRanges)
if err != nil {
Expand Down