Automating preauthorization using the API

I’ve set up a cloud function in Firebase Functions that my device triggers by publishing to a pubsub topic. The cloud function makes the fetch request to the preAuth endpoint;

https://hosted.mender.io/api/management/v2/devauth/devices'.

The plan being that my device manufacturer would boot the device to test it before shipping to the customer. This sets the device up to receive software updates as soon as the customer receives it and boots it again for their use.

In my logs I get the response from the POST request in the promise callback as shown in the API example;

body: {"domain":{"domain":null,"_events":{},"_eventsCount":3,"members":[]}}

The problem is I don’t see the device show up in any of the hosted Mender categories(Pending, Preauthorized or rejected).

if anyone can help with what I may be missing it would be appreciated.

Thanks

Hi @bradw, for preauthorization, you need to do a POST to the API endpoint with the identity data and public key of the device. See this link for full details.
https://docs.mender.io/api/#preauthorize
Drew

Hi @drewmoseley,

That’s what I did from my Firebase Functions backend. Here is the code. I got the response I posted above back but nothing showed up under my hosted Mender dashboard.

const fetch = require('node-fetch');
const functions = require('firebase-functions');

module.exports = functions.pubsub.topic('menderPreauthorize').onPublish(async (message) => {
    const deviceId = message.data ? Buffer.from(message.data, 'base64').toString() : null;
    let res
    if (deviceId) {
      const sn = deviceId.split('y')[1]
      res = await fetch ('https://hosted.mender.io/api/management/v2/devauth/devices',
        {
           method: 'POST',
           body: {
             "identity_data": {
                "sku": deviceId,
                "sn": sn
              },
              pubkey: process.env.MENDER_PUBKEY
            },
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              'Authorization': process.env.MENDER_API_KEY
          }
       })
       .then((res) => {
          console.log(`body: ${JSON.stringify(res.json())}`)
          return res.json
        })
        .catch((err) => {
           console.log(`Error: ${JSON.stringify(err)}`)
           return err
        })
    } else {
      res = 'deviceId was null.'
    }
    return res
 })

@merlin can you help here?

I’m still hung up on this. It’s one of the last things I wanted to have handled before sending the image over to my prototype manufacturer.

I don’t see anything obviously wrong with this but it’s hard to know if the env settings are formatted correctly or if the other data types are properly converted to strings before providing them to the API. Is there any debug you can enable to see the exact contents of the API call?
Drew

Environment variables get plugged in through Google Cloud’s dashboard and there is an output log for errors, success, console.log, etc.

This is what I got back as a response. It suggests to me that the request succeeded but the information there isn’t particularly useful and the lack of anything in my Hosted Mender dashboard would suggest that it wasn’t.

@tranchitella any thoughts on this?

I added a couple of console.log for the public and api keys. It looks like they’re getting passed through OK. I had also checked that the values coming in for identity_data with console.log earlier

I updated my code to look a little more like the example in the API reference.
const fetch = require(‘node-fetch’);
const functions = require(‘firebase-functions’);

module.exports = functions.pubsub.topic('menderPreauthorize').onPublish((message) => {
  const deviceId = message.data ? Buffer.from(message.data, 'base64').toString() : null;
  let response
  if (deviceId) {
    const sn = deviceId.split('y')[1]
    const inputBody = {
    "identity_data": {
        "sku": deviceId,
        "sn": sn
      },
      "pubkey": process.env.MENDER_PUBKEY,
    };
    const headers = {
      'Content-Type':'application/json',
      'Accept':'application/json',
      'Authorization':process.env.MENDER_API_KEY
    };
    response = fetch ('https://hosted.mender.io/api/management/v2/devauth/devices',
      {
        method: 'POST',
        body: inputBody,
        headers: headers
      })
      .then((res) => {
        console.log(`body: ${JSON.stringify(res)}`)
        return res.json()
      })
      .catch((err) => {
        console.log(`Error: ${JSON.stringify(err)}`)
        return err
      })
  } else {
    response = 'deviceId was null.'
  }
  return response
})

It returned a different response from the then block;
Screen Shot 2021-02-02 at 2.45.33 PM

But there is still nothing showing up in the Hosted Mender dashboard.

Hi @bradw
Would it be possible that you translate this into copy-pastable curl commands?
This would make reproducing the issue it much simpler.

Be Well,
Alan

When I follow the Using the APIs tutorial in the docs and reach the “Verify you can call the APIs” section, after calling;

curl -H "Authorization: Bearer $JWT" $MENDER_SERVER_URI/api/management/v1/useradm/users | jq '.'

I get:

