Compare commits

...

119 Commits

Author SHA1 Message Date
TIP Automation User
a9c4cdf0b7 Chg: update image tag in helm values to v3.0.0-RC2 2023-12-15 23:03:32 +00:00
Stephane Bourque
c34c10b637 Merge pull request #92 from Telecominfraproject/main
https://telecominfraproject.atlassian.net/browse/WIFI-13200
2023-12-15 09:15:00 -08:00
stephb9959
b7b58196e6 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:59:22 -08:00
stephb9959
f5b5b3eb13 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:47:31 -08:00
stephb9959
5a8d5a1fa1 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:47:07 -08:00
stephb9959
4e92a19b90 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:19:01 -08:00
stephb9959
713b995d01 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:15:41 -08:00
stephb9959
8eb60b00ad https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 08:12:21 -08:00
stephb9959
eb241d9be4 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-15 07:44:01 -08:00
stephb9959
836fb44991 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 17:59:22 -08:00
stephb9959
3eb579038c https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 17:55:35 -08:00
stephb9959
0121ed5073 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 17:26:12 -08:00
stephb9959
51d7e599fb https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:37:56 -08:00
stephb9959
fc307dace5 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:36:19 -08:00
stephb9959
5a646ebd49 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:33:55 -08:00
stephb9959
a296c31127 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:30:18 -08:00
stephb9959
f506b6e2ab https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:25:59 -08:00
stephb9959
f5676b0917 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:19:05 -08:00
stephb9959
5094157f98 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:16:30 -08:00
stephb9959
dee0f1fc01 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:13:44 -08:00
stephb9959
43e9d8a775 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 15:05:50 -08:00
stephb9959
951164128c https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-14 14:59:15 -08:00
stephb9959
1caa757a77 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-11 09:44:12 -08:00
stephb9959
7972b7cd6a https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-11 09:29:22 -08:00
stephb9959
6eb50d1318 https://telecominfraproject.atlassian.net/browse/WIFI-13200
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-11 09:19:37 -08:00
stephb9959
1bb9f492d2 https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-04 08:30:12 -08:00
stephb9959
0ecf5fdef9 https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-04 07:44:12 -08:00
stephb9959
a20dd5ad47 https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-03 13:22:16 -08:00
stephb9959
09351c4bbb https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-03 12:06:44 -08:00
stephb9959
e5999a3810 https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-12-02 13:26:48 -08:00
TIP Automation User
e930cc5b59 Chg: update image tag in helm values to v3.0.0-RC1 2023-11-27 17:38:27 +00:00
stephb9959
52e698c5db https://telecominfraproject.atlassian.net/browse/WIFI-13172
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-11-22 09:19:54 -08:00
stephb9959
8735dafbb0 https://telecominfraproject.atlassian.net/browse/WIFI-13151
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-11-20 20:59:33 -08:00
stephb9959
60ff1e76d3 https://telecominfraproject.atlassian.net/browse/WIFI-13151
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-11-13 11:41:25 -08:00
stephb9959
c1fbac422b https://telecominfraproject.atlassian.net/browse/WIFI-13151
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-11-13 10:00:40 -08:00
stephb9959
089edd2864 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-11-08 06:51:08 -08:00
stephb9959
09306f8547 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-26 14:02:41 -07:00
stephb9959
885619e5ae https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-26 13:41:09 -07:00
stephb9959
3d32768bd4 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-23 09:06:51 -07:00
stephb9959
5300b56ab7 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-23 08:04:48 -07:00
stephb9959
d9eb14c962 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:33:32 -07:00
stephb9959
c7043fa12c https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:29:13 -07:00
stephb9959
541266f7cf https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:24:28 -07:00
stephb9959
ecf660e568 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:18:13 -07:00
stephb9959
f82739688b https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:14:40 -07:00
stephb9959
969bcb0c25 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 15:05:35 -07:00
stephb9959
d74e791fae https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-18 14:55:59 -07:00
stephb9959
08976831f2 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 10:45:38 -07:00
stephb9959
eb4722d944 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 10:03:48 -07:00
stephb9959
bf17e99ccf https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 09:58:37 -07:00
stephb9959
4af09f15cf https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 08:56:15 -07:00
stephb9959
f74a3877ae https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 08:49:27 -07:00
stephb9959
cf2f3f57e9 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 07:39:11 -07:00
stephb9959
c3938921ce https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-16 06:56:13 -07:00
stephb9959
174f62992c https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-15 23:12:44 -07:00
stephb9959
8ba53d416b https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-15 22:29:13 -07:00
stephb9959
2c7b9cf1bd https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-09 12:52:52 -07:00
stephb9959
91826d136a https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 12:49:50 -07:00
stephb9959
a6ac483ec3 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 12:21:12 -07:00
stephb9959
ce3ae0650f https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 12:13:27 -07:00
stephb9959
a0c0efff73 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 09:36:07 -07:00
stephb9959
ae9c464fb3 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 09:27:23 -07:00
stephb9959
6575e47c74 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 09:17:14 -07:00
stephb9959
507ece011f https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 09:13:36 -07:00
stephb9959
7f5fb52157 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-06 09:06:27 -07:00
stephb9959
e6bc329e7b https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-05 08:15:55 -07:00
stephb9959
acf3c060c2 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 22:58:48 -07:00
stephb9959
0437a8ed6a https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 22:51:02 -07:00
stephb9959
3b2d94172d https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 22:27:45 -07:00
stephb9959
c573601a91 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 22:20:36 -07:00
stephb9959
fcd9c48569 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:57:58 -07:00
stephb9959
ad31dedf22 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:53:03 -07:00
stephb9959
6ff4308f7e https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:48:39 -07:00
stephb9959
5bb9c1f427 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:45:50 -07:00
stephb9959
e1af5adccb https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:42:08 -07:00
stephb9959
aec31441d4 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:38:49 -07:00
stephb9959
14efffa612 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 15:25:26 -07:00
stephb9959
25ebd7f203 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 13:12:42 -07:00
stephb9959
8cb6d58573 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 13:01:59 -07:00
stephb9959
6d9b9747a0 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 12:54:32 -07:00
stephb9959
a951cb0549 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 12:39:43 -07:00
stephb9959
27f6d7c552 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 12:18:31 -07:00
stephb9959
9ed74e0149 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 09:58:08 -07:00
stephb9959
b8ca24183d https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 09:55:04 -07:00
stephb9959
af6a30d248 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 09:06:49 -07:00
stephb9959
3469b20c28 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 08:39:20 -07:00
stephb9959
65e5669bd5 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 08:27:48 -07:00
stephb9959
a8581f8f95 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-04 08:24:21 -07:00
stephb9959
fcce87d160 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 22:58:12 -07:00
stephb9959
e5f9759667 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 22:35:07 -07:00
stephb9959
817aeb405c https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 22:26:19 -07:00
stephb9959
3292649808 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 22:25:26 -07:00
stephb9959
a8da1a4223 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 22:11:33 -07:00
stephb9959
69e507a5bd https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 21:52:56 -07:00
stephb9959
7dd33ca841 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:54:02 -07:00
stephb9959
3029fbd596 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:49:25 -07:00
stephb9959
b7cb91b022 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:29:39 -07:00
stephb9959
4658f046d9 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:09:44 -07:00
stephb9959
9afdf685a4 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:05:21 -07:00
stephb9959
b4f5f8bde1 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 09:03:22 -07:00
stephb9959
05ddc258ac https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:57:27 -07:00
stephb9959
23120feb82 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:51:12 -07:00
stephb9959
16f8f788d5 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:41:00 -07:00
stephb9959
0e54497c57 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:31:01 -07:00
stephb9959
2c612ab136 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:28:25 -07:00
stephb9959
48d3831052 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 08:26:24 -07:00
stephb9959
8388d12c88 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 07:25:09 -07:00
stephb9959
bc8e7e8ac9 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 07:14:11 -07:00
stephb9959
74ba4d8d8c https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-03 06:54:24 -07:00
stephb9959
87c4b714b1 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-02 22:28:47 -07:00
stephb9959
91d833b669 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-10-02 10:20:35 -07:00
stephb9959
30e38c21fc https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-29 07:58:55 -07:00
stephb9959
723e20de44 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-29 07:37:05 -07:00
stephb9959
03bd284183 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-29 07:30:32 -07:00
stephb9959
9ea65ebe5d https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-28 20:48:16 -07:00
stephb9959
26a1d5df44 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-28 08:56:23 -07:00
stephb9959
dfc97ee8f9 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-27 23:07:58 -07:00
stephb9959
8e07eeb000 https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-27 22:50:00 -07:00
stephb9959
3ed97e6c18 https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-27 22:37:06 -07:00
75 changed files with 3694 additions and 1303 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(owprov VERSION 2.11.0)
project(owprov VERSION 3.0.0)
set(CMAKE_CXX_STANDARD 17)
@@ -209,12 +209,37 @@ add_executable(owprov
src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h
src/Tasks/VenueRebooter.h src/Tasks/VenueUpgrade.h
src/sdks/SDK_fms.cpp src/sdks/SDK_fms.h
src/RESTAPI/RESTAPI_overrides_handler.cpp src/RESTAPI/RESTAPI_overrides_handler.h src/OpenRoamin_GlobalReach.cpp src/OpenRoamin_GlobalReach.h src/storage/storage_glblraccounts.cpp src/storage/storage_glblraccounts.h src/storage/storage_glblrcerts.cpp src/storage/storage_glblrcerts.h src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.h src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.h src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.h src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.h src/RESTAPI/RESTAPI_openroaming_orion_list_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_orion_list_acct_handler.h src/RESTAPI/RESTAPI_openroaming_orion_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_orion_acct_handler.h src/storage/storage_orion_accounts.cpp src/storage/storage_orion_accounts.h)
src/RESTAPI/RESTAPI_overrides_handler.cpp src/RESTAPI/RESTAPI_overrides_handler.h
src/storage/storage_glblraccounts.cpp src/storage/storage_glblraccounts.h
src/storage/storage_glblrcerts.cpp src/storage/storage_glblrcerts.h
src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.h
src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.h
src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.h
src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.h
src/RESTAPI/RESTAPI_openroaming_orion_list_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_orion_list_acct_handler.h
src/RESTAPI/RESTAPI_openroaming_orion_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_orion_acct_handler.h
src/storage/storage_orion_accounts.cpp src/storage/storage_orion_accounts.h
src/storage/storage_radius_endpoints.cpp
src/storage/storage_radius_endpoints.h
src/RESTAPI/RESTAPI_radiusendpoint_list_handler.cpp
src/RESTAPI/RESTAPI_radiusendpoint_list_handler.h
src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp
src/RESTAPI/RESTAPI_radius_endpoint_handler.h
src/RadiusEndpointTypes/GlobalReach.cpp src/RadiusEndpointTypes/GlobalReach.h
src/RadiusEndpointTypes/OrionWifi.h
src/RadiusEndpointUpdater.cpp
src/RadiusEndpointUpdater.h
src/RadiusEndpointTypes/Radsec.cpp
src/RadiusEndpointTypes/Radsec.h
src/RadiusEndpointTypes/GenericRadius.cpp
src/RadiusEndpointTypes/GenericRadius.h
)
target_link_libraries(owprov PUBLIC
${Poco_LIBRARIES}
${MySQL_LIBRARIES}
${ZLIB_LIBRARIES}
CppKafka::cppkafka
resolv
fmt::fmt)

2
build
View File

@@ -1 +1 @@
32
10

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images:
owprov:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov
tag: main
tag: v3.0.0-RC2
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io

View File

@@ -1,6 +1,6 @@
openapi: 3.0.1
info:
title: OpenWiFi OpenRoaming Provisioning Model for Global Reach
title: OpenWiFi RadiusEndpointTypes Provisioning Model for Global Reach
description: Definitions and APIs to Open Roaming WiFi.
version: 2.5.0
license:
@@ -92,7 +92,7 @@ paths:
/openroaming/globalreach/accounts:
get:
tags:
- OpenRoaming-Global Reach
- RadiusEndpointTypes-Global Reach
operationId: getOpenRoamingGlobalReachAccountList
summary: Retrieve account list.
parameters:
@@ -135,7 +135,7 @@ paths:
/openroaming/globalreach/account/{name}:
get:
tags:
- OpenRoaming-Global Reach
- RadiusEndpointTypes-Global Reach
operationId: getOpenRoamingGlobalReachAccount
summary: Retrieve account information.
parameters:
@@ -157,7 +157,7 @@ paths:
delete:
tags:
- OpenRoaming-Global Reach
- RadiusEndpointTypes-Global Reach
operationId: deleteOpenRoamingGlobalReachAccount
summary: Delete account information.
parameters:
@@ -179,7 +179,7 @@ paths:
post:
tags:
- OpenRoaming-Global Reach
- RadiusEndpointTypes-Global Reach
operationId: createOpenRoamingGlobalReachAccount
summary: Create account information.
parameters:
@@ -206,7 +206,7 @@ paths:
put:
tags:
- OpenRoaming-Global Reach
- RadiusEndpointTypes-Global Reach
operationId: modifyOpenRoamingGlobalReachAccount
summary: Modify account information.
parameters:
@@ -234,7 +234,7 @@ paths:
/openroaming/globalreach/certificates/{account}:
get:
tags:
- OpenRoaming-Global Reach Certificate
- RadiusEndpointTypes-Global Reach Certificate
operationId: getOpenRoamingGlobalReachCertificateList
summary: Retrieve certificate list.
parameters:
@@ -283,7 +283,7 @@ paths:
/openroaming/globalreach/certificate/{account}/{id}:
get:
tags:
- OpenRoaming-Global Reach Certificate
- RadiusEndpointTypes-Global Reach Certificate
operationId: getOpenRoamingGlobalReachCertificate
summary: Retrieve certificate information.
parameters:
@@ -311,7 +311,7 @@ paths:
delete:
tags:
- OpenRoaming-Global Reach Certificate
- RadiusEndpointTypes-Global Reach Certificate
operationId: deleteOpenRoamingGlobalReachCertificate
summary: Delete certificate information.
parameters:
@@ -339,7 +339,7 @@ paths:
post:
tags:
- OpenRoaming-Global Reach Certificate
- RadiusEndpointTypes-Global Reach Certificate
operationId: createOpenRoamingGlobalReachCertificate
summary: Create certificate information.
parameters:
@@ -370,3 +370,38 @@ paths:
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- RadiusEndpointTypes-Global Reach Certificate
operationId: updateOpenRoamingGlobalReachCertificate
summary: Update certificate information.
parameters:
- in: path
description: The account name - this is the provisioning ID for the account. Not the GlobalReach ID.
name: account
schema:
type: string
required: true
- in: path
description: the UUID of the certificate
name: id
schema:
type: string
required: true
- in: query
description: Update an existing certificate
name: updateCertificate
schema:
type: boolean
default: false
required: false
responses:
200:
$ref: '#/components/schemas/GLBLRCertificateInfo'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -1,6 +1,6 @@
openapi: 3.0.1
info:
title: OpenWiFi OpenRoaming Provisioning Model for Google Orion
title: OpenWiFi RadiusEndpointTypes Provisioning Model for Google Orion
description: Definitions and APIs to Open Roaming WiFi.
version: 2.5.0
license:
@@ -54,7 +54,7 @@ paths:
/openroaming/orion/accounts:
get:
tags:
- OpenRoaming-Google Orion
- RadiusEndpointTypes-Google Orion
operationId: getOpenRoamingGlobalReachAccountList
summary: Retrieve account list.
parameters:
@@ -97,15 +97,16 @@ paths:
/openroaming/orion/account/{id}:
get:
tags:
- OpenRoaming-Google Orion
- RadiusEndpointTypes-Google Orion
operationId: getOpenRoamingGlobalReachAccount
summary: Retrieve account information.
parameters:
- in: path
description: The account name
name: name
description: The account ID
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
@@ -119,15 +120,16 @@ paths:
delete:
tags:
- OpenRoaming-Google Orion
- RadiusEndpointTypes-Google Orion
operationId: deleteOpenRoamingGlobalReachAccount
summary: Delete account information.
parameters:
- in: path
description: The account name
name: name
description: The account ID
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
@@ -141,15 +143,16 @@ paths:
post:
tags:
- OpenRoaming-Google Orion
- RadiusEndpointTypes-Google Orion
operationId: createOpenRoamingGlobalReachAccount
summary: Create account information.
parameters:
- in: path
description: The account name
name: name
description: The account ID
name: id
schema:
type: string
format: uuid
required: true
requestBody:
content:
@@ -168,15 +171,16 @@ paths:
put:
tags:
- OpenRoaming-Google Orion
- RadiusEndpointTypes-Google Orion
operationId: modifyOpenRoamingGlobalReachAccount
summary: Modify account information.
parameters:
- in: path
description: The account name
name: name
description: The account ID
name: id
schema:
type: string
format: uuid
required: true
requestBody:
content:

View File

