This is directory that contains source code responsible for CLI for user to interact with server, broker and devices.
- Docker
For running on host:
- Python 3.6
- Charm Crypto (See Running tests section for instructions)
docker pull martinheinz/iot_cloud_cli:latest
docker run -it --network host martinheinz/iot_cloud_cli
Note: this is only needed when running on host (not using Docker)
To install CLI
- Create Python venv (Python 3.x required; from
IoT-Cloud
directory):
python3 -m venv venv
- Activate venv:
source ./venv/bin/activate
- install CLI (from
IoT-Cloud
directory):pip install --editable .
- Test if it's working:
iot-cloud-cli --help
Expected output:
Options:
--debug / --no-debug
-b, --broker TEXT
-p, --port INTEGER
--help Show this message and exit.
Commands:
device
user
These are example sequences of commands to show how to perform various tasks using CLI
-
Register to Server by accessing
https://localhost/login
-
Set Server
access_token
returned by registration:export ACCESS_TOKEN=<value>
-
Register to AA by accessing
https://localhost/attr_auth/login
-
Set AA
access_token
returned by registration:export AA_ACCESS_TOKEN=<value>
-
Set AA username to that is used in Server (your GitHub username) :
iot-cloud-cli user attr-auth-set-api-username <GitHub username>
-
Set broker URL on
MQTT_BROKER
variable in./client/cli.py
(or use-b
option in following commands) -
Register to broker
iot-cloud-cli user register-to-broker <your-password>
broker_id
andbroker_password
are added tokeystore.json
-
Initialize per-user global hashing and encryption keys
iot-cloud-cli user init-global-keys
-
Create new device type
iot-cloud-cli user create-device-type <some-description>
- Save the device type ID from response for future use
- example ID:
"type_id": "3d5a490c-42da-43c4-abe8-b687c49c51b5"
-
Create device
iot-cloud-cli user create-device <type_id> <device_name> <device_pass>
- Device, ACLs and association with user are created on server
- Client saves device record in
keystore.json
(device_id
and client generated device keys) - Save
device_id
,device_name
anddevice_pass
for future use
-
Initialize device client
iot-cloud-cli device init <device_id> <device_pass> <user_broker_id> <list_of_action_names>
- example:
iot-cloud-cli device init 46 test_pass 11890454 On Off
- Device record is created in
data.json
as well data for integrity checking (column seeds, bounds of inserted rows and types of encryption used in columns)
-
Connect device to broker
- Follow steps in
node-red
setup readme
- Follow steps in
-
Start exchange of shared key with device
iot-cloud-cli user send-key-to-device <device_id>
- users public key is send to device
- public and private keys are temporarily saved to
keystore.json
- device receives user public key, generates own key-pair and performs exchange (generates shared key), which is saved to
data.json
- device sends public key to server for user to retrieve
- device key-pair is wiped
-
Retrieve device public key
iot-cloud-cli user retrieve-device-public-key <device_id>
- user retrieves device public key and performs key exchange
- shared key is saved to
keystore.json
and user key-pair is wiped
-
Perform key setup for ABE keys
iot-cloud-cli user get-attr-auth-keys
- Key setup is performed by server - public key and master key are generated by AA, public key and master key are saved at AA, public key is send to user
- user saves public key to
keystore.json
-
Request private ABE key for device
iot-cloud-cli user attr-auth-device-keygen <device_id> <attr_list>
- example:
iot-cloud-cli user attr-auth-device-keygen 46 U-11890454 D-46 D-46-GUEST
where11890454
is auser_broker_id
, also please use only capital letters in attributes, because when parsing policies all letters are evaluated to caps - Device private key is generated by AA using user master and public keys saved at AA and provided attribute list and then sent to user
- Device private key is saved to users
keystore.json
together with attribute list
-
Generate and send all encryption keys to device
iot-cloud-cli user send-column-keys <user_id> <device_id> <policy>
- example:
iot-cloud-cli user send-column-keys 11890454 46 "(u-11890454 OR d-46 OR d-46-GUEST)"
, Note: policy here evaluates to((U-11890454 or D-46) or D-46-GUEST)
, so if you previously used attributes with lowercase chars, then you won't be able to decrypt. - user client generates all column keys and encrypts them together with ABE device private key using shared key and sends them using MQTT broker to device
- device retrieves encrypted keys, decrypts them and saves them in
data.json
-
User sets device actions on server
iot-cloud-cli user set-action <device_id> <action_name>
- example:
iot-cloud-cli user set-action 46 On
andiot-cloud-cli user set-action 46 Off
-
Now user can trigger device action
iot-cloud-cli user trigger-action <device_id> <device_name> <action_name>
- Note: there is also optional
--real/--fake
parameter (--real
by default) that allows user to send fake action - user client computes Blind Index of
device_name
andaction_name
and sends it to server - server looks up device and action using Blind Index and sends message using MQTT broker
- device receives message, decrypts it and resolves whether it is real of fake
- if it's real, action is triggered (see
node-red
debug output)
-
User can also send raw JSON message
iot-cloud-cli user send-message <user_id> <device_id> <JSON string>
- example:
iot-cloud-cli user send-message 11890454 46 "{\"action\": stuff}"
- Message is sent directly over broker and encrypted using shared key
-
To send fake data from device to server, click
send_add_fake_tuple
inject node innode-red
flow- When node is clicked device generates fake tuple using integrity data - upper index bound and seed are used to generate fake values, these values are then encrypted using column keys. Also correctness hash and tuple ID (positive) Blind Index are created
- Generated tuple is sent to server over MQTT, where it is saved
-
To remove fake data by device, click
remove_add_fake_tuple
inject node innode-red
flow- Here happens same thing as with
send_add_fake_tuple
, only difference is that device uses lower index bound for tuple values and tuple ID - This generated tuple is send to server over MQTT, which deletes it
- Here happens same thing as with
-
To send real device data from device, click
send_save_data
inject node innode-red
flow- Data (parameters of node) are encrypted and together with tuple ID (negative) and correctness hash are send to server over MQTT
- Server saves received payload
-
To retrieve device data
iot-cloud-cli user get-device-data <user_id> <device_id> <device_name>
- users client computes device name Blind Index and sends data request to server
- server returns all device data
- users client sends fake tuple information request to device over MQTT
- device returns fake tuple information encrypted with shared key
- users client decrypts fake tuple information and uses it to generate expected fake records
- users client decrypts data from server
- users client divides fake and real records using tuple ID
- users client verifies presence of all expected fake records
- users client verifies integrity of each row using correctness hash attached to each row
- users client outputs decrypted real data and info about integrity checks
-
To retrieve device data using range query
iot-cloud-cli user get-device-data-by-num-range <user_id> <device_id> <device_name> --lower <lower_bound> --upper <upper_bound>
- Same as previous option, only difference is that server uses encrypted bounds to make range query and returns only data that satisfy the range
- To create scene
iot-cloud-cli user create-scene <scene_name> <scene_description>
- users client generates Blind Index for
scene_name
- users client encrypts
scene_name
andscene_description
- users client sends data to server which saves it
- To add action to scene
iot-cloud-cli user add-scene-action <scene_name> <action_name> <device_id>
- users client generates Blind Indices for
scene_name
andaction_name
and sends them to server - server looks up scene and action by Blind Indices and adds this action to scene
- Note: if you want to create another device to trigger actions of multiple devices, you will have to copy whole project and repeat whole process of setting device. As an alternative you can add multiple actions of single device to scene to see multiple actions being triggered
- To trigger scene
iot-cloud-cli user trigger-scene <scene_name>
- user client generates Blind Index for
scene_name
and sends it to server - server looks up scene and sends messages over MQTT to all devices with actions associated with scene
- rest is same as when triggering one action
- to see actions being triggered see
node-red
debug console - Note: it's also possible to use
--fake
option to make fake trigger of scene
- Note: to have multiple users on same device, you will have to copy project or temporarily remove existing
keystore.json
when performing actions as other user - To authorize user
iot-cloud-cli user authorize-user <device_id> <device_name> <other_user_id>
- user client generates Blind Index for
device_name
and sends it to server together withother_user_id
- server creates ACLs for user being authorized and for device, as well as association object and saves them
- To revoke user
iot-cloud-cli user revoke-user <device_id> <device_name> <other_user_id>
- user client generates Blind Index for
device_name
and sends it to server together withother_user_id
- server removes ACLs and association object for user being revoked and for device
- Setup device
- First owner needs to generate private key for authorized user
iot-cloud-cli user attr-auth-keygen <auth_user_api_username> <device_id> <attr_list>
- private ABE key with attributes in
attr_list
is generated for user withauth_user_api_username
to query data from device withdevice_id
, the key is stored at AA, so the user can retrieve it
- Next, authorized user needs to setup the device keys
iot-cloud-cli user setup-authorized-device <device_id> <path_to_owners_public_ABE_key> <device_blind_index_key> --token <authorized_users_aa_access_token>
- authorized users client adds record for device with
device_id
intokeystore.json
. This record also includes ABE public key and device Blind Index key provided by owner as well as private key generated by owner, which is retrieved from AA
- First owner needs to generate private key for authorized user
- Trigger action
iot-cloud-cli user trigger-action <device_id> <device_name> <action_name> --no-owner
- Note: to make it possible for authorized user to trigger action owner has to share action names
- To query device data
iot-cloud-cli user get-device-data <authorized_user_id> <device_id> <device_name> --no-owner --token <authorized_users_access_token>
- User can trigger fake actions using
iot-cloud-cli user trigger-action <device_id> <device_name> <action_name> --fake
- here device can distinguish between real and fake action by decrypting
additional_data
field added by users client, only if the value isreal
action is triggered
- User can schedule fake actions
iot-cloud-cli user schedule-fake-actions <device_id> <device_name> <start_time> <end_time> <number_of_actions> <actions_name_list>
- example:
iot-cloud-cli user schedule-fake-actions 46 test_device '2019-04-06 18:29:00' '2019-04-06 18:30:00' 3 On Off
- Scheduler sends specified number of fake actions at random times in the time range, each time choosing random action from supplied list