---
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
---

> ## 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; };
```

@(Info)(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.

@(Info)(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!
