Skip to content

Non-deterministic ACL Behavior #2137

@CadyShockTrimble

Description

@CadyShockTrimble

Describe the bug

Hello! I'm currently working on a project where we are attempting to define an ACL that restricts publishing on a key to a single user. We want the 'auth' user to be exclusively allowed to publish to the 'myhome/kitchen/temp' key, with all other users able to subscribe to that key but not publish to it. We also want all other keys to have enabled behavior by default. This is our configuration file:


  plugins: {
    rest: {
      http_port: 8000
    },
    storage_manager: {
      storages: {
        myhome: {
          key_expr: "myhome/**",
          volume: {
            id: "memory"
          }
        }
      }
    }
  },

  transport: {
    auth: {
      usrpwd: {
        user: "routerusername",
        password: "routerpassword",
        dictionary_file: "/root/credentials.txt",
      },
    },
  },

  access_control: {
    "enabled": true,
    "default_permission": "allow",
    "rules": [
      {
        "id": "restrict clients from publishing responses to requests",
        "messages": [
          "put"
        ],
        "flows":["ingress"],
        "permission": "deny",
        "key_exprs": [
          "myhome/kitchen/temp"
        ],
      },
      {
        "id": "allow clients to publish responses to requests",
        "messages": [
          "put"
        ],
        "flows":["ingress"],
        "permission": "allow",
        "key_exprs": [
          "myhome/kitchen/temp"
        ],
      },
    ],

    "subjects": [
      {
        "id": "all clients"
      },
      {
        "id": "clients allowed to publish responses to requests",
        "usernames": [
          "auth"
        ]
      },
    ],

    "policies": [
      {
        "rules": ["restrict clients from publishing responses to requests"],
        "subjects": [
          "all clients"
        ]
      },
      {
        "rules": ["allow clients to publish responses to requests"],
        "subjects": [
          "clients allowed to publish responses to requests"
        ]
      },
    ],
  },
}

Our issue with this configuration is we observe non-deterministic allow/deny behavior, where our auth user is sometimes allowed to publish on that key, and other times, our auth user is blocked from publishing on that key, with no observed error in the rust logs. We observed this behavior on linux 20.04, using zenoh version 1.5, running zenohd in docker.

Whether the publish succeeded was consistent on a single instance of the zenohd broker, but changed between runs of the broker. So when we ran docker compose, whether the publisher would be allowed was entirely random. It can take a few runs before the behavior occurs. As far as we can tell, there are no state changes we were able to find between runs that work and those that don't. We tested this on different systems and saw the same behavior.

To reproduce

  1. Create the config.json5 above and credentials.txt file in the working directory. The content of credentials.txt:
auth:password
noauth:password
  1. Run docker compose up with this docker-compose.yml file:
services:
  zenoh:
    image: eclipse/zenoh
    restart: unless-stopped
    ports:
      - 7447:7447
      - 8000:8000
    volumes:
      - ./config.json5:/root/config.json5
      - ./credentials.txt:/root/credentials.txt
      - ./zenoh_docker:/root/.zenoh
    environment:
      - RUST_LOG=debug
    command: ['--config /root/config.json5']
  1. Start the publisher with python3 publisher.py:
import zenoh, random, time, json

random.seed()

def read_temp():
    return random.randint(15, 30)

session_config= {
            "transport": {
                "auth": {
                    "usrpwd": {
                        "user": "auth",
                        "password": "password",
                    },
                }
            }
        }

if __name__ == "__main__":
    with zenoh.open(zenoh.Config.from_json5(json.dumps(session_config))) as session:
        key = 'myhome/kitchen/temp'
        pub = session.declare_publisher(key)
        while True:
            t = read_temp()
            buf = f"{t}"
            print(f"Putting Data ('{key}': '{buf}')...")
            pub.put(buf)
            time.sleep(1)
  1. Start the subscriber with python3 subscriber.py:
import zenoh, time, json

def listener(sample):
    print(f"Received {sample.kind} ('{sample.key_expr}': '{sample.payload.to_string()}')")

session_config= {
            "transport": {
                "auth": {
                    "usrpwd": {
                        "user": "noauth",
                        "password": "password",
                    },
                }
            }
        }

if __name__ == "__main__":
    with zenoh.open(zenoh.Config.from_json5(json.dumps(session_config))) as session:
        sub = session.declare_subscriber('myhome/kitchen/temp', listener)
        time.sleep(600)
  1. This behavior is intermittent, and it may take a few runs to see the issue. You may need to restart the publisher and the docker container a few times. You should expect the subscriber to receive the published messages. However, sometimes the messages are not received as expected.

System info

  • Platform : 20.04.1-Ubuntu
  • CPU: Intel(R) Xeon(R) W-2155 CPU @ 3.30GHz
  • Zenoh Version: 1.5

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions