Skip to content

Commit 8a6e7bd

Browse files
committed
cli wip
1 parent 8f54bb5 commit 8a6e7bd

File tree

2 files changed

+58
-59
lines changed

2 files changed

+58
-59
lines changed

src/nrfcredstore/cli.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ def parse_args(in_args):
5757

5858
deleteall_parser = subparsers.add_parser('deleteall', help='Delete all keys in a secure tag')
5959

60+
imei_parser = subparsers.add_parser('imei', help='Get IMEI of the modem')
61+
62+
attoken_parser = subparsers.add_parser('attoken', help='Get attestation token of the modem')
63+
6064
# add generate command and args
6165
generate_parser = subparsers.add_parser('generate', help='Generate private key')
6266
generate_parser.add_argument('tag', type=int,
@@ -70,7 +74,8 @@ def parse_args(in_args):
7074

7175
def exec_cmd(args, credstore):
7276
if args.subcommand:
73-
credstore.func_mode(FUN_MODE_OFFLINE)
77+
if not credstore.func_mode(FUN_MODE_OFFLINE):
78+
raise RuntimeError("Failed to set modem to offline mode.")
7479

7580
if args.subcommand == 'list':
7681
ct = CredType[args.type]
@@ -106,12 +111,24 @@ def exec_cmd(args, credstore):
106111
credstore.keygen(args.tag, args.file, args.attributes)
107112
print(f'New private key generated in secure tag {args.tag}')
108113
print(f'Wrote CSR in DER format to {args.file.name}')
114+
elif args.subcommand=='imei':
115+
imei = credstore.command_interface.get_imei()
116+
if imei is None:
117+
raise RuntimeError("Failed to get IMEI.")
118+
print(f'IMEI: {imei}')
119+
elif args.subcommand=='attoken':
120+
attoken = credstore.command_interface.get_attestation_token()
121+
if attoken is None:
122+
raise RuntimeError("Failed to get attestation token.")
123+
print(f'Attestation token: {attoken}')
109124

110125
def exit_with_msg(exitcode, msg):
111126
print(msg)
112127
exit(exitcode)
113128

114129
def main(args, credstore):
130+
credstore.command_interface.detect_shell_mode()
131+
credstore.command_interface.enable_error_codes()
115132
exec_cmd(args, credstore)
116133

117134
def run():
@@ -132,7 +149,5 @@ def run():
132149
comms = Comms(port=args.dev, baudrate=args.baudrate, timeout=args.timeout)
133150

134151
cred_if = ATCommandInterface(comms)
135-
cred_if.detect_shell_mode()
136-
cred_if.enable_error_codes()
137152

138153
main(args, CredStore(cred_if))

tests/test_cli.py

Lines changed: 40 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from unittest.mock import Mock, ANY, patch
44
from serial import SerialException
5-
from nrfcredstore.cli import main, parse_args
5+
from nrfcredstore.cli import main, parse_args, FUN_MODE_OFFLINE
66

77
from nrfcredstore.credstore import CredType
88
from nrfcredstore.exceptions import NoATClientException, ATCommandError
@@ -28,111 +28,95 @@ def empty_cred_list(self, credstore):
2828
# non-responsive device
2929
def test_non_responsive_device(self, credstore, command_interface):
3030
command_interface.detect_shell_mode.side_effect = TimeoutError()
31-
with pytest.raises(SystemExit) as e:
31+
with pytest.raises(TimeoutError) as e:
3232
main(parse_args(['fakedev', 'list']), credstore)
33-
assert e.type == SystemExit
34-
assert e.value.code == 12
33+
assert e.type == TimeoutError
3534

3635

37-
def test_list_default(self, credstore, offline, empty_cred_list):
36+
def test_list_default(self, credstore, empty_cred_list):
3837
main(parse_args(['fakedev', 'list']), credstore)
38+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
3939
credstore.list.assert_called_with(None, CredType.ANY)
4040

41-
def test_list_with_tag(self, credstore, offline, empty_cred_list):
41+
def test_list_with_tag(self, credstore, empty_cred_list):
4242
main(parse_args(['fakedev', 'list', '--tag', '123']), credstore)
43+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
4344
credstore.list.assert_called_with(123, ANY)
4445

45-
def test_list_with_type(self, credstore, offline, empty_cred_list):
46+
def test_list_with_type(self, credstore, empty_cred_list):
4647
main(parse_args(['fakedev', 'list', '--tag', '123', '--type', 'CLIENT_KEY']), credstore)
48+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
4749
credstore.list.assert_called_with(ANY, CredType.CLIENT_KEY)
4850

49-
def test_write_tag_and_type(self, credstore, offline):
51+
def test_write_tag_and_type(self, credstore):
5052
credstore.write.return_value = True
5153
main(parse_args(['fakedev', 'write', '123', 'ROOT_CA_CERT', 'tests/fixtures/root-ca.pem']), credstore)
54+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
5255
credstore.write.assert_called_with(123, CredType.ROOT_CA_CERT, ANY)
5356

5457
@patch('builtins.open')
55-
def test_write_file(self, mock_file, credstore, offline):
58+
def test_write_file(self, mock_file, credstore):
5659
credstore.write.return_value = True
5760
main(parse_args(['fakedev', 'write', '123', 'ROOT_CA_CERT', 'foo.pem']), credstore)
61+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
5862
mock_file.assert_called_with('foo.pem', 'r', ANY, ANY, ANY)
5963

6064
@patch('builtins.open')
61-
def test_write_psk_file(self, mock_file, credstore, offline):
65+
def test_write_psk_file(self, mock_file, credstore):
6266
credstore.write.return_value = True
6367
main(parse_args(['fakedev', 'write', '123', 'PSK', 'foo.psk']), credstore)
68+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
6469
mock_file.assert_called_with('foo.psk', 'r', ANY, ANY, ANY)
6570

66-
def test_delete(self, credstore, offline):
71+
def test_delete(self, credstore):
6772
credstore.delete.return_value = True
6873
main(parse_args(['fakedev', 'delete', '123', 'CLIENT_KEY']), credstore)
74+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
6975
credstore.delete.assert_called_with(123, CredType.CLIENT_KEY)
7076

71-
def test_delete_any_should_fail(self, credstore, offline):
77+
def test_delete_any_should_fail(self, credstore):
7278
with pytest.raises(SystemExit):
7379
main(parse_args(['fakedev', 'delete', '123', 'ANY']), credstore)
7480

7581
@patch('builtins.open')
76-
def test_generate_tag(self, mock_file, credstore, offline):
82+
def test_generate_tag(self, mock_file, credstore):
7783
credstore.keygen.return_value = True
7884
main(parse_args(['fakedev', 'generate', '123', 'foo.der']), credstore)
85+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
7986
credstore.keygen.assert_called_with(123, ANY, ANY)
8087

8188
@patch('builtins.open')
82-
def test_generate_file(self, mock_file, credstore, offline):
89+
def test_generate_file(self, mock_file, credstore):
8390
credstore.keygen.return_value = True
8491
main(parse_args(['fakedev', 'generate', '123', 'foo.der']), credstore)
92+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
8593
mock_file.assert_called_with('foo.der', 'wb', ANY, ANY, ANY)
8694

8795
@patch('builtins.open')
88-
def test_generate_with_attributes(self, credstore, offline):
96+
def test_generate_with_attributes(self, credstore):
8997
credstore.keygen.return_value = True
9098
main(parse_args(['fakedev', 'generate', '123', 'foo.der', '--attributes', 'CN=foo']), credstore)
99+
credstore.func_mode.assert_called_with(FUN_MODE_OFFLINE)
91100
credstore.keygen.assert_called_with(123, ANY, 'CN=foo')
92101

93-
def test_no_at_client_exit_code(self, credstore, at_client):
94-
at_client.verify.side_effect = NoATClientException()
95-
with pytest.raises(SystemExit) as e:
102+
def test_imei(self, credstore):
103+
credstore.command_interface.get_imei.return_value = '123456789012345'
104+
args = parse_args(['fakedev', 'imei'])
105+
main(args, credstore)
106+
credstore.command_interface.get_imei.assert_called_once()
107+
108+
def test_attestation_token(self, credstore):
109+
credstore.command_interface.get_attestation_token.return_value = '2dn3hQFQUDYxVDkxRPCAIhIbZAFifQNQGv86y_GmR2SiY0wmRsHGVFDT791_BPH8YOWFiyCHND1q.0oRDoQEmoQRBIfZYQGuXwJliinHc6xDPruiyjsaXyXZbZVpUuOhHG9YS8L05VuglCcJhMN4EUhWVGpaHgNnHHno6ahi-d5tOeZmAcNY'
110+
args = parse_args(['fakedev', 'attoken'])
111+
main(args, credstore)
112+
credstore.command_interface.get_attestation_token.assert_called_once()
113+
114+
def test_at_command_error_exit_code(self, credstore):
115+
credstore.func_mode.side_effect = RuntimeError("Failed to set modem to offline mode.")
116+
with pytest.raises(RuntimeError) as e:
96117
main(parse_args(['fakedev', 'list']), credstore)
97-
assert e.type == SystemExit
98-
assert e.value.code == 10
99-
100-
def test_at_command_error_exit_code(self, credstore, at_client):
101-
at_client.verify.side_effect = ATCommandError()
102-
with pytest.raises(SystemExit) as e:
103-
main(parse_args(['fakedev', 'list']), credstore)
104-
assert e.type == SystemExit
105-
assert e.value.code == 11
106-
107-
def test_timeout_error_exit_code(self, credstore, at_client):
108-
at_client.verify.side_effect = TimeoutError()
109-
with pytest.raises(SystemExit) as e:
110-
main(parse_args(['fakedev', 'list']), credstore)
111-
assert e.type == SystemExit
112-
assert e.value.code == 12
113-
114-
def test_serial_exception_exit_code(self, credstore, at_client):
115-
at_client.connect.side_effect = SerialException()
116-
with pytest.raises(SystemExit) as e:
117-
main(parse_args(['fakedev', 'list']), credstore)
118-
assert e.type == SystemExit
119-
assert e.value.code == 13
120-
121-
def test_unhandled_exception_exit_code(self, credstore, at_client):
122-
at_client.verify.side_effect = Exception()
123-
with pytest.raises(SystemExit) as e:
124-
main(parse_args(['fakedev', 'list']), credstore)
125-
assert e.type == SystemExit
126-
assert e.value.code == 1
118+
assert e.type == RuntimeError
127119

128120
# plan for new tests:
129121
# Comms cannot find device
130-
# Comms cannot detect shell mode
131122
# Comms cannot enable error codes
132-
# list successful
133-
# list with tag successful
134-
# list with tag and type successful
135-
# write successful
136-
# delete successful - check that we don't try to delete reserved tags
137-
# deleteall successful
138-
# generate successful

0 commit comments

Comments
 (0)