-
Notifications
You must be signed in to change notification settings - Fork 5
/
fake-lmp-device-register
executable file
·153 lines (130 loc) · 4.32 KB
/
fake-lmp-device-register
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/python3
from argparse import ArgumentParser
import os
import subprocess
import sys
from tempfile import NamedTemporaryFile
from typing import NamedTuple, Tuple
from uuid import uuid4
import requests
import logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
log = logging.getLogger(__name__)
class Options(NamedTuple):
factory: str
sota_dir: str
tags: str
apps: str
hwid: str
uuid: str
name: str
registration_url: str
production: bool
def create_key(uuid: str, factory: str, production: bool, sota_dir: str) -> bytes:
log.info("Setting path for the private key file: %s", sota_dir)
keyfile_path = os.path.join(sota_dir, "pkey.pem")
log.info("Creating key for UUID: %s, Factory: %s", uuid, factory)
subprocess.check_call(
["openssl", "ecparam", "-genkey", "-name", "prime256v1", "-out", keyfile_path]
)
log.info("Creating CSR for UUID: %s, Factory: %s", uuid, factory)
with NamedTemporaryFile() as cnf:
cnf.write(
f"""[req]
prompt = no
distinguished_name = dn
req_extensions = ext
[dn]
CN={uuid}
OU={factory}
""".encode()
)
if production:
cnf.write(b"businessCategory=production\n")
cnf.write(
b"""
[ext]
keyUsage=critical, digitalSignature
extendedKeyUsage=critical, clientAuth
"""
)
cnf.flush()
r = subprocess.run(
["openssl", "req", "-new", "-config", cnf.name, "-key", keyfile_path],
stdout=subprocess.PIPE,
)
r.check_returncode()
return r.stdout
def main(opts: Options):
log.info("Creating key and CSR")
csr = create_key(opts.uuid, opts.factory, opts.production, opts.sota_dir)
data = {
"name": opts.name,
"uuid": opts.uuid,
"csr": csr.decode(),
"hardware-id": opts.hwid,
"sota-config-dir": opts.sota_dir,
"overrides": {
"pacman": {
"type": '"ostree+compose_apps"',
"tags": '"' + opts.tags + '"',
"compose_apps_root": os.path.join(opts.sota_dir, "compose-apps"),
},
},
}
if opts.apps:
data["overrides"]["pacman"]["compose_apps"] = '"' + opts.apps + '"' # type: ignore
r = requests.post(opts.registration_url, json=data)
r.raise_for_status()
log.debug("Successfully registered device with status code: %d", r.status_code)
for k, v in r.json().items():
with open(os.path.join(opts.sota_dir, k), mode="w") as f: # type: ignore
f.write(v)
with open(os.path.join(opts.sota_dir, "curl"), "wb") as f:
os.fchmod(f.fileno(), 0o755)
f.write(
f"""#!/bin/sh -e
cd {opts.sota_dir}
curl --cert client.pem --key pkey.pem --cacert root.crt $*""".encode()
)
def get_parser() -> ArgumentParser:
p = ArgumentParser(description="Example client to ease local testing")
p.add_argument(
"--factory", "-f", required=True, help="Name of factory to register device in"
)
p.add_argument("--production", action="store_true", help="Make 'production' cert")
p.add_argument("--sota-dir", "-d", default=os.path.join(os.getcwd(), "var", "sota"), help="default=%(default)s")
p.add_argument("--tags", "-t", default="master", help="default=%(default)s")
p.add_argument("--apps", "-a")
p.add_argument(
"--hwid", "-i", default="intel-corei7-64", help="default=%(default)s"
)
p.add_argument("--uuid", "-u", help="Default value is a random uuid")
p.add_argument("--name", "-n", help="Default value is the uuid")
p.add_argument(
"--registration-url",
"-r",
default="http://localhost:80/sign",
help="factory-registration-ref url. default=%(default)s",
)
return p
if __name__ == "__main__":
args = get_parser().parse_args()
if not args.uuid:
args.uuid = str(uuid4())
if not args.name:
args.name = args.uuid
args.sota_dir = os.path.abspath(args.sota_dir)
options = Options(
factory=args.factory,
sota_dir=args.sota_dir,
tags=args.tags,
apps=args.apps,
hwid=args.hwid,
uuid=args.uuid,
name=args.name,
registration_url=args.registration_url,
production=args.production,
)
main(options)