@@ -0,0 +1,342 @@
openapi: 3.0.1
info:
title: OpenWiFi RADIUS Resource Model
description: Definitions and APIs to manage RADIUS Resources.
version: 1.0.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://localhost:16005/api/v1'
security:
- bearerAuth: []
- ApiKeyAuth: []
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-KEY
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
NotFound:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
Unauthorized:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
Success:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
BadRequest:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
schemas:
RADIUSServer:
type: object
properties:
Hostname:
type: string
IP:
type: string
Port:
type: integer
format: int32
Secret:
type: string
RADIUSEndPointRadiusType:
type: object
properties:
Authentication:
type: array
items:
$ref: '#/components/schemas/RADIUSServer'
Accounting:
type: array
items:
$ref: '#/components/schemas/RADIUSServer'
CoA:
type: array
items:
$ref: '#/components/schemas/RADIUSServer'
AccountingInterval:
type: integer
format: int32
RADIUSEndPointRadsecType:
type: object
properties:
Hostname:
type: string
IP:
type: string
Port:
type: integer
Secret:
type: string
default: radsec
UseOpenRoamingAccount:
type: string
format: uuid
Weight:
type: integer
format: int32
Certificate:
type: string
PrivateKey:
type: string
CaCerts:
type: array
items:
type: string
AllowSelfSigned:
type: boolean
default: false
RADIUSEndPoint:
type: object
properties:
allOf:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-owprov/blob/main/openpapi/owprov.yaml#/components/schemas/ObjectInfo'
Type:
type: string
enum:
- generic
- radsec
- globalreach
- orion
default: radius
RadsecServers:
type: array
items:
$ref: '#/components/schemas/RADIUSEndPointRadsecType'
RadiusServers:
type: array
items:
$ref: '#/components/schemas/RADIUSEndPointRadiusType'
PoolStrategy:
type: string
enum:
- round_robin
- weighted
- random
default: random
UseGWProxy:
type: boolean
default: true
Index:
type: string
example:
- 0.0.1.1: a ficticious IP address that should be between 0.0.1.1 and 0.0.2.254
UsedBy:
type: array
description: list of configuration using this endpoint
items:
type: string
format: uuid
NasIdentifier:
type: string
AccountingInterval:
type: integer
format: int64
RADIUSEndpointUpdateStatus:
type: object
properties:
lastUpdate:
type: integer
format: int64
lastConfigurationChange:
type: integer
format: int64
paths:
/RADIUSEndPoints:
get:
tags:
- RADIUS Endpoints
operationId: getRADIUSEndPoints
summary: Retrieve the lists of RADIUSendPoints
parameters:
- in: query
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: offset
schema:
type: integer
required: false
- in: query
description: Maximum number of entries to return (if absent, no limit is assumed)
name: limit
schema:
type: integer
required: false
- in: query
description: return the number of certificates
name: countOnly
schema:
type: boolean
required: false
- in: query
description: return the last update time
name: currentStatus
schema:
type: boolean
required: false
responses:
200:
description: The list of endpoints
content:
application/json:
schema:
oneOf:
- type: array
items:
$ref: '#/components/schemas/RADIUSEndPoint'
- $ref: '#/components/schemas/RADIUSEndpointUpdateStatus'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- RADIUS Endpoints
operationId: updateRADIUSEndpoints
summary: Force an Update to teh RADIUSendPoints in the controller
parameters:
- in: query
name: updateEndpoints
schema:
type: boolean
required: false
responses:
200:
description: The list of endpoints
content:
application/json:
schema:
type: object
properties:
Error:
type: string
ErrorNum:
type: integer
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/RADIUSEndPoint/{id}:
get:
tags:
- RADIUS Endpoints
operationId: getRADIUSEndPoint
summary: Retrieve a RADIUSendPoint
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
description: The endpoint
content:
application/json:
schema:
$ref: '#/components/schemas/RADIUSEndPoint'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- RADIUS Endpoints
operationId: deleteRADIUSEndPoint
summary: Delete a RADIUSendPoint
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
$ref: '#/components/responses/Success'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- RADIUS Endpoints
operationId: createRADIUSEndPoint
summary: Create a RADIUSendPoint
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RADIUSEndPoint'
responses:
200:
$ref: '#/components/schemas/RADIUSEndPoint'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- RADIUS Endpoints
operationId: modifyRADIUSEndPoint
summary: Modify a RADIUSendPoint
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RADIUSEndPoint'
responses:
200:
$ref: '#/components/schemas/RADIUSEndPoint'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -133,29 +133,32 @@ paths:
summary: Run a specific or default RRM algorithm. The UI user or CLI user will have the ability to run an algorithm on demand.
parameters:
- in: query
description:
description: The venue this algorithm should be run on.
name: venue
schema:
type: string
format: uuid
required: true
- in: query
description: Perform RRM without updating anything. This may be used by an admin to see what RRM would do.
name: mock
description: Perform RRM asynchronously, synchronously or in mockRun mode (without updating anything, this may be used by an admin to see what RRM would do).
name: mode
schema:
type: boolean
default: false
type: string
enum: [ async, sync, mockRun ]
required: false
- in: query
description: Specify the RRM algorithm to use. If omitted, select the default algorithm.
name: algorithm
schema:
type: string
required: false
- in: query
description: Specify the parameters to use with the RRM algorithm to use. If omitted, select the default parameters.
description: Specify the comma separated name=value parameters to use with the RRM algorithm to use. If omitted, select the default parameters.
name: parameters
schema:
type: string
required: false
responses:
200:
description: Return the list of actions that were or would be performed.

View File

