mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	Add cache_capacity option to dnssec middleware for the capacity of LRU cache (#339)
				
					
				
			This fix adds a `cache_capacity` option to dnssec middleware, so that it is possible to specify the capacity of the LRU cache used by dnssec middleware. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
		| @@ -26,6 +26,7 @@ TODO(miek): think about key rollovers, and how to do them automatically. | |||||||
| ~~~ | ~~~ | ||||||
| dnssec [ZONES... ] { | dnssec [ZONES... ] { | ||||||
|     key file KEY... |     key file KEY... | ||||||
|  |     cache_capacity CAPACITY | ||||||
| } | } | ||||||
| ~~~ | ~~~ | ||||||
|  |  | ||||||
| @@ -33,4 +34,9 @@ dnssec [ZONES... ] { | |||||||
|   will be signed with all keys. Generating a key can be done with `dnssec-keygen`: `dnssec-keygen -a |   will be signed with all keys. Generating a key can be done with `dnssec-keygen`: `dnssec-keygen -a | ||||||
|   ECDSAP256SHA256 <zonename>`. A key created for zone *A* can be safely used for zone *B*. |   ECDSAP256SHA256 <zonename>`. A key created for zone *A* can be safely used for zone *B*. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | * `cache_capacity` indicates the capacity of the LRU cache. The dnssec middleware uses LRU cache to manage | ||||||
|  |   objects and the default capacity is 10000. | ||||||
|  |  | ||||||
|  |  | ||||||
| ## Examples | ## Examples | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package dnssec | package dnssec | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/miekg/coredns/core/dnsserver" | 	"github.com/miekg/coredns/core/dnsserver" | ||||||
| @@ -18,12 +19,12 @@ func init() { | |||||||
| } | } | ||||||
|  |  | ||||||
| func setup(c *caddy.Controller) error { | func setup(c *caddy.Controller) error { | ||||||
| 	zones, keys, err := dnssecParse(c) | 	zones, keys, capacity, err := dnssecParse(c) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return middleware.Error("dnssec", err) | 		return middleware.Error("dnssec", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	cache, err := lru.New(defaultCap) | 	cache, err := lru.New(capacity) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -34,10 +35,12 @@ func setup(c *caddy.Controller) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, error) { | func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, int, error) { | ||||||
| 	zones := []string{} | 	zones := []string{} | ||||||
|  |  | ||||||
| 	keys := []*DNSKEY{} | 	keys := []*DNSKEY{} | ||||||
|  |  | ||||||
|  | 	capacity := defaultCap | ||||||
| 	for c.Next() { | 	for c.Next() { | ||||||
| 		if c.Val() == "dnssec" { | 		if c.Val() == "dnssec" { | ||||||
| 			// dnssec [zones...] | 			// dnssec [zones...] | ||||||
| @@ -49,47 +52,57 @@ func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, error) { | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			for c.NextBlock() { | 			for c.NextBlock() { | ||||||
| 				k, e := keyParse(c) | 				switch c.Val() { | ||||||
| 				if e != nil { | 				case "key": | ||||||
| 					return nil, nil, e | 					k, e := keyParse(c) | ||||||
|  | 					if e != nil { | ||||||
|  | 						return nil, nil, 0, e | ||||||
|  | 					} | ||||||
|  | 					keys = append(keys, k...) | ||||||
|  | 				case "cache_capacity": | ||||||
|  | 					if !c.NextArg() { | ||||||
|  | 						return nil, nil, 0, c.ArgErr() | ||||||
|  | 					} | ||||||
|  | 					value := c.Val() | ||||||
|  | 					cacheCap, err := strconv.Atoi(value) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return nil, nil, 0, err | ||||||
|  | 					} | ||||||
|  | 					capacity = cacheCap | ||||||
| 				} | 				} | ||||||
| 				keys = append(keys, k...) |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	for i := range zones { | 	for i := range zones { | ||||||
| 		zones[i] = middleware.Host(zones[i]).Normalize() | 		zones[i] = middleware.Host(zones[i]).Normalize() | ||||||
| 	} | 	} | ||||||
| 	return zones, keys, nil | 	return zones, keys, capacity, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func keyParse(c *caddy.Controller) ([]*DNSKEY, error) { | func keyParse(c *caddy.Controller) ([]*DNSKEY, error) { | ||||||
| 	keys := []*DNSKEY{} | 	keys := []*DNSKEY{} | ||||||
|  |  | ||||||
| 	what := c.Val() |  | ||||||
| 	if !c.NextArg() { | 	if !c.NextArg() { | ||||||
| 		return nil, c.ArgErr() | 		return nil, c.ArgErr() | ||||||
| 	} | 	} | ||||||
| 	value := c.Val() | 	value := c.Val() | ||||||
| 	switch what { | 	if value == "file" { | ||||||
| 	case "key": | 		ks := c.RemainingArgs() | ||||||
| 		if value == "file" { | 		for _, k := range ks { | ||||||
| 			ks := c.RemainingArgs() | 			base := k | ||||||
| 			for _, k := range ks { | 			// Kmiek.nl.+013+26205.key, handle .private or without extension: Kmiek.nl.+013+26205 | ||||||
| 				base := k | 			if strings.HasSuffix(k, ".key") { | ||||||
| 				// Kmiek.nl.+013+26205.key, handle .private or without extension: Kmiek.nl.+013+26205 | 				base = k[:len(k)-4] | ||||||
| 				if strings.HasSuffix(k, ".key") { |  | ||||||
| 					base = k[:len(k)-4] |  | ||||||
| 				} |  | ||||||
| 				if strings.HasSuffix(k, ".private") { |  | ||||||
| 					base = k[:len(k)-8] |  | ||||||
| 				} |  | ||||||
| 				k, err := ParseKeyFile(base+".key", base+".private") |  | ||||||
| 				if err != nil { |  | ||||||
| 					return nil, err |  | ||||||
| 				} |  | ||||||
| 				keys = append(keys, k) |  | ||||||
| 			} | 			} | ||||||
|  | 			if strings.HasSuffix(k, ".private") { | ||||||
|  | 				base = k[:len(k)-8] | ||||||
|  | 			} | ||||||
|  | 			k, err := ParseKeyFile(base+".key", base+".private") | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 			keys = append(keys, k) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return keys, nil | 	return keys, nil | ||||||
|   | |||||||
| @@ -13,19 +13,25 @@ func TestSetupDnssec(t *testing.T) { | |||||||
| 		shouldErr          bool | 		shouldErr          bool | ||||||
| 		expectedZones      []string | 		expectedZones      []string | ||||||
| 		expectedKeys       []string | 		expectedKeys       []string | ||||||
|  | 		expectedCapacity   int | ||||||
| 		expectedErrContent string | 		expectedErrContent string | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			`dnssec`, false, nil, nil, "", | 			`dnssec`, false, nil, nil, defaultCap, "", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			`dnssec miek.nl`, false, []string{"miek.nl."}, nil, "", | 			`dnssec miek.nl`, false, []string{"miek.nl."}, nil, defaultCap, "", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			`dnssec miek.nl { | ||||||
|  | 				cache_capacity 100 | ||||||
|  | 			}`, false, []string{"miek.nl."}, nil, 100, "", | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for i, test := range tests { | 	for i, test := range tests { | ||||||
| 		c := caddy.NewTestController("dns", test.input) | 		c := caddy.NewTestController("dns", test.input) | ||||||
| 		zones, keys, err := dnssecParse(c) | 		zones, keys, capacity, err := dnssecParse(c) | ||||||
|  |  | ||||||
| 		if test.shouldErr && err == nil { | 		if test.shouldErr && err == nil { | ||||||
| 			t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input) | 			t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input) | ||||||
| @@ -51,6 +57,9 @@ func TestSetupDnssec(t *testing.T) { | |||||||
| 					t.Errorf("Dnssec not correctly set for input %s. Expected: '%s', actual: '%s'", test.input, k, keys[i].K.Header().Name) | 					t.Errorf("Dnssec not correctly set for input %s. Expected: '%s', actual: '%s'", test.input, k, keys[i].K.Header().Name) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 			if capacity != test.expectedCapacity { | ||||||
|  | 				t.Errorf("Dnssec not correctly set capacity for input '%s' Expected: '%d', actual: '%d'", test.input, capacity, test.expectedCapacity) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user