mirror of
https://github.com/coredns/coredns.git
synced 2025-12-07 10:55:17 -05: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