@@ -9,6 +9,11 @@
#include "Poco/StringTokenizer.h"
#include "fmt/format.h"
#include <RadiusEndpointTypes/OrionWifi.h>
#include <RadiusEndpointTypes/GlobalReach.h>
#include <RadiusEndpointTypes/Radsec.h>
#include <RadiusEndpointTypes/GenericRadius.h>
namespace OpenWifi {
APConfig::APConfig(const std::string &SerialNumber, const std::string &DeviceType,
@@ -55,75 +60,128 @@ namespace OpenWifi {
*/
}
bool APConfig::ReplaceVariablesInObject(const Poco::JSON::Object::Ptr &Original,
Poco::JSON::Object::Ptr &Result) {
bool APConfig::InsertRadiusEndPoint(const ProvObjects::RADIUSEndPoint &RE, Poco::JSON::Object &Result) {
if(RE.UseGWProxy) {
Poco::JSON::Object ServerSettings;
if (RE.Type == "orion") {
return OpenRoaming_Orion()->Render(RE, SerialNumber_, Result);
} else if (RE.Type == "globalreach") {
return OpenRoaming_GlobalReach()->Render(RE, SerialNumber_, Result);
} else if (RE.Type == "radsec") {
return OpenRoaming_Radsec()->Render(RE, SerialNumber_, Result);
} else if (RE.Type == "generic") {
return OpenRoaming_GenericRadius()->Render(RE, SerialNumber_, Result);
}
Result.set( "radius" , ServerSettings);
} else {
std::cout << "Radius proxy off" << RE.info.name << std::endl;
}
return false;
}
bool APConfig::ReplaceVariablesInObject(const Poco::JSON::Object &Original,
Poco::JSON::Object &Result) {
// get all the names and expand
auto Names = Original->getNames();
auto Names = Original.getNames();
for (const auto &i : Names) {
if (i == "__variableBlock") {
if (Original->isArray(i)) {
auto UUIDs = Original->getArray(i);
for (const auto &uuid : *UUIDs) {
ProvObjects::VariableBlock VB;
if (StorageService()->VariablesDB().GetRecord("id", uuid, VB)) {
for (const auto &var : VB.variables) {
Poco::JSON::Parser P;
auto VariableBlockInfo =
P.parse(var.value).extract<Poco::JSON::Object::Ptr>();
auto VarNames = VariableBlockInfo->getNames();
for (const auto &j : VarNames) {
Result->set(j, VariableBlockInfo->get(j));
}
}
}
}
}
} else if (Original->isArray(i)) {
auto Arr = Poco::makeShared<Poco::JSON::Array>();
auto Obj = Original->getArray(i);
ReplaceVariablesInArray(Obj, Arr);
Result->set(i, Arr);
} else if (Original->isObject(i)) {
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
auto Obj = Original->getObject(i);
ReplaceVariablesInObject(Obj, Expanded);
Result->set(i, Expanded);
if (i == "__variableBlock") {
if (Original.isArray(i)) {
auto UUIDs = Original.getArray(i);
for (const auto &uuid: *UUIDs) {
ProvObjects::VariableBlock VB;
if (StorageService()->VariablesDB().GetRecord("id", uuid, VB)) {
for (const auto &var: VB.variables) {
Poco::JSON::Parser P;
auto VariableBlockInfo =
P.parse(var.value).extract<Poco::JSON::Object::Ptr>();
auto VarNames = VariableBlockInfo->getNames();
for (const auto &j: VarNames) {
// std::cout << "Name: " << j << std::endl;
if(VariableBlockInfo->isArray(j)) {
auto Elements = VariableBlockInfo->getArray(j);
if(Elements->size()>0) {
Poco::JSON::Array InnerArray;
ReplaceVariablesInArray(*Elements, InnerArray);
Result.set(j, InnerArray);
// std::cout << "Array!!!" << std::endl;
} else {
// std::cout << "Empty Array!!!" << std::endl;
}
} else if(VariableBlockInfo->isObject(j)) {
Poco::JSON::Object InnerEval;
// std::cout << "Visiting object " << j << std::endl;
auto O = VariableBlockInfo->getObject(j);
ReplaceVariablesInObject(*O,InnerEval);
Result.set(j, InnerEval);
} else {
Result.set(j, VariableBlockInfo->get(j));
}
}
}
}
}
}
} else if (i == "__radiusEndpoint") {
auto EndPointId = Original.get(i).toString();
ProvObjects::RADIUSEndPoint RE;
// std::cout << "ID->" << EndPointId << std::endl;
if(StorageService()->RadiusEndpointDB().GetRecord("id",EndPointId,RE)) {
InsertRadiusEndPoint(RE, Result);
} else {
poco_error(Logger_, fmt::format("RADIUS Endpoint {} could not be found. Please delete this configuration and recreate it."));
return false;
}
} else if (Original.isArray(i)) {
Poco::JSON::Array Arr;
auto Obj = Original.getArray(i);
if(Obj->size()>0) {
ReplaceVariablesInArray(*Obj, Arr);
Result.set(i, Arr);
}
} else if (Original.isObject(i)) {
Poco::JSON::Object Expanded;
auto Obj = Original.getObject(i);
ReplaceVariablesInObject(*Obj, Expanded);
Result.set(i, Expanded);
} else {
Result->set(i, Original->get(i));
Result.set(i, Original.get(i));
}
}
return true;
}
bool APConfig::ReplaceVariablesInArray(const Poco::JSON::Array::Ptr &Original,
Poco::JSON::Array::Ptr &ResultArray) {
for (const auto &element : *Original) {
bool APConfig::ReplaceVariablesInArray(const Poco::JSON::Array &Original,
Poco::JSON::Array &ResultArray) {
for (const auto &element : Original) {
// std::cout << element.toString() << std::endl;
if (element.isArray()) {
auto Expanded = Poco::makeShared<Poco::JSON::Array>();
const auto &Object = element.extract<Poco::JSON::Array::Ptr>();
ReplaceVariablesInArray(Object, Expanded);
ResultArray->add(Expanded);
Poco::JSON::Array Expanded;
const auto Object = element.extract<Poco::JSON::Array::Ptr>();
if(Object->size()>0) {
ReplaceVariablesInArray(*Object, Expanded);
ResultArray.add(Expanded);
}
} else if (element.isStruct()) {
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
Poco::JSON::Object Expanded;
const auto &Object = element.extract<Poco::JSON::Object::Ptr>();
ReplaceVariablesInObject(Object, Expanded);
ResultArray->add(Expanded);
ReplaceVariablesInObject(*Object, Expanded);
ResultArray.add(Expanded);
} else if (element.isString() || element.isNumeric() || element.isBoolean() ||
element.isInteger() || element.isSigned()) {
ResultArray->add(element);
ResultArray.add(element);
} else {
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
Poco::JSON::Object Expanded;
const auto &Object = element.extract<Poco::JSON::Object::Ptr>();
ReplaceVariablesInObject(Object, Expanded);
ResultArray->add(Expanded);
ReplaceVariablesInObject(*Object, Expanded);
ResultArray.add(Expanded);
}
}
return true;
}
bool APConfig::Get(Poco::JSON::Object::Ptr &Configuration) {
if (Config_.empty()) {
Explanation_.clear();
try {
@@ -177,8 +235,8 @@ namespace OpenWifi {
ExObj.set("element", OriginalArray);
Explanation_.add(ExObj);
}
auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>();
ReplaceVariablesInArray(OriginalArray, ExpandedArray);
Poco::JSON::Array ExpandedArray;
ReplaceVariablesInArray(*OriginalArray, ExpandedArray);
Configuration->set(SectionName, ExpandedArray);
} else if (O->isObject(SectionName)) {
auto OriginalSection =
@@ -191,8 +249,8 @@ namespace OpenWifi {
ExObj.set("element", OriginalSection);
Explanation_.add(ExObj);
}
auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>();
ReplaceVariablesInObject(OriginalSection, ExpandedSection);
Poco::JSON::Object ExpandedSection;
ReplaceVariablesInObject(*OriginalSection, ExpandedSection);
Configuration->set(SectionName, ExpandedSection);
} else {
poco_warning(Logger(), fmt::format("Unknown config element type: {}",O->get(SectionName).toString()));
@@ -225,7 +283,7 @@ namespace OpenWifi {
RadioArray->get(RadioIndex).extract<Poco::JSON::Object::Ptr>();
if (Tokens[2] == "tx-power") {
IndexedRadio->set(
"rx-power",
"tx-power",
std::strtoull(col.parameterValue.c_str(), nullptr, 10));
if (Explain_) {
Poco::JSON::Object ExObj;
@@ -317,6 +375,7 @@ namespace OpenWifi {
ProvObjects::DeviceConfiguration Config;
if (StorageService()->ConfigurationDB().GetRecord("id", UUID, Config)) {
// std::cout << Config.info.name << ":" << Config.configuration.size() << std::endl;
if (!Config.configuration.empty()) {
if (DeviceTypeMatch(DeviceType_, Config.deviceTypes)) {
for (const auto &i : Config.configuration) {

View File

@@ -45,10 +45,10 @@ namespace OpenWifi {
bool Sub_ = false;
Poco::Logger &Logger() { return Logger_; }
bool ReplaceVariablesInArray(const Poco::JSON::Array::Ptr &O,
Poco::JSON::Array::Ptr &Result);
bool ReplaceVariablesInObject(const Poco::JSON::Object::Ptr &Original,
Poco::JSON::Object::Ptr &Result);
bool ReplaceVariablesInArray(const Poco::JSON::Array &O,
Poco::JSON::Array &Result);
bool ReplaceVariablesInObject(const Poco::JSON::Object &Original,
Poco::JSON::Object &Result);
bool FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr,
Poco::JSON::Object::Ptr &Radio);
@@ -58,5 +58,6 @@ namespace OpenWifi {
Poco::JSON::Object::Ptr &C);
bool RemoveBand(const std::string &Band, const Poco::JSON::Array::Ptr &A_in,
Poco::JSON::Array::Ptr &A_Out);
bool InsertRadiusEndPoint(const ProvObjects::RADIUSEndPoint &EP, Poco::JSON::Object &Result);
};
} // namespace OpenWifi

View File

@@ -23,7 +23,10 @@
#include "UI_Prov_WebSocketNotifications.h"
#include "framework/ConfigurationValidator.h"
#include "framework/UI_WebSocketClientServer.h"
#include "OpenRoamin_GlobalReach.h"
#include <RadiusEndpointTypes/GlobalReach.h>
#include <RadiusEndpointTypes/OrionWifi.h>
#include <RadiusEndpointTypes/Radsec.h>
#include <RadiusEndpointTypes/GenericRadius.h>
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
@@ -37,7 +40,9 @@ namespace OpenWifi {
AutoDiscovery(), JobController(),
UI_WebSocketClientServer(), FindCountryFromIP(),
Signup(), FileDownloader(),
OpenRoaming_GlobalReach()
OpenRoaming_GlobalReach(),
OpenRoaming_Orion(), OpenRoaming_Radsec(),
OpenRoaming_GenericRadius()
});
}
return instance_;

View File

@@ -63,17 +63,9 @@ namespace OpenWifi {
std::lock_guard G(Mutex_);
Initialized_ = true;
std::string DeviceTypes;
if (AppServiceRegistry().Get("deviceTypes", DeviceTypes)) {
Poco::JSON::Parser P;
try {
auto O = P.parse(DeviceTypes).extract<Poco::JSON::Array::Ptr>();
for (const auto &i : *O) {
DeviceTypes_.insert(i.toString());
}
} catch (...) {
}
}
std::vector<std::string> DeviceTypes;
AppServiceRegistry().Get("deviceTypes", DeviceTypes);
std::for_each(DeviceTypes.begin(),DeviceTypes.end(),[&](const std::string &s){ DeviceTypes_.insert(s);});
}
inline bool UpdateDeviceTypes() {
@@ -107,15 +99,9 @@ namespace OpenWifi {
inline void SaveCache() {
std::lock_guard G(Mutex_);
Poco::JSON::Array Arr;
for (auto const &i : DeviceTypes_)
Arr.add(i);
std::stringstream OS;
Arr.stringify(OS);
AppServiceRegistry().Set("deviceTypes", OS.str());
std::vector<std::string> DeviceTypes;
std::for_each(DeviceTypes_.begin(),DeviceTypes_.end(),[&](const std::string &s){DeviceTypes.emplace_back(s);});
AppServiceRegistry().Set("deviceTypes", DeviceTypes);
}
};

View File

@@ -24,8 +24,15 @@ namespace OpenWifi {
void FileDownloader::onTimer([[maybe_unused]] Poco::Timer &timer) {
const static std::vector<std::pair<std::string, std::string>> Files{
{ "https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/ucentral.schema.json",
"ucentral.schema.json"} };
{
"https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/ucentral.schema.pretty.json",
"ucentral.schema.pretty.json"
},
{
"https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/ucentral.schema.json",
"ucentral.schema.json"
}
};
Utils::SetThreadName("file-dmnldr");

View File

@@ -1,196 +0,0 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "OpenRoamin_GlobalReach.h"
#include <Poco/JWT/Token.h>
#include <Poco/JWT/Signer.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/URI.h>
#include <Poco/TemporaryFile.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <framework/RESTAPI_Handler.h>
#include <framework/MicroServiceFuncs.h>
#include <StorageService.h>
namespace OpenWifi {
int OpenRoaming_GlobalReach::Start() {
poco_information(Logger(), "Starting...");
InitCache();
return 0;
}
void OpenRoaming_GlobalReach::Stop() {
poco_information(Logger(), "Stopping...");
poco_information(Logger(), "Stopped...");
}
void OpenRoaming_GlobalReach::InitCache() {
auto F=[&](const ProvObjects::GLBLRAccountInfo &Info) {
poco_information(Logger(),fmt::format("Adding {} to cache.",Info.info.name));
if(!Info.privateKey.empty() && !Info.GlobalReachAcctId.empty() ) {
MakeToken(Info.GlobalReachAcctId, Info.privateKey);
}
return true;
};
StorageService()->GLBLRAccountInfoDB().Iterate(F);
}
bool OpenRoaming_GlobalReach::CreateRADSECCertificate(
const std::string &GlobalReachAccountId,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
try {
std::cout << __LINE__ << ":" << GlobalReachAccountId << std::endl;
auto BearerToken = MakeToken(GlobalReachAccountId);
Poco::URI URI{"https://config.openro.am/v1/radsec/issue"};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Poco::JSON::Object CertRequestBody;
CertRequestBody.set("name", Name);
CertRequestBody.set("csr", CSR);
std::ostringstream os;
CertRequestBody.stringify(os);
Request.setContentType("application/json");
Request.setContentLength((long) os.str().size());
auto &Body = Session.sendRequest(Request);
Body << os.str();
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
RESTAPIHandler::AssignIfPresent(Result,"certificate",NewCertificate.certificate);
RESTAPIHandler::AssignIfPresent(Result,"certificate_chain",NewCertificate.certificateChain);
RESTAPIHandler::AssignIfPresent(Result,"certificate_id",NewCertificate.certificateId);
RESTAPIHandler::AssignIfPresent(Result,"expires_at",NewCertificate.expiresAt);
return true;
}
Poco::JSON::Parser P;
std::ostringstream oos;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
Result->stringify(oos);
} catch( const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Could not create a new RADSEC certificate: {},{}",E.name(),E.displayText()));
}
return false;
}
bool OpenRoaming_GlobalReach::GetRADSECCertificate(
const std::string &GlobalReachAccountId,
std::string &CertificateId,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
try {
Poco::URI URI{fmt::format("https://config.openro.am/v1/radsec/cert/{}", CertificateId)};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
auto BearerToken = MakeToken(GlobalReachAccountId);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
RESTAPIHandler::AssignIfPresent(Result,"certificate",NewCertificate.certificate);
RESTAPIHandler::AssignIfPresent(Result,"certificate_chain",NewCertificate.certificateChain);
RESTAPIHandler::AssignIfPresent(Result,"certificate_id",NewCertificate.certificateId);
RESTAPIHandler::AssignIfPresent(Result,"expires_at",NewCertificate.expiresAt);
return true;
}
} catch( const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Could not retrieve the certificate from GlobalReach: {},{}",E.name(),E.displayText()));
}
return false;
}
std::string OpenRoaming_GlobalReach::MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey) {
try {
Poco::JWT::Token token;
token.setType("JWT");
token.setAlgorithm("ES256");
token.setIssuedAt(std::time(nullptr));
token.payload().set("iss", GlobalReachAccountId);
token.payload().set("iat", (unsigned long) std::time(nullptr));
Poco::SharedPtr<Poco::Crypto::ECKey> Key;
auto KeyHash = Utils::ComputeHash(PrivateKey);
auto KeyHint = PrivateKeys_.find(GlobalReachAccountId);
if (KeyHint != PrivateKeys_.end() && PrivateKey.empty() ) {
Key = KeyHint->second.second;
} else {
if (PrivateKey.empty()) {
return "";
}
Poco::TemporaryFile F;
std::ofstream ofs(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
ofs << PrivateKey;
ofs.close();
auto NewKey = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(), ""));
Key = NewKey;
PrivateKeys_[GlobalReachAccountId] = std::make_pair(KeyHash, NewKey);
}
Poco::JWT::Signer Signer;
Signer.setECKey(Key);
Signer.addAllAlgorithms();
return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256);
} catch (const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Cannot create a Global Reach token: {},{}",E.name(),E.displayText()));
}
return "";
}
bool OpenRoaming_GlobalReach::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name) {
auto BearerToken = MakeToken(GlobalReachAccountId, PrivateKey);
Poco::URI URI{"https://config.openro.am/v1/config"};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
if(Result->has("name")) {
Name = Result->get("name").toString();
}
return true;
}
return false;
}
} // OpenWifi

View File

@@ -1,43 +0,0 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "framework/SubSystemServer.h"
#include "Poco/JSON/Object.h"
#include "RESTObjects/RESTAPI_ProvObjects.h"
namespace OpenWifi {
class OpenRoaming_GlobalReach : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new OpenRoaming_GlobalReach;
return instance_;
}
int Start() override;
void Stop() override;
bool CreateRADSECCertificate(const std::string &AccountName,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool GetRADSECCertificate(const std::string &AccountName, std::string & CertificateId, ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name);
void InitCache();
private:
std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey="");
std::map<std::string,std::pair<std::string,Poco::SharedPtr<Poco::Crypto::ECKey>>> PrivateKeys_;
OpenRoaming_GlobalReach() noexcept
: SubSystemServer("OpenRoaming_GlobalReach", "GLBL-REACH", "globalreach") {
}
};
inline auto OpenRoaming_GlobalReach() { return OpenRoaming_GlobalReach::instance(); }
} // OpenWifi

View File

@@ -3,7 +3,7 @@
//
#include "RESTAPI_openroaming_gr_acct_handler.h"
#include "OpenRoamin_GlobalReach.h"
#include <RadiusEndpointTypes/GlobalReach.h>
namespace OpenWifi {
@@ -13,7 +13,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo Record;
RecordType Record;
if(DB_.GetRecord("id",Account,Record)) {
return ReturnObject(Record);
}
@@ -26,7 +26,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo Record;
RecordType Record;
if(!DB_.GetRecord("id",Account,Record)) {
return NotFound();
}
@@ -44,7 +44,7 @@ namespace OpenWifi {
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRAccountInfo NewObject;
RecordType NewObject;
if( !NewObject.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
@@ -85,7 +85,7 @@ namespace OpenWifi {
ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewObject.info);
if(DB_.CreateRecord(NewObject)) {
ProvObjects::GLBLRAccountInfo StoredObject;
RecordType StoredObject;
DB_.GetRecord("id",NewObject.info.id,StoredObject);
return ReturnObject(StoredObject);
}
@@ -100,12 +100,12 @@ namespace OpenWifi {
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRAccountInfo Modify;
RecordType Modify;
if(!Modify.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
ProvObjects::GLBLRAccountInfo Existing;
RecordType Existing;
if(!DB_.GetRecord("id",Account,Existing)) {
return NotFound();
}
@@ -115,7 +115,7 @@ namespace OpenWifi {
}
if(DB_.UpdateRecord("id",Existing.info.id,Existing)) {
ProvObjects::GLBLRAccountInfo StoredObject;
RecordType StoredObject;
DB_.GetRecord("id",Existing.info.id,StoredObject);
return ReturnObject(StoredObject);
}

View File

@@ -22,6 +22,7 @@ namespace OpenWifi {
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/account/{id}"}; };
private:
using RecordType = ProvObjects::GLBLRAccountInfo;
GLBLRAccountInfoDB &DB_ = StorageService()->GLBLRAccountInfoDB();
void DoGet() final;
void DoPost() final;

View File

@@ -3,7 +3,7 @@
//
#include "RESTAPI_openroaming_gr_cert_handler.h"
#include <OpenRoamin_GlobalReach.h>
#include <RadiusEndpointTypes/GlobalReach.h>
namespace OpenWifi {
@@ -19,7 +19,7 @@ namespace OpenWifi {
return NotFound();
}
std::vector<ProvObjects::GLBLRCertificateInfo> Certificates;
std::vector<RecordType> Certificates;
DB_.GetRecords(0,1,Certificates,fmt::format(" accountId='{}' and id='{}' ", Account, Id));
if(Certificates.empty()) {
return NotFound();
@@ -51,7 +51,7 @@ namespace OpenWifi {
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRCertificateInfo NewObject;
RecordType NewObject;
if( !NewObject.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
@@ -71,7 +71,7 @@ namespace OpenWifi {
NewObject.created = Utils::Now();
NewObject.csr = AccountInfo.CSR;
DB_.CreateRecord(NewObject);
ProvObjects::GLBLRCertificateInfo CreatedObject;
RecordType CreatedObject;
DB_.GetRecord("id",NewObject.id,CreatedObject);
return ReturnObject(CreatedObject);
}
@@ -79,4 +79,35 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_openroaming_gr_cert_handler::DoPut() {
auto Account = GetBinding("account","");
auto Id = GetBinding("id","");
auto UpdateCertificate = GetBoolParameter("updateCertificate",false);
if(Account.empty() || Id.empty() || !UpdateCertificate){
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo AccountInfo;
if(!StorageService()->GLBLRAccountInfoDB().GetRecord("id",Account, AccountInfo)) {
return BadRequest(RESTAPI::Errors::InvalidGlobalReachAccount);
}
ProvObjects::GLBLRCertificateInfo Existing;
if(!DB_.GetRecord("id",Id,Existing)) {
return NotFound();
}
if(OpenRoaming_GlobalReach()->CreateRADSECCertificate(AccountInfo.GlobalReachAcctId,Existing.name,AccountInfo.CSR, Existing)) {
Existing.created = Utils::Now();
DB_.UpdateRecord("id",Existing.id,Existing);
RecordType CreatedObject;
DB_.GetRecord("id",Existing.id,CreatedObject);
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.ChangeConfiguration();
return ReturnObject(CreatedObject);
}
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
} // OpenWifi

View File

@@ -16,15 +16,17 @@ namespace OpenWifi {
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/certificate/{account}/{id}"}; };
private:
using RecordType = ProvObjects::GLBLRCertificateInfo;
GLBLRCertsDB &DB_ = StorageService()->GLBLRCertsDB();
void DoGet() final;
void DoPost() final;
void DoPut() final {};
void DoPut() final ;
void DoDelete() final;
};
} // namespace OpenWifi

View File

@@ -12,7 +12,7 @@ namespace OpenWifi {
return ReturnCountOnly(DB_.Count());
}
std::vector<ProvObjects::GLBLRAccountInfo> Accounts;
std::vector<RecordType> Accounts;
DB_.GetRecords(QB_.Offset,QB_.Limit,Accounts);
return ReturnObject(Accounts);
}

View File

@@ -20,6 +20,7 @@ namespace OpenWifi {
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/accounts"}; };
private:
using RecordType = ProvObjects::GLBLRAccountInfo;
GLBLRAccountInfoDB &DB_ = StorageService()->GLBLRAccountInfoDB();
void DoGet() final;
void DoPost() final{};

View File

@@ -7,19 +7,28 @@
namespace OpenWifi {
void RESTAPI_openroaming_gr_list_certificates::DoGet() {
auto Account = GetBinding("account","");
auto Account = GetBinding("account");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto Where = fmt::format(" accountId='{}'", Account);
if(Account=="*") {
std::vector< ProvObjects::GLBLRCertificateInfo> Arr;
for(const auto &cert:QB_.Select) {
ProvObjects::GLBLRCertificateInfo CInfo;
if(StorageService()->GLBLRCertsDB().GetRecord("id",cert,CInfo)) {
Arr.emplace_back(CInfo);
}
}
return ReturnObject(Arr);
}
auto Where = fmt::format(" accountId='{}'", Account);
if(GetBoolParameter("countOnly")) {
return ReturnCountOnly(DB_.Count(Where));
}
std::vector<ProvObjects::GLBLRCertificateInfo> Certificates;
std::vector<RecordType> Certificates;
DB_.GetRecords(QB_.Offset,QB_.Limit,Certificates, Where);
return ReturnObject(Certificates);
}

View File

@@ -19,6 +19,7 @@ namespace OpenWifi {
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/certificates/{account}"}; };
private:
using RecordType = ProvObjects::GLBLRCertificateInfo;
GLBLRCertsDB &DB_ = StorageService()->GLBLRCertsDB();
void DoGet() final;
void DoPost() final{};

View File

@@ -3,7 +3,6 @@
//
#include "RESTAPI_openroaming_orion_acct_handler.h"
#include "OpenRoamin_GlobalReach.h"
namespace OpenWifi {
@@ -13,7 +12,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GooglOrionAccountInfo Record;
RecordType Record;
if(DB_.GetRecord("id",Account,Record)) {
return ReturnObject(Record);
}
@@ -26,7 +25,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GooglOrionAccountInfo Record;
RecordType Record;
if(!DB_.GetRecord("id",Account,Record)) {
return NotFound();
}
@@ -41,7 +40,7 @@ namespace OpenWifi {
}
const auto &RawObject = ParsedBody_;
ProvObjects::GooglOrionAccountInfo NewObject;
RecordType NewObject;
if( !NewObject.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
@@ -61,7 +60,7 @@ namespace OpenWifi {
ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewObject.info);
if(DB_.CreateRecord(NewObject)) {
ProvObjects::GooglOrionAccountInfo StoredObject;
RecordType StoredObject;
DB_.GetRecord("id",NewObject.info.id,StoredObject);
return ReturnObject(StoredObject);
}
@@ -75,12 +74,12 @@ namespace OpenWifi {
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRAccountInfo Modify;
RecordType Modify;
if(!Modify.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
ProvObjects::GooglOrionAccountInfo Existing;
RecordType Existing;
if(!DB_.GetRecord("id",Account,Existing)) {
return NotFound();
}
@@ -90,7 +89,7 @@ namespace OpenWifi {
}
if(DB_.UpdateRecord("id",Existing.info.id,Existing)) {
ProvObjects::GooglOrionAccountInfo StoredObject;
RecordType StoredObject;
DB_.GetRecord("id",Existing.info.id,StoredObject);
return ReturnObject(StoredObject);
}

View File

@@ -22,6 +22,7 @@ namespace OpenWifi {
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/orion/account/{id}"}; };
private:
using RecordType = ProvObjects::GooglOrionAccountInfo;
OrionAccountsDB &DB_ = StorageService()->OrionAccountsDB();
void DoGet() final;
void DoPost() final;

View File

@@ -8,12 +8,10 @@
namespace OpenWifi {
void RESTAPI_openroaming_orion_list_acct_handler::DoGet() {
if(GetBoolParameter("countOnly")) {
return ReturnCountOnly(DB_.Count());
}
std::vector<ProvObjects::GooglOrionAccountInfo> Accounts;
std::vector<RecordType > Accounts;
DB_.GetRecords(QB_.Offset,QB_.Limit,Accounts);
return ReturnObject(Accounts);
}

View File

@@ -19,6 +19,7 @@ namespace OpenWifi {
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/orion/accounts"}; };
private:
using RecordType = ProvObjects::GooglOrionAccountInfo;
OrionAccountsDB &DB_ = StorageService()->OrionAccountsDB();
void DoGet() final;
void DoPost() final{};

View File

@@ -0,0 +1,202 @@
//
// Created by stephane bourque on 2023-09-27.
//
#include "RESTAPI_radius_endpoint_handler.h"
#include <storage/storage_orion_accounts.h>
#include <RESTObjects/RESTAPI_GWobjects.h>
namespace OpenWifi {
void RESTAPI_radius_endpoint_handler::DoGet() {
auto id = GetBinding("id");
if(id.empty()) {
return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation);
}
RecordType Record;
if(DB_.GetRecord("id",id,Record)) {
return ReturnObject(Record);
}
return NotFound();
}
void RESTAPI_radius_endpoint_handler::DoDelete() {
auto id = GetBinding("id");
if(id.empty()) {
return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation);
}
RecordType Record;
if(DB_.GetRecord("id",id,Record)) {
DB_.DeleteRecord("id",id);
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.ChangeConfiguration();
return OK();
}
return NotFound();
}
static bool ValidPort(std::uint32_t P) {
return P>0 && P<65535;
}
static bool ValidRadiusServer(const ProvObjects::RADIUSServer &S) {
if(S.Hostname.empty() || !ValidPort(S.Port) || !Utils::ValidIP(S.IP) || S.Secret.empty()) {
return false;
}
return true;
}
static bool ValidRadiusServer(const std::vector<ProvObjects::RADIUSServer> &ServerList) {
return std::all_of(ServerList.begin(),ServerList.end(),[](const ProvObjects::RADIUSServer &Server)->bool { return ValidRadiusServer(Server); });
}
void RESTAPI_radius_endpoint_handler::DoPost() {
auto id = GetBinding("id");
if(id.empty()) {
return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation);
}
const auto &RawObject = ParsedBody_;
RecordType NewRecord;
if(!NewRecord.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(GWObjects::RadiusEndpointType(NewRecord.Type)==GWObjects::RadiusEndpointType::unknown) {
return BadRequest(RESTAPI::Errors::InvalidRadiusTypeEndpoint);
}
if(GWObjects::RadiusPoolStrategy(NewRecord.PoolStrategy)==GWObjects::RadiusPoolStrategy::unknown) {
return BadRequest(RESTAPI::Errors::InvalidRadiusEndpointPoolStrategy);
}
if(!NewRecord.RadiusServers.empty() && !NewRecord.RadsecServers.empty()) {
return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers);
}
auto EndPointType = GWObjects::RadiusEndpointType(NewRecord.Type);
switch(EndPointType) {
case GWObjects::RadiusEndpointType::radsec:
case GWObjects::RadiusEndpointType::orion:
case GWObjects::RadiusEndpointType::globalreach:
{
if(NewRecord.RadsecServers.empty()) {
return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers);
}
} break;
case GWObjects::RadiusEndpointType::generic: {
if(NewRecord.RadiusServers.empty()) {
return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers);
}
} break;
default:
return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers);
}
if(NewRecord.Index.empty() || !RadiusEndpointDB::ValidIndex(NewRecord.Index)) {
return BadRequest(RESTAPI::Errors::RadiusEndpointIndexInvalid);
}
// Make sure that nobody is using that index
auto where = fmt::format(" index='{}' ", NewRecord.Index);
if(DB_.Count(where)!=0) {
return BadRequest(RESTAPI::Errors::RadiusEndpointIndexInvalid);
}
if(EndPointType==GWObjects::RadiusEndpointType::generic) {
for(const auto &Server:NewRecord.RadiusServers) {
if(!ValidRadiusServer(Server.Authentication) ||
!ValidRadiusServer(Server.Accounting) ||
!ValidRadiusServer(Server.CoA)) {
return BadRequest(RESTAPI::Errors::InvalidRadiusServer);
}
}
} else {
switch(EndPointType) {
case GWObjects::RadiusEndpointType::orion: {
for(const auto &Server:NewRecord.RadsecServers) {
if(!StorageService()->OrionAccountsDB().Exists("id",Server.UseOpenRoamingAccount)) {
return BadRequest(RESTAPI::Errors::OrionAccountMustExist);
}
}
} break;
case GWObjects::RadiusEndpointType::globalreach: {
for(const auto &Server:NewRecord.RadsecServers) {
if(!StorageService()->GLBLRCertsDB().Exists("id",Server.UseOpenRoamingAccount)) {
return BadRequest(RESTAPI::Errors::GlobalReachCertMustExist);
}
}
} break;
case GWObjects::RadiusEndpointType::radsec: {
for(const auto &Server:NewRecord.RadsecServers) {
if(Server.Certificate.empty() || !Utils::ValidX509Certificate(Server.Certificate)) {
return BadRequest(RESTAPI::Errors::InvalidRadsecMainCertificate);
}
if(Server.CaCerts.empty() || !Utils::ValidX509Certificate(Server.CaCerts)) {
return BadRequest(RESTAPI::Errors::InvalidRadsecCaCertificate);
}
if(Server.PrivateKey.empty() || !Utils::VerifyPrivateKey(Server.PrivateKey)) {
return BadRequest(RESTAPI::Errors::InvalidRadsecPrivteKey);
}
if(!Utils::ValidIP(Server.IP)) {
return BadRequest(RESTAPI::Errors::InvalidRadsecIPAddress);
}
if(!(Server.Port>0 && Server.Port<65535)) {
return BadRequest(RESTAPI::Errors::InvalidRadsecPort);
}
if(Server.Secret.empty()) {
return BadRequest(RESTAPI::Errors::InvalidRadsecSecret);
}
}
} break;
default: {
}
}
}
ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewRecord.info);
if(DB_.CreateRecord(NewRecord)) {
RecordType AddedRecord;
DB_.GetRecord("id", NewRecord.info.id, AddedRecord);
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.ChangeConfiguration();
return ReturnObject(AddedRecord);
}
return BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_radius_endpoint_handler::DoPut() {
auto id = GetBinding("id");
if(id.empty()) {
return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation);
}
const auto &RawObject = ParsedBody_;
RecordType ModifiedRecord;
if(!ModifiedRecord.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
RecordType Existing;
if(!DB_.GetRecord("id",id,Existing)) {
return NotFound();
}
AssignIfPresent(RawObject,"NasIdentifier", Existing.NasIdentifier);
AssignIfPresent(RawObject,"AccountingInterval", Existing.AccountingInterval);
ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
if(DB_.UpdateRecord("id", Existing.info.id, Existing)) {
RecordType AddedRecord;
DB_.GetRecord("id", Existing.info.id, AddedRecord);
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.ChangeConfiguration();
return ReturnObject(AddedRecord);
}
return BadRequest(RESTAPI::Errors::NotImplemented);
}
} // OpenWifi

View File

@@ -0,0 +1,33 @@
//
// Created by stephane bourque on 2023-09-27.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_radius_endpoint_handler : public RESTAPIHandler {
public:
RESTAPI_radius_endpoint_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/RADIUSEndPoint/{id}"}; };
private:
using RecordType = ProvObjects::RADIUSEndPoint;
RadiusEndpointDB &DB_ = StorageService()->RadiusEndpointDB();
void DoGet() final;
void DoPost() final;
void DoPut() final;
void DoDelete() final;
};
} // namespace OpenWifi

View File

@@ -0,0 +1,49 @@
//
// Created by stephane bourque on 2023-09-27.
//
#include "RESTAPI_radiusendpoint_list_handler.h"
#include "framework/AppServiceRegistry.h"
#include "RadiusEndpointUpdater.h"
namespace OpenWifi {
void RESTAPI_radiusendpoint_list_handler::DoGet() {
if(GetBoolParameter("currentStatus")) {
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.Read();
return ReturnObject(Status);
}
if(QB_.CountOnly) {
return ReturnCountOnly(DB_.Count());
}
std::vector<RecordType> Records;
DB_.GetRecords(QB_.Offset,QB_.Limit,Records);
return ReturnObject(Records);
}
void RESTAPI_radiusendpoint_list_handler::DoPut() {
if( UserInfo_.userinfo.userRole!=SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN) {
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
}
if(GetBoolParameter("updateEndpoints")) {
RadiusEndpointUpdater R;
std::uint64_t ErrorCode;
std::string ErrorDetails;
std::string ErrorDescription;
if(!R.UpdateEndpoints(this, ErrorCode, ErrorDetails,ErrorDescription)) {
return InternalError(RESTAPI::Errors::msg{.err_num = ErrorCode, .err_txt = ErrorDetails + ":" + ErrorDescription});
}
return OK();
}
return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation);
}
} // OpenWifi

View File

@@ -0,0 +1,31 @@
//
// Created by stephane bourque on 2023-09-27.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_radiusendpoint_list_handler : public RESTAPIHandler {
public:
RESTAPI_radiusendpoint_list_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/RADIUSEndPoints"}; };
private:
using RecordType = ProvObjects::RADIUSEndPoint;
RadiusEndpointDB &DB_ = StorageService()->RadiusEndpointDB();
void DoGet() final;
void DoPost() final{};
void DoPut() final;
void DoDelete() final{};
};
} // namespace OpenWifi

View File

@@ -41,6 +41,8 @@
#include "RESTAPI/RESTAPI_openroaming_gr_list_certificates.h"
#include "RESTAPI/RESTAPI_openroaming_orion_acct_handler.h"
#include "RESTAPI/RESTAPI_openroaming_orion_list_acct_handler.h"
#include "RESTAPI/RESTAPI_radiusendpoint_list_handler.h"
#include "RESTAPI/RESTAPI_radius_endpoint_handler.h"
#include "framework/RESTAPI_SystemCommand.h"
#include "framework/RESTAPI_WebSocketServer.h"
@@ -69,7 +71,8 @@ namespace OpenWifi {
RESTAPI_op_location_list_handler, RESTAPI_asset_server, RESTAPI_overrides_handler,
RESTAPI_openroaming_gr_acct_handler, RESTAPI_openroaming_gr_list_acct_handler,
RESTAPI_openroaming_gr_cert_handler, RESTAPI_openroaming_gr_list_certificates,
RESTAPI_openroaming_orion_acct_handler, RESTAPI_openroaming_orion_list_acct_handler>(
RESTAPI_openroaming_orion_acct_handler, RESTAPI_openroaming_orion_list_acct_handler,
RESTAPI_radiusendpoint_list_handler, RESTAPI_radius_endpoint_handler>(
Path, Bindings, L, S, TransactionId);
}
@@ -94,7 +97,8 @@ namespace OpenWifi {
RESTAPI_op_location_list_handler, RESTAPI_overrides_handler,
RESTAPI_openroaming_gr_acct_handler, RESTAPI_openroaming_gr_list_acct_handler,
RESTAPI_openroaming_gr_cert_handler, RESTAPI_openroaming_gr_list_certificates,
RESTAPI_openroaming_orion_acct_handler, RESTAPI_openroaming_orion_list_acct_handler>(Path, Bindings, L, S,
TransactionId);
RESTAPI_openroaming_orion_acct_handler, RESTAPI_openroaming_orion_list_acct_handler,
RESTAPI_radiusendpoint_list_handler, RESTAPI_radius_endpoint_handler>(
Path, Bindings, L, S,TransactionId);
}
} // namespace OpenWifi

View File

@@ -276,21 +276,19 @@ namespace OpenWifi {
auto testUpdateOnly = GetBoolParameter("testUpdateOnly");
if (testUpdateOnly) {
ProvObjects::SerialNumberList SNL;
StorageService()->InventoryDB().GetDevicesForVenue(UUID, SNL.serialNumbers);
Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices;
SNL.to_json(Answer);
return ReturnObject(Answer);
}
if (GetBoolParameter("updateAllDevices")) {
ProvObjects::SerialNumberList SNL;
StorageService()->InventoryDB().GetDevicesForVenue(UUID, SNL.serialNumbers);
Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices;
auto JobId = MicroServiceCreateUUID();
Types::StringVec Parameters{UUID};
;
auto NewJob = new VenueConfigUpdater(JobId, "VenueConfigurationUpdater", Parameters, 0,
UserInfo_.userinfo, Logger());
JobController()->AddJob(dynamic_cast<Job *>(NewJob));
@@ -302,11 +300,10 @@ namespace OpenWifi {
if (GetBoolParameter("upgradeAllDevices")) {
if (GetBoolParameter("revisionsAvailable")) {
std::set<std::string> DeviceTypes;
for (const auto &serialNumber : Existing.devices) {
ProvObjects::InventoryTag Device;
if (StorageService()->InventoryDB().GetRecord("id", serialNumber, Device)) {
DeviceTypes.insert(Device.deviceType);
}
std::vector<ProvObjects::InventoryTag> ExistingDevices;
StorageService()->InventoryDB().GetDevicesForVenue(UUID, ExistingDevices);
for (const auto &device : ExistingDevices) {
DeviceTypes.insert(device.deviceType);
}
// Get all the revisions for all the device types
@@ -374,18 +371,17 @@ namespace OpenWifi {
return ReturnObject(Answer);
}
ProvObjects::SerialNumberList SNL;
auto Revision = GetParameter("revision", "");
if (Revision.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::SerialNumberList SNL;
StorageService()->InventoryDB().GetDevicesForVenue(UUID, SNL.serialNumbers);
Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices;
auto JobId = MicroServiceCreateUUID();
Types::StringVec Parameters{UUID, Revision};
;
auto NewJob = new VenueUpgrade(JobId, "VenueFirmwareUpgrade", Parameters, 0,
UserInfo_.userinfo, Logger());
JobController()->AddJob(dynamic_cast<Job *>(NewJob));
@@ -396,9 +392,9 @@ namespace OpenWifi {
if (GetBoolParameter("rebootAllDevices")) {
ProvObjects::SerialNumberList SNL;
StorageService()->InventoryDB().GetDevicesForVenue(UUID, SNL.serialNumbers);
Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices;
auto JobId = MicroServiceCreateUUID();
Types::StringVec Parameters{UUID};
;

View File

@@ -171,6 +171,31 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "lastModified", LastModified);
}
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType);
field_to_json(Obj, "description", Description);
field_to_json(Obj, "uri", uri);
field_to_json(Obj, "revision", revision);
field_to_json(Obj, "imageCreationDate", imageCreationDate);
field_to_json(Obj, "created", Created);
field_to_json(Obj, "lastModified", LastModified);
}
bool DefaultFirmware::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "deviceType", deviceType);
field_from_json(Obj, "description", Description);
field_from_json(Obj, "uri", uri);
field_from_json(Obj, "revision", revision);
field_from_json(Obj, "imageCreationDate", imageCreationDate);
field_from_json(Obj, "created", Created);
field_from_json(Obj, "lastModified", LastModified);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void CommandDetails::to_json(Poco::JSON::Object &Obj) const {
EmbedDocument("details", Obj, Details);
EmbedDocument("results", Obj, Results);
@@ -246,6 +271,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_to_json(Obj, "connectReason", connectReason);
#ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
@@ -403,6 +430,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "acctConfig", acctConfig);
field_to_json(Obj, "coaConfig", coaConfig);
field_to_json(Obj, "useByDefault", useByDefault);
field_to_json(Obj, "radsecKeepAlive", radsecKeepAlive);
field_to_json(Obj, "poolProxyIp", poolProxyIp);
field_to_json(Obj, "radsecPoolType", radsecPoolType);
field_to_json(Obj, "enabled", enabled);
}
bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -413,6 +444,10 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj, "acctConfig", acctConfig);
field_from_json(Obj, "coaConfig", coaConfig);
field_from_json(Obj, "useByDefault", useByDefault);
field_from_json(Obj, "radsecKeepAlive", radsecKeepAlive);
field_from_json(Obj, "poolProxyIp", poolProxyIp);
field_from_json(Obj, "radsecPoolType", radsecPoolType);
field_from_json(Obj, "enabled", enabled);
return true;
} catch (const Poco::Exception &E) {
}
@@ -630,18 +665,50 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
field_to_json(Obj, "interface", interface);
field_to_json(Obj, "secret", secret);
field_to_json(Obj, "nasId", nasId);
field_to_json(Obj, "calledStationId", calledStationId);
}
void RADIUSSessionList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "sessions", sessions);
}
void RadiusCoADMParameters::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "accountingSessionId", accountingSessionId);
field_to_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
field_to_json(Obj, "callingStationId", callingStationId);
field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
field_to_json(Obj, "userName", userName);
}
bool RadiusCoADMParameters::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "accountingSessionId", accountingSessionId);
field_from_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
field_from_json(Obj, "callingStationId", callingStationId);
field_from_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
field_from_json(Obj, "userName", userName);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool DeviceTransferRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "server", server);
field_from_json(Obj, "port", port);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "encodedCertificate", encodedCertificate);
return true;
} catch (const Poco::Exception &E) {
}

View File

@@ -42,12 +42,13 @@ namespace OpenWifi::GWObjects {
uint64_t sessionId = 0;
double connectionCompletionTime = 0.0;
std::uint64_t certificateExpiryDate = 0;
bool hasRADIUSSessions = false;
std::uint64_t hasRADIUSSessions = 0;
bool hasGPS = false;
std::uint64_t sanity=0;
std::double_t memoryUsed=0.0;
std::double_t load=0.0;
std::double_t temperature=0.0;
std::string connectReason;
void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
};
@@ -181,6 +182,26 @@ namespace OpenWifi::GWObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DefaultFirmware {
std::string deviceType;
std::string Description;
std::string uri;
std::string revision;
uint64_t imageCreationDate;
uint64_t Created;
uint64_t LastModified;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DefaultFirmwareList {
std::vector<DefaultFirmware> firmwares;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct CommandDetails {
std::string UUID;
std::string SerialNumber;
@@ -339,6 +360,10 @@ namespace OpenWifi::GWObjects {
RadiusProxyServerConfig acctConfig;
RadiusProxyServerConfig coaConfig;
bool useByDefault = false;
std::string radsecPoolType;
std::string poolProxyIp;
std::uint64_t radsecKeepAlive=25;
bool enabled=true;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
@@ -393,7 +418,8 @@ namespace OpenWifi::GWObjects {
callingStationId,
chargeableUserIdentity,
secret,
interface;
interface,
nasId;
std::uint64_t inputPackets = 0,
outputPackets = 0,
inputOctets = 0,
@@ -401,6 +427,7 @@ namespace OpenWifi::GWObjects {
inputGigaWords = 0,
outputGigaWords = 0;
std::uint32_t sessionTime = 0;
std::string calledStationId;
#ifdef TIP_GATEWAY_SERVICE
RADIUS::RadiusPacket accountingPacket;
@@ -418,7 +445,68 @@ namespace OpenWifi::GWObjects {
std::string accountingSessionId,
accountingMultiSessionId,
callingStationId,
chargeableUserIdentity;
chargeableUserIdentity,
userName;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
enum class RadiusPoolStrategy {
round_robin, random, weighted, unknown
};
enum class RadiusEndpointType {
generic, radsec, globalreach, orion, unknown
};
static inline RadiusEndpointType RadiusEndpointType(const std::string &T) {
if(T=="generic") return RadiusEndpointType::generic;
if(T=="radsec") return RadiusEndpointType::radsec;
if(T=="globalreach") return RadiusEndpointType::globalreach;
if(T=="orion") return RadiusEndpointType::orion;
return RadiusEndpointType::unknown;
}
static inline RadiusPoolStrategy RadiusPoolStrategy(const std::string &T) {
if(T=="round_robin") return RadiusPoolStrategy::round_robin;
if(T=="random") return RadiusPoolStrategy::random;
if(T=="weighted") return RadiusPoolStrategy::weighted;
return RadiusPoolStrategy::unknown;
}
static inline std::string to_string(enum RadiusEndpointType T) {
switch(T) {
case RadiusEndpointType::generic: return "generic";
case RadiusEndpointType::radsec: return "radsec";
case RadiusEndpointType::globalreach: return "globalreach";
case RadiusEndpointType::orion: return "orion";
default:
return "unknown";
}
}
static inline std::string to_string(enum RadiusPoolStrategy T) {
switch(T) {
case RadiusPoolStrategy::round_robin: return "round_robin";
case RadiusPoolStrategy::random: return "random";
case RadiusPoolStrategy::weighted: return "weighted";
default:
return "unknown";
}
}
struct DeviceTransferRequest {
std::string serialNumber;
std::string server;
std::uint64_t port;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceCertificateUpdateRequest {
std::string serialNumber;
std::string encodedCertificate;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};

View File

@@ -78,21 +78,22 @@ namespace OpenWifi::OWLSObjects {
return false;
}
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "simulationId", simulationId);
field_to_json(Obj, "state", state);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
field_to_json(Obj, "msgsTx", msgsTx);
field_to_json(Obj, "msgsRx", msgsRx);
field_to_json(Obj, "liveDevices", liveDevices);
field_to_json(Obj, "timeToFullDevices", timeToFullDevices);
field_to_json(Obj, "startTime", startTime);
field_to_json(Obj, "endTime", endTime);
field_to_json(Obj, "errorDevices", errorDevices);
field_to_json(Obj, "owner", owner);
}
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "simulationId", simulationId);
field_to_json(Obj, "state", state);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
field_to_json(Obj, "msgsTx", msgsTx);
field_to_json(Obj, "msgsRx", msgsRx);
field_to_json(Obj, "liveDevices", liveDevices);
field_to_json(Obj, "timeToFullDevices", timeToFullDevices);
field_to_json(Obj, "startTime", startTime);
field_to_json(Obj, "endTime", endTime);
field_to_json(Obj, "errorDevices", errorDevices);
field_to_json(Obj, "owner", owner);
field_to_json(Obj, "expectedDevices", expectedDevices);
}
void Dashboard::to_json([[maybe_unused]] Poco::JSON::Object &Obj) const {}

View File

@@ -43,23 +43,24 @@ namespace OpenWifi::OWLSObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SimulationStatus {
std::string id;
std::string simulationId;
std::string state;
uint64_t tx;
uint64_t rx;
uint64_t msgsTx;
uint64_t msgsRx;
uint64_t liveDevices;
uint64_t timeToFullDevices;
uint64_t startTime;
uint64_t endTime;
uint64_t errorDevices;
std::string owner;
struct SimulationStatus {
std::string id;
std::string simulationId;
std::string state;
uint64_t tx;
uint64_t rx;
uint64_t msgsTx;
uint64_t msgsRx;
uint64_t liveDevices;
uint64_t timeToFullDevices;
uint64_t startTime;
uint64_t endTime;
uint64_t errorDevices;
std::string owner;
uint64_t expectedDevices;
void to_json(Poco::JSON::Object &Obj) const;
};
void to_json(Poco::JSON::Object &Obj) const;
};
struct Dashboard {
int O;

View File

@@ -1278,5 +1278,159 @@ namespace OpenWifi::ProvObjects {
return false;
}
void RADIUSServer::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "Hostname", Hostname);
field_to_json(Obj, "IP", IP);
field_to_json(Obj, "Port", Port);
field_to_json(Obj, "Secret", Secret);
}
bool RADIUSServer::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "Hostname", Hostname);
field_from_json(Obj, "IP", IP);
field_from_json(Obj, "Port", Port);
field_from_json(Obj, "Secret", Secret);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RADIUSEndPointRadiusType::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "Authentication", Authentication);
field_to_json(Obj, "Accounting", Accounting);
field_to_json(Obj, "CoA", CoA);
field_to_json(Obj, "AccountingInterval", AccountingInterval);
}
bool RADIUSEndPointRadiusType::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "Authentication", Authentication);
field_from_json(Obj, "Accounting", Accounting);
field_from_json(Obj, "CoA", CoA);
field_from_json(Obj, "AccountingInterval", AccountingInterval);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RADIUSEndPointRadsecType::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "Hostname", Hostname);
field_to_json(Obj, "IP", IP);
field_to_json(Obj, "Port", Port);
field_to_json(Obj, "Secret", Secret);
field_to_json(Obj, "OpenRoamingType", OpenRoamingType);
field_to_json(Obj, "UseOpenRoamingAccount", UseOpenRoamingAccount);
field_to_json(Obj, "Weight", Weight);
field_to_json(Obj, "Certificate", Certificate);
field_to_json(Obj, "PrivateKey", PrivateKey);
field_to_json(Obj, "CaCerts", CaCerts);
field_to_json(Obj, "AllowSelfSigned", AllowSelfSigned);
}
bool RADIUSEndPointRadsecType::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "Hostname", Hostname);
field_from_json(Obj, "IP", IP);
field_from_json(Obj, "Port", Port);
field_from_json(Obj, "Secret", Secret);
field_from_json(Obj, "OpenRoamingType", OpenRoamingType);
field_from_json(Obj, "UseOpenRoamingAccount", UseOpenRoamingAccount);
field_from_json(Obj, "Weight", Weight);
field_from_json(Obj, "Certificate", Certificate);
field_from_json(Obj, "PrivateKey", PrivateKey);
field_from_json(Obj, "CaCerts", CaCerts);
field_from_json(Obj, "AllowSelfSigned", AllowSelfSigned);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RADIUSEndPoint::to_json(Poco::JSON::Object &Obj) const {
info.to_json(Obj);
field_to_json(Obj, "Type", Type);
field_to_json(Obj, "RadsecServers", RadsecServers);
field_to_json(Obj, "RadiusServers", RadiusServers);
field_to_json(Obj, "PoolStrategy", PoolStrategy);
field_to_json(Obj, "Index", Index);
field_to_json(Obj, "UsedBy", UsedBy);
field_to_json(Obj, "UseGWProxy", UseGWProxy);
field_to_json(Obj, "NasIdentifier", NasIdentifier);
field_to_json(Obj, "AccountingInterval", AccountingInterval);
}
bool RADIUSEndPoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
info.from_json(Obj);
field_from_json(Obj, "Type", Type);
field_from_json(Obj, "RadsecServers", RadsecServers);
field_from_json(Obj, "RadiusServers", RadiusServers);
field_from_json(Obj, "PoolStrategy", PoolStrategy);
field_from_json(Obj, "Index", Index);
field_from_json(Obj, "UsedBy", UsedBy);
field_from_json(Obj, "UseGWProxy", UseGWProxy);
field_from_json(Obj, "NasIdentifier", NasIdentifier);
field_from_json(Obj, "AccountingInterval", AccountingInterval);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RADIUSEndpointUpdateStatus::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "lastUpdate", lastUpdate);
field_to_json(Obj, "lastConfigurationChange", lastConfigurationChange);
}
bool RADIUSEndpointUpdateStatus::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "lastUpdate", lastUpdate);
field_from_json(Obj, "lastConfigurationChange", lastConfigurationChange);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool RADIUSEndpointUpdateStatus::Read() {
Poco::File F(OpenWifi::MicroServiceDataDirectory()+"/RADIUSEndpointUpdateStatus.json");
try {
if (F.exists()) {
Poco::JSON::Parser P;
std::ifstream ifs(F.path(), std::ios_base::in | std::ios_base::binary);
auto Obj = P.parse(ifs);
return from_json(Obj.extract<Poco::JSON::Object::Ptr>());
}
} catch (...) {
}
return false;
}
bool RADIUSEndpointUpdateStatus::Save() {
Poco::File F(OpenWifi::MicroServiceDataDirectory()+"/RADIUSEndpointUpdateStatus.json");
try {
Poco::JSON::Object Obj;
to_json(Obj);
std::ofstream O(F.path(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
Poco::JSON::Stringifier::stringify(Obj, O);
return true;
} catch (...) {
}
return false;
}
bool RADIUSEndpointUpdateStatus::ChangeConfiguration() {
Read();
lastConfigurationChange = Utils::Now();
return Save();
}
} // namespace OpenWifi::ProvObjects

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
//
// Created by stephane bourque on 2023-10-18.
//
#include "GenericRadius.h"
namespace OpenWifi {
} // OpenWifi

View File

@@ -0,0 +1,67 @@
//
// Created by stephane bourque on 2023-10-18.
//
#pragma once
#include <Poco/Net/IPAddress.h>
#include <Poco/Net/SocketAddress.h>
#include <framework/utils.h>
#include <framework/SubSystemServer.h>
#include <RESTObjects/RESTAPI_ProvObjects.h>
namespace OpenWifi {
namespace GenericRadius {
class OpenRoaming : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new OpenRoaming;
return instance_;
}
inline int Start() override {
return 0;
}
inline void Stop() override {
}
inline bool Render(const OpenWifi::ProvObjects::RADIUSEndPoint &RE, const std::string &SerialNumber,
Poco::JSON::Object &Result) {
if (RE.UseGWProxy) {
Poco::JSON::Object Auth, Acct, CoA;
Auth.set("host", RE.Index);
Auth.set("port", RE.RadiusServers[0].Authentication[0].Port);
Auth.set("secret", RE.RadiusServers[0].Authentication[0].Secret);
Acct.set("host", RE.Index);
Acct.set("port", RE.RadiusServers[0].Accounting[0].Port);
Acct.set("secret", RE.RadiusServers[0].Accounting[0].Secret);
Acct.set("interval", RE.AccountingInterval);
CoA.set("host", RE.Index);
CoA.set("port", RE.RadiusServers[0].CoA[0].Port);
CoA.set("secret", RE.RadiusServers[0].CoA[0].Secret);
Result.set("nas-identifier", RE.NasIdentifier.empty() ? SerialNumber : RE.NasIdentifier);
Result.set("authentication", Auth);
Result.set("accounting", Acct);
Result.set("dynamic-authorization", CoA);
} else {
}
return false;
}
private:
OpenRoaming() noexcept
: SubSystemServer("OpenRoaming_GenericRadius", "GENRAD", "genrad") {
}
};
}
inline auto OpenRoaming_GenericRadius() { return GenericRadius::OpenRoaming::instance(); }
}

