加固命令行阿里云域名保护校验

This commit is contained in:
xuans 2026-09-16 04:14:45 +08:00
parent bbabc35cbf
commit bbc86937a2
3 changed files with 41 additions and 26 deletions

View File

@ -44,6 +44,10 @@ func newDNSPermissionCommand(verify dnsPermissionVerifier) *cobra.Command {
if !confirmWrite {
return errors.New("此检查会写入并删除专用临时 TXT 记录;确认已获目标域名测试授权后,请添加 --confirm-dns-write")
}
// 保护域必须在读取配置、凭据或构造云端客户端前拒绝,避免诊断入口产生任何外部副作用。
if err := dnsprovider.ValidateAliyunTargetDomains(dnsprovider.Aliyun, []string{requestedDomain}); err != nil {
return err
}
cfg, err := loadConfig()
if err != nil {
return err
@ -66,9 +70,6 @@ func newDNSPermissionCommand(verify dnsPermissionVerifier) *cobra.Command {
if err != nil {
return fmt.Errorf("读取阿里云 DNS 凭据失败:%w", err)
}
if err := dnsprovider.ValidateAliyunTargetDomains(dnsprovider.Aliyun, []string{requestedDomain}); err != nil {
return err
}
ctx, cancel := context.WithTimeout(cmd.Context(), dnsprovider.PermissionVerificationTimeoutFor(dnsprovider.Aliyun))
defer cancel()
report, verifyErr := verify(ctx, requestedDomain, credentials)

View File

@ -11,6 +11,8 @@ import (
"testing"
"time"
"github.com/spf13/cobra"
"git.pcux.cn/xuans/Scert/backend/internal/config"
"git.pcux.cn/xuans/Scert/backend/internal/dnsprovider"
"git.pcux.cn/xuans/Scert/backend/internal/secretstore"
@ -31,38 +33,38 @@ func TestDNSCheckRequiresExplicitWriteConfirmation(t *testing.T) {
}
}
func TestDNSCheckRejectsOutsideScopeBeforeVerifier(t *testing.T) {
prepareDNSCheckConfig(t)
func TestDNSCheckRejectsProtectedDomainBeforeConfigurationOrVerifier(t *testing.T) {
oldPath := configPath
configPath = filepath.Join(t.TempDir(), "missing-scert.json")
t.Cleanup(func() { configPath = oldPath })
command := newDNSCheckCommand(func(context.Context, string, map[string]string) (dnsprovider.AuthorizationReport, error) {
t.Fatal("CLI 越界不得进入云端验证")
t.Fatal("保护域不得进入云端验证")
return dnsprovider.AuthorizationReport{}, nil
})
command.SilenceUsage, command.SilenceErrors = true, true
command.SetArgs([]string{"--domain", "outside.net", "--confirm-dns-write"})
if err := command.Execute(); err == nil {
t.Fatal("确认写入不等于允许扩大范围")
command.SetArgs([]string{"--domain", "pcux.cn", "--confirm-dns-write"})
if err := command.Execute(); err == nil || !strings.Contains(err.Error(), "pcux.cn") {
t.Fatalf("保护域必须在读取配置前被拒绝:%v", err)
}
}
func TestDNSInspectDoesNotRequireWriteOrPromoteReadableToVerified(t *testing.T) {
prepareDNSCheckConfig(t)
command := newDNSInspectCommand(func(context.Context, string, map[string]string) (dnsprovider.AuthorizationReport, error) {
return dnsprovider.AuthorizationReport{
Provider: "aliyun", Domains: []dnsprovider.AuthorizationDomain{{Domain: "example.com", Listed: true}},
}, nil
})
var output bytes.Buffer
command.SetOut(&output)
command.SetArgs([]string{"--domain", "example.com"})
if err := command.Execute(); err != nil {
t.Fatal(err)
func TestDNSCommandOnlyExposesConfirmedWriteCheck(t *testing.T) {
command := newDNSCommand()
var check *cobra.Command
for _, child := range command.Commands() {
if child.Name() == "inspect" {
t.Fatal("不得暴露会被误解为可签发授权的只读 inspect 命令")
}
if child.Name() == "check" {
check = child
}
}
var report dnsprovider.AuthorizationReport
if err := json.Unmarshal(output.Bytes(), &report); err != nil || report.Verified || report.Domains[0].Writable {
t.Fatalf("只读成功不能升级为写权限通过:%s", output.String())
if check == nil {
t.Fatal("必须提供 dns check 命令")
}
if command.Flag("confirm-dns-write") != nil {
t.Fatal("只读命令不得提供写入开关")
if check.Flag("domain") == nil || check.Flag("confirm-dns-write") == nil {
t.Fatal("dns check 必须同时要求明确域名和写入确认")
}
}

View File

@ -0,0 +1,12 @@
package dnsverification
type Stage struct {
Name string `json:"name"`
Status string `json:"status"`
Message string `json:"message"`
}
type Report struct {
RecordName string `json:"record_name"`
Stages []Stage `json:"stages"`
}