1
1
import { type DynamoDBClient } from '@aws-sdk/client-dynamodb'
2
2
import type { SSMClient } from '@aws-sdk/client-ssm'
3
+ import { isFingerprint } from '@hello.nrfcloud.com/proto/fingerprint'
3
4
import chalk from 'chalk'
5
+ import { execSync } from 'node:child_process'
4
6
import { readFile } from 'node:fs/promises'
5
7
import os from 'node:os'
6
8
import { table } from 'table'
@@ -22,19 +24,59 @@ export const importDevicesCommand = ({
22
24
} ) : CommandDefinition => ( {
23
25
command : 'import-devices <model> <provisioningList>' ,
24
26
action : async ( model , provisioningList ) => {
25
- const devices : [ imei : string , fingerprint : string , publicKey : string ] [ ] = (
26
- await readFile ( provisioningList , 'utf-8' )
27
- )
27
+ const devicesList = ( await readFile ( provisioningList , 'utf-8' ) )
28
28
. trim ( )
29
29
. split ( '\r\n' )
30
30
. map ( ( s ) =>
31
31
s . split ( ';' ) . map ( ( s ) => s . replace ( / ^ " / , '' ) . replace ( / " $ / , '' ) ) ,
32
32
)
33
33
. slice ( 1 )
34
- . map (
35
- ( [ imei , _ , fingerprint , publicKey ] ) =>
36
- [ imei , fingerprint , publicKey ] as [ string , string , string ] ,
37
- )
34
+ const devices : [ imei : string , fingerprint : string , publicKey : string ] [ ] =
35
+ devicesList
36
+ . map (
37
+ ( [ imei , _ , fingerprint , publicKey ] ) =>
38
+ [ imei , fingerprint , ( publicKey ?? '' ) . replace ( / \\ n / g, os . EOL ) ] as [
39
+ string ,
40
+ string ,
41
+ string ,
42
+ ] ,
43
+ )
44
+ . filter ( ( [ imei , fingerprint , publicKey ] ) => {
45
+ if ( ! isIMEI ( imei ) ) {
46
+ console . error (
47
+ chalk . yellow ( '⚠️' ) ,
48
+ chalk . yellow ( `Not an IMEI:` ) ,
49
+ chalk . red ( imei ) ,
50
+ )
51
+ return false
52
+ }
53
+ if ( ! isFingerprint ( fingerprint ) ) {
54
+ console . error (
55
+ chalk . yellow ( '⚠️' ) ,
56
+ chalk . yellow ( `Not a fingerprint:` ) ,
57
+ chalk . red ( fingerprint ) ,
58
+ )
59
+ return false
60
+ }
61
+ try {
62
+ execSync ( 'openssl x509 -text -noout' , { input : publicKey } )
63
+ } catch ( err ) {
64
+ console . error ( err )
65
+ console . error (
66
+ chalk . yellow ( '⚠️' ) ,
67
+ chalk . yellow ( `Not a public key:` ) ,
68
+ chalk . red ( publicKey ) ,
69
+ )
70
+ return false
71
+ }
72
+ return true
73
+ } )
74
+
75
+ if ( devices . length === 0 ) {
76
+ console . error ( chalk . red ( `No devices found in` ) )
77
+ console . error ( devicesList )
78
+ process . exit ( 1 )
79
+ }
38
80
39
81
console . log (
40
82
table ( [
@@ -59,7 +101,7 @@ export const importDevicesCommand = ({
59
101
const registration = await client . registerDevices (
60
102
devices . map ( ( [ imei , _ , publicKey ] ) => {
61
103
const deviceId = `oob-${ imei } `
62
- const certPem = publicKey . replace ( / \\ n / g , os . EOL )
104
+ const certPem = publicKey
63
105
return {
64
106
deviceId,
65
107
subType : model . replace ( / [ ^ 0 - 9 a - z - ] / gi, '-' ) ,
@@ -98,13 +140,14 @@ export const importDevicesCommand = ({
98
140
console . error ( res . error . message )
99
141
} else {
100
142
console . log (
101
- chalk . green (
102
- `Registered device ${ deviceId } with fingerprint ${ fingerprint } ` ,
103
- ) ,
143
+ chalk . green ( `Registered device ${ deviceId } with fingerprint` ) ,
104
144
chalk . cyan ( fingerprint ) ,
105
145
)
106
146
}
107
147
}
108
148
} ,
109
149
help : 'Import factory provisioned devices' ,
110
150
} )
151
+
152
+ export const isIMEI = ( imei ?: string ) : imei is string =>
153
+ / ^ 3 5 [ 0 - 9 ] { 13 } $ / . test ( imei ?? '' )
0 commit comments