View File

@@ -0,0 +1,258 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "GlobalReach.h"
#include <Poco/JWT/Token.h>
#include <Poco/JWT/Signer.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/Net/DNS.h>
#include <Poco/URI.h>
#include <Poco/TemporaryFile.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <framework/RESTAPI_Handler.h>
#include <framework/MicroServiceFuncs.h>
#include <StorageService.h>
namespace OpenWifi {
namespace GlobalReach {
int OpenRoaming::Start() {
poco_information(Logger(), "Starting...");
InitCache();
return 0;
}
void OpenRoaming::Stop() {
poco_information(Logger(), "Stopping...");
poco_information(Logger(), "Stopped...");
}
void OpenRoaming::InitCache() {
auto F = [&](const ProvObjects::GLBLRAccountInfo &Info) {
poco_information(Logger(), fmt::format("Adding {} to cache.", Info.info.name));
if (!Info.privateKey.empty() && !Info.GlobalReachAcctId.empty()) {
MakeToken(Info.GlobalReachAcctId, Info.privateKey);
}
return true;
};
StorageService()->GLBLRAccountInfoDB().Iterate(F);
}
bool OpenRoaming::Render(const OpenWifi::ProvObjects::RADIUSEndPoint &RE, const std::string &SerialNumber, Poco::JSON::Object &Result) {
if(RE.UseGWProxy) {
Poco::JSON::Object Auth, Acct, CoA;
Auth.set("host", RE.Index);
Auth.set("port", 1812 );
Auth.set("secret", RE.RadsecServers[0].Secret);
Acct.set("host", RE.Index);
Acct.set("port", 1813);
Acct.set("secret", RE.RadsecServers[0].Secret);
Acct.set("interval", RE.AccountingInterval);
CoA.set("host", RE.Index);
CoA.set("port", 3799);
CoA.set("secret", RE.RadsecServers[0].Secret);
Result.set("nas-identifier", RE.NasIdentifier.empty() ? SerialNumber : RE.NasIdentifier );
Result.set("authentication", Auth);
Result.set("accounting", Acct);
Result.set("dynamic-authorization", CoA);
} else {
}
return false;
}
bool OpenRoaming::CreateRADSECCertificate(
const std::string &GlobalReachAccountId,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
try {
auto BearerToken = MakeToken(GlobalReachAccountId);
Poco::URI URI{"https://config.openro.am/v1/radsec/issue"};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Poco::JSON::Object CertRequestBody;
CertRequestBody.set("name", Name);
CertRequestBody.set("csr", CSR);
std::ostringstream os;
CertRequestBody.stringify(os);
Request.setContentType("application/json");
Request.setContentLength((long) os.str().size());
auto &Body = Session.sendRequest(Request);
Body << os.str();
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
RESTAPIHandler::AssignIfPresent(Result, "certificate", NewCertificate.certificate);
RESTAPIHandler::AssignIfPresent(Result, "certificate_chain", NewCertificate.certificateChain);
RESTAPIHandler::AssignIfPresent(Result, "certificate_id", NewCertificate.certificateId);
RESTAPIHandler::AssignIfPresent(Result, "expires_at", NewCertificate.expiresAt);
return true;
}
Poco::JSON::Parser P;
std::ostringstream oos;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
Result->stringify(oos);
} catch (const Poco::Exception &E) {
poco_error(Logger(),
fmt::format("Could not create a new RADSEC certificate: {},{}", E.name(), E.displayText()));
}
return false;
}
bool OpenRoaming::GetRADSECCertificate(
const std::string &GlobalReachAccountId,
std::string &CertificateId,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
try {
Poco::URI URI{fmt::format("https://config.openro.am/v1/radsec/cert/{}", CertificateId)};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
auto BearerToken = MakeToken(GlobalReachAccountId);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
RESTAPIHandler::AssignIfPresent(Result, "certificate", NewCertificate.certificate);
RESTAPIHandler::AssignIfPresent(Result, "certificate_chain", NewCertificate.certificateChain);
RESTAPIHandler::AssignIfPresent(Result, "certificate_id", NewCertificate.certificateId);
RESTAPIHandler::AssignIfPresent(Result, "expires_at", NewCertificate.expiresAt);
return true;
}
} catch (const Poco::Exception &E) {
poco_error(Logger(), fmt::format("Could not retrieve the certificate from GlobalReach: {},{}", E.name(),
E.displayText()));
}
return false;
}
std::string
OpenRoaming::MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey) {
try {
Poco::JWT::Token token;
token.setType("JWT");
token.setAlgorithm("ES256");
token.setIssuedAt(std::time(nullptr));
token.payload().set("iss", GlobalReachAccountId);
token.payload().set("iat", (unsigned long) std::time(nullptr));
Poco::SharedPtr<Poco::Crypto::ECKey> Key;
auto KeyHash = Utils::ComputeHash(PrivateKey);
auto KeyHint = PrivateKeys_.find(GlobalReachAccountId);
if (KeyHint != PrivateKeys_.end() && PrivateKey.empty()) {
Key = KeyHint->second.second;
} else {
if (PrivateKey.empty()) {
return "";
}
Poco::TemporaryFile F;
std::ofstream ofs(F.path().c_str(),
std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
ofs << PrivateKey;
ofs.close();
auto NewKey = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(), ""));
Key = NewKey;
PrivateKeys_[GlobalReachAccountId] = std::make_pair(KeyHash, NewKey);
}
Poco::JWT::Signer Signer;
Signer.setECKey(Key);
Signer.addAllAlgorithms();
return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256);
} catch (const Poco::Exception &E) {
poco_error(Logger(),
fmt::format("Cannot create a Global Reach token: {},{}", E.name(), E.displayText()));
}
return "";
}
bool
OpenRoaming::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey,
std::string &Name) {
auto BearerToken = MakeToken(GlobalReachAccountId, PrivateKey);
Poco::URI URI{"https://config.openro.am/v1/config"};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
if (Result->has("name")) {
Name = Result->get("name").toString();
}
return true;
}
return false;
}
// static std::string ServiceName{"\"aaa+auth:radius.tls.tcp\""};
static std::string ServiceName{"\"x-openroam:radius.tls.tcp\""};
std::vector<Utils::HostNameServerResult> OpenRoaming::GetServers() {
const std::string &domain = "openro.am";
auto Naptrs = Utils::getNAPTRRecords(domain);
std::vector<Utils::HostNameServerResult> Results;
for(const auto &rec:Naptrs) {
if(rec.service==ServiceName) {
auto Srvs = Utils::getSRVRecords(rec.replacement);
for(const auto &srv:Srvs) {
Utils::HostNameServerResult R{srv.srvname,srv.port};
if(!Utils::ValidIP(srv.srvname)) {
auto Server = Poco::Net::DNS::hostByName(srv.srvname).addresses();
if(!Server.empty()) {
R.Hostname = Server[0].toString();
}
}
Results.emplace_back(R);
}
}
}
return Results;
}
}
} // OpenWifi

