github.com/letsencrypt/boulder@v0.20251208.0/cmd/admin/overrides_toggle.go (about) 1 package main 2 3 import ( 4 "context" 5 "errors" 6 "flag" 7 "fmt" 8 "net/netip" 9 "strings" 10 11 "github.com/letsencrypt/boulder/identifier" 12 "github.com/letsencrypt/boulder/policy" 13 rl "github.com/letsencrypt/boulder/ratelimits" 14 sapb "github.com/letsencrypt/boulder/sa/proto" 15 ) 16 17 type subcommandToggleOverride struct { 18 enabled bool 19 limit string 20 regId int64 21 singleIdentifier string 22 setOfIdentifiers string 23 subscriberIP string 24 } 25 26 func (*subcommandToggleOverride) Desc() string { 27 return "Enable or disable a rate limit override." 28 } 29 30 func (c *subcommandToggleOverride) Flags(f *flag.FlagSet) { 31 f.BoolVar(&c.enabled, "enabled", false, "true to enable, false to disable (default: false)") 32 f.StringVar(&c.limit, "limit", "", "ratelimit name (required)") 33 f.Int64Var(&c.regId, "regId", 0, "a single registration/account ID") 34 f.StringVar(&c.singleIdentifier, "singleIdentifier", "", "a single identifier (e.g. example.com or www.example.com or 55.66.77.88 or 2602:80a:6000::1)") 35 f.StringVar(&c.setOfIdentifiers, "setOfIdentifiers", "", "comma-separated list of unique identifiers (e.g. example.com,www.example.com,55.66.77.88,2602:80a:6000::1)") 36 f.StringVar(&c.subscriberIP, "subscriberIP", "", "a single IPv4/IPv6 address the subscriber uses for requests") 37 } 38 39 func (c *subcommandToggleOverride) Run(ctx context.Context, a *admin) error { 40 if c.limit == "" { 41 return errors.New("--limit is required") 42 } 43 name, ok := rl.StringToName[c.limit] 44 if !ok { 45 return fmt.Errorf("unknown limit name %q, must be one in %s", c.limit, rl.LimitNames) 46 } 47 48 var subscriberIP netip.Addr 49 var err error 50 if c.subscriberIP != "" { 51 subscriberIP, err = netip.ParseAddr(c.subscriberIP) 52 if err != nil { 53 return fmt.Errorf("invalid subscriberIP %q", err) 54 } 55 err := policy.ValidIP(c.subscriberIP) 56 if err != nil { 57 return fmt.Errorf("invalid subscriberIP %q: %w", c.subscriberIP, err) 58 } 59 } 60 61 singleIdent := identifier.FromString(c.singleIdentifier) 62 err = validateIdentifiers(singleIdent) 63 if err != nil { 64 return fmt.Errorf("invalid singleIdentifier: %w", err) 65 } 66 67 var setOfIdents identifier.ACMEIdentifiers 68 if c.setOfIdentifiers != "" { 69 setOfIdents = identifier.FromStringSlice(strings.Split(c.setOfIdentifiers, ",")) 70 err := validateIdentifiers(setOfIdents...) 71 if err != nil { 72 return fmt.Errorf("invalid setOfIdentifiers: %w", err) 73 } 74 } 75 76 bucketKey, err := rl.BuildBucketKey(name, c.regId, singleIdent, setOfIdents, subscriberIP) 77 if err != nil { 78 return fmt.Errorf("building bucket key for limit %s: %s", name, err) 79 } 80 81 if c.enabled { 82 _, err := a.sac.EnableRateLimitOverride(ctx, &sapb.EnableRateLimitOverrideRequest{ 83 LimitEnum: int64(name), 84 BucketKey: bucketKey, 85 }) 86 if err != nil { 87 return fmt.Errorf("enabling override for limit %s key %q: %s", name, bucketKey, err) 88 } 89 a.log.Infof("Enabled override for limit %s key %q\n", name, bucketKey) 90 return nil 91 } 92 93 _, err = a.sac.DisableRateLimitOverride(ctx, &sapb.DisableRateLimitOverrideRequest{ 94 LimitEnum: int64(name), 95 BucketKey: bucketKey, 96 }) 97 if err != nil { 98 return fmt.Errorf("disabling override for limit %s key %q: %s", name, bucketKey, err) 99 } 100 a.log.Infof("Disabled override for limit %s key %q\n", name, bucketKey) 101 return nil 102 }