On-Prem Model Service¶
The Snap Store’s Model Service is the device serial provisioning service that is intended to supersede the Serial Vault. While the Serial Vault had to be deployed separately in on-prem scenarios, the Model Service is packaged into the Snap Store Proxy.
The Model Service is currently only available in air-gapped mode. When operating in online mode, the Proxy can forward serial requests made by devices to the online Serial Vault or the online Model Service.
The following requirements need to be met to use the on-prem Model Service:
A PKCS#11-compatible Hardware Security Module (HSM) or Smart Card.
The PKCS#11 module / shared library for the hardware. e.g.
opensc-pkcs11.so
The Snap Store Proxy host machine must run Ubuntu 22.04 (Jammy) with the
p11-kit
andgnutls-bin
packages installed.Revision 99 of
snap-store-proxy
and revision 28 ofstore-admin
, or newer.
The supported way to manage models, signing keys, and serial policies in the on-prem Model Service is via the store-admin
snap.
HSM-based key management and signing¶
Currently, only PKCS#11-compatible hardware can be used for key generation and signing device serial requests. Software key generation and signing are not supported, with the exception of using a software PKCS#11 emulator such as SoftHSMv2.
p11-kit is used as an abstraction layer for hardware-agnostic PKCS#11 support.
Setup¶
This section assumes that the Snap Store Proxy has been installed and configured in air-gapped mode and that the Brand Store has been imported, as per the installation steps in the Offline store section. On Brand Store import, the Brand account and admin user will be automatically set up in the Model Service.
Store admin token¶
To login using store-admin
to the Model Service, set the STORE_ADMIN_TOKEN
environment variable, obtained after running store-admin export store
:
$ store-admin export store myDeviceViewStoreID --key <model-assertion-account-key-sha3-384>
...
Creating the export archive...
Store data exported to: /home/ubuntu/snap/store-admin/common/export/store-export-myDeviceViewStoreID-20240109T123041.tar.gz
Admin token exported to: /home/ubuntu/snap/store-admin/common/export/store-export-myDeviceViewStoreID-20240109T123041.macaroon
Admin token usage:
export STORE_ADMIN_TOKEN=$(cat /home/ubuntu/snap/store-admin/common/export/store-export-myDeviceViewStoreID-20240109T123041.macaroon)
As outlined in the air-gapped store setup instructions, the account-key assertion for the key(s) used to sign the model assertion(s) must also be exported and pushed to the Proxy. Include them in the store export bundle by specifying the --key
flag for each account-key SHA3-384.
Import the store bundle on the Proxy, then login to the air-gapped store from the admin machine:
$ store-admin login --offline <http-location-of-the-store> <same-email-as-in-export-store>
Exchanging store admin macaroon for a publisher gateway admin macaroon...
Access via the store-admin
snap should now be set up for the Model Service.
p11-kit server¶
On the Proxy host, start the p11-kit server.
Obtain the pkcs11:
identifier using p11tool
, e.g.:
$ p11tool --provider "/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so" --list-token-urls | sed 's/;token=.*//g'
pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0300972
Start the server, ensuring that the Unix socket runs under /var/snap/snap-store-proxy/common/pkcs11
. See the p11-kit documentation for other configuration options.
$ sudo p11-kit server --provider /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so "pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0300972" -n "/var/snap/snap-store-proxy/common/pkcs11" -f
P11_KIT_SERVER_ADDRESS=unix:path=/var/snap/snap-store-proxy/common/pkcs11; export P11_KIT_SERVER_ADDRESS;
P11_KIT_SERVER_PID=26963; export P11_KIT_SERVER_PID;
Restart the Model Service (this needs to be done each time the p11-kit server is restarted):
snap restart snap-store-proxy.snapmodels
Snap Store Proxy configuration¶
Set the HSM label and pin in the Proxy snap:
$ p11tool --list-tokens
Token 0:
Label: SmartCard-HSM (UserPIN)
...
$ sudo snap-proxy config proxy.hsm.token-label="SmartCard-HSM (UserPIN)"
$ sudo snap-proxy config proxy.hsm.token-pin=74656
Model Service CLI Usage¶
The Model Service management CLI is provided by the store-admin
snap.
Create a signing key on the HSM¶
Create a signing key using store-admin
for signing serial requests:
$ BRAND_ACCOUNT_ID=<brand-account-id> store-admin create key test-key
Generating a signing keypair on the proxy's HSM. This may take some time.
Signing key 'test-key' created.
$ store-admin list keys
Name SHA3-384
-------- ----------------------------------------------------------------
test-key PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see
The BRAND_ACCOUNT_ID
environment variable only needs to be set once; it will be stored and automatically used subsequently.
Note
If a 4096-bit RSA key takes more than 15 seconds to generate on your hardware
(e.g. Nitrokeys), then you would first have to extend the Proxy’s internal service timeout:
sudo snap-store-proxy config internal.publishergw.snapmodels.read-timeout={timeout-in-seconds}
The key needs to be registered with the online Snap Store before it can sign serials:
$ store-admin register-key PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see
Registering signing key with the global Snap Store...
...
Key PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see registered.
The account-key assertion needs to be pushed to the air-gapped Proxy. First, export the assertion:
snap known --remote account-key public-key-sha3-384=PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see > test-key.assert
Copy the assertion to the Snap Store Proxy’s $SNAP_COMMON
directory on the Proxy host, then push the assertion to the Proxy:
sudo snap-proxy push-account-keys /var/snap/snap-store-proxy/common/test-key.assert
Note
Repeat these steps to add new account-keys to the proxy, if any are created after the initial store import and are used to sign new model assertions.
Add a model in the Model Service¶
To sign the serial requests for devices of a model, the model name as configured in the Model Service must match that in the model assertion:
$ store-admin create model model-a
API key (alphanumeric, `pwgen 40` for options): model-a-apikey
Model 'model-a' created.
Configure a serial signing policy¶
The serial policy for a model identifies the signing key that the Model Service should use to sign serial requests for that model. To configure the Model Service to sign model-a
device serial requests with the earlier-created test-key
:
$ store-admin create serial-policy
Model to attach the serial signing policy: model-a
Signing key to use (SHA3-384): PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see
Model 'model-a' configured to sign serials with key 'PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see'.
$ store-admin list models
Name API key Active serial signing key
------- -------------- ---------------------------
model-a model-a-apikey test-key
The key can be changed by creating a new serial policy revision for the model:
$ store-admin create key new-key
...
$ store-admin list keys
Name SHA3-384
-------- ----------------------------------------------------------------
test-key PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see
new-key 4aPBeXLPu2xoriNr-6e1Ja448wC7IAS86Ijs6r0sHWiZ6Y9WYprxeWkK7HETCyh6
$ store-admin create serial-policy
Model to attach the serial signing policy: model-a
Signing key to use (SHA3-384): 4aPBeXLPu2xoriNr-6e1Ja448wC7IAS86Ijs6r0sHWiZ6Y9WYprxeWkK7HETCyh6
Model 'model-a' configured to sign serials with key '4aPBeXLPu2xoriNr-6e1Ja448wC7IAS86Ijs6r0sHWiZ6Y9WYprxeWkK7HETCyh6'.
$ store-admin list models
Name API key Active serial signing key
------- -------------- ---------------------------
model-a model-a-apikey new-key
Device gadget snap¶
The prepare-device
hook in the device gadget snap should be configured with the proxy host URL and the model API key defined in the Proxy Model Service.
On first startup, a model-a
device should request and obtain a serial assertion from the Snap Store Proxy:
$ snap model --serial --assertion
type: serial
...
model: model-a
...
sign-key-sha3-384: PPkB6XcYjkxzA9c6dXsaM0sg9r_d5DZ2kDYvWPTeuSXofXGzMDBt7DoD_Xiw3see
...