View File

@@ -0,0 +1,57 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "framework/SubSystemServer.h"
#include "framework/utils.h"
#include "Poco/JSON/Object.h"
#include "RESTObjects/RESTAPI_ProvObjects.h"
namespace OpenWifi {
namespace GlobalReach {
class OpenRoaming : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new OpenRoaming;
return instance_;
}
int Start() override;
void Stop() override;
bool CreateRADSECCertificate(const std::string &AccountName,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool GetRADSECCertificate(const std::string &AccountName, std::string &CertificateId,
ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool
VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name);
void InitCache();
bool Render(const OpenWifi::ProvObjects::RADIUSEndPoint &RE, const std::string & SerialNUmber, Poco::JSON::Object &Result);
std::vector<Utils::HostNameServerResult> GetServers();
private:
std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey = "");
std::map<std::string, std::pair<std::string, Poco::SharedPtr<Poco::Crypto::ECKey>>> PrivateKeys_;
OpenRoaming() noexcept
: SubSystemServer("OpenRoaming_GlobalReach", "GLBL-REACH", "globalreach") {
}
};
}
inline auto OpenRoaming_GlobalReach() { return GlobalReach::OpenRoaming::instance(); }
} // OpenWifi

View File

@@ -0,0 +1,79 @@
//
// Created by stephane bourque on 2023-09-28.
//
#pragma once
#include <Poco/Net/IPAddress.h>
#include <Poco/Net/SocketAddress.h>
#include <framework/utils.h>
#include <framework/SubSystemServer.h>
namespace OpenWifi {
namespace Orion {
class OpenRoaming : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new OpenRoaming;
return instance_;
}
inline int Start() override {
return 0;
}
inline void Stop() override {
}
static inline const std::vector<Utils::HostNameServerResult> OrionWifiServerAddresses = {
{"216.239.32.91", 2083},
{"216.239.34.91", 2083}
};
inline std::vector<Utils::HostNameServerResult> GetServers() {
return OrionWifiServerAddresses;
}
inline bool Render(const OpenWifi::ProvObjects::RADIUSEndPoint &RE, const std::string &SerialNumber, Poco::JSON::Object &Result) {
if(RE.UseGWProxy) {
Poco::JSON::Object Auth, Acct, CoA;
Auth.set("host", RE.Index);
Auth.set("port", 1812 );
Auth.set("secret", RE.RadsecServers[0].Secret);
Acct.set("host", RE.Index);
Acct.set("port", 1813);
Acct.set("secret", RE.RadsecServers[0].Secret);
Acct.set("interval", RE.AccountingInterval);
CoA.set("host", RE.Index);
CoA.set("port", 3799);
CoA.set("secret", RE.RadsecServers[0].Secret);
Result.set("nas-identifier", RE.NasIdentifier.empty() ? SerialNumber : RE.NasIdentifier );
Result.set("authentication", Auth);
Result.set("accounting", Acct);
Result.set("dynamic-authorization", CoA);
} else {
}
return false;
}
private:
OpenRoaming() noexcept
: SubSystemServer("OpenRoaming_Orion", "ORION", "orion") {
}
};
}
inline auto OpenRoaming_Orion() { return Orion::OpenRoaming::instance(); }
}

View File

@@ -0,0 +1,8 @@
//
// Created by stephane bourque on 2023-10-03.
//
#include "Radsec.h"
namespace OpenWidi {
} // OpenWidi

View File

@@ -0,0 +1,71 @@
//
// Created by stephane bourque on 2023-10-03.
//
#pragma once
#include <Poco/Net/IPAddress.h>
#include <Poco/Net/SocketAddress.h>
#include <framework/utils.h>
#include <framework/SubSystemServer.h>
#include <RESTObjects/RESTAPI_ProvObjects.h>
namespace OpenWifi {
namespace Radsec {
class OpenRoaming : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new OpenRoaming;
return instance_;
}
inline int Start() override {
return 0;
}
inline void Stop() override {
}
inline bool Render(const OpenWifi::ProvObjects::RADIUSEndPoint &RE, const std::string &SerialNumber, Poco::JSON::Object &Result) {
if(RE.UseGWProxy) {
Poco::JSON::Object Auth, Acct, CoA;
Auth.set("host", RE.Index);
Auth.set("port", 1812 );
Auth.set("secret", RE.RadsecServers[0].Secret);
Acct.set("host", RE.Index);
Acct.set("port", 1813);
Acct.set("secret", RE.RadsecServers[0].Secret);
Acct.set("interval", RE.AccountingInterval);
CoA.set("host", RE.Index);
CoA.set("port", 3799);
CoA.set("secret", RE.RadsecServers[0].Secret);
Result.set("nas-identifier", RE.NasIdentifier.empty() ? SerialNumber : RE.NasIdentifier );
Result.set("authentication", Auth);
Result.set("accounting", Acct);
Result.set("dynamic-authorization", CoA);
} else {
}
return false;
}
private:
OpenRoaming() noexcept
: SubSystemServer("OpenRoaming_Raadsec", "RADSEC", "radsec") {
}
};
}
inline auto OpenRoaming_Radsec() { return Radsec::OpenRoaming::instance(); }
}

