How to get RBAC running

RBAC Using Candid: Using Candid to add users to MAAS

Candid & Canonical-RBAC


Candid is an open source, macaroon-based authentication service, written in Go, that supports multiple backends as a source of authentication. It can be used to provide authentication to LXD, Juju, and MAAS.

Candid supports a variety of identity providers including:

  • ADFS
  • Azure
  • Google
  • Keycloak
  • Keystone
  • LDAP
  • OpenID
  • UbuntuOne
  • Static


The Canonical RBAC service is an external service to MAAS that extends the functionality of MAAS and provides role-based access control. Written in Python, RBAC is closed source. The private license requires Ubuntu Advantage to be gain access to the private PPA.

RBAC uses Candid as an authentication source, and sports a nice UI.

Launch a VM

For the lab, we will need a machine (preferably not a container) where we can deploy MAAS. 2vCPU with 4G would be ideal but you can probably get away with half. A t2.medium on AWS works pretty well. Must be amd64. You will need access to port 5240 (MAAS), and 8081 (candid), and 5000 (RBAC) in addition to port 22 (ssh). Or use sshuttle to tunnel into the VM.

Install MAAS For Testing

Create a script with some important variables:

$ cat <<EOF> ~/
MAAS_VIP= # external host/IP you access MAAS with
$ source ~/

Install MAAS

MAAS doesn’t have a latest/stable channel. When we leave off the channel, we get the latest supported version. This allows us to track updates for that specific version and upgrade to newer versions at our convenience.

$ sudo snap install maas --channel=3.2/stable

Install PostgreSQL

There is a snap called maas-test-db that sets up a PostgreSQL database specially designed for a quick MAAS test but the canonical-rbac install will ensure the postgresql package is installed so we might as well use it.

$ sudo apt update
$ sudo apt install -y postgresql
$ sudo -u postgres psql -c "create user maas
    with encrypted password 'mysecretmaaspw'"
$ sudo -u postgres createdb -O maas maasdb
$ PGVER=$(ls -1 /etc/postgresql | tail -1)
$ echo -e "\nhost maasdb maas 0/0 md5" |
    sudo tee -a /etc/postgresql/$PGVER/main/pg_hba.conf

Initialize MAAS

Point MAAS at the DB:

$ sudo maas init region+rack \
    --database-uri "postgres://maas:mysecretmaaspw@localhost/maasdb"

Create an admin user:

$ sudo maas createadmin --username=root \

Log in:

$ maas login root http://$MAAS_VIP:5240/MAAS/ \
  $(sudo maas apikey --username=root | tee maas-api)


$ maas root tags read
Machine-readable output follows:
	"name": "virtual",
	"definition": "",
	"comment": "",
	"kernel_opts": "",
	"resource_uri": "/MAAS/api/2.0/tags/virtual/"

Install Candid & Canonical-RBAC

Configure APT

Find Canonical RBAC ppa. This should be listed in for all Canonical employees. Be sure to choose the ppa for the stable package.

Copy the user and password from the above into an auth.conf.d file:

$ echo "machine login lpid password x" | sudo tee /etc/apt/auth.conf.d/canonical-rbac.conf
$ sudo chmod 600 /etc/apt/auth.conf.d/canonical-rbac.conf

Configure Canonical-RBAC PPA

Import the OpenPGP key (also from ppa page):

$ wget -qO- '' | sudo tee /etc/apt/trusted.gpg.d/canonical-rbac.asc

Add the apt source:

$ cat <<EOF | sudo tee /etc/apt/sources.list.d/canonical-rbac.list
# access to Canonical RBAC - stable packages
deb bionic main
deb-src bionic main
$ sudo apt update

Prepare Database

The postgres helper from the canonical-rbac package expects to find postgresql 10 (because the package is for bionic). We have to trick it. If you are running focal, we’ll have version 12. And jammy has 14. The correct version should be in the PGVER variable from earlier.

$ sudo ln -s $PGVER /etc/postgresql/10

Install Canonical-RBAC

Note that this also installs the canonical-rbac and candid snaps.