zsh: command not found: jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   229  100   229    0     0    190      0  0:00:01  0:00:01 --:--:--   190
(23) Failed writing body

It looks like you don’t have the “jq” utility installed.

Drew

OK, after I install the jq utility. I get the following error;

{"error":"failed to decode preauth request: cannot decode public key","request_id":"3d8a6687-8d31-4875-b96e-2448dcb873d5"} **%**

When I call;

curl -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" -X POST -d "{ \"identity_data\" : $DEVICE_IDENTITY_JSON_OBJECT_STRING, \"pubkey\" : \"$DEVICE_PUBLIC_KEY\" }" $MENDER_SERVER_URI/api/management/v2/devauth/devices

OK. That would seem to suggest that the DEVICE_PUBLIC_KEY environment variable is not formatted properly for our API. When using the example from our docs, the following command is used to format it:

DEVICE_PUBLIC_KEY="$(cat keys-client-generated/public.key | sed -e :a -e ‘N;s/\n/\n/;ta’)"

Can you compare yours to something generated as above to see if there are any differences?
Drew

When I run that command from my /mender directory, which contains /keys-client-generated/public.key, to set it I get;

{"error":"failed to decode preauth request: pubkey: non zero value required","request_id":"f4666836-0676-40ae-9c22-906207803cff"} **%**

And I enter $MENDER_PUBLIC_KEY and indeed it has no value set.

It seems that something is wrong with the public.key file. I just ran the setup from scratch and could not replicate your issue. Can you review the public.key file and make sure it’s correct? The temp one I just generated is as follows:

-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA6t3sewLzVf8uVLl0z0pS
DcbrHA4/h7exXE2/oQqwuYgBy5RBVTeOpx1YU4mf5yyFzWXxlwVNIcQH3GZgelv5
+hBWZZsvbmYgRJTy7cNfQvw7Jit07g+EzOxFwS1SP1gEwuM8ZMDhlim6OiSdl1m+
XipnpeXKMzgG2mAdnT5k/13IZIZCq3FVMgIydP7k50PMqmcrR1KycZ9rzl+X333k
1vH6lee2MYDMZmLCuf0oNHapBxGnWqPST4X2LGditREpVEbqt1jUMu68kFHS2ctN
+C410WfFeA5XbtEpTYOnVoSKMd898urv/WHxsILbRf1VOeDP2g91YOP0rzkl4RVc
kDjB8vLwNIr6AOPeId6KaQK98rd7wjTqZpJXK/XlUyfqs01xurqSDN/1/Yk6sSnf
yrbN89Yid8SCS3lx23cByqCvL4+chPgMjo8w0uxkg2a9mzzuJ+q7hHDSKcCLflO9
CvfM7T1BYGzMSO2oH4YiaQAgueff8gmzkpkXTfJRVqMFAgMBAAE=
-----END PUBLIC KEY-----

My line breaks don’t look like this but otherwise it looks the same.

OK. Can you run just the following command to see what the sed command is producing?

cat keys-client-generated/public.key | sed -e :a -e ‘N;s/\n/\n/;ta’

In my case (with different key than I posted above) it looks like the following:

$ cat keys-client-generated/public.key | sed -e :a  -e 'N;s/\n/\\n/;ta'
-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtWoRQOJ02lraa3hjBnsA\n8gcZL1CWovNVX+tjadl0rX+/LPaVJa6mNRKMY7JXyIiDhL+hm71S3SSWu9iADmDn\nPEfJ9WDkZb60fEOCI69zTmSAkeuETrJyetBk2018GiX9h6FlkFe6tZi8G1W+Ns9C\nLQiH9q8wPSDzIfA+nBvd+hKZn7oqXrIpVxjHoDXqryFOa8C6LLy3Rf0JDAuMJelh\n+1nO7ua3RqckklbxaHgO6QMDozEmEotApW9BvaQOtEVO1hfLm1IC/4DNBUXWRCan\nHaTnba0RIztiJgqeO5dPH82SW32EZ0bxUiITGGxeaqkf+TJyEbN49axqDi+J+wn+\n6sf0PAxHWY1feK/oc0LwqCx6ywmdilyEn4KEsK+dZ0GsY/nPqXeGDLuCcKRC4R1w\nvHghUlXfCM6duI83ItV6P+mW/JyQVn1H5wXkDP/yGAd8Trmvpn8dUZQtTI3/doLJ\n/GhTf/HU6ei+SGEoiIwHT7y9iXwGB2EgVo7jmT3BsMK1AgMBAAE=\n-----END PUBLIC KEY-----

What is your host OS? I wonder if the newline format from your sed implementation or some such is different.

Drew