View File

@@ -0,0 +1,5 @@
//
// Created by stephane bourque on 2023-10-02.
//
#include "RadiusEndpointUpdater.h"

225
src/RadiusEndpointUpdater.h Normal file
View File

@@ -0,0 +1,225 @@
//
// Created by stephane bourque on 2023-10-02.
//
#pragma once
#include <vector>
#include <utility>
#include <framework/AppServiceRegistry.h>
#include <framework/utils.h>
#include <StorageService.h>
#include <RadiusEndpointTypes/OrionWifi.h>
#include <RadiusEndpointTypes/GlobalReach.h>
#include <sdks/SDK_gw.h>
#include <RESTObjects/RESTAPI_GWobjects.h>
namespace OpenWifi {
class RadiusEndpointUpdater {
public:
void ParseCertChain(const std::string &Chain, std::vector<std::string> &ChainVec) {
std::istringstream os(Chain);
std::string CurrentCert;
bool InCert = false;
std::string Line;
while(std::getline(os,Line)) {
if(Line=="-----BEGIN CERTIFICATE-----") {
InCert = true;
CurrentCert += Line;
CurrentCert += "\n";
continue;
}
if(Line=="-----END CERTIFICATE-----" && InCert) {
InCert = false;
CurrentCert += Line;
CurrentCert += "\n";
ChainVec.emplace_back(CurrentCert);
continue;
}
if(InCert) {
CurrentCert += Line;
CurrentCert += "\n";
}
}
}
void UpdateRadiusServerEntry( GWObjects::RadiusProxyServerConfig &Config,
const ProvObjects::RADIUSEndPoint &Endpoint,
const std::vector<ProvObjects::RADIUSServer> &Servers) {
Config.monitor = false;
Config.strategy = Endpoint.PoolStrategy;
Config.monitorMethod = "none";
Config.strategy = "random";
for (const auto &Server: Servers) {
GWObjects::RadiusProxyServerEntry PE;
PE.radsec = false;
PE.name = Server.Hostname;
PE.ignore = false;
PE.ip = Server.IP;
PE.port = PE.radsecPort = Server.Port;
PE.allowSelfSigned = false;
PE.weight = 10;
PE.secret = PE.radsecSecret = "radsec";
Config.servers.emplace_back(PE);
}
}
inline bool UpdateEndpoints( RESTAPIHandler *Client, std::uint64_t & ErrorCode,
std::string & ErrorDetails,
std::string & ErrorDescription) {
std::vector<ProvObjects::RADIUSEndPoint> Endpoints;
GWObjects::RadiusProxyPoolList Pools;
StorageService()->RadiusEndpointDB().GetRecords(0,500,Endpoints);
for(const auto &Endpoint:Endpoints) {
GWObjects::RadiusProxyPool PP;
PP.name = Endpoint.info.name;
PP.description = Endpoint.info.description;
PP.useByDefault = false;
PP.poolProxyIp = Endpoint.Index;
PP.radsecKeepAlive = 25;
PP.enabled = true;
if(Endpoint.Type=="orion" && !Endpoint.RadsecServers.empty()) {
auto Svrs = OpenRoaming_Orion()->GetServers();
PP.radsecPoolType="orion";
ProvObjects::GooglOrionAccountInfo OA;
if(StorageService()->OrionAccountsDB().GetRecord("id", Endpoint.RadsecServers[0].UseOpenRoamingAccount, OA)) {
for(auto *ServerType:{&PP.authConfig, &PP.acctConfig, &PP.coaConfig}) {
ServerType->monitor = false;
ServerType->strategy = Endpoint.PoolStrategy;
ServerType->monitorMethod = "none";
ServerType->strategy = "random";
int i=1;
for (const auto &Server: Svrs) {
GWObjects::RadiusProxyServerEntry PE;
PE.radsecCert = Utils::base64encode((const u_char *)OA.certificate.c_str(),OA.certificate.size());
PE.radsecKey = Utils::base64encode((const u_char *)OA.privateKey.c_str(),OA.privateKey.size());
for(const auto &cert:OA.cacerts) {
auto C = Utils::base64encode((const u_char *)cert.c_str(),cert.size());
PE.radsecCacerts.emplace_back(C);
}
PE.radsec = true;
PE.name = fmt::format("Server {}",i++);
PE.ignore = false;
PE.ip = Server.Hostname;
PE.port = PE.radsecPort = Server.Port;
PE.allowSelfSigned = false;
PE.weight = 10;
PE.secret = PE.radsecSecret = "radsec";
ServerType->servers.emplace_back(PE);
}
}
Pools.pools.emplace_back(PP);
}
} else if(Endpoint.Type=="globalreach" && !Endpoint.RadsecServers.empty()) {
auto Svrs = OpenRoaming_GlobalReach()->GetServers();
PP.radsecPoolType="globalreach";
ProvObjects::GLBLRCertificateInfo GRCertificate;
ProvObjects::GLBLRAccountInfo GRAccountInfo;
if( StorageService()->GLBLRCertsDB().GetRecord("id",Endpoint.RadsecServers[0].UseOpenRoamingAccount,GRCertificate) &&
StorageService()->GLBLRAccountInfoDB().GetRecord("id",GRCertificate.accountId,GRAccountInfo)) {
for(auto *ServerType:{&PP.authConfig, &PP.acctConfig, &PP.coaConfig}) {
ServerType->monitor = false;
ServerType->monitorMethod = "none";
ServerType->strategy = Endpoint.PoolStrategy;
ServerType->strategy = "random";
int i = 1;
for (const auto &Server: Svrs) {
GWObjects::RadiusProxyServerEntry PE;
PE.radsecCert = Utils::base64encode((const u_char *)GRCertificate.certificate.c_str(),GRCertificate.certificate.size());
PE.radsecKey = Utils::base64encode((const u_char *)GRAccountInfo.CSRPrivateKey.c_str(),GRAccountInfo.CSRPrivateKey.size());
std::vector<std::string> Chain;
ParseCertChain(GRCertificate.certificateChain,Chain);
for(const auto &cert:Chain) {
PE.radsecCacerts.emplace_back( Utils::base64encode((const u_char *)cert.c_str(),cert.size()));
}
PE.radsec = true;
PE.name = fmt::format("Server {}", i++);
PE.ignore = false;
PE.ip = Server.Hostname;
PE.port = PE.radsecPort = Server.Port;
PE.allowSelfSigned = false;
PE.weight = 10;
PE.secret = PE.radsecSecret = "radsec";
ServerType->servers.emplace_back(PE);
}
}
Pools.pools.emplace_back(PP);
}
} else if(Endpoint.Type=="radsec" && !Endpoint.RadsecServers.empty()) {
PP.radsecPoolType="radsec";
for(auto *ServerType:{&PP.authConfig, &PP.acctConfig, &PP.coaConfig}) {
ServerType->monitor = false;
ServerType->strategy = Endpoint.PoolStrategy;
ServerType->monitorMethod = "none";
ServerType->strategy = "random";
for (const auto &Server: Endpoint.RadsecServers) {
GWObjects::RadiusProxyServerEntry PE;
PE.radsecCert = Utils::base64encode((const u_char *)Server.Certificate.c_str(), Server.Certificate.size());
PE.radsecKey = Utils::base64encode((const u_char *)Server.PrivateKey.c_str(),Server.PrivateKey.size());
for(const auto &C:Server.CaCerts) {
PE.radsecCacerts.emplace_back(Utils::base64encode(
(const u_char *) C.c_str(),
C.size()));
}
PE.radsec = true;
PE.name = Server.Hostname;
PE.ignore = false;
PE.ip = Server.IP;
PE.port = PE.radsecPort = Server.Port;
PE.allowSelfSigned = false;
PE.weight = 10;
PE.secret = PE.radsecSecret = "radsec";
ServerType->servers.emplace_back(PE);
}
}
Pools.pools.emplace_back(PP);
} else if(Endpoint.Type=="generic" && !Endpoint.RadiusServers.empty()) {
PP.radsecPoolType="generic";
UpdateRadiusServerEntry(PP.authConfig, Endpoint, Endpoint.RadiusServers[0].Authentication);
UpdateRadiusServerEntry(PP.acctConfig, Endpoint, Endpoint.RadiusServers[0].Accounting);
UpdateRadiusServerEntry(PP.coaConfig, Endpoint, Endpoint.RadiusServers[0].CoA);
Pools.pools.emplace_back(PP);
}
}
/*
Poco::JSON::Object oo;
Pools.to_json(oo);
oo.stringify(std::cout,2,2);
*/
GWObjects::RadiusProxyPoolList NewPools;
Poco::JSON::Object ErrorObj;
if(SDK::GW::RADIUS::SetConfiguration(Client, Pools, NewPools, ErrorObj)) {
ProvObjects::RADIUSEndpointUpdateStatus Status;
Status.Read();
Status.lastConfigurationChange = Status.lastUpdate = Utils::Now();
return Status.Save();
}
/*
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
*/
if(ErrorObj.has("ErrorCode") && !ErrorObj.isNull("ErrorCode"))
ErrorCode = ErrorObj.get("ErrorCode");
if(ErrorObj.has("ErrorDescription") && !ErrorObj.isNull("ErrorDescription"))
ErrorDescription = ErrorObj.get("ErrorDescription").toString();
if(ErrorObj.has("ErrorDetails") && !ErrorObj.isNull("ErrorDetails"))
ErrorDetails += ErrorObj.get("ErrorDetails").toString();
return false;
}
private:
};
} // OpenWifi

View File

