nrfcloud-utils 3.2.1__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/PKG-INFO +3 -3
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/pyproject.toml +3 -3
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/cli_helpers.py +14 -2
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/device_credentials_installer.py +57 -11
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/nrf93_onboard.py +3 -1
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/nrf_cloud_device_mgmt.py +4 -3
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/nrf_cloud_diap.py +2 -1
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/nrf_cloud_onboard.py +9 -7
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/LICENSE.txt +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/README.md +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/__init__.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/ca_certs.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/claim_and_provision_device.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/claim_devices.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/cli.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/create_ca_cert.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/create_device_credentials.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/create_proxy_jwt.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/gather_attestation_tokens.py +0 -0
- {nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/modem_credentials_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nrfcloud-utils
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Scripts and utilities for working with the nRF Cloud
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
License-File: LICENSE.txt
|
|
@@ -12,10 +12,10 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
-
Requires-Dist: cbor2 (>=5.
|
|
15
|
+
Requires-Dist: cbor2 (>=5.9.0)
|
|
16
16
|
Requires-Dist: cffi (>=2.0.0)
|
|
17
17
|
Requires-Dist: cryptography (>=49.0.0)
|
|
18
|
-
Requires-Dist: idna (>=3.
|
|
18
|
+
Requires-Dist: idna (>=3.15)
|
|
19
19
|
Requires-Dist: inquirer (>=3.4.0)
|
|
20
20
|
Requires-Dist: nrfcredstore (>=2.1.0)
|
|
21
21
|
Requires-Dist: pyjwt (>=2.13.0)
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nrfcloud-utils"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.3.0"
|
|
8
8
|
description = "Scripts and utilities for working with the nRF Cloud"
|
|
9
9
|
license = "BSD-3-Clause"
|
|
10
10
|
readme = "README.md"
|
|
@@ -13,11 +13,11 @@ authors = [
|
|
|
13
13
|
{ name = "Nordic Semiconductor ASA" }
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
|
-
"cbor2>=5.
|
|
16
|
+
"cbor2>=5.9.0",
|
|
17
17
|
"cryptography>=49.0.0",
|
|
18
18
|
"cffi>=2.0.0",
|
|
19
19
|
"requests>=2.34.2",
|
|
20
|
-
"idna>=3.
|
|
20
|
+
"idna>=3.15",
|
|
21
21
|
"urllib3>=2.7.0",
|
|
22
22
|
"semver>=3.0.0",
|
|
23
23
|
"pyjwt>=2.13.0",
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
from os import path
|
|
8
8
|
from os import makedirs
|
|
9
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
9
10
|
import platform
|
|
10
11
|
import os
|
|
11
12
|
import csv
|
|
@@ -21,6 +22,16 @@ full_encoding = 'mbcs' if is_windows else 'ascii'
|
|
|
21
22
|
|
|
22
23
|
logger = logging.getLogger(__name__)
|
|
23
24
|
|
|
25
|
+
try:
|
|
26
|
+
_package_version = version('nrfcloud-utils')
|
|
27
|
+
except PackageNotFoundError:
|
|
28
|
+
_package_version = 'unknown'
|
|
29
|
+
|
|
30
|
+
USER_AGENT = (
|
|
31
|
+
f'nrfcloud-utils/{_package_version} '
|
|
32
|
+
f'({platform.system()} {platform.release()}; Python {platform.python_version()})'
|
|
33
|
+
)
|
|
34
|
+
|
|
24
35
|
def setup_logging(level='info', fmt='%(levelname)-8s %(message)s', use_color=True):
|
|
25
36
|
"""
|
|
26
37
|
Configure colored logging with dark-terminal-friendly colors.
|
|
@@ -217,6 +228,7 @@ CMD_TERM_DICT = {'NULL': '\0',
|
|
|
217
228
|
CMD_TYPE_AT = "at"
|
|
218
229
|
CMD_TYPE_AT_SHELL = "at_shell"
|
|
219
230
|
CMD_TYPE_TLS_SHELL = "tls_cred_shell"
|
|
231
|
+
CMD_TYPE_NRF_CLOUD_CRED_SHELL = "nrf_cloud_cred_shell"
|
|
220
232
|
CMD_TYPE_AUTO = "auto"
|
|
221
233
|
|
|
222
234
|
def parser_add_comms_args(parser):
|
|
@@ -244,8 +256,8 @@ def parser_add_comms_args(parser):
|
|
|
244
256
|
parser.add_argument("--rtt",
|
|
245
257
|
help="Use RTT instead of serial. Requires device run Modem Shell sample application configured with RTT overlay",
|
|
246
258
|
action='store_true', default=False)
|
|
247
|
-
parser.add_argument("--cmd-type", default=CMD_TYPE_AUTO, choices=[CMD_TYPE_AUTO, CMD_TYPE_AT, CMD_TYPE_AT_SHELL, CMD_TYPE_TLS_SHELL], type=str.lower,
|
|
248
|
-
help=f"Specify the device command line type. '{CMD_TYPE_AT}' will use AT commands, '{CMD_TYPE_AT_SHELL}' will prefix AT commands with 'at ',
|
|
259
|
+
parser.add_argument("--cmd-type", default=CMD_TYPE_AUTO, choices=[CMD_TYPE_AUTO, CMD_TYPE_AT, CMD_TYPE_AT_SHELL, CMD_TYPE_TLS_SHELL, CMD_TYPE_NRF_CLOUD_CRED_SHELL], type=str.lower,
|
|
260
|
+
help=f"Specify the device command line type. '{CMD_TYPE_AT}' will use AT commands, '{CMD_TYPE_AT_SHELL}' will prefix AT commands with 'at ', '{CMD_TYPE_TLS_SHELL}' will use TLS Credentials Shell commands, and '{CMD_TYPE_NRF_CLOUD_CRED_SHELL}' will use the nrf_cloud_cred shell commands to generate the device key and CSR on-device.")
|
|
249
261
|
parser.add_argument("--term", type=str,
|
|
250
262
|
help="AT command termination",choices=list(CMD_TERM_DICT.keys()),
|
|
251
263
|
default='CRLF')
|
{nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/device_credentials_installer.py
RENAMED
|
@@ -9,12 +9,13 @@ import re
|
|
|
9
9
|
import os
|
|
10
10
|
import sys
|
|
11
11
|
import uuid
|
|
12
|
+
import base64
|
|
12
13
|
import semver
|
|
13
14
|
import logging
|
|
14
15
|
from nrfcloud_utils import create_device_credentials, ca_certs, modem_credentials_parser
|
|
15
16
|
from nrfcloud_utils.cli_helpers import write_file, save_devinfo_csv, save_onboarding_csv, full_encoding, setup_logging
|
|
16
|
-
from nrfcloud_utils.cli_helpers import CMD_TERM_DICT, CMD_TYPE_AUTO, CMD_TYPE_AT, CMD_TYPE_AT_SHELL, CMD_TYPE_TLS_SHELL, parser_add_comms_args
|
|
17
|
-
from nrfcredstore.command_interface import ATCommandInterface, TLSCredShellInterface
|
|
17
|
+
from nrfcloud_utils.cli_helpers import CMD_TERM_DICT, CMD_TYPE_AUTO, CMD_TYPE_AT, CMD_TYPE_AT_SHELL, CMD_TYPE_TLS_SHELL, CMD_TYPE_NRF_CLOUD_CRED_SHELL, parser_add_comms_args
|
|
18
|
+
from nrfcredstore.command_interface import ATCommandInterface, TLSCredShellInterface, NrfCloudCredShellInterface
|
|
18
19
|
from nrfcredstore.comms import Comms
|
|
19
20
|
|
|
20
21
|
from cryptography import x509
|
|
@@ -148,7 +149,9 @@ def check_mfw_version(cred_if):
|
|
|
148
149
|
# check for required version
|
|
149
150
|
parsed_ver = parse_mfw_ver(ver)
|
|
150
151
|
|
|
151
|
-
if
|
|
152
|
+
if "ntn" in ver:
|
|
153
|
+
pass
|
|
154
|
+
elif parsed_ver is None:
|
|
152
155
|
logger.error('Unexpected modem FW version format... continuing')
|
|
153
156
|
elif semver.Version.parse(parsed_ver).compare(MIN_REQD_MFW_VER) < 0:
|
|
154
157
|
logger.error(f'Modem FW version must be >= {MIN_REQD_MFW_VER}')
|
|
@@ -172,8 +175,13 @@ def get_csr(cred_if, custom_dev_id = "", sectag = 0, local = False):
|
|
|
172
175
|
logger.error('Failed to obtain CSR from device')
|
|
173
176
|
sys.exit(9)
|
|
174
177
|
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
if isinstance(cred_if, NrfCloudCredShellInterface):
|
|
179
|
+
# The nrf_cloud_cred shell returns a plain Base64-encoded DER CSR,
|
|
180
|
+
# not the modem's "body.cose" format.
|
|
181
|
+
csr = x509.load_der_x509_csr(base64.b64decode(csr_blob))
|
|
182
|
+
else:
|
|
183
|
+
csr_bytes, _, _, _ = modem_credentials_parser.parse_keygen_output(csr_blob)
|
|
184
|
+
csr = x509.load_pem_x509_csr(csr_bytes)
|
|
177
185
|
|
|
178
186
|
return csr, local_priv_key
|
|
179
187
|
|
|
@@ -217,7 +225,14 @@ def main(in_args):
|
|
|
217
225
|
logger.error(f"cmd_type '{CMD_TYPE_TLS_SHELL}' currently requires --local_cert or --local_cert_file")
|
|
218
226
|
sys.exit(1)
|
|
219
227
|
|
|
220
|
-
if args.cmd_type ==
|
|
228
|
+
if args.cmd_type == CMD_TYPE_NRF_CLOUD_CRED_SHELL and (args.local_cert or args.local_cert_file):
|
|
229
|
+
# The key and CSR are generated on-device; generating a key on the host
|
|
230
|
+
# would defeat the purpose and is almost certainly a mistake.
|
|
231
|
+
logger.error(f"cmd_type '{CMD_TYPE_NRF_CLOUD_CRED_SHELL}' generates the key on-device; "
|
|
232
|
+
"do not use --local-cert or --local-cert-file")
|
|
233
|
+
sys.exit(1)
|
|
234
|
+
|
|
235
|
+
if args.cmd_type in (CMD_TYPE_TLS_SHELL, CMD_TYPE_NRF_CLOUD_CRED_SHELL) and id_len == 0:
|
|
221
236
|
args.id_str = str(uuid.uuid4())
|
|
222
237
|
|
|
223
238
|
cmd_type_has_at = args.cmd_type in (CMD_TYPE_AT, CMD_TYPE_AT_SHELL, CMD_TYPE_AUTO)
|
|
@@ -250,6 +265,10 @@ def main(in_args):
|
|
|
250
265
|
cred_if = TLSCredShellInterface(serial_interface)
|
|
251
266
|
has_shell = True
|
|
252
267
|
|
|
268
|
+
if args.cmd_type == CMD_TYPE_NRF_CLOUD_CRED_SHELL:
|
|
269
|
+
cred_if = NrfCloudCredShellInterface(serial_interface)
|
|
270
|
+
has_shell = True
|
|
271
|
+
|
|
253
272
|
# prepare modem so we can interact with security keys
|
|
254
273
|
if (cmd_type_has_at):
|
|
255
274
|
logger.info('Disabling LTE and GNSS...')
|
|
@@ -416,10 +435,11 @@ def main(in_args):
|
|
|
416
435
|
|
|
417
436
|
# AT-command-based SHA check has a modem firmware version requirement
|
|
418
437
|
if (cmd_type_has_at):
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
438
|
+
if "ntn" not in mfw_ver:
|
|
439
|
+
parsed_ver = parse_mfw_ver(mfw_ver)
|
|
440
|
+
if parsed_ver and semver.Version.parse(parsed_ver).compare(MIN_REQD_MFW_VER_FOR_VERIFY) < 0:
|
|
441
|
+
logger.error(f'Skipping SHA verification, modem FW version must be >= {MIN_REQD_MFW_VER_FOR_VERIFY}')
|
|
442
|
+
check_sha = False
|
|
423
443
|
|
|
424
444
|
verify_res = verify_credentials(cred_if, args.sectag, nrf_ca_cert_text, dev_text, prv_text,
|
|
425
445
|
check_sha=check_sha)
|
|
@@ -443,6 +463,27 @@ def main(in_args):
|
|
|
443
463
|
if args.devinfo:
|
|
444
464
|
save_devinfo_csv(args.devinfo, args.devinfo_append, args.replace, dev_id, mfw_ver, imei)
|
|
445
465
|
|
|
466
|
+
def verify_on_device_key(cred_if, sec_tag, client_cert):
|
|
467
|
+
# The on-device private key is non-exportable, so it cannot be verified by
|
|
468
|
+
# hash. Instead, confirm that the device public key matches the public key
|
|
469
|
+
# in the installed device certificate.
|
|
470
|
+
logger.info('Verifying Private Key')
|
|
471
|
+
dev_pub = cred_if.get_pubkey(sec_tag)
|
|
472
|
+
if not dev_pub:
|
|
473
|
+
logger.error('...Failed to read device public key')
|
|
474
|
+
return False
|
|
475
|
+
|
|
476
|
+
cert = x509.load_pem_x509_certificate(client_cert.encode())
|
|
477
|
+
cert_pub = cert.public_key().public_bytes(
|
|
478
|
+
serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)
|
|
479
|
+
|
|
480
|
+
if dev_pub != cert_pub:
|
|
481
|
+
logger.error('...Device public key does not match the device certificate')
|
|
482
|
+
return False
|
|
483
|
+
|
|
484
|
+
logger.info('...Private Key matches device certificate')
|
|
485
|
+
return True
|
|
486
|
+
|
|
446
487
|
def verify_credentials(cred_if, sec_tag, ca_cert, client_cert, client_prv=None, check_sha=False):
|
|
447
488
|
# verify the CA cert
|
|
448
489
|
if not verify_credential(cred_if, sec_tag, 0, ca_cert, verify_hash = check_sha):
|
|
@@ -452,6 +493,11 @@ def verify_credentials(cred_if, sec_tag, ca_cert, client_cert, client_prv=None,
|
|
|
452
493
|
if not verify_credential(cred_if, sec_tag, 1, client_cert, verify_hash = check_sha):
|
|
453
494
|
return False
|
|
454
495
|
|
|
496
|
+
# The on-device key is opaque (held in PSA); verify it by matching the
|
|
497
|
+
# device public key to the certificate instead of by hash.
|
|
498
|
+
if isinstance(cred_if, NrfCloudCredShellInterface):
|
|
499
|
+
return verify_on_device_key(cred_if, sec_tag, client_cert)
|
|
500
|
+
|
|
455
501
|
if not verify_credential(cred_if, sec_tag, 2, client_prv, get_hash = check_sha,
|
|
456
502
|
verify_hash = (client_prv is not None) and check_sha):
|
|
457
503
|
return False
|
|
@@ -493,7 +539,7 @@ def verify_credential(cred_if, sec_tag, cred_type, cred = None, get_hash = False
|
|
|
493
539
|
logger.error(f'...Failed to calculate hash for {cred_type_name}')
|
|
494
540
|
logger.debug(f'Error details: {e}')
|
|
495
541
|
return False
|
|
496
|
-
|
|
542
|
+
|
|
497
543
|
if hash != expected_hash:
|
|
498
544
|
logger.error(f'{cred_type_name} - SHA mismatch:')
|
|
499
545
|
logger.error(f'\tDevice : {hash}')
|
|
@@ -12,6 +12,7 @@ import requests
|
|
|
12
12
|
import coloredlogs
|
|
13
13
|
from nrfcredstore.comms import Comms
|
|
14
14
|
from nrfcredstore.command_interface import ATCommandInterface
|
|
15
|
+
from nrfcloud_utils.cli_helpers import USER_AGENT
|
|
15
16
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
17
18
|
|
|
@@ -144,7 +145,7 @@ def set_dev_stage(stage = ''):
|
|
|
144
145
|
return api_url
|
|
145
146
|
|
|
146
147
|
def fetch_tenant_id(api_key):
|
|
147
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
148
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
148
149
|
req = api_url + "account"
|
|
149
150
|
response = requests.get(req, headers=hdr)
|
|
150
151
|
if not response.ok:
|
|
@@ -192,6 +193,7 @@ def onboard_device(api_key, dev_id, sub_type, tags, fw_types, onboarding_token):
|
|
|
192
193
|
hdr = {
|
|
193
194
|
'Authorization': 'Bearer ' + api_key,
|
|
194
195
|
'Accept': 'application/json',
|
|
196
|
+
'User-Agent': USER_AGENT,
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
req = api_url + "devices/" + dev_id
|
|
@@ -12,6 +12,7 @@ import urllib
|
|
|
12
12
|
from urllib.parse import quote_plus as url_encode
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from enum import Enum
|
|
15
|
+
from nrfcloud_utils.cli_helpers import USER_AGENT
|
|
15
16
|
|
|
16
17
|
API_URL = "https://api.nrfcloud.com/v1/"
|
|
17
18
|
|
|
@@ -229,7 +230,7 @@ def parse_args(in_args):
|
|
|
229
230
|
|
|
230
231
|
def get_bundle_list(api_key, modem_only):
|
|
231
232
|
|
|
232
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
233
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
233
234
|
req_base = f'{GET_BUNDLES_BASE}?pageLimit={GET_BUNDLES_PAGE_LIMIT}'
|
|
234
235
|
|
|
235
236
|
if modem_only:
|
|
@@ -273,7 +274,7 @@ def get_requested_bundles(api_key, fota_type):
|
|
|
273
274
|
return [i for i in bundles if i.type == fota_type.name]
|
|
274
275
|
|
|
275
276
|
def get_device_list(api_key, fota_types_list, device_id):
|
|
276
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
277
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
277
278
|
req_base = GET_DEVICES_BASE + f'&pageLimit={GET_DEVICES_PAGE_LIMIT}'
|
|
278
279
|
|
|
279
280
|
if fota_types_list:
|
|
@@ -321,7 +322,7 @@ def print_api_result(custom_text, api_result, print_response_txt):
|
|
|
321
322
|
|
|
322
323
|
def create_fota_job(api_key, json_payload_obj):
|
|
323
324
|
jobId = None
|
|
324
|
-
hdr = {'Authorization': f'Bearer {api_key}'}
|
|
325
|
+
hdr = {'Authorization': f'Bearer {api_key}', 'User-Agent': USER_AGENT}
|
|
325
326
|
req = FOTA_JOBS_BASE
|
|
326
327
|
|
|
327
328
|
api_res = requests.post(req, json=json_payload_obj, headers=hdr)
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import requests
|
|
8
8
|
import logging
|
|
9
9
|
from nrfcloud_utils import ca_certs
|
|
10
|
+
from nrfcloud_utils.cli_helpers import USER_AGENT
|
|
10
11
|
|
|
11
12
|
DEV_STAGE_DICT = {'dev': '.dev.',
|
|
12
13
|
'beta': '.beta.',
|
|
@@ -44,7 +45,7 @@ def set_dev_stage(stage = ''):
|
|
|
44
45
|
def get_auth_header(api_key):
|
|
45
46
|
if not api_key:
|
|
46
47
|
return None
|
|
47
|
-
return
|
|
48
|
+
return { AUTH : BEARER + api_key, 'User-Agent': USER_AGENT }
|
|
48
49
|
|
|
49
50
|
def claim_device(api_key, claim_token, tags = None):
|
|
50
51
|
global api_url
|
|
@@ -15,7 +15,7 @@ import io
|
|
|
15
15
|
import logging
|
|
16
16
|
from os import makedirs
|
|
17
17
|
from enum import Enum
|
|
18
|
-
from nrfcloud_utils.cli_helpers import write_file, setup_logging
|
|
18
|
+
from nrfcloud_utils.cli_helpers import write_file, setup_logging, USER_AGENT
|
|
19
19
|
|
|
20
20
|
logger = logging.getLogger(__name__)
|
|
21
21
|
|
|
@@ -105,22 +105,22 @@ def set_dev_stage(stage = ''):
|
|
|
105
105
|
return api_url
|
|
106
106
|
|
|
107
107
|
def get_bulk_ops_result(api_key, bulk_ops_req_id):
|
|
108
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
108
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
109
109
|
req = api_url + "bulk-ops-requests/" + bulk_ops_req_id
|
|
110
110
|
return requests.get(req, headers=hdr)
|
|
111
111
|
|
|
112
112
|
def update_device_shadow(api_key, device_id, json_payload):
|
|
113
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
113
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
114
114
|
req = api_url + "devices/" + device_id + "/state"
|
|
115
115
|
return requests.patch(req, json=json_payload, headers=hdr)
|
|
116
116
|
|
|
117
117
|
def fetch_device(api_key, device_id):
|
|
118
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
118
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
119
119
|
req = api_url + "devices/" + device_id
|
|
120
120
|
return requests.get(req, headers=hdr)
|
|
121
121
|
|
|
122
122
|
def update_device_name(api_key, device_id, name):
|
|
123
|
-
hdr = {'Authorization': 'Bearer ' + api_key}
|
|
123
|
+
hdr = {'Authorization': 'Bearer ' + api_key, 'User-Agent': USER_AGENT}
|
|
124
124
|
req = api_url + "devices/" + device_id + "/name"
|
|
125
125
|
json_payload = [name]
|
|
126
126
|
return requests.put(req, json=json_payload, headers=hdr)
|
|
@@ -128,7 +128,8 @@ def update_device_name(api_key, device_id, name):
|
|
|
128
128
|
def onboard_device(api_key, dev_id, sub_type, tags, fw_types, cert_pem_str):
|
|
129
129
|
hdr = {'Authorization': 'Bearer ' + api_key,
|
|
130
130
|
'content-type' : 'text/plain',
|
|
131
|
-
'Accept-Encoding' : '*'
|
|
131
|
+
'Accept-Encoding' : '*',
|
|
132
|
+
'User-Agent': USER_AGENT}
|
|
132
133
|
|
|
133
134
|
req = api_url + "devices"
|
|
134
135
|
|
|
@@ -139,7 +140,8 @@ def onboard_device(api_key, dev_id, sub_type, tags, fw_types, cert_pem_str):
|
|
|
139
140
|
def onboard_devices(api_key, csv_filepath):
|
|
140
141
|
hdr = {'Authorization': 'Bearer ' + api_key,
|
|
141
142
|
'content-type' : 'text/csv',
|
|
142
|
-
'Accept-Encoding' : '*'
|
|
143
|
+
'Accept-Encoding' : '*',
|
|
144
|
+
'User-Agent': USER_AGENT}
|
|
143
145
|
|
|
144
146
|
req = api_url + "devices"
|
|
145
147
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/claim_and_provision_device.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/create_device_credentials.py
RENAMED
|
File without changes
|
|
File without changes
|
{nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/gather_attestation_tokens.py
RENAMED
|
File without changes
|
{nrfcloud_utils-3.2.1 → nrfcloud_utils-3.3.0}/src/nrfcloud_utils/modem_credentials_parser.py
RENAMED
|
File without changes
|