System user

By default, Ubuntu Core images run a program called console-conf when they’re first instantiated on a device.

Ubuntu Core profile setup

As shown above, console-conf is a text-based menu system that uses a connected keyboard and display, or a serial connection, to configure a device’s network connection and to add a user. A user is added by entering an Ubuntu SSO registered email address with one or more registered SSH keys. This user can then access the device over SSH to perform various management and configuration functions.

Some systems, however, suppress console-conf and its user creation.

To create a system user on these systems, a system-user assertion needs to be embedded within a file called auto-import.assert that’s added to the system via the root directory of a removable USB storage device. This process is covered below.



Managed vs unmanaged systems:

A managed system already has a user account whereas an unmanaged system does not. A system user cannot typically be added to a system that is already managed.

Creating users with auto-import.assert

The auto-import.assert file contains the following assertions:

A system-user assertion for the new user needs to be created, as described below, but both account and account-key assertions are output automatically as part of the auto-import.assert creation process.

The following are required by for the system-user assertion and by the creation process:

  • the brand-id and model fields taken from a device’s model assertion
  • access to the key used to sign the new assertion

The snap daemon (snapd) can import these assertions through the auto-import.assert file on an external USB storage device. If those assertions are valid for the given system, a system user is created. After this, you can log into the device (locally or over SSH) using the username and password defined.

Inside model assertions

Creating a valid system-user assertion is limited by the model assertion which contains store account ID defined as brand-id and authority-id, alongside the model name, model.

If your device is built from an image created from your own Custom model assertion, then you should already have access to these values.

The following is an example a custom model assertion showing bJzr2XzZg6Qv6Z53dsjhg20975Skjs as the account ID and mymodel as the model name:

{
  "type": "model",
  "authority-id": "bJzr2XzZg6Qv6Z53dsjhg20975Skjs",
  "brand-id": "bJzr2XzZg6Qv6Z53dsjhg20975Skjs",
  "series": "16",
  "model": "mymodel",
  "architecture": "armhf",
  "kernel": "pi2-kernel",
  "gadget": "cm3",
  "timestamp": "2021-01-11T15:55:59+00:00"
}

Another source of the store account ID is the Snap account-id from https://dashboard.snapcraft.io:

Ubuntu Core store account id

When a model assertion lacks a system-user-authority field, the system-user assertion can only be signed by:

  • a key registered to the store account specified by the brand-id field (bJzr2XzZg6Qv6Z53dsjhg20975Skjs in our example)
  • the key that’s part of the account-key assertion when the system-user assertion is submitted to the device

Specifying system-user-authority

The optional system-user-authority field can be added to a model assertion to list a set of account IDs that are authorised to sign system-user assertions for any image built with the assertion:

{
  "type": "model",
  "authority-id": "bJzr2XzZg6Qv6Z53dsjhg20975Skjs",
  "brand-id": "bJzr2XzZg6Qv6Z53dsjhg20975Skjs",
  "system-user-authority": [
    "<ANOTHER-ACCOUNT-ID>",
    "<YET-ANOTHER-ACCOUNT_ID>"
  ],
  "series": "16",
  "model": "mymodel",
  "architecture": "armhf",
  "kernel": "pi2-kernel",
  "gadget": "cm3",
  "timestamp": "2021-01-11T15:55:59+00:00"
}

Anyone who can log in to either ANOTHER-ACCOUNT-ID or YET-ANOTHER-ACCOUNT_ID accounts can sign system-user assertions with keys registered to those accounts. And such system-user assertions are valid for systems built with this model.

Self-signed system-user assertions

A model can also specify that anyone with a registered key can create a valid system-user assertion. This is done with an asterisk ("*") in the system-user-authority field:

{
  "type": "model",
  "authority-id": "<ACCOUNT-ID>",
  "brand-id": "<ACCOUNT-ID>",
  "system-user-authority": "*",
  "series": "16",
  "model": "mymodel",
  "architecture": "armhf",
  "kernel": "pi2-kernel",
  "gadget": "cm3",
  "timestamp": "2017-07-11T15:55:59+00:00"
}

mymodel will also need to be the same as the model assertion.

Creating the system-user assertion

As covered earlier, to create a user assertion you will need access to the following:

  • store account ID or brand-id/authority-id
  • model name from the model assertion
  • the name of the key used to sign the assertion and its passphrase
  • username, email address and password for the account you want to create

These details then need to be added to the following system-user template and saved to a new system-user.json file:

{
    "type": "system-user",
    "authority-id": "ACCOUNT-ID",
    "series": ["16"],
    "brand-id": "ACCOUNT-ID",
    "email": "<UBUNTU-CORE-NEW-ACCOUNT-EMAIL>",
    "models": ["my-model"],
    "name": "<UBUNTU-CORE-NEW-ACCOUNT-NAME>",
    "username": "<UBUNTU-CORE-NEW-USERNAME>",
    "password": "<UBUNTU-CORE-NEW-USER-HASHED-PASSWORD>",
    "since": "2020-05-16T18:06:04+00:00",
    "until": "2064-05-16T18:06:04+00:00"
}