@@ -42,6 +42,7 @@ namespace OpenWifi {
GLBLRAccountInfoDB_ = std::make_unique<OpenWifi::GLBLRAccountInfoDB>(dbType_, *Pool_, Logger());
GLBLRCertsDB_ = std::make_unique<OpenWifi::GLBLRCertsDB>(dbType_, *Pool_, Logger());
OrionAccountsDB_ = std::make_unique<OpenWifi::OrionAccountsDB>(dbType_, *Pool_, Logger());
RadiusEndpointDB_ = std::make_unique<OpenWifi::RadiusEndpointDB>(dbType_, *Pool_, Logger());
EntityDB_->Create();
PolicyDB_->Create();
@@ -65,6 +66,7 @@ namespace OpenWifi {
GLBLRAccountInfoDB_->Create();
GLBLRCertsDB_->Create();
OrionAccountsDB_->Create();
RadiusEndpointDB_->Create();
ExistFunc_[EntityDB_->Prefix()] = [=](const char *F, std::string &V) -> bool {
return EntityDB_->Exists(F, V);
@@ -129,9 +131,12 @@ namespace OpenWifi {
ExistFunc_[GLBLRCertsDB_->Prefix()] = [=](const char *F, std::string &V) -> bool {
return GLBLRCertsDB_->Exists(F, V);
};
ExistFunc_[GLBLRCertsDB_->Prefix()] = [=](const char *F, std::string &V) -> bool {
ExistFunc_[OrionAccountsDB_->Prefix()] = [=](const char *F, std::string &V) -> bool {
return OrionAccountsDB_->Exists(F, V);
};
ExistFunc_[RadiusEndpointDB_->Prefix()] = [=](const char *F, std::string &V) -> bool {
return RadiusEndpointDB_->Exists(F, V);
};
@@ -240,6 +245,11 @@ namespace OpenWifi {
[[maybe_unused]] std::string &Name,
[[maybe_unused]] std::string &Description) -> bool { return false; };
ExpandFunc_[RadiusEndpointDB_->Prefix()] =
[=]([[maybe_unused]] const char *F, [[maybe_unused]] std::string &V,
[[maybe_unused]] std::string &Name,
[[maybe_unused]] std::string &Description) -> bool { return false; };
InventoryDB_->InitializeSerialCache();
ConsistencyCheck();
InitializeSystemDBs();

View File

@@ -31,6 +31,7 @@
#include "storage/storage_glblraccounts.h"
#include "storage/storage_glblrcerts.h"
#include "storage/storage_orion_accounts.h"
#include "storage/storage_radius_endpoints.h"
#include "Poco/URI.h"
#include "framework/ow_constants.h"
@@ -72,6 +73,7 @@ namespace OpenWifi {
inline OpenWifi::GLBLRAccountInfoDB &GLBLRAccountInfoDB() { return *GLBLRAccountInfoDB_; }
inline OpenWifi::GLBLRCertsDB &GLBLRCertsDB() { return *GLBLRCertsDB_; }
inline OpenWifi::OrionAccountsDB &OrionAccountsDB() { return *OrionAccountsDB_; }
inline OpenWifi::RadiusEndpointDB &RadiusEndpointDB() { return *RadiusEndpointDB_; }
bool Validate(const Poco::URI::QueryParameters &P, RESTAPI::Errors::msg &Error);
bool Validate(const Types::StringVec &P, std::string &Error);
@@ -134,6 +136,7 @@ namespace OpenWifi {
std::unique_ptr<OpenWifi::GLBLRAccountInfoDB> GLBLRAccountInfoDB_;
std::unique_ptr<OpenWifi::GLBLRCertsDB> GLBLRCertsDB_;
std::unique_ptr<OpenWifi::OrionAccountsDB> OrionAccountsDB_;
std::unique_ptr<OpenWifi::RadiusEndpointDB> RadiusEndpointDB_;
std::string DefaultOperator_;
typedef std::function<bool(const char *FieldName, std::string &Value)> exist_func;

View File

@@ -118,8 +118,9 @@ namespace OpenWifi {
Poco::ThreadPool Pool_;
std::list<VenueDeviceConfigUpdater *> JobList;
for (const auto &uuid : Venue.devices) {
std::vector<std::string> DeviceList;
StorageService()->InventoryDB().GetDevicesUUIDForVenue(Venue.info.id, DeviceList);
for (const auto &uuid : DeviceList) {
auto NewTask = new VenueDeviceConfigUpdater(uuid, Venue.info.name, Logger());
bool TaskAdded = false;
while (!TaskAdded) {

View File

@@ -68,8 +68,10 @@ namespace OpenWifi {
Poco::ThreadPool Pool_;
std::list<VenueDeviceRebooter *> JobList;
std::vector<std::string> DeviceList;
StorageService()->InventoryDB().GetDevicesUUIDForVenue(Venue.info.id, DeviceList);
for (const auto &uuid : Venue.devices) {
for (const auto &uuid : DeviceList) {
auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger());
bool TaskAdded = false;
while (!TaskAdded) {

View File

@@ -28,7 +28,7 @@ namespace OpenWifi {
Storage::ApplyRules(rules_, Device.deviceRules);
if (Device.deviceRules.firmwareUpgrade == "no") {
poco_debug(Logger(), fmt::format("Skipped Upgrade: {}", Device.serialNumber));
poco_debug(Logger(), fmt::format("Skipped Upgrade: {} : Venue rules prevent upgrading", Device.serialNumber));
skipped_++;
done_ = true;
return;
@@ -36,10 +36,15 @@ namespace OpenWifi {
FMSObjects::Firmware F;
if (SDK::FMS::Firmware::GetFirmware(Device.deviceType, revision_, F)) {
if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri)) {
Logger().debug(
fmt::format("{}: Upgraded to {}.", Device.serialNumber, revision_));
upgraded_++;
std::string Status;
if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri, Status)) {
if(Status=="pending") {
pending_++;
poco_debug(Logger(), fmt::format("Upgrade Pending: {} : {}", Device.serialNumber, Status));
} else {
upgraded_++;
poco_debug(Logger(), fmt::format("Upgrade Success: {} : {}", Device.serialNumber, Status));
}
} else {
poco_information(Logger(), fmt::format("{}: Not Upgraded to {}.",
Device.serialNumber, revision_));
@@ -53,10 +58,9 @@ namespace OpenWifi {
}
}
done_ = true;
// std::cout << "Done push for " << Device.serialNumber << std::endl;
}
std::uint64_t upgraded_ = 0, not_connected_ = 0, skipped_ = 0, no_firmware_ = 0;
std::uint64_t upgraded_ = 0, not_connected_ = 0, skipped_ = 0, no_firmware_ = 0, pending_ = 0;
bool started_ = false, done_ = false;
std::string SerialNumber;
@@ -85,7 +89,7 @@ namespace OpenWifi {
ProvWebSocketNotifications::VenueFWUpgradeList_t N;
ProvObjects::Venue Venue;
uint64_t upgraded_ = 0, not_connected_ = 0, skipped_ = 0, no_firmware_ = 0;
uint64_t upgraded_ = 0, not_connected_ = 0, skipped_ = 0, no_firmware_ = 0, pending_=0;
if (StorageService()->VenueDB().GetRecord("id", VenueUUID_, Venue)) {
N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name);
@@ -96,8 +100,10 @@ namespace OpenWifi {
ProvObjects::DeviceRules Rules;
StorageService()->VenueDB().EvaluateDeviceRules(Venue.info.id, Rules);
std::vector<std::string> DeviceList;
StorageService()->InventoryDB().GetDevicesUUIDForVenue(Venue.info.id, DeviceList);
for (const auto &uuid : Venue.devices) {
for (const auto &uuid : DeviceList) {
auto NewTask =
new VenueDeviceUpgrade(uuid, Venue.info.name, Revision_, Rules, Logger());
bool TaskAdded = false;
@@ -121,10 +127,13 @@ namespace OpenWifi {
N.content.not_connected.push_back(current_job->SerialNumber);
else if (current_job->no_firmware_)
N.content.no_firmware.push_back(current_job->SerialNumber);
else if (current_job->pending_)
N.content.pending.push_back(current_job->SerialNumber);
upgraded_ += current_job->upgraded_;
skipped_ += current_job->skipped_;
no_firmware_ += current_job->no_firmware_;
not_connected_ += current_job->not_connected_;
pending_ += current_job->pending_;
job_it = JobList.erase(job_it);
delete current_job;
} else {
@@ -146,10 +155,13 @@ namespace OpenWifi {
N.content.not_connected.push_back(current_job->SerialNumber);
else if (current_job->no_firmware_)
N.content.no_firmware.push_back(current_job->SerialNumber);
else if (current_job->pending_)
N.content.pending.push_back(current_job->SerialNumber);
upgraded_ += current_job->upgraded_;
skipped_ += current_job->skipped_;
no_firmware_ += current_job->no_firmware_;
not_connected_ += current_job->not_connected_;
pending_ += current_job->pending_;
job_it = JobList.erase(job_it);
delete current_job;
} else {
@@ -158,8 +170,8 @@ namespace OpenWifi {
}
N.content.details = fmt::format(
"Job {} Completed: {} upgraded, {} not connected, {} skipped, {} no firmware.",
JobId(), upgraded_, not_connected_, skipped_, no_firmware_);
"Job {} Completed: {} upgraded, {} not connected, {} skipped, {} no firmware, {} pending.",
JobId(), upgraded_, not_connected_, skipped_, no_firmware_, pending_);
} else {
N.content.details = fmt::format("Venue {} no longer exists.", VenueUUID_);
Logger().warning(N.content.details);

View File

@@ -60,6 +60,7 @@ namespace OpenWifi::ProvWebSocketNotifications {
RESTAPI_utils::field_to_json(Obj, "success", success);
RESTAPI_utils::field_to_json(Obj, "notConnected", not_connected);
RESTAPI_utils::field_to_json(Obj, "noFirmware", no_firmware);
RESTAPI_utils::field_to_json(Obj, "pending", pending);
RESTAPI_utils::field_to_json(Obj, "skipped", skipped);
RESTAPI_utils::field_to_json(Obj, "timeStamp", timeStamp);
RESTAPI_utils::field_to_json(Obj, "details", details);
@@ -71,6 +72,7 @@ namespace OpenWifi::ProvWebSocketNotifications {
RESTAPI_utils::field_from_json(Obj, "jobId", jobId);
RESTAPI_utils::field_from_json(Obj, "success", success);
RESTAPI_utils::field_from_json(Obj, "notConnected", not_connected);
RESTAPI_utils::field_from_json(Obj, "pending", pending);
RESTAPI_utils::field_from_json(Obj, "noFirmware", no_firmware);
RESTAPI_utils::field_from_json(Obj, "skipped", skipped);
RESTAPI_utils::field_from_json(Obj, "timeStamp", timeStamp);

View File

@@ -32,7 +32,7 @@ namespace OpenWifi::ProvWebSocketNotifications {
struct FWUpgradeList {
std::string title, details, jobId;
std::vector<std::string> success, skipped, no_firmware, not_connected;
std::vector<std::string> success, skipped, no_firmware, not_connected, pending;
uint64_t timeStamp = OpenWifi::Utils::Now();
void to_json(Poco::JSON::Object &Obj) const;

View File

@@ -11,10 +11,12 @@
#include "Poco/File.h"
#include "Poco/StreamCopier.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "framework/MicroServiceFuncs.h"
#include "nlohmann/json.hpp"
// #include "nlohmann/json.hpp"
namespace OpenWifi {
@@ -28,11 +30,11 @@ namespace OpenWifi {
if (F.exists()) {
std::ostringstream OS;
std::ifstream IF(FileName);
Poco::StreamCopier::copyStream(IF, OS);
Registry_ = nlohmann::json::parse(OS.str());
Poco::JSON::Parser P;
Registry_ = P.parse(IF).extract<Poco::JSON::Object::Ptr>();
}
} catch (...) {
Registry_ = nlohmann::json::parse("{}");
Registry_ = Poco::makeShared<Poco::JSON::Object>();
}
}
@@ -44,54 +46,47 @@ namespace OpenWifi {
inline ~AppServiceRegistry() { Save(); }
inline void Save() {
std::istringstream IS(to_string(Registry_));
std::ofstream OF;
OF.open(FileName, std::ios::binary | std::ios::trunc);
Poco::StreamCopier::copyStream(IS, OF);
Registry_->stringify(OF);
}
inline void Set(const char *Key, uint64_t Value) {
Registry_[Key] = Value;
void Set(const char *key, const std::vector<std::string> &V) {
Poco::JSON::Array Arr;
for(const auto &s:V) {
Arr.add(s);
}
Registry_->set(key,Arr);
Save();
}
template<class T> void Set(const char *key, const T &Value) {
Registry_->set(key,Value);
Save();
}
inline void Set(const char *Key, const std::string &Value) {
Registry_[Key] = Value;
Save();
}
bool Get(const char *key, std::vector<std::string> &Value) {
if(Registry_->has(key) && !Registry_->isNull(key) && Registry_->isArray(key)) {
auto Arr = Registry_->get(key);
for(const auto &v:Arr) {
Value.emplace_back(v);
}
return true;
}
return false;
}
inline void Set(const char *Key, bool Value) {
Registry_[Key] = Value;
Save();
}
inline bool Get(const char *Key, bool &Value) {
if (Registry_[Key].is_boolean()) {
Value = Registry_[Key].get<bool>();
return true;
}
return false;
}
inline bool Get(const char *Key, uint64_t &Value) {
if (Registry_[Key].is_number_unsigned()) {
Value = Registry_[Key].get<uint64_t>();
return true;
}
return false;
}
inline bool Get(const char *Key, std::string &Value) {
if (Registry_[Key].is_string()) {
Value = Registry_[Key].get<std::string>();
return true;
}
return false;
}
template<class T> bool Get(const char *key, T &Value) {
if(Registry_->has(key) && !Registry_->isNull(key)) {
Value = Registry_->getValue<T>(key);
return true;
}
return false;
}
private:
std::string FileName;
nlohmann::json Registry_;
Poco::JSON::Object::Ptr Registry_;
};
inline auto AppServiceRegistry() { return AppServiceRegistry::instance(); }

View File

@@ -9,8 +9,6 @@
namespace OpenWifi {
EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
void EventBusManager::run() {
Running_ = true;
Utils::SetThreadName("fmwk:EventMgr");

View File

@@ -12,6 +12,16 @@ namespace OpenWifi {
class EventBusManager : public Poco::Runnable {
public:
EventBusManager() :
Logger_(Poco::Logger::create(
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())) {
}
static auto instance() {
static auto instance_ = new EventBusManager;
return instance_;
}
explicit EventBusManager(Poco::Logger &L);
void run() final;
void Start();
@@ -24,4 +34,6 @@ namespace OpenWifi {
Poco::Logger &Logger_;
};
inline auto EventBusManager() { return EventBusManager::instance(); }
} // namespace OpenWifi

View File

@@ -307,10 +307,8 @@ namespace OpenWifi {
}
[[nodiscard]] std::string KafkaManager::WrapSystemId(const std::string & PayLoad) {
return fmt::format( R"lit({{ "system" : {{ "id" : {},
"host" : "{}" }},
"payload" : {} }})lit", MicroServiceID(),
MicroServicePrivateEndPoint(), PayLoad ) ;
return fmt::format( R"lit({{ "system" : {{ "id" : {}, "host" : "{}" }}, "payload" : {} }})lit",
MicroServiceID(), MicroServicePrivateEndPoint(), PayLoad ) ;
}
void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList &partitions) {

View File

@@ -20,6 +20,7 @@ namespace OpenWifi::KafkaTopics {
inline const char * DEVICE_EVENT_QUEUE = "device_event_queue";
inline const char * DEVICE_TELEMETRY = "device_telemetry";
inline const char * PROVISIONING_CHANGE = "provisioning_change";
inline const char * RRM = "rrm";
namespace ServiceEvents {
inline const char * EVENT_JOIN = "join";

View File

@@ -33,9 +33,23 @@ namespace OpenWifi {
void MicroService::Exit(int Reason) { std::exit(Reason); }
static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
std::string SvcList;
for (const auto &Svc : Services) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
}
return SvcList;
}
void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
const std::string &Payload) {
std::lock_guard G(InfraMutex_);
Poco::Logger &BusLogger = EventBusManager()->Logger();
try {
Poco::JSON::Parser P;
auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
@@ -55,13 +69,10 @@ namespace OpenWifi {
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
auto PrivateEndPoint =
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
Services_.find(PrivateEndPoint) != Services_.end()) {
Services_[PrivateEndPoint].LastUpdate = Utils::Now();
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
Services_.erase(PrivateEndPoint);
poco_debug(
logger(),
poco_information(
BusLogger,
fmt::format(
"Service {} ID={} leaving system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
@@ -69,14 +80,7 @@ namespace OpenWifi {
ID));
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
poco_debug(
logger(),
fmt::format(
"Service {} ID={} joining system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
Services_[PrivateEndPoint] = Types::MicroServiceMeta{
auto ServiceInfo = Types::MicroServiceMeta{
.Id = ID,
.Type = Poco::toLower(
Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
@@ -94,20 +98,46 @@ namespace OpenWifi {
.toString(),
.LastUpdate = Utils::Now()};
std::string SvcList;
for (const auto &Svc : Services_) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
auto s1 = MakeServiceListString(Services_);
auto PreviousSize = Services_.size();
Services_[PrivateEndPoint] = ServiceInfo;
auto CurrentSize = Services_.size();
if(Event == KafkaTopics::ServiceEvents::EVENT_JOIN) {
if(!s1.empty()) {
poco_information(
BusLogger,
fmt::format(
"Service {} ID={} is joining the system.",
Object
->get(
KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
}
std::string SvcList;
for (const auto &Svc : Services_) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
}
poco_information(
BusLogger,
fmt::format("Current list of microservices: {}", SvcList));
} else if(CurrentSize!=PreviousSize) {
poco_information(
BusLogger,
fmt::format(
"Service {} ID={} is being added back in.",
Object
->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
}
poco_information(
logger(),
fmt::format("Current list of microservices: {}", SvcList));
}
} else {
poco_error(
logger(),
poco_information(
BusLogger,
fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
Event));
}
@@ -118,32 +148,39 @@ namespace OpenWifi {
Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
#endif
} else {
poco_error(
logger(),
poco_information(
BusLogger,
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
}
} else {
poco_error(logger(),
poco_information(BusLogger,
fmt::format("Unknown Event: {} Source: {}", Event, ID));
}
}
} else {
poco_error(logger(), "Bad bus message.");
std::ostringstream os;
Object->stringify(std::cout);
std::ostringstream os;
Object->stringify(std::cout);
poco_error(BusLogger, fmt::format("Bad bus message: {}", os.str()));
}
auto i = Services_.begin();
auto ServiceHint = Services_.begin();
auto now = Utils::Now();
for (; i != Services_.end();) {
if ((now - i->second.LastUpdate) > 60) {
i = Services_.erase(i);
auto si1 = Services_.size();
auto ss1 = MakeServiceListString(Services_);
while(ServiceHint!=Services_.end()) {
if ((now - ServiceHint->second.LastUpdate) > 120) {
poco_information(BusLogger, fmt::format("ZombieService: Removing service {}, ", ServiceHint->second.PublicEndPoint));
ServiceHint = Services_.erase(ServiceHint);
} else
++i;
++ServiceHint;
}
if(Services_.size() != si1) {
auto ss2 = MakeServiceListString(Services_);
poco_information(BusLogger, fmt::format("Current list of microservices: {} -> {}", ss1, ss2));
}
} catch (const Poco::Exception &E) {
logger().log(E);
BusLogger.log(E);
}
}
@@ -412,7 +449,7 @@ namespace OpenWifi {
try {
DataDir.createDirectory();
} catch (const Poco::Exception &E) {
logger().log(E);
Logger_.log(E);
}
}
WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
@@ -530,14 +567,12 @@ namespace OpenWifi {
for (auto i : SubSystems_) {
i->Start();
}
EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
EventBusManager_->Start();
EventBusManager()->Start();
}
void MicroService::StopSubSystemServers() {
AddActivity("Stopping");
EventBusManager_->Stop();
EventBusManager()->Stop();
for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
(*i)->Stop();
}
@@ -697,7 +732,7 @@ namespace OpenWifi {
auto APIKEY = Request.get("X-API-KEY");
return APIKEY == MyHash_;
} catch (const Poco::Exception &E) {
logger().log(E);
Logger_.log(E);
}
return false;
}

View File

@@ -201,7 +201,6 @@ namespace OpenWifi {
Poco::JWT::Signer Signer_;
Poco::Logger &Logger_;
Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
std::unique_ptr<EventBusManager> EventBusManager_;
};
inline MicroService *MicroService::instance_ = nullptr;

View File

@@ -129,4 +129,8 @@ namespace OpenWifi {
return ALBHealthCheckServer()->RegisterExtendedHealthMessage(Callback);
}
std::string MicroServiceAccessKey() {
return MicroService::instance().Hash();
}
} // namespace OpenWifi

View File

@@ -22,6 +22,7 @@ namespace OpenWifi {
std::string MicroServicePublicEndPoint();
std::string MicroServiceConfigGetString(const std::string &Key,
const std::string &DefaultValue);
std::string MicroServiceAccessKey();
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
std::string MicroServicePrivateEndPoint();

View File

@@ -47,6 +47,8 @@ namespace OpenWifi {
}
Poco::Data::SessionPool &Pool() { return *Pool_; }
private:
inline int Setup_SQLite();
inline int Setup_MySQL();

View File

@@ -576,8 +576,8 @@ namespace ORM {
bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
try {
assert(ValidFieldName(FieldName));
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Update(Session);
RecordTuple RT;
@@ -593,6 +593,7 @@ namespace ORM {
Update.execute();
if (Cache_)
Cache_->UpdateCache(R);
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
@@ -662,6 +663,7 @@ namespace ORM {
assert(ValidFieldName(FieldName));
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Delete(Session);
std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
@@ -671,6 +673,7 @@ namespace ORM {
Delete.execute();
if (Cache_)
Cache_->Delete(FieldName, Value);
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
@@ -682,11 +685,13 @@ namespace ORM {
try {
assert(!WhereClause.empty());
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Delete(Session);
std::string St = "delete from " + TableName_ + " where " + WhereClause;
Delete << St;
Delete.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);

View File

@@ -414,10 +414,24 @@ namespace OpenWifi::RESTAPI::Errors {
};
static const struct msg DefFirmwareNameExists { 1175, "Firmware name already exists." };
static const struct msg NotAValidECKey { 1176, "Not a valid Signing Key." };
static const struct msg NotAValidRadiusPoolType { 1177, "Not a valid RADIUS pool type." };
static const struct msg InvalidRadiusTypeEndpoint { 1178, "Invalid RADIUS Server Endpoint type." };
static const struct msg InvalidRadiusEndpointPoolStrategy { 1179, "Invalid RADIUS Server Endpoint Pool strategy." };
static const struct msg EndpointMustHaveOneTypeOfServers { 1180, "All servers must be either RADIUS or RADSEC." };
static const struct msg RadiusEndpointIndexInvalid { 1181, "Index must be an address between 0.0.1.1 and 0.0.2.254" };
static const struct msg RadiusEndpointIndexMustBeUnique { 1182, "Index must be unique." };
static const struct msg OrionAccountMustExist { 1183, "Orion account must exist." };
static const struct msg GlobalReachCertMustExist { 1184, "Global Reach certificate must exist." };
static const struct msg InvalidRadsecMainCertificate { 1185, "Invalid Radsec main certificate." };
static const struct msg InvalidRadsecCaCertificate { 1186, "Invalid Radsec CA certificates." };
static const struct msg InvalidRadsecPrivteKey { 1187, "Invalid Radsec Private key." };
static const struct msg InvalidRadsecIPAddress { 1188, "Invalid Radsec IP Address." };
static const struct msg InvalidRadsecPort { 1189, "Invalid Radsec Port." };
static const struct msg InvalidRadsecSecret { 1190, "Invalid Radsec Secret." };
static const struct msg InvalidRadiusServer { 1191, "Invalid Radius Server." };
static const struct msg InvalidRRMAction { 1192, "Invalid RRM Action." };
static const struct msg SimulationDoesNotExist {
7000, "Simulation Instance ID does not exist."
@@ -549,6 +563,10 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *CONTENTDISPOSITION = "Content-Disposition";
static const char *CONTENTTYPE = "Content-Type";
static const char *TRANSFER = "transfer";
static const char *CERTUPDATE = "certupdate";
static const char *RRM = "rrm";
static const char *REQUIREMENTS = "requirements";
static const char *PASSWORDPATTERN = "passwordPattern";
static const char *ACCESSPOLICY = "accessPolicy";
@@ -666,6 +684,12 @@ namespace OpenWifi::uCentralProtocol {
static const char *RADIUSCOA = "coa";
static const char *RADIUSDST = "dst";
static const char *IES = "ies";
static const char *TRANSFER = "transfer";
static const char *CERTUPDATE = "certupdate";
static const char *RRM = "rrm";
static const char *ACTIONS = "actions";
} // namespace OpenWifi::uCentralProtocol
namespace OpenWifi::uCentralProtocol::Events {
@@ -758,6 +782,9 @@ namespace OpenWifi::APCommands {
telemetry,
ping,
script,
rrm,
certupdate,
transfer,
unknown
};
@@ -770,7 +797,10 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::LEDS, RESTAPI::Protocol::TRACE,
RESTAPI::Protocol::REQUEST, RESTAPI::Protocol::WIFISCAN,
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT};
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER
};
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }

View File

@@ -14,6 +14,8 @@
#include <string>
#include <algorithm>
#include <resolv.h>
namespace OpenWifi::Utils {
bool NormalizeMac(std::string &Mac) {
@@ -783,6 +785,10 @@ namespace OpenWifi::Utils {
return false;
}
bool VerifyPrivateKey(const std::string &key) {
return VerifyECKey(key) || VerifyRSAKey(key);
}
bool ValidX509Certificate([[
maybe_unused]] const std::string &Cert) {
try {
@@ -862,4 +868,78 @@ namespace OpenWifi::Utils {
return password;
}
// Function to query NAPTR records for a domain and return them in a vector
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain) {
std::vector<NAPTRRecord> naptrRecords;
unsigned char buf[4096];
ns_msg handle;
ns_initparse(buf, NS_PACKETSZ, &handle);
// Query NAPTR records for the given domain
int response = res_query(domain.c_str(), ns_c_in, ns_t_naptr, buf, sizeof(buf));
if (response < 0) {
return naptrRecords;
}
if(ns_initparse(buf, response, &handle) < 0) {
return naptrRecords;
}
// Iterate through the DNS response and extract NAPTR records
int count = ns_msg_count(handle, ns_s_an);
for (int i = 0; i < count; ++i) {
ns_rr rr;
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
char rdata[256];
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
NAPTRRecord record;
std::istringstream os(rdata);
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.order >> record.preference >> record.flags
>> record.service >> record.regexp >> record.replacement;
naptrRecords.push_back(record);
}
}
return naptrRecords;
}
std::vector<SrvRecord> getSRVRecords(const std::string& domain) {
std::vector<SrvRecord> srvRecords;
// Buffer to hold the DNS response
unsigned char buf[4096];
ns_msg handle;
ns_initparse(buf, NS_PACKETSZ, &handle);
// Query NAPTR records for the given domain
int response = res_query(domain.c_str(), ns_c_in, ns_t_srv, buf, sizeof(buf));
if (response < 0) {
std::cerr << "DNS query failed for " << domain << ": " << hstrerror(h_errno) << std::endl;
return srvRecords;
}
if(ns_initparse(buf, response, &handle) < 0) {
return srvRecords;
}
// Iterate through the DNS response and extract NAPTR records
int count = ns_msg_count(handle, ns_s_an);
for (int i = 0; i < count; ++i) {
ns_rr rr;
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
char rdata[256];
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
SrvRecord record;
std::istringstream os(rdata);
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.pref >> record.weight >>
record.port >> record.srvname ;
srvRecords.push_back(record);
}
}
return srvRecords;
}
} // namespace OpenWifi::Utils

View File

@@ -247,6 +247,24 @@ namespace OpenWifi::Utils {
return count;
}
inline std::uint32_t IPtoInt(const std::string &A) {
Poco::Net::IPAddress IP;
std::uint32_t Result=0;
if(Poco::Net::IPAddress::tryParse(A,IP)) {
for(const auto i:IP.toBytes()) {
Result <<= 8;
Result += i;
}
}
return Result;
}
inline bool ValidIP(const std::string &IPstr) {
Poco::Net::IPAddress IP;
return Poco::Net::IPAddress::tryParse(IPstr,IP);
}
struct CSRCreationParameters {
std::string Country, Province, City,
Organization, CommonName;
@@ -261,7 +279,127 @@ namespace OpenWifi::Utils {
std::string generateStrongPassword(int minLength, int maxLength, int numDigits, int minLowercase, int minSpecial, int minUppercase);
bool VerifyECKey(const std::string &key);
bool VerifyRSAKey(const std::string &key);
bool VerifyPrivateKey(const std::string &key);
bool ValidX509Certificate(const std::string &Cert);
bool ValidX509Certificate(const std::vector<std::string> &Certs);
struct NAPTRRecord {
std::string name;
std::string ttl;
std::string rclass;
std::string rtype;
uint32_t order=0;
uint32_t preference=0;
std::string flags;
std::string service;
std::string regexp;
std::string replacement;
};
// Function to query NAPTR records for a domain and return them in a vector
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
struct SrvRecord {
std::string name;
std::string ttl;
std::string rclass;
std::string rtype;
uint32_t pref = 0;
uint32_t weight = 0;
uint32_t port = 0;
std::string srvname;
};
std::vector<SrvRecord> getSRVRecords(const std::string& domain);
struct HostNameServerResult{
std::string Hostname;
uint32_t Port;
};
class CompressedString {
public:
CompressedString() {
DecompressedSize_ = 0;
};
explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
CompressIt(Data);
}
CompressedString(const CompressedString &Data) {
this->DecompressedSize_ = Data.DecompressedSize_;
this->CompressedData_ = Data.CompressedData_;
}
CompressedString& operator=(const CompressedString& rhs) {
if (this != &rhs) {
this->DecompressedSize_ = rhs.DecompressedSize_;
this->CompressedData_ = rhs.CompressedData_;
}
return *this;
}
CompressedString& operator=(CompressedString&& rhs) {
if (this != &rhs) {
this->DecompressedSize_ = rhs.DecompressedSize_;
this->CompressedData_ = rhs.CompressedData_;
}
return *this;
}
~CompressedString() = default;
operator std::string() const {
return DecompressIt();
}
CompressedString &operator=(const std::string &Data) {
DecompressedSize_ = Data.size();
CompressIt(Data);
return *this;
}
auto CompressedSize() const { return CompressedData_.size(); }
auto DecompressedSize() const { return DecompressedSize_; }
private:
std::string CompressedData_;
std::size_t DecompressedSize_;
inline void CompressIt(const std::string &Data) {
z_stream strm; // = {0};
CompressedData_.resize(Data.size());
strm.next_in = (Bytef *)Data.data();
strm.avail_in = Data.size();
strm.next_out = (Bytef *)CompressedData_.data();
strm.avail_out = Data.size();
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
deflate(&strm, Z_FINISH);
deflateEnd(&strm);
CompressedData_.resize(strm.total_out);
}
[[nodiscard]] std::string DecompressIt() const {
std::string Result;
if(DecompressedSize_!=0) {
Result.resize(DecompressedSize_);
z_stream strm ; //= {0};
strm.next_in = (Bytef *)CompressedData_.data();
strm.avail_in = CompressedData_.size();
strm.next_out = (Bytef *)Result.data();
strm.avail_out = Result.size();
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
inflateInit2(&strm, 15 + 32);
inflate(&strm, Z_FINISH);
inflateEnd(&strm);
}
return Result;
}
};
} // namespace OpenWifi::Utils

View File

@@ -36,15 +36,18 @@ namespace OpenWifi::SDK::FMS {
static const std::string EndPoint{"/api/v1/firmwares"};
OpenWifi::OpenAPIRequestGet API(uSERVICE_FIRMWARE, EndPoint,
{{"deviceType", device_type}}, 50000);
{{"deviceType", device_type},
{"offset","0"},
{"limit","1000"}}, 50000);
auto CallResponse = Poco::makeShared<Poco::JSON::Object>();
auto StatusCode = API.Do(CallResponse);
if (StatusCode == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Array::Ptr FirmwareArr = CallResponse->getArray("firmwares");
for (uint64_t i = 0; i < FirmwareArr->size(); i++) {
for(const auto &firmware:*FirmwareArr) {
auto Object = firmware.extract<Poco::JSON::Object::Ptr>();
FMSObjects::Firmware F;
F.from_json(FirmwareArr->getObject(i));
F.from_json(Object);
FirmWares.emplace_back(F);
}
return true;

View File

@@ -79,7 +79,7 @@ namespace OpenWifi::SDK::GW {
}
bool Upgrade(RESTAPIHandler *client, const std::string &SerialNumber, uint64_t When,
const std::string &ImageName) {
const std::string &ImageName, std::string &status) {
Poco::JSON::Object Body;
Body.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber);
@@ -92,6 +92,7 @@ namespace OpenWifi::SDK::GW {
auto ResponseStatus =
API.Do(CallResponse, client ? client->UserInfo_.webtoken.access_token_ : "");
if (ResponseStatus == Poco::Net::HTTPResponse::HTTP_OK) {
status = CallResponse->get("status").toString();
return true;
}
return false;
@@ -238,4 +239,44 @@ namespace OpenWifi::SDK::GW {
return false;
}
} // namespace Device
namespace RADIUS {
bool GetConfiguration(RESTAPIHandler *client, GWObjects::RadiusProxyPoolList &Pools) {
OpenWifi::OpenAPIRequestGet R(OpenWifi::uSERVICE_GATEWAY,
"/api/v1/radiusProxyConfig", {},
60000);
auto CallResponse = Poco::makeShared<Poco::JSON::Object>();
auto ResponseStatus =
R.Do(CallResponse, client ? client->UserInfo_.webtoken.access_token_ : "");
if(ResponseStatus == Poco::Net::HTTPResponse::HTTP_OK) {
return Pools.from_json(CallResponse);
}
return false;
}
bool SetConfiguration(RESTAPIHandler *client, const Poco::JSON::Object &Configuration,
GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj) {
OpenWifi::OpenAPIRequestPut R(OpenWifi::uSERVICE_GATEWAY,
"/api/v1/radiusProxyConfig", {}, Configuration,
60000);
auto CallResponse = Poco::makeShared<Poco::JSON::Object>();
auto ResponseStatus =
R.Do(CallResponse, client ? client->UserInfo_.webtoken.access_token_ : "");
ErrorObj = *CallResponse;
if(ResponseStatus == Poco::Net::HTTPResponse::HTTP_OK) {
return NewPools.from_json(CallResponse);
}
return false;
}
bool SetConfiguration(RESTAPIHandler *client, const GWObjects::RadiusProxyPoolList &Pools,
GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj) {
Poco::JSON::Object Body;
Pools.to_json(Body);
return SetConfiguration(client,Body,NewPools, ErrorObj);
}
}
} // namespace OpenWifi::SDK::GW

View File

@@ -23,7 +23,7 @@ namespace OpenWifi::SDK::GW {
bool Configure(RESTAPIHandler *client, const std::string &Mac,
Poco::JSON::Object::Ptr &Configuration, Poco::JSON::Object::Ptr &Response);
bool Upgrade(RESTAPIHandler *client, const std::string &Mac, uint64_t When,
const std::string &ImageName);
const std::string &ImageName, std::string &status);
bool SetVenue(RESTAPIHandler *client, const std::string &SerialNumber,
const std::string &uuid);
@@ -38,4 +38,11 @@ namespace OpenWifi::SDK::GW {
const std::string &entity, const std::string &venue,
const std::string &subscriber);
} // namespace Device
namespace RADIUS {
bool GetConfiguration(RESTAPIHandler *client, GWObjects::RadiusProxyPoolList &Pools);
bool SetConfiguration(RESTAPIHandler *client, const GWObjects::RadiusProxyPoolList &Pools,
GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj);
bool SetConfiguration(RESTAPIHandler *client, const Poco::JSON::Object &Configuration,
GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj);
}
} // namespace OpenWifi::SDK::GW

View File

@@ -232,6 +232,69 @@ namespace OpenWifi {
}
return true;
}
bool InventoryDB::GetDevicesForVenue(const std::string &venue_uuid, std::vector<std::string> &devices) {
try {
std::vector<ProvObjects::InventoryTag> device_list;
if(GetRecords(0, 1000, device_list, fmt::format(" venue='{}' ", venue_uuid))) {
for(auto &i:device_list) {
devices.push_back(i.serialNumber);
}
return true;
}
} catch(const Poco::Exception &E) {
Logger().log(E);
return false;
} catch(const std::exception &E) {
Logger().error(fmt::format("std::exception: {}",E.what()));
return false;
} catch(...) {
Logger().error("Unknown exception");
return false;
}
return false;
}
bool InventoryDB::GetDevicesUUIDForVenue(const std::string &venue_uuid, std::vector<std::string> &devices) {
try {
std::vector<ProvObjects::InventoryTag> device_list;
if(GetRecords(0, 1000, device_list, fmt::format(" venue='{}' ", venue_uuid))) {
for(auto &i:device_list) {
devices.push_back(i.info.id);
}
return true;
}
} catch(const Poco::Exception &E) {
Logger().log(E);
return false;
} catch(const std::exception &E) {
Logger().error(fmt::format("std::exception: {}",E.what()));
return false;
} catch(...) {
Logger().error("Unknown exception");
return false;
}
return false;
}
bool InventoryDB::GetDevicesForVenue(const std::string &venue_uuid, std::vector<ProvObjects::InventoryTag> &devices) {
try {
return GetRecords(0, 1000, devices, fmt::format(" venue='{}' ", venue_uuid));
} catch(const Poco::Exception &E) {
Logger().log(E);
return false;
} catch(const std::exception &E) {
Logger().error(fmt::format("std::exception: {}",E.what()));
return false;
} catch(...) {
Logger().error("Unknown exception");
return false;
}
return false;
}
} // namespace OpenWifi
template <>

View File

@@ -38,6 +38,10 @@ namespace OpenWifi {
bool Upgrade(uint32_t from, uint32_t &to) override;
bool GetDevicesForVenue(const std::string &uuid, std::vector<std::string> &devices);
bool GetDevicesUUIDForVenue(const std::string &uuid, std::vector<std::string> &devices);
bool GetDevicesForVenue(const std::string &uuid, std::vector<ProvObjects::InventoryTag> &devices);
private:
bool EvaluateDeviceRules(const ProvObjects::InventoryTag &T,
ProvObjects::DeviceRules &Rules);

View File

@@ -0,0 +1,92 @@
//
// Created by stephane bourque on 2023-09-27.
//
#include "storage_radius_endpoints.h"
#include <framework/RESTAPI_utils.h>
namespace OpenWifi {
static ORM::FieldVec RadiusEndpointDB_Fields{// object info
ORM::Field{"id", 64, true},
ORM::Field{"name", ORM::FieldType::FT_TEXT},
ORM::Field{"description", ORM::FieldType::FT_TEXT},
ORM::Field{"notes", ORM::FieldType::FT_TEXT},
ORM::Field{"created", ORM::FieldType::FT_BIGINT},
ORM::Field{"modified", ORM::FieldType::FT_BIGINT},
ORM::Field{"Type", ORM::FieldType::FT_TEXT},
ORM::Field{"RadsecServers", ORM::FieldType::FT_TEXT},
ORM::Field{"RadiusServers", ORM::FieldType::FT_TEXT},
ORM::Field{"PoolStrategy", ORM::FieldType::FT_TEXT},
ORM::Field{"Index", ORM::FieldType::FT_TEXT},
ORM::Field{"UsedBy", ORM::FieldType::FT_TEXT},
ORM::Field{"UseGWProxy", ORM::FieldType::FT_BOOLEAN},
ORM::Field{"NasIdentifier", ORM::FieldType::FT_TEXT},
ORM::Field{"AccountingInterval", ORM::FieldType::FT_BIGINT}
};
static ORM::IndexVec RadiusEndpointDB_Indexes{
{std::string("radius_ep_name_index"),
ORM::IndexEntryVec{{std::string("name"), ORM::Indextype::ASC}}}};
RadiusEndpointDB::RadiusEndpointDB(OpenWifi::DBType T, Poco::Data::SessionPool &P, Poco::Logger &L)
: DB(T, "radius_endpoints", RadiusEndpointDB_Fields, RadiusEndpointDB_Indexes, P, L, "rep") {}
bool RadiusEndpointDB::Upgrade([[maybe_unused]] uint32_t from, uint32_t &to) {
to = Version();
std::vector<std::string> Script{
"alter table " + TableName_ + " add column NasIdentifier TEXT;",
"alter table " + TableName_ + " add column AccountingInterval BIGINT;"
};
for (const auto &i : Script) {
try {
auto Session = Pool_.get();
Session << i, Poco::Data::Keywords::now;
} catch (...) {
}
}
return true;
}
} // namespace OpenWifi
template <>
void ORM::DB<OpenWifi::RadiusEndpointDbRecordType, OpenWifi::ProvObjects::RADIUSEndPoint>::Convert(
const OpenWifi::RadiusEndpointDbRecordType &In, OpenWifi::ProvObjects::RADIUSEndPoint &Out) {
Out.info.id = In.get<0>();
Out.info.name = In.get<1>();
Out.info.description = In.get<2>();
Out.info.notes =
OpenWifi::RESTAPI_utils::to_object_array<OpenWifi::SecurityObjects::NoteInfo>(In.get<3>());
Out.info.created = In.get<4>();
Out.info.modified = In.get<5>();
Out.Type = In.get<6>();
Out.RadsecServers = OpenWifi::RESTAPI_utils::to_object_array<OpenWifi::ProvObjects::RADIUSEndPointRadsecType>(In.get<7>());
Out.RadiusServers = OpenWifi::RESTAPI_utils::to_object_array<OpenWifi::ProvObjects::RADIUSEndPointRadiusType>(In.get<8>());
Out.PoolStrategy = In.get<9>();
Out.Index = In.get<10>();
Out.UsedBy = OpenWifi::RESTAPI_utils::to_object_array(In.get<11>());
Out.UseGWProxy = In.get<12>();
Out.NasIdentifier = In.get<13>();
Out.AccountingInterval = In.get<14>();
}
template <>
void ORM::DB<OpenWifi::RadiusEndpointDbRecordType, OpenWifi::ProvObjects::RADIUSEndPoint>::Convert(
const OpenWifi::ProvObjects::RADIUSEndPoint &In, OpenWifi::RadiusEndpointDbRecordType &Out) {
Out.set<0>(In.info.id);
Out.set<1>(In.info.name);
Out.set<2>(In.info.description);
Out.set<3>(OpenWifi::RESTAPI_utils::to_string(In.info.notes));
Out.set<4>(In.info.created);
Out.set<5>(In.info.modified);
Out.set<6>(In.Type);
Out.set<7>(OpenWifi::RESTAPI_utils::to_string(In.RadsecServers));
Out.set<8>(OpenWifi::RESTAPI_utils::to_string(In.RadiusServers));
Out.set<9>(In.PoolStrategy);
Out.set<10>(In.Index);
Out.set<11>(OpenWifi::RESTAPI_utils::to_string(In.UsedBy));
Out.set<12>(In.UseGWProxy);
Out.set<13>(In.NasIdentifier);
Out.set<14>(In.AccountingInterval);
}

View File

@@ -0,0 +1,46 @@
//
// Created by stephane bourque on 2023-09-27.
//
#pragma once
#include "RESTObjects/RESTAPI_ProvObjects.h"
#include "framework/orm.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
uint64_t,
uint64_t,
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
bool,
std::string,
std::uint64_t
> RadiusEndpointDbRecordType;
class RadiusEndpointDB : public ORM::DB<RadiusEndpointDbRecordType, ProvObjects::RADIUSEndPoint> {
public:
RadiusEndpointDB(OpenWifi::DBType T, Poco::Data::SessionPool &P, Poco::Logger &L);
virtual ~RadiusEndpointDB(){};
bool Upgrade(uint32_t from, uint32_t &to) override;
static inline bool ValidIndex(const std::string &I) {
static uint32_t Low = Utils::IPtoInt("0.0.1.1");
static uint32_t High = Utils::IPtoInt("0.0.2.254");
auto IP = Utils::IPtoInt(I);
return (IP>=Low) && (IP<=High);
}
private:
};
} // namespace OpenWifi