mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 10:13:14 -04:00 
			
		
		
		
	Merge commit from fork
Instead of casting lease ID to uint32, fix the TTL() function to use etcd time-to-live API for determining TTL. Add configurable min-lease-ttl and max-lease-ttl options to prevent extreme TTL values. By default, lease records now go through bounds checking with 30s to 1d as the min/max. Added unit tests for validation and docs. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
This commit is contained in:
		| @@ -2,7 +2,11 @@ package etcd | ||||
|  | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"errors" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/coredns/caddy" | ||||
| 	"github.com/coredns/coredns/core/dnsserver" | ||||
| @@ -33,7 +37,11 @@ func setup(c *caddy.Controller) error { | ||||
|  | ||||
| func etcdParse(c *caddy.Controller) (*Etcd, error) { | ||||
| 	config := dnsserver.GetConfig(c) | ||||
| 	etc := Etcd{PathPrefix: "skydns"} | ||||
| 	etc := Etcd{ | ||||
| 		PathPrefix:  "skydns", | ||||
| 		MinLeaseTTL: defaultLeaseMinTTL, | ||||
| 		MaxLeaseTTL: defaultLeaseMaxTTL, | ||||
| 	} | ||||
| 	var ( | ||||
| 		tlsConfig *tls.Config | ||||
| 		err       error | ||||
| @@ -88,6 +96,24 @@ func etcdParse(c *caddy.Controller) (*Etcd, error) { | ||||
| 					return &Etcd{}, c.Errf("credentials requires 2 arguments, username and password") | ||||
| 				} | ||||
| 				username, password = args[0], args[1] | ||||
| 			case "min-lease-ttl": | ||||
| 				if !c.NextArg() { | ||||
| 					return &Etcd{}, c.ArgErr() | ||||
| 				} | ||||
| 				minLeaseTTL, err := parseTTL(c.Val()) | ||||
| 				if err != nil { | ||||
| 					return &Etcd{}, c.Errf("invalid min-lease-ttl value: %v", err) | ||||
| 				} | ||||
| 				etc.MinLeaseTTL = minLeaseTTL | ||||
| 			case "max-lease-ttl": | ||||
| 				if !c.NextArg() { | ||||
| 					return &Etcd{}, c.ArgErr() | ||||
| 				} | ||||
| 				maxLeaseTTL, err := parseTTL(c.Val()) | ||||
| 				if err != nil { | ||||
| 					return &Etcd{}, c.Errf("invalid max-lease-ttl value: %v", err) | ||||
| 				} | ||||
| 				etc.MaxLeaseTTL = maxLeaseTTL | ||||
| 			default: | ||||
| 				if c.Val() != "}" { | ||||
| 					return &Etcd{}, c.Errf("unknown property '%s'", c.Val()) | ||||
| @@ -124,3 +150,35 @@ func newEtcdClient(endpoints []string, cc *tls.Config, username, password string | ||||
| } | ||||
|  | ||||
| const defaultEndpoint = "http://localhost:2379" | ||||
|  | ||||
| // parseTTL parses a TTL value with flexible time units using Go's standard duration parsing. | ||||
| // Supports formats like: "30", "30s", "5m", "1h", "90s", "2h30m", etc. | ||||
| func parseTTL(s string) (uint32, error) { | ||||
| 	s = strings.TrimSpace(s) | ||||
| 	if s == "" { | ||||
| 		return 0, nil | ||||
| 	} | ||||
|  | ||||
| 	// Handle plain numbers (assume seconds) | ||||
| 	if _, err := strconv.ParseUint(s, 10, 64); err == nil { | ||||
| 		// If it's just a number, append "s" for seconds | ||||
| 		s += "s" | ||||
| 	} | ||||
|  | ||||
| 	// Use Go's standard time.ParseDuration for robust parsing | ||||
| 	duration, err := time.ParseDuration(s) | ||||
| 	if err != nil { | ||||
| 		return 0, errors.New("invalid TTL format, use format like '30', '30s', '5m', '1h', or '2h30m'") | ||||
| 	} | ||||
|  | ||||
| 	// Convert to seconds and check bounds | ||||
| 	seconds := duration.Seconds() | ||||
| 	if seconds < 0 { | ||||
| 		return 0, errors.New("TTL must be non-negative") | ||||
| 	} | ||||
| 	if seconds > 4294967295 { // uint32 max value | ||||
| 		return 0, errors.New("TTL too large, maximum is 4294967295 seconds") | ||||
| 	} | ||||
|  | ||||
| 	return uint32(seconds), nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user