Turning on and off the Public Device URL from code on the device

Hey team Balena,

I was poking around your api documentation trying to find a way to turn on and off the public device URL. The purpose of this would be to turn on an off access programmatically to add a layer of just-in-time security to a devices remote access.

I have set device tags in the past using this bit of python code:

def set_device_tag(self, name, value):
    logging.debug(f'set_device_tag: {name}, {value}')
    if type(value) == float:
        value = f'{value:.1f}'
    else:
        value = str(value)

    try:
        self.balena.models.tag.device.set(self.env['BALENA_DEVICE_UUID'], str(name), value)
    except Exception as e:
        logging.error("Tag set seems to have failed")
        handle_process_exception(e, debug=True)
        raise ConnectionError

def get_device_id(self):
    try:
        proc1 = subprocess.Popen("""curl --connect-timeout 10 --max-time 30 -sSL "$BALENA_API_URL/v3/device?\$select=id,uuid&\$filter=uuid%20eq%20'$BALENA_DEVICE_UUID'" -H "Authorization: Bearer $BALENA_API_KEY" | jq '.d[0].id'""",
                                 shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                 close_fds=True, encoding='UTF-8')
        stdout, stderr = proc1.communicate()
        if proc1.returncode != 0:
            raise ConnectionError
    except subprocess.CalledProcessError as e:
        handle_process_exception(e)
        raise ConnectionError
    if stdout and not stdout == '':
        self.balena_device_id = stdout.strip('\n')
        return
    # """curl -sSL "$BALENA_API_URL/v3/device?\$select=id,uuid&\$filter=uuid%20eq%20'$BALENA_DEVICE_UUID'"
    # -H "Authorization: Bearer $BALENA_API_KEY" | jq '.d[0].id'"""

I see the in is_web_accessible var the api docs for the deivce, but I can’t find anywhere I could possibly set that.

Thanks,
-Thomas

Hi @taclog, as far as I’m aware we don’t have a special API endpoint/method to set or toggle the public URL.

There is a way around this by using Pine queries (pine is our backend engine, handling our backend resources), but this will only work for our NodeJS SDK.
Here is a snippet:


  const { getSdk } = require('balena-sdk')
  const balena = getSdk({
    apiUrl: "https://api.balena-cloud.com/"
  })

  await balena.auth.loginWithToken('AUTH_TOKEN')
  await balena.pine.patch({
    resource: 'device',
    id: DEVICE_ID,
    body: {
      is_web_accessible: true
    }
  })

AFAIK you can’t run pine queries from our python SDK. This doesn’t seem right to me so let me get back to you once I talk to the python guys, as I might be misreading the docs.

Actually, for the NodeJS there are specific methods to enable/disable publicURL:

Thanks @tmigone that’s very helpful.

I am a bit new to node.js but I tired to throw something together.
Could I run this from python by pathing together two simple node scripts?

Add this to my Dockerfile.template

RUN apt-get update && install -y \
nodejs npm && \
apt-get clean && \
npm install --save balena-sdk
WORKDIR /usr/src/app
RUM mkdir /usr/src/app/balena

Then setting up a node script like this:

const { getSdk } = require(‘balena-sdk’);

const balena = getSdk({
apiUrl: “https://api.balena-cloud.com/”,
dataDirectory: “/usr/src/app/balena”
});

(async () => {
await balena.auth.loginWithToken(process.env.BALENA_API_KEY);
await balena.models.device.disableDeviceUrl(process.env.BALENA_DEVICE_UUID);
console.log(“Url turned off”);
})();

And call it from python with: os.system('node turnOffUrl.js')

Does that seem like it would work? Can you log into the sdk with the BALENA_API_KEY env var from an application on a device?

This works, I just tested it. @tmigone Thanks for your help!

-Thomas

1 Like

Also for other poeple that find this the python sdk also supports this:

Thank you for sharing how it worked for you @taclog