The password hash must be of the form “$integer-id$salt$hash” and can be generated with the following mkpasswd command:

mkpasswd -m sha-512 -S <8CHARSALT> -s

You will be asked for the password and the output can be inserted into the system-user template.

For further details on system-user fields, including since and until, see the System-user assertion documentation.

Generating auto-import.assert

First, make sure you’re logged in with both snap and snapcraft:

snap login
snapcraft login

See Snapcraft overview if snapcraft is not installed. To retrieve the name of the key to sign the assertion with, use the snapcraft keys command:

$ snapcraft keys
Name         SHA3-384
my-key-name  E-n0AOKPFjIyy4S_i9JxTT4tkuaZf7rP9D2mBNXjlgTGDjL8euFSlb87U0NPl

See Signing a model assertion for details on creating and uploading keys.

The contents of the system-user template needs to be signed. This is accomplished with the snap command, which can also generate the accompanying account and account-key assertions at the same time:

snap sign -k my-key-name system-user.json --chain > auto-import.assert

After asking for the passphrase for my-key-name, the above command will generate output similar to the following:

The system-user data can be alternatively piped directly into the snap sign command. The additional --chain argument will output the account and account-key assertions alongside the newly signed system-user assertion.

The result is auto-import.assert in your current directory. This can be used on any qualifying image (described above) that is not already managed to make a system user.

Simply copy auto-import.assert to the root directory of a USB drive, insert it, and the system user is created.

Tip: If you are creating the system user on the first boot, it may take some minutes for the assertion to be imported and for the system user to be created.

Checking the system-user assertion

If you can log in with the username and password, the system user has been created.

You can also use the snap known system-user command. If there is a system user, the signed assertion is output.

2 Likes

A number of questions to clarify the content of this page.

Does console-conf, if it runs, add a system user? This page starts by saying it adds a user, but is not specific. That needs to be clarified for the rest of this page to make sense.

Next, “To create a system user on these systems, …”. Just to be clear, this is to create a system user after the device has already been instantiated and gone through the firstboot process, correct? Make this clear.

Again, there is ambiguity in, “A managed system already has a user account whereas an unmanaged system does not. A system user cannot typically be added to a system that is already managed.” Distinguish between a user account and a system user account.

If you use auto-import.assert to add a system user, is the device now a “managed” device? Can you add a second system user to the same device using the same procedure? All these details should be right at the top of this page so the reader knows what’s coming.

Oh, “Some systems , however, suppress console-conf and its user creation.” Why? It might be informative to tell the reader why some systems suppress this step.

Hi @degville,
I have a few feedback because of the latest improvements;
a) There are two tracks defined for make-system-user snap now; 20 and 22. If the host is Ubuntu 20.04, then users needs to install with snap install make-system-user --classic --channel=20/stable and if the host is Ubuntu 22.04 then snap install make-system-user --classic --channel=22/stable.

b) There is no need to use sudo while running the make-system-user snap.

Thanks,
Bugra

Thanks for the new details - I’ve now updated the doc.

1 Like

@degville FYI, make-system-user does not seem to work with Snapcraft v7. Confirmed by multiple users. Current workaround is to downgrade snapcraft to v6. I personally tested make-system-user version 12 (rev27) from 22/stable.

See this post in the snapcraft forum and the Github issue for make-system-user for details. Seems to be an issue with snap store credentials being handled differently by snapcraft now.

Thanks so much for letting me know. I just tested it and get the same error. I’ve added a comment in the document and will keep an eye on the issue so I can update the doc when it’s resolved.

@degville for reference, the make-system-user snap should probably be considered deprecated and updating it to work with snapcraft 7 will probably not be happening. The Field team is working out what we should do in the future for creating system-user assertions.

1 Like

Is there an update to this? What is the recommended way to create a user assertion now? Doing it through the serial vault only allows password auth, not SSH. As an enterprise customer, having tools taken away with no replacement is frustrating.

We were just talking about this yesterday!

There is indeed a new way to do this – we’re still working on cleaning up all the old methods in the documentation, but you can refer to this page for an updated set of instructions – the new way leverages a new --chain flag to the snap sign command to concatenate all the required keys to the system-user assertion file.

edit

I see now that this page is different from the one I commented on yesterday; this page is already updated to specify the new method.

Note that the Serial Vault method only really applies to Core18 deployments and should not be used for Core20 or Core22 devices. This new method should work on both Core20 and Core22 devices. I do not believe there are any dependencies on model assertion revision for any system-user assertion features.