Jumpnow Technologies

home code consulting contact

Working with a Mender CLI

16 Feb 2018

I came across a useful Python utility for working with the Mender server from a command line.

It simplifies uploading mender artifacts from a headless build server.


I am testing with a collection of boards running a mender server locally

The mender server is from the 1.3.x branch using the standard install instructions with two small exceptions.

  1. I have dynomite logging disabled as per this mailing list thread and patch from Mender. Without it the dynomite docker volume gets big really fast.

  2. I changed the Mender keygen script to add a SubjectAltName section to the certs it generates. This quiets warnings from Python. The keygen patch is not necessary but explains why you might see more warnings then I am showing in the examples. The patch is at the bottom of this post.


Typical python requests module stuff, I exported a REQUESTS_CA_BUNDLE environment variable so local certs are accepted. I pointed it at the server.crt generated by the keygen script. The same server.crt used in the mender recipe and installed onto the devices.

~$ export REQUESTS_CA_BUNDLE=~/mender/mender-server/production/keys-generated/certs/server.crt

Using the mender-backend cli

I cloned the mender-backend-cli and am running it from there. I didn’t bother with the install script.

I already have a user account on the server, so I am logging in with that

~/mender/mender-backend-cli$ ./mender-backend -s https://fractal.jumpnow user login -u scott@jumpnowtek.com -p <some-password>
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): fractal.jumpnow
INFO:root:request successful
   ... <long token here>

That command created a usertoken file in the local directory that gets used automatically by later commands.

scott@fractal:~/mender/mender-backend-cli$ ls -l usertoken
-rw-rw-r-- 1 scott scott 773 Jan  7 11:29 usertoken

You can use –help for any command.

~/mender/mender-backend-cli$ ./mender-backend --help
usage: mender-backend [-h] [-d] [-s SERVICE] [-n] [--cacert CACERT]
                      [-u USER_TOKEN]

mender backend client

positional arguments:
    deployment          Deployments
    artifact            Artifacts
    admission           Admission
    authentication      Device Authentication
    inventory           Inventory
    user                User commands
    device              Device
    client              Simulate a mender client

optional arguments:
  -h, --help            show this help message and exit
  -d, --debug           Enable debugging output (default: False)
  -s SERVICE, --service SERVICE
                        Service address (default: https://fractal.jumpnow)
  -n, --no-verify       Skip certificate verification (default: False)
  --cacert CACERT       Server certificate for verification (default: )
  -u USER_TOKEN, --user-token USER_TOKEN
                        User token file (default: usertoken)

Every command requires the -s SERVER and the default value pointing to Mender’s server is not very useful so I changed the default to my local server by editing this file


I will switch the code to using an environment variable later, but for the following examples this is why the commands I am showing do not have a -s SERVER specified.

I will show a few commands.

Here is a list of devices.

scott@fractal:~/mender/mender-backend-cli$ ./mender-backend inventory device list
INFO:root:loading user token from usertoken
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): fractal.jumpnow
5a54f15cd502db00014b77c3 (type: beaglebone, updated: 2018-02-10T18:54:43.616Z)
5a5d1f42d502db0001689ab1 (type: duovero, updated: 2018-02-10T18:55:07.918Z)
5a772d02d502db0001bbcfcd (type: odroid-c2, updated: 2018-02-10T18:54:53.118Z)
5a778a68d502db0001bbcfd3 (type: wandboard, updated: 2018-02-10T18:52:38.75Z)
5a778a5cd502db0001bbcfd1 (type: wandboard, updated: 2018-02-10T18:55:12.87Z)

I built a new mender-test-image with Yocto.

I then created a signed artifact of that image using the sign-mender-image.sh script

~/bbb-mender/meta-bbb/scripts$ ./sign-mender-image.sh
Creating artifact using the following parameters
TMPDIR: /oe7/bbbm/tmp-rocko
Artifact name: bbg-test-2
Private key: /home/scott/bbb-mender/mender-keys/private.key
Public key: /home/scott/bbb-mender/mender-keys/public.key
Source: /oe7/bbbm/tmp-rocko/deploy/images/beaglebone/mender-test-image-beaglebone.ext4

Running mender-artifact to create signed artifact

Wrote artifact to /home/scott/bbb-mender/upload/bbg-test-2-signed.mender
Checking artifact

Mender artifact:
  Name: bbg-test-2
  Format: mender
  Version: 2
  Signature: signed and verified correctly
  Compatible devices: '[beaglebone]'

    Type:   rootfs-image
      name:     mender-test-image-beaglebone.ext4
      size:     1073741824
      modified: 2018-01-09 17:32:38 -0500 EST
      checksum: 6789a9fd29595b5b2faa31daffa97fff550cc8124c11fd9e8f0db2be070c653b

Result from mender-artifact read: 0

So now I can use mender-backend to upload the artifact

~/mender/mender-backend-cli$ ./mender-backend artifact add \
    -n bbg-test-2 \
    -e 'cli test' \
INFO:root:loading user token from usertoken90 - 00:00:00
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): fractal.jumpnow
created with URL: ./management/v1/deployments/artifacts/5364e050-390b-41f8-8b8c-9edf9f197e4d
artifact ID:  5364e050-390b-41f8-8b8c-9edf9f197e4d

And now to start a deployment to the BeagleBone Green device

$ ./mender-backend deployment add \
    -a 'bbg-test-2' \
    -n test \
    -e 5a54f15cd502db00014b77c3 
INFO:root:loading user token from usertoken
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): fractal.jumpnow
created with URL: ./management/v1/deployments/deployments/fab35a4c-4399-443d-a706-2756fb9027ad
deployment ID:  fab35a4c-4399-443d-a706-2756fb9027ad

If you wanted to deploy to multiple devices at one time you would use the -e parameter multiple times.

So for example deploying a previously uploaded artifact wandq-test-5 to both wandboards in my test network

~/mender/mender-backend-cli$ ./mender-backend deployment add \
    -a wandq-test-5 \
    -n wandboards  \
    -e 5a54b487d502db00014b77b5 \
    -e 5a563257d502db00014b77c7

keygen patch

This keeps both python and browsers from complaining about the missing SubjectAltName entry from the certs generated by the mender-server keygen script.

The details on how to add SubjectAltName in a one-liner came from this StackExchange post.

Here’s the patch.

Now when running the keygen script instead of this command

CERT_API_CN=fractal.jumpnow CERT_STORAGE_CN=fractal.jumpnow ../keygen

I am using this instead

CERT_API_CN=fractal.jumpnow CERT_API_SAN=DNS:fractal.jumpnow CERT_STORAGE_CN=fractal.jumpnow CERT_STORAGE_SAN=DNS:fractal.jumpnow ../keygen