$ sudo apt install canonical-rbac debconf-utils -y

If installing on an HA MAAS, the PG_VIP will be a real vip and the apt install post-install script will fail. Run this line to swap localhost for the real vip:

$ sudo snap set canonical-rbac db.url="$(sudo snap get canonical-rbac db.url |
    sed "s/localhost/$PG_VIP/")"


If the install fails the post-installation script but doesn’t give any specific reason (locale warnings can be ignored) then it may be that uwsgi has set “cheaper” higher than “workers” in /var/snap/canonical-rbac/current/conf/uwsgi.ini. This is only likely with servers with more than 50 CPUs.

$ cheaper=$(awk '/^workers/{print $3-1}' \
$ sudo sed -E -i -e 's/^(^cheaper(-initial)? = ).*/\1 '$cheaper'/' \
$ sudo systemctl restart snap.canonical-rbac.uwsgi.service
$ sudo dpkg --configure canonical-rbac

DB Update

Skip these commands if PG_VIP is localhost. We need to update the database URLs in canonical-rbac and candid.

$ sudo debconf-get-selections | grep canonical-rbac |
    sed 's/localhost/'$PG_VIP'/' | tee debconf.rbac |
    sudo debconf-set-selections
$ sudo sed -i -e "s/localhost/$PG_VIP/" /var/snap/candid/current/config.yaml
$ sudo -u postgres psql rbac -c "update config set value=regexp_replace(value::text,'//[^:]*:','//$PG_VIP:')::jsonb"

DB Update

Let’s rewrite the pg_hba.conf using existing maasdb entries as a template:

$ hba_file=/etc/postgresql/$PGVER/main/pg_hba.conf
$ sudo sed -E -i -e '/(candid|rbac)/d' $hba_file
$ sudo grep maasdb $hba_file | sort -u |
    sed -E -e 's/maas(db)?/candid/g' | sudo tee -a $hba_file
$ sudo grep maasdb $hba_file | sort -u |
    sed -E -e 's/maas(db)?/rbac/g'   | sudo tee -a $hba_file

Reload DB & Restart Candid

$ cluster=$(pg_conftool show cluster_name | awk -F\' '{print $2}')
$ sudo -u postgres pg_ctlcluster ${cluster%/*} ${cluster#*/} reload
$ sudo snap restart candid

Modify Candid Config

Edit candid config.yaml to point at the MAAS vip and to modify the admin user. Reminder: This uses MAAS_PW from

$ sudo sed -E -i -e 's/(^location:[^/]*..)[^:]*(.*)/\1'$MAAS_VIP'\2/; s/(password: ).*/\1'$MAAS_PW'/; s/group1/admin/; /group2/d' /var/snap/candid/current/config.yaml

There’s also a url in admin.keys:

$ sudo sed -E -i -e 's/(.*url[^/]*..)[^:]*(.*)/\1'$MAAS_VIP'\2/' \
$ sudo snap restart candid

Test Candid

Now candid and canonical-rbac are running on the MAAS node, backed by the same database.

We should be able to test the browser login using a candid command. This will prompt you to open a URL and authenticate using admin and the password set in config.yaml:

$ candid show -u admin

Configure MAAS

We can configure maas to talk directly to candid if we’re not using canonical-rbac.

$ sudo cp /var/snap/candid/current/admin.keys /tmp/snap.maas/tmp/.
$ sudo maas configauth --rbac-url '' --candid-agent-file /tmp/admin.keys \
    --candid-domain '' --candid-admin-group admin


We now have lost access with our previous login. This will fail (print Usage):

$ maas root tags read

When we re-login, this time we will omit the api key.

$ maas login root http://$MAAS_VIP:5240/MAAS/

This will either open a web browser or present you with a URL that needs to be visited. Click “Static” and then login with “admin” and the pw in

Add A User

To add/modify users, edit the config.yaml in var/snap/candid/current. Copy the lines for the admin user and make a new user called “user1”, or whatever. Add this new user to a non-admin group such as “group1”. Restart candid to for it to see the new user.

$ sudo snap restart candid

Log into MAAS WebUI

We should be able to log into MAAS using either user in our static provider configuration.a We could stop here. However, this doesn’t give us much control over what roles each kind of user has.

Configure Canonical-RBAC

Copy the admin keys to /root:

$ sudo cp /var/snap/candid/current/admin.keys /root/.

Create an agent file and tell RBAC to use it:

$ sudo canonical-rbac create-candid-agent /root/admin.keys \
    --service-agent-file /root/rbac.agent
$ sudo canonical-rbac config --candid-agent-file /root/rbac.agent

The service URL will have localhost. Update it with the externally accessible host/IP:

$ sudo canonical-rbac config --service-url $RBAC_URL

Configure Canonical-RBAC

Configure the admin user as an admin in canonical-rbac. Run this command on the MAAS node:

$ sudo canonical-rbac create-admin

Now, in a web browser, visit the canonical-rbac url (from

$ echo $RBAC_URL

Configure Canonical-RBAC

Click the login button. A new window will open similar to the previous auth steps.

  1. Log in as admin, then close that window.
  2. Back on the canonical-rbac page, it’ll give you the option to add a service.
  3. We’ll add a MAAS service called “maas01”. The name should be descriptive and unique. We will use it later when configuring maas.
  4. For admin, we’ll choose group and use the “admin” group. You can add a description if you wish.
  5. Click Add Service and the service permissions page will come up.

Configure MAAS

Now we’ll configure MAAS to use canonical-rbac. “maas01” is the service name we chose previously.

$ sudo maas configauth --rbac-url $RBAC_URL --rbac-service-name maas01

You’ll be prompted to open a URL for authentication. Login as admin. Once successful, you’ll see 'Service “maas01” registered."

Manage Roles With RBAC

We can now manage MAAS users with the WebUI.


Adding RBAC to FCE installed MAAS supports RBAC for MAAS with LDAP.

Install LXD

In the strange scenario where you don’t already have LXD installed, you can easily install it with snap:

$ sudo snap install lxd

We’ll initialize it with all the defaults:

$ lxd init --auto


MAAS DNS listens on all interfaces. We need to ensure LXD starts up first so that LXD can properly bind dnsmasq to the lxdbr0 interface for dns and dhcp.

$ lxddir=/etc/systemd/system/snap.lxd.daemon.service.d
$ sudo mkdir -p $lxddir
$ cat <<EOF | sudo tee $lxddir/00-before-maas.conf 
$ sudo systemctl daemon-reload
$ sudo systemctl restart snap.maas.supervisor snap.lxd.daemon

Point LXD to Candid

Tell LXD where to find candid:

$ lxc config set candid.api.url $CANDID_URL

Configure the public key:

$ lxc config set candid.api.key \
    "$(awk '/^public/{print $2}' /var/snap/candid/current/config.yaml)"

Set LXD to listen on 8443:

$ lxc config set core.https_address :8443

Configure Client For Candid

Add a new remote to talk to the local server using candid:

$ lxc remote add candidlocal https://localhost:8443 --auth-type=candid

This will bring up the (now familiar) message to open a URL in a browser.
We can list the remotes with:

$ lxc remote list

And make the new remote the default:

$ lxc remote switch candidlocal

Now users must use candid to access our lxd over the network. Or we could restrict access to the socket (/var/snap/lxd/common/lxd/unix.socket) to force users to access the local lxd via the candid interface.


$ sudo vi /var/snap/candid/current/config.yaml
$ sudo snap restart candid
$ candid show -u vern
ERROR Get permission denied

Install Juju

$ sudo snap install juju --classic

Juju doesn’t like ipv6 networks with lxd.

$ lxc network set lxdbr0 ipv6.address none
$ juju bootstrap --config identity-url="$CANDID_URL" \
    --config identity-public-key="$(awk '/^public/{print $2}' \
    /var/snap/candid/current/config.yaml)" localhost candid-controller
$ juju add-model candid-model
$ juju grant -c candid-controller user1@example admin candid-model
$ juju change-user-password
$ juju logout
$ juju login -c candid-controller -u user1@example

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.