--- title: "Using Access Control Lists (ACLs) with both addresses and keys" slug: "aa-00723" description: "How can I configure allow-update to permit updates using ACLs? Read this and find out." updated: 2018-09-06T19:56:00Z published: 2018-09-06T19:56:00Z canonical: "kb.isc.org/aa-00723" stale: true --- > ## Documentation Index > Fetch the complete documentation index at: https://kb.isc.org/llms.txt > Use this file to discover all available pages before exploring further. # Using Access Control Lists (ACLs) with both addresses and keys ### Question: How can I configure allow-update to permit updates, only if BOTH of the following are true? - They hold the secret key (TSIG) - They're in the 'permitted' subnet ### Answer: Here's the long version: ``` acl address_allow { 10/8; }; acl address_reject { !address_allow; any; }; allow-update { !address_reject; key "...."; }; ``` And now in shorthand: ``` allow-update { !{!10/8;any;}; key update-key; }; ``` Doesn't this permit any clients on the 10/8 network?Intuitively, by (mistakenly) attempting to apply Boolean logic *(despite the lack of an AND operator in BIND ACLs)* , you might think that it does, but it doesn't.  What it actually says is 'deny anyone who isn't in subnet 10/8', **and** then 'allow anyone using this key'. ACLs aren't boolean. The ACL elements are processed in order (from left to right) and each ACL element has **three** possible results instead of **two** : - match and accept - match and reject - no match *(which means "continue processing")* When an ordinary ACL element matches and is negated (for example, the element is "!10/8;" and the address is 10.0.0.1) that means "match and reject." But if the match is inside of a *nested* ACL, then it's treated differently. A negative result means "the nested ACL didn't match"--and so you continue processing. Remember that a 'match' inside a nested ACL is treated differently to a match of an ordinary ACL element.The point explained immediately above this information box is significant and important, hence the repetition with emphasis! Therefore if you're checking address A against an ACL of one of the following forms, these will be the results: ```     {     A;    B; }   == A is allowed, accept immediately {  {  A; }; B; }   == A is allowed, accept immediately {    !A;    B; }   == A is forbidden, reject immediately { !{  A; }; B; }   == A is forbidden, reject immediately {  { !A; }; B; }   == A matched but was negated, try element B { !{ !A; }; B; }   == A matched but was negated, try element B ``` Those last two lines there are confusingly similar (and, as written, useless). The difference is what happens if you're checking an address **other** than A, and something else in the nested ACL matches it. ```     {  { !A; any; }; B; }  == any address other than A is accepted at once, but A is only accepted if B matches too. boolean translation: ((not A) or (A and B)) { !{ !A; any; }; B; }  == any address other than A is *rejected* at once, but A is accepted as long as B matches too. boolean translation: (A and B) ``` Hope that's helpful!