Compare commits

..

106 Commits

Author SHA1 Message Date
Dmitry Dunaev
0a2190b43f Chg: helm set v2.0.0-RC1 image 2021-10-01 14:46:18 +03:00
stephb9959
467c6edc23 Merge remote-tracking branch 'origin/main' 2021-09-29 20:27:54 -07:00
stephb9959
2dbdfec748 Adding required security logging 2021-09-29 20:27:47 -07:00
Dmitry Dunaev
b828619fc9 [WIFI-4240] Add: mailer.sender in all configuration files 2021-09-28 13:20:09 +03:00
Dmitry Dunaev
1c959935cf [WIFI-4240] Fix: template name in helm config template 2021-09-28 13:03:54 +03:00
stephb9959
8211eebd23 Adding standard normlized errors/ 2021-09-27 22:52:18 -07:00
stephb9959
905fcdbe79 Build number. 2021-09-27 15:43:19 -07:00
Stephane Bourque
cbe46adcd1 Merge pull request #16 from Telecominfraproject/dev-2.2
Dev 2.2
2021-09-27 14:06:20 -07:00
Stephane Bourque
9690b75764 Merge pull request #14 from Telecominfraproject/WIFI-4240-adapt-ucentral-sdk
[WIFI-4240] Adapt uCentral SDK for deployment changes
2021-09-27 14:05:10 -07:00
Stephane Bourque
16ac5171ba Merge pull request #15 from Telecominfraproject/feature/wifi-4240--adapt-helm
[WIFI-4240] Chg: adapt helm files to 2.2 renaming
2021-09-27 14:04:53 -07:00
stephb9959
2ad8156d0d Fixing daemon reload. 2021-09-27 09:45:51 -07:00
stephb9959
f9de771cfa Fixing daemon reload. 2021-09-27 09:44:19 -07:00
stephb9959
3918d677a7 Fixing daemon reload. 2021-09-27 09:37:18 -07:00
stephb9959
c4f0650f88 Merge remote-tracking branch 'origin/dev-2.2' into dev-2.2
# Conflicts:
#	build
#	src/RESTAPI_handler.cpp
#	src/RESTAPI_handler.h
#	src/RESTAPI_system_command.cpp
2021-09-27 09:33:24 -07:00
stephb9959
c752af8206 Fixing daemon reload. 2021-09-27 09:33:03 -07:00
oblom0v
57e2bfb9e5 Adapt Github actions workflows 2021-09-27 15:27:38 +02:00
Dmitry Dunaev
cbfc223bff [WIFI-4240] Chg: adapt helm files to 2.2 renaming 2021-09-27 16:02:30 +03:00
oblom0v
45d992bb94 Fix renamed binary again 2021-09-27 14:10:40 +02:00
oblom0v
27802bb697 Fix renamed binary in copy statement 2021-09-27 14:09:36 +02:00
oblom0v
07d25cac7e Adapt renaming in Docker and associated config 2021-09-23 19:48:38 +02:00
stephb9959
234d100673 Fixing daemon reload. 2021-09-23 19:37:55 +02:00
stephb9959
74aed838b4 Adding more logging around oAuth2 requests. 2021-09-23 19:37:54 +02:00
stephb9959
7d5fed59e1 Missing field 2021-09-23 19:37:54 +02:00
stephb9959
e7a0f53115 Updating cli/documentation 2021-09-23 19:37:54 +02:00
stephb9959
4185a44665 Adding system reload command. 2021-09-23 19:37:54 +02:00
stephb9959
6152068317 Adding system reload command. 2021-09-23 19:37:54 +02:00
stephb9959
6f0da2d17e Adding system reload command. 2021-09-23 19:37:54 +02:00
stephb9959
0bca097dff Adding systeminfo command. 2021-09-23 19:37:54 +02:00
stephb9959
a38f9e925a Changing version API 2021-09-23 19:37:54 +02:00
stephb9959
9001d11121 Adding proper security logging. 2021-09-23 19:37:53 +02:00
stephb9959
5aa514238a Adding proper security logging. 2021-09-23 19:37:53 +02:00
stephb9959
4731362218 Adding proper security logging. 2021-09-23 19:37:53 +02:00
stephb9959
ca39daf062 Completing RESTAPI refactor. 2021-09-23 19:37:53 +02:00
stephb9959
7e5b6d333d Completing RESTAPI refactor. 2021-09-23 19:37:53 +02:00
stephb9959
1d026b2262 Completing RESTAPI refactor. 2021-09-23 19:37:53 +02:00
stephb9959
62b8e0a16a Completing RESTAPI refactor. 2021-09-23 19:37:53 +02:00
stephb9959
23569ffe58 Completing RESTAPI refactor. 2021-09-23 19:37:52 +02:00
stephb9959
8e1e6567af Completing RESTAPI refactor. 2021-09-23 19:37:52 +02:00
stephb9959
bca0454086 Completing RESTAPI refactor. 2021-09-23 19:37:52 +02:00
stephb9959
5d060ec43f Completing RESTAPI refactor. 2021-09-23 19:37:52 +02:00
stephb9959
2bde1536f8 Adding complete token database and including a revocation DB. 2021-09-23 19:37:52 +02:00
stephb9959
520c73f1a5 Adding revocation DB for tokens. 2021-09-23 19:37:52 +02:00
stephb9959
09851d2fb9 Refactoring namespace for OpenWifi. 2021-09-23 19:37:52 +02:00
stephb9959
d7033d29dc Refactoring namespace for OpenWifi. 2021-09-23 19:37:52 +02:00
stephb9959
ce216400b7 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
e88ce1a73e Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
067f3a1720 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
6371e63e6b Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
f31d1cbad8 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
b71b4bb1f0 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
9157578994 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
b75716ecb6 Refactoring namespace for OpenWifi. 2021-09-23 19:37:51 +02:00
stephb9959
b08d8cefd7 Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
f856f800e3 Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
eb445bdddb Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
40eaf90165 Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
24f662ff9f Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
17b58ef0bc Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
4a46d8fa96 Refactoring namespace for OpenWifi. 2021-09-23 19:37:50 +02:00
stephb9959
5ef3de7df0 Refactoring namespace for OpenWifi. 2021-09-23 19:37:49 +02:00
stephb9959
3757e7b5ac Refactoring namespace for OpenWifi. 2021-09-23 19:37:49 +02:00
stephb9959
1236dcbd10 no tracking 2021-09-23 19:37:49 +02:00
Johann Hoffmann
60550cc9c3 [WIFI-3938] Remove ./add-ca-cert.sh script in Docker Compose deployment (#13)
* Update ca-certificates in entrypoint script

* Add restapi-ca.pem to Docker image
2021-09-21 18:59:33 +02:00
stephb9959
aa95294a51 Fixing daemon reload. 2021-09-21 08:56:37 -07:00
stephb9959
ba20e9a16f Adding more logging around oAuth2 requests. 2021-09-20 07:49:41 -07:00
stephb9959
6c16543003 Missing field 2021-09-19 21:58:01 -07:00
stephb9959
5f38e163a1 Updating cli/documentation 2021-09-19 16:12:27 -07:00
stephb9959
e09012c413 Adding system reload command. 2021-09-18 22:30:53 -07:00
stephb9959
54f5cffa3f Adding system reload command. 2021-09-18 21:59:56 -07:00
stephb9959
8da84ed078 Adding system reload command. 2021-09-18 16:09:44 -07:00
stephb9959
930b1eec63 Adding systeminfo command. 2021-09-18 10:44:48 -07:00
stephb9959
16d48e7bf4 Changing version API 2021-09-18 10:26:58 -07:00
stephb9959
a983a957f3 Adding proper security logging. 2021-09-16 22:09:43 -07:00
stephb9959
8bf4290a8f Adding proper security logging. 2021-09-15 11:57:50 -07:00
stephb9959
f242ebdfcb Adding proper security logging. 2021-09-15 11:43:37 -07:00
stephb9959
7ebc775b20 Completing RESTAPI refactor. 2021-09-12 14:33:24 -07:00
stephb9959
6b79d89084 Completing RESTAPI refactor. 2021-09-12 10:46:59 -07:00
stephb9959
17e0af0b2f Completing RESTAPI refactor. 2021-09-12 10:43:25 -07:00
stephb9959
3bf5db5f24 Completing RESTAPI refactor. 2021-09-12 10:40:14 -07:00
stephb9959
46187d5bc5 Completing RESTAPI refactor. 2021-09-12 10:39:07 -07:00
stephb9959
45def2aaf9 Completing RESTAPI refactor. 2021-09-12 10:36:57 -07:00
stephb9959
c1c624ec05 Completing RESTAPI refactor. 2021-09-12 10:34:26 -07:00
stephb9959
cee623f0b2 Completing RESTAPI refactor. 2021-09-12 10:27:18 -07:00
stephb9959
24d2ae453f Adding complete token database and including a revocation DB. 2021-09-10 22:28:57 -07:00
stephb9959
27ae51a130 Adding revocation DB for tokens. 2021-09-09 12:58:55 -07:00
stephb9959
8cc3966a4b Refactoring namespace for OpenWifi. 2021-09-02 23:35:51 -07:00
stephb9959
11637076ae Refactoring namespace for OpenWifi. 2021-09-02 23:33:42 -07:00
stephb9959
cc11739a4f Refactoring namespace for OpenWifi. 2021-09-02 23:28:57 -07:00
stephb9959
d4ea19f520 Refactoring namespace for OpenWifi. 2021-09-02 23:18:56 -07:00
stephb9959
de23d81632 Refactoring namespace for OpenWifi. 2021-09-02 23:17:25 -07:00
stephb9959
7bce1b7e70 Refactoring namespace for OpenWifi. 2021-09-02 23:08:58 -07:00
stephb9959
18a700d2a3 Refactoring namespace for OpenWifi. 2021-09-02 19:08:45 -07:00
stephb9959
c0137c256c Refactoring namespace for OpenWifi. 2021-09-02 19:03:52 -07:00
stephb9959
8873c70e8a Refactoring namespace for OpenWifi. 2021-09-02 18:15:05 -07:00
stephb9959
0cff9077ce Refactoring namespace for OpenWifi. 2021-09-02 18:13:23 -07:00
stephb9959
aa4b2fd0f0 Refactoring namespace for OpenWifi. 2021-09-02 18:11:10 -07:00
stephb9959
72a2e7ab65 Refactoring namespace for OpenWifi. 2021-09-02 16:35:19 -07:00
stephb9959
4665d62e2d Refactoring namespace for OpenWifi. 2021-09-02 16:30:47 -07:00
Johann Hoffmann
92aa8a022e Add template and envsubst call in docker-entrypoint.sh (#12) 2021-09-02 18:51:36 +02:00
stephb9959
4211012a3b Refactoring namespace for OpenWifi. 2021-08-31 15:22:55 -07:00
stephb9959
ba8f11836a Refactoring namespace for OpenWifi. 2021-08-31 14:26:53 -07:00
stephb9959
f14b2a8671 Refactoring namespace for OpenWifi. 2021-08-31 11:34:27 -07:00
stephb9959
a5105227b0 Refactoring namespace for OpenWifi. 2021-08-31 11:33:26 -07:00
stephb9959
f9cd540b06 Refactoring namespace for OpenWifi. 2021-08-31 11:31:39 -07:00
stephb9959
5f6f101395 Refactoring namespace for OpenWifi. 2021-08-31 11:30:40 -07:00
stephb9959
7054894ccc no tracking 2021-08-31 11:30:21 -07:00
81 changed files with 2527 additions and 1618 deletions

View File

@@ -28,7 +28,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t wlan-cloud-ucentralsec:${{ github.sha }} .
run: docker build -t wlan-cloud-owsec:${{ github.sha }} .
- name: Tag Docker image
run: |
@@ -52,7 +52,7 @@ jobs:
echo "Result tags: $TAGS"
for tag in $TAGS; do
docker tag wlan-cloud-ucentralsec:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/ucentralsec:$tag
docker tag wlan-cloud-owsec:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owsec:$tag
done
- name: Log into Docker registry
@@ -66,4 +66,4 @@ jobs:
- name: Push Docker images
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main'
run: |
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/ucentralsec | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owsec | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}

View File

@@ -16,4 +16,4 @@ jobs:
steps:
- run: |
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/ucentralsec/$PR_BRANCH_TAG"
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owsec/$PR_BRANCH_TAG"

85
CLI.md
View File

@@ -1,9 +1,9 @@
# Security Service CLI Documentation
## Before using the CLI
You must set the environment variable `UCENTRALSEC`. You must specify the host and port for the security service. Here is an example
You must set the environment variable `OWSEC`. You must specify the host and port for the security service. Here is an example
```csh
export UCENTRALSEC=mysecurityservice,example.com:16001
export OWSEC=mysecurityservice,example.com:16001
```
Once set, you can start using the `CLI`.
@@ -12,64 +12,59 @@ Most commands will take from 0 to 2 parameters. You should include all parameter
## The commands
### `cli createuser <email> <initial password>`
This will create a simple user as admin using the email as login ID and setting the initial password.
### listendpoints
Get all the system endpoints.
### `cli createuser_v <email> <initial password>`
This will create a simple user and force email verification.
### emailtest
Generate a forgot Password e-amil to the logged in user.
### `cli deleteuser <id>`
Delete the specified user using the user's UUID.
### me
Show information about the logged user.
### `cli getuser <id>`
Get the specified user using the user's UUID.
### createuser <email> <password>
Create a user with an initial password and force the user to change password.
### `cli listusers`
Get a list of users.
### createuser_v <email> <password>
Same as create user but also force an e-mail verification.
### `cli policies`
List the link used to display password and usage policies for the management site.
### deleteuser <user UUID>
Delete the user.
### `cli setavatar <id> <filename>`
Sets the avatar for the user with ID. The file should be gif, png, svg.
### getuser <user UUID>
Get the user information.
### `cli deleteavatar <id>`
Remove the avatar fort the specified user ID.
### listusers
List users.
### `cli secversion`
Get the vewrsion of the secufiry service.
### policies
List the login and access policies.
### `cli sectimes`
Get the starttime and uptime for the security service.
### setavatar <user UUID> <filename>
Sets the avatar for user to the image in filename.
### getavatar <user UUID>
Get the avatar for the user.
### deleteavatar <user UUID>
Remove the avatar for a user.
### sendemail <recipient> <from>
Sends a test email to see if the e-mail system is working.
### `cli revisions`
Get the list of currently available revisions.
### setloglevel <subsystem> <loglevel>
Set the log level for s specific subsystem.
### `cli devicetypes`
Retrieve the list of known `device_types`
### getloglevels
Get the current log levels for all subsystems.
### `cli firmwareage <device_type> <revision>`
If you specify your `device_type` and `revision`, the system will do its best to estimate how
far in the past you `revision` is compared to the latest revision.
### getloglevelnames
Get the log level names available.
### `cli gethistory <serialNumber>`
Get the revision history for a given device.
### getsubsystemnames
Get the list of subsystems.
### `cli connecteddevices`
Get a list of the currently known devices and the last connection information we have about the,
### `cli connecteddevice <serialNumber>`
Get the information relevant to a specific device.
### `cli devicereport`
Give a simplified dashboard report of the data in the service.
### `cli fmsversion`
Display the version of the service.
### `cli fmstimes`
Display the uptime and start time of the service.
### systeminfo
Get basic system information.
### reloadsubsystem <subsystem name>
Reload the configuration for a subsystem.

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(ucentralsec VERSION 2.1.0)
project(owsec VERSION 2.2.0)
set(CMAKE_CXX_STANDARD 17)
@@ -47,7 +47,7 @@ find_package(PostgreSQL REQUIRED)
find_package(MySQL REQUIRED)
find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataSQLite DataPostgreSQL DataMySQL)
add_executable( ucentralsec
add_executable( owsec
build
src/Daemon.h src/Daemon.cpp
src/MicroService.cpp src/MicroService.h
@@ -73,14 +73,18 @@ add_executable( ucentralsec
src/RESTAPI_AssetServer.cpp src/RESTAPI_AssetServer.h
src/RESTAPI_avatarHandler.cpp src/RESTAPI_avatarHandler.h
src/storage_avatar.cpp src/storage_avatar.h src/storage_users.h
src/OpenWifiTypes.h )
src/OpenWifiTypes.h src/RESTAPI_email_handler.cpp src/RESTAPI_email_handler.h
src/storage_tokens.cpp
src/RESTAPI_GenericServer.h src/RESTAPI_GenericServer.cpp
src/RESTAPI_errors.h
)
if(NOT SMALL_BUILD)
target_link_libraries(ucentralsec PUBLIC
target_link_libraries(owsec PUBLIC
${Poco_LIBRARIES} ${Boost_LIBRARIES} ${MySQL_LIBRARIES} ${ZLIB_LIBRARIES}
CppKafka::cppkafka
)
if(UNIX AND NOT APPLE)
target_link_libraries(ucentralsec PUBLIC PocoJSON)
target_link_libraries(owsec PUBLIC PocoJSON)
endif()
endif()

View File

@@ -26,36 +26,39 @@ RUN cmake ..
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
ADD CMakeLists.txt build /ucentralsec/
ADD cmake /ucentralsec/cmake
ADD src /ucentralsec/src
ADD CMakeLists.txt build /owsec/
ADD cmake /owsec/cmake
ADD src /owsec/src
WORKDIR /ucentralsec
WORKDIR /owsec
RUN mkdir cmake-build
WORKDIR /ucentralsec/cmake-build
WORKDIR /owsec/cmake-build
RUN cmake ..
RUN cmake --build . --config Release -j8
FROM alpine
ENV UCENTRALSEC_USER=ucentralsec \
UCENTRALSEC_ROOT=/ucentralsec-data \
UCENTRALSEC_CONFIG=/ucentralsec-data
ENV OWSEC_USER=owsec \
OWSEC_ROOT=/owsec-data \
OWSEC_CONFIG=/owsec-data
RUN addgroup -S "$UCENTRALSEC_USER" && \
adduser -S -G "$UCENTRALSEC_USER" "$UCENTRALSEC_USER"
RUN addgroup -S "$OWSEC_USER" && \
adduser -S -G "$OWSEC_USER" "$OWSEC_USER"
RUN mkdir /ucentral
RUN mkdir -p "$UCENTRALSEC_ROOT" "$UCENTRALSEC_CONFIG" && \
chown "$UCENTRALSEC_USER": "$UCENTRALSEC_ROOT" "$UCENTRALSEC_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec
COPY --from=builder /ucentralsec/cmake-build/ucentralsec /ucentral/ucentralsec
RUN mkdir /openwifi
RUN mkdir -p "$OWSEC_ROOT" "$OWSEC_CONFIG" && \
chown "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates
COPY --from=builder /owsec/cmake-build/owsec /openwifi/owsec
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
COPY --from=builder /poco/cmake-build/lib/* /lib/
COPY owsec.properties.tmpl ${OWSEC_CONFIG}/
COPY docker-entrypoint.sh /
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
EXPOSE 16001 17001 16101
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/ucentral/ucentralsec"]
CMD ["/openwifi/owsec"]

View File

@@ -21,7 +21,7 @@ The entire uCentral systems uses several MicroServices. In order for the whole s
access
- Security
- Properties file: ucentralsec.properties
- Properties file: owsec.properties
- Ports
- Public: 16001
- Private: 17001
@@ -42,7 +42,7 @@ access
- ALB: 16104
## Security Configuration
The service relies on a properties configuration file called `ucentralsec.properties`. In this file, you should configure several entries. Many values are optional
The service relies on a properties configuration file called `owsec.properties`. In this file, you should configure several entries. Many values are optional
and you can rely on the defaults. Here are some values of note:
### `authentication.default.password`
@@ -52,7 +52,7 @@ Set the hash of the default username and password. Please look below on how to d
Set the default username to use to login.
### Default username and password
The default username and password are set in `ucentralsec.properties` file. The following entries manage the username and password
The default username and password are set in `owsec.properties` file. The following entries manage the username and password
```text
authentication.default.username = tip@ucentral.com
authentication.default.password = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -97,19 +97,19 @@ This security service uses Kafka to coordinate security with other services that
in order to use this. You can find several examples of Kafka services available with Docker. Here are the values you need to configure.
```asm
ucentral.kafka.group.id = security
ucentral.kafka.client.id = security1
ucentral.kafka.enable = true
ucentral.kafka.brokerlist = my.kafkaserver.arilia.com:9092
ucentral.kafka.auto.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
openwifi.kafka.group.id = security
openwifi.kafka.client.id = security1
openwifi.kafka.enable = true
openwifi.kafka.brokerlist = my.kafkaserver.arilia.com:9092
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
```
#### `ucentral.kafka.brokerlist`
#### `openwifi.kafka.brokerlist`
This is the list of your kafka brokers. This is a comma separated list. You should use IP addresses or FQDNs and the relevant ports, usually 9092 is the
default.
#### `ucentral.kafka.group.id`
#### `openwifi.kafka.group.id`
Every service on the Kafka bux must have a unique value (at least in our case). This should be a string. We suggest using a name corresponding to the
function provided. In this case, security.
@@ -124,17 +124,17 @@ Here are the parameters for the public interface. The important files are:
- `restapi-ca.pem` : the CA of your certificate
- `restapi-cert.pem` : the certificate for the public interface
- `restapi-key.pem` : the key associated with this certificate
- `ucentral.restapi.host.0.key.password` : if you key is password protected, you may supply that password here.
- `openwifi.restapi.host.0.key.password` : if you key is password protected, you may supply that password here.
```asm
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16001
ucentral.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = 16001
openwifi.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.key.password = mypassword
```
#### The private interface
@@ -142,14 +142,14 @@ The private interface is used for service-to-service communication. You can use
to the filenames used in the previous section.
```asm
ucentral.internal.restapi.host.0.backlog = 100
ucentral.internal.restapi.host.0.security = relaxed
ucentral.internal.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address = *
ucentral.internal.restapi.host.0.port = 17001
ucentral.internal.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.key.password = mypassword
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = 17001
openwifi.internal.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.internal.restapi.host.0.key.password = mypassword
```
### Other important values
@@ -157,19 +157,19 @@ Here are other important values you must set.
```asm
ucentral.system.data = $UCENTRALSEC_ROOT/data
ucentral.system.uri.private = https://localhost:17001
ucentral.system.uri.public = https://ucentral.dpaas.arilia.com:16001
ucentral.system.commandchannel = /tmp/app.ucentralsec
ucentral.service.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
openwifi.system.data = $OWSEC_ROOT/data
openwifi.system.uri.private = https://localhost:17001
openwifi.system.uri.public = https://openwifi.dpaas.arilia.com:16001
openwifi.system.commandchannel = /tmp/app.ucentralsec
openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem
```
#### `ucentral.system.data`
#### `openwifi.system.data`
The location of some important data files including the user name database.
#### `ucentral.system.uri.private`
#### `openwifi.system.uri.private`
This is the FQDN used internally between services.
#### `ucentral.system.uri.public`
#### `openwifi.system.uri.public`
This is the FQDN used externally serving the OpenAPI interface.

2
build
View File

@@ -1 +1 @@
11
29

View File

@@ -1,11 +1,56 @@
#!/bin/sh
set -e
if [ "$1" = '/ucentral/ucentralsec' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$UCENTRALSEC_USER": "$UCENTRALSEC_ROOT" "$UCENTRALSEC_CONFIG"
if [ "$SELFSIGNED_CERTS" = 'true' ]; then
update-ca-certificates
fi
exec su-exec "$UCENTRALSEC_USER" "$@"
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; then
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16001"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
RESTAPI_WWWASSETS=${RESTAPI_WWWASSETS:-"\$OWSEC_ROOT/wwwassets"} \
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \
INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17001"} \
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
AUTHENTICATION_DEFAULT_USERNAME=${AUTHENTICATION_DEFAULT_USERNAME:-"tip@ucentral.com"} \
AUTHENTICATION_DEFAULT_PASSWORD=${AUTHENTICATION_DEFAULT_PASSWORD:-"13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf"} \
SYSTEM_DATA=${SYSTEM_DATA:-"\$OWSEC_ROOT/data"} \
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17001"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16001"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SERVICE_KEY=${SERVICE_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
MAILER_HOSTNAME=${MAILER_HOSTNAME:-"smtp.gmail.com"} \
MAILER_USERNAME=${MAILER_USERNAME:-"************************"} \
MAILER_PASSWORD=${MAILER_PASSWORD:-"************************"} \
MAILER_SENDER=${MAILER_SENDER:-"OpenWIFI"} \
MAILER_PORT=${MAILER_PORT:-"587"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \
STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owsec"} \
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"owsec"} \
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"owsec"} \
STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \
STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"owsec"} \
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owsec"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owsec"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
envsubst < $OWSEC_CONFIG/owsec.properties.tmpl > $OWSEC_CONFIG/owsec.properties
fi
if [ "$1" = '/openwifi/owsec' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
fi
exec su-exec "$OWSEC_USER" "$@"
fi
exec "$@"

View File

@@ -1,7 +1,7 @@
apiVersion: v2
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: ucentralsec
name: owsec
version: 0.1.0
dependencies:
- name: postgresql

View File

@@ -1,6 +1,6 @@
# ucentralsec
# owsec
This Helm chart helps to deploy uCentralSec to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as uCentralSec requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment.
This Helm chart helps to deploy OpenWIFI Security (further on refered as __Security__) to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as Security requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment.
## TL;DR;
@@ -11,7 +11,7 @@ $ helm install .
## Introduction
This chart bootstraps an ucentralsec on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
This chart bootstraps the Security on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
## Installing the Chart
@@ -23,7 +23,7 @@ To install the chart with the release name `my-release`:
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralsec@helm?ref=main
```
The command deploys ucentralsec on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
The command deploys the Security on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
@@ -47,30 +47,30 @@ The following table lists the configurable parameters of the chart and their def
| strategyType | string | Application deployment strategy | `'Recreate'` |
| nameOverride | string | Override to be used for application deployment | |
| fullnameOverride | string | Override to be used for application deployment (has priority over nameOverride) | |
| images.ucentralsec.repository | string | Docker image repository | |
| images.ucentralsec.tag | string | Docker image tag | `'master'` |
| images.ucentralsec.pullPolicy | string | Docker image pull policy | `'Always'` |
| services.ucentralsec.type | string | uCentralSec service type | `'LoadBalancer'` |
| services.ucentralsec.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16001` |
| services.ucentralsec.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16001` |
| services.ucentralsec.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` |
| services.ucentralsec.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17001` |
| services.ucentralsec.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17001` |
| services.ucentralsec.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` |
| checks.ucentralsec.liveness.httpGet.path | string | Liveness check path to be used | `'/'` |
| checks.ucentralsec.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16101` |
| checks.ucentralsec.readiness.httpGet.path | string | Readiness check path to be used | `'/'` |
| checks.ucentralsec.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16101` |
| images.owsec.repository | string | Docker image repository | |
| images.owsec.tag | string | Docker image tag | `'master'` |
| images.owsec.pullPolicy | string | Docker image pull policy | `'Always'` |
| services.owsec.type | string | OpenWIFI Security service type | `'LoadBalancer'` |
| services.owsec.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16001` |
| services.owsec.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16001` |
| services.owsec.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` |
| services.owsec.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17001` |
| services.owsec.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17001` |
| services.owsec.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` |
| checks.owsec.liveness.httpGet.path | string | Liveness check path to be used | `'/'` |
| checks.owsec.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16101` |
| checks.owsec.readiness.httpGet.path | string | Readiness check path to be used | `'/'` |
| checks.owsec.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16101` |
| ingresses.restapi.enabled | boolean | Defines if REST API endpoint should be exposed via Ingress controller | `False` |
| ingresses.restapi.hosts | array | List of hosts for exposed REST API | |
| ingresses.restapi.paths | array | List of paths to be exposed for REST API | |
| volumes.ucentralsec | array | Defines list of volumes to be attached to uCentralSec | |
| persistence.enabled | boolean | Defines if uCentralSec requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` |
| volumes.owsec | array | Defines list of volumes to be attached to the Security | |
| persistence.enabled | boolean | Defines if Security requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` |
| persistence.accessModes | array | Defines PV access modes | |
| persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to uCentralSec | |
| configProperties | hash | Configuration properties that should be passed to the application in `ucentralsec.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to uCentralSec (PEM format is adviced to be used) (see `volumes.ucentralsec` on where it is mounted) | |
| public_env_variables | hash | Defines list of environment variables to be passed to the Security | |
| configProperties | hash | Configuration properties that should be passed to the application in `owsec.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to the Security (PEM format is adviced to be used) (see `volumes.owsec` on where it is mounted) | |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,

View File

@@ -1,4 +1,4 @@
{{- define "ucentralsec.config" -}}
{{- define "owsec.config" -}}
{{- range $key, $value := .Values.configProperties }}
{{ $key }} = {{ $value }}
{{- end }}

View File

@@ -2,7 +2,7 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "ucentralsec.name" -}}
{{- define "owsec.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
@@ -11,7 +11,7 @@ Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "ucentralsec.fullname" -}}
{{- define "owsec.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
@@ -27,6 +27,6 @@ If release name contains chart name it will be used as a full name.
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ucentralsec.chart" -}}
{{- define "owsec.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -3,10 +3,10 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ucentralsec.fullname" . }}
name: {{ include "owsec.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "ucentralsec.name" . }}
helm.sh/chart: {{ include "ucentralsec.chart" . }}
app.kubernetes.io/name: {{ include "owsec.name" . }}
helm.sh/chart: {{ include "owsec.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
@@ -15,28 +15,28 @@ spec:
type: {{ .Values.strategyType }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "ucentralsec.name" . }}
app.kubernetes.io/name: {{ include "owsec.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.ucentralsec.labels }}
{{- with .Values.services.owsec.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
template:
metadata:
annotations:
checksum/config: {{ include "ucentralsec.config" . | sha256sum }}
checksum/config: {{ include "owsec.config" . | sha256sum }}
labels:
app.kubernetes.io/name: {{ include "ucentralsec.name" . }}
app.kubernetes.io/name: {{ include "owsec.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.ucentralsec.labels }}
{{- with .Values.services.owsec.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: ucentralsec
image: "{{ .Values.images.ucentralsec.repository }}:{{ .Values.images.ucentralsec.tag }}"
imagePullPolicy: {{ .Values.images.ucentralsec.pullPolicy }}
- name: owsec
image: "{{ .Values.images.owsec.repository }}:{{ .Values.images.owsec.tag }}"
imagePullPolicy: {{ .Values.images.owsec.pullPolicy }}
env:
- name: KUBERNETES_DEPLOYED
@@ -49,19 +49,19 @@ spec:
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "ucentralsec.fullname" $root }}-env
name: {{ include "owsec.fullname" $root }}-env
key: {{ $key }}
{{- end }}
ports:
{{- range $port, $portValue := .Values.services.ucentralsec.ports }}
{{- range $port, $portValue := .Values.services.owsec.ports }}
- name: {{ $port }}
containerPort: {{ $portValue.targetPort }}
protocol: {{ $portValue.protocol }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.ucentralsec }}
{{- range .Values.volumes.owsec }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
@@ -69,13 +69,13 @@ spec:
{{- end }}
{{- end }}
{{- if .Values.checks.ucentralsec.liveness }}
{{- if .Values.checks.owsec.liveness }}
livenessProbe:
{{- toYaml .Values.checks.ucentralsec.liveness | nindent 12 }}
{{- toYaml .Values.checks.owsec.liveness | nindent 12 }}
{{- end }}
{{- if .Values.checks.ucentralsec.readiness }}
{{- if .Values.checks.owsec.readiness }}
readinessProbe:
{{- toYaml .Values.checks.ucentralsec.readiness | nindent 12 }}
{{- toYaml .Values.checks.owsec.readiness | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
@@ -91,7 +91,7 @@ spec:
imagePullSecrets:
{{- range $image, $imageValue := .Values.images }}
{{- if $imageValue.regcred }}
- name: {{ include "ucentralsec.fullname" $root }}-{{ $image }}-regcred
- name: {{ include "owsec.fullname" $root }}-{{ $image }}-regcred
{{- end }}
{{- end }}

View File

@@ -5,10 +5,10 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ include "ucentralsec.fullname" $root }}-{{ $ingress }}
name: {{ include "owsec.fullname" $root }}-{{ $ingress }}
labels:
app.kubernetes.io/name: {{ include "ucentralsec.name" $root }}
helm.sh/chart: {{ include "ucentralsec.chart" $root }}
app.kubernetes.io/name: {{ include "owsec.name" $root }}
helm.sh/chart: {{ include "owsec.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
{{- with $ingressValue.annotations }}
@@ -37,7 +37,7 @@ spec:
{{- range $ingressValue.paths }}
- path: {{ .path }}
backend:
serviceName: {{ include "ucentralsec.fullname" $root }}-{{ .serviceName }}
serviceName: {{ include "owsec.fullname" $root }}-{{ .serviceName }}
servicePort: {{ .servicePort }}
{{- end }}
{{- end }}

View File

@@ -3,10 +3,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ template "ucentralsec.fullname" . }}-pvc
name: {{ template "owsec.fullname" . }}-pvc
labels:
app.kubernetes.io/name: {{ include "ucentralsec.name" . }}
helm.sh/chart: {{ include "ucentralsec.chart" . }}
app.kubernetes.io/name: {{ include "owsec.name" . }}
helm.sh/chart: {{ include "owsec.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Values.persistence.annotations }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralsec.name" . }}
helm.sh/chart: {{ include "ucentralsec.chart" . }}
app.kuberentes.io/name: {{ include "owsec.name" . }}
helm.sh/chart: {{ include "owsec.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralsec.fullname" . }}-certs
name: {{ include "owsec.fullname" . }}-certs
kind: Secret
type: Opaque
data:

View File

@@ -2,12 +2,12 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralsec.name" . }}
helm.sh/chart: {{ include "ucentralsec.chart" . }}
app.kuberentes.io/name: {{ include "owsec.name" . }}
helm.sh/chart: {{ include "owsec.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralsec.fullname" . }}-config
name: {{ include "owsec.fullname" . }}-config
kind: Secret
type: Opaque
data:
ucentralsec.properties: {{ include "ucentralsec.config" . | b64enc }}
owsec.properties: {{ include "owsec.config" . | b64enc }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralsec.name" . }}
helm.sh/chart: {{ include "ucentralsec.chart" . }}
app.kuberentes.io/name: {{ include "owsec.name" . }}
helm.sh/chart: {{ include "owsec.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralsec.fullname" . }}-env
name: {{ include "owsec.fullname" . }}-env
kind: Secret
type: Opaque
data:

View File

@@ -10,11 +10,11 @@ kind: Secret
type: kubernetes.io/dockerconfigjson
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralsec.name" $root }}
helm.sh/chart: {{ include "ucentralsec.chart" $root }}
app.kuberentes.io/name: {{ include "owsec.name" $root }}
helm.sh/chart: {{ include "owsec.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
name: {{ include "ucentralsec.fullname" $root }}-{{ $image }}-regcred
name: {{ include "owsec.fullname" $root }}-{{ $image }}-regcred
data:
.dockerconfigjson: {{ template "imagePullSecret" $imageValue.regcred }}
{{- end }}

View File

@@ -4,14 +4,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "ucentralsec.fullname" $root }}-{{ $service }}
name: {{ include "owsec.fullname" $root }}-{{ $service }}
{{- with $serviceValue.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
app.kubernetes.io/name: {{ include "ucentralsec.name" $root }}
helm.sh/chart: {{ include "ucentralsec.chart" $root }}
app.kubernetes.io/name: {{ include "owsec.name" $root }}
helm.sh/chart: {{ include "owsec.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
@@ -39,7 +39,7 @@ spec:
{{- end }}
{{- end }}
selector:
app.kubernetes.io/name: {{ include "ucentralsec.name" $root }}
app.kubernetes.io/name: {{ include "owsec.name" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
{{- with $serviceValue.labels }}
{{- toYaml . | nindent 4 }}

View File

@@ -6,9 +6,9 @@ nameOverride: ""
fullnameOverride: ""
images:
ucentralsec:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralsec
tag: v2.1.0-RC1
owsec:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
tag: v2.2.0-RC1
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -16,7 +16,7 @@ images:
# password: password
services:
ucentralsec:
owsec:
type: LoadBalancer
ports:
restapi:
@@ -29,7 +29,7 @@ services:
protocol: TCP
checks:
ucentralsec:
owsec:
liveness:
httpGet:
path: /
@@ -49,29 +49,29 @@ ingresses:
- restapi.chart-example.local
paths:
- path: /
serviceName: ucentralsec
serviceName: owsec
servicePort: restapi
volumes:
ucentralsec:
owsec:
- name: config
mountPath: /ucentralsec-data/ucentralsec.properties
subPath: ucentralsec.properties
mountPath: /owsec-data/owsec.properties
subPath: owsec.properties
# Template below will be rendered in template
volumeDefinition: |
secret:
secretName: {{ include "ucentralsec.fullname" . }}-config
secretName: {{ include "owsec.fullname" . }}-config
- name: certs
mountPath: /ucentralsec-data/certs
mountPath: /owsec-data/certs
volumeDefinition: |
secret:
secretName: {{ include "ucentralsec.fullname" . }}-certs
secretName: {{ include "owsec.fullname" . }}-certs
# Change this if you want to use another volume type
- name: persist
mountPath: /ucentralsec-data/persist
mountPath: /owsec-data/persist
volumeDefinition: |
persistentVolumeClaim:
claimName: {{ template "ucentralsec.fullname" . }}-pvc
claimName: {{ template "owsec.fullname" . }}-pvc
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -104,48 +104,49 @@ persistence:
# Application
public_env_variables:
UCENTRALSEC_ROOT: /ucentralsec-data
UCENTRALSEC_CONFIG: /ucentralsec-data
OWSEC_ROOT: /owsec-data
OWSEC_CONFIG: /owsec-data
secret_env_variables: {}
configProperties:
# -> Public part
# REST API
ucentral.restapi.host.0.backlog: 100
ucentral.restapi.host.0.security: relaxed
ucentral.restapi.host.0.rootca: $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address: "*"
ucentral.restapi.host.0.port: 16001
ucentral.restapi.host.0.cert: $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.restapi.wwwassets: $UCENTRALSEC_ROOT/wwwassets
ucentral.internal.restapi.host.0.backlog: 100
ucentral.internal.restapi.host.0.security: relaxed
ucentral.internal.restapi.host.0.rootca: $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address: "*"
ucentral.internal.restapi.host.0.port: 17001
ucentral.internal.restapi.host.0.cert: $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.backlog: 100
openwifi.restapi.host.0.security: relaxed
openwifi.restapi.host.0.rootca: $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address: "*"
openwifi.restapi.host.0.port: 16001
openwifi.restapi.host.0.cert: $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key: $OWSEC_ROOT/certs/restapi-key.pem
openwifi.restapi.wwwassets: $OWSEC_ROOT/wwwassets
openwifi.internal.restapi.host.0.backlog: 100
openwifi.internal.restapi.host.0.security: relaxed
openwifi.internal.restapi.host.0.rootca: $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address: "*"
openwifi.internal.restapi.host.0.port: 17001
openwifi.internal.restapi.host.0.cert: $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key: $OWSEC_ROOT/certs/restapi-key.pem
# Authentication
authentication.enabled: true
authentication.default.access: master
authentication.service.type: internal
# Mailer
mailer.hostname: smtp.gmail.com
mailer.sender: OpenWIFI
mailer.loginmethod: login
mailer.port: 587
mailer.templates: $UCENTRALSEC_ROOT/templates
mailer.templates: $OWSEC_ROOT/templates
# ALB
alb.enable: "true"
alb.port: 16101
# Kafka
ucentral.kafka.enable: "false"
ucentral.kafka.group.id: security
ucentral.kafka.client.id: security1
ucentral.kafka.brokerlist: localhost:9092
ucentral.kafka.auto.commit: false
ucentral.kafka.queue.buffering.max.ms: 50
openwifi.kafka.enable: "false"
openwifi.kafka.group.id: security
openwifi.kafka.client.id: security1
openwifi.kafka.brokerlist: localhost:9092
openwifi.kafka.auto.commit: false
openwifi.kafka.queue.buffering.max.ms: 50
# Storage
storage.type: sqlite # (sqlite|postgresql|mysql|odbc)
## SQLite
@@ -156,24 +157,24 @@ configProperties:
storage.type.postgresql.maxsessions: 64
storage.type.postgresql.idletime: 60
storage.type.postgresql.host: localhost
storage.type.postgresql.database: ucentral
storage.type.postgresql.database: owsec
storage.type.postgresql.port: 5432
storage.type.postgresql.connectiontimeout: 60
## MySQL
storage.type.mysql.maxsessions: 64
storage.type.mysql.idletime: 60
storage.type.mysql.host: localhost
storage.type.mysql.database: ucentral
storage.type.mysql.database: owsec
storage.type.mysql.port: 3306
storage.type.mysql.connectiontimeout: 60
# System
ucentral.service.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.system.data: $UCENTRALSEC_ROOT/persist
ucentral.system.debug: "true"
ucentral.system.uri.private: https://localhost:17001
ucentral.system.uri.public: https://localhost:16001
ucentral.system.uri.ui: https://localhost
ucentral.system.commandchannel: /tmp/app_ucentralsec
openwifi.service.key: $OWSEC_ROOT/certs/restapi-key.pem
openwifi.system.data: $OWSEC_ROOT/persist
openwifi.system.debug: "true"
openwifi.system.uri.private: https://localhost:17001
openwifi.system.uri.public: https://localhost:16001
openwifi.system.uri.ui: https://localhost
openwifi.system.commandchannel: /tmp/app_owsec
# Logging
logging.formatters.f1.class: PatternFormatter
logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
@@ -181,7 +182,7 @@ configProperties:
logging.channels.c1.class: ConsoleChannel
logging.channels.c1.formatter: f1
logging.channels.c2.class: FileChannel
logging.channels.c2.path: /tmp/log_ucentralsec
logging.channels.c2.path: /tmp/log_owsec
logging.channels.c2.formatter.class: PatternFormatter
logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.channels.c2.rotation: "20 M"
@@ -194,8 +195,8 @@ configProperties:
# -> Secret part
# REST API
ucentral.restapi.host.0.key.password: mypassword
ucentral.internal.restapi.host.0.key.password: mypassword
openwifi.restapi.host.0.key.password: mypassword
openwifi.internal.restapi.host.0.key.password: mypassword
# Authentication
authentication.default.username: tip@ucentral.com
authentication.default.password: 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf
@@ -224,10 +225,10 @@ postgresql:
repository: bitnami/postgresql
tag: 11.13.0-debian-10-r0
postgresqlPostgresPassword: ""
postgresqlUsername: postgres
postgresqlPassword: ""
postgresqlDatabase: ""
postgresqlPostgresPassword: "rootPassword"
postgresqlUsername: stephb
postgresqlPassword: snoopy99
postgresqlDatabase: owgw
persistence:
enabled: true
@@ -244,10 +245,10 @@ mysql:
tag: 8.0.26-debian-10-r10
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:
@@ -265,10 +266,10 @@ mariadb:
tag: 10.5.12-debian-10-r0
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:

View File

@@ -287,6 +287,8 @@ components:
securityPolicyChange:
type: integer
format: int64
userTypeProprietaryInfo:
type: string
UserList:
type: object
@@ -296,6 +298,21 @@ components:
items:
$ref: '#/components/schemas/UserInfo'
EMailInfo:
type: object
properties:
from:
type: string
format: email
subject:
type: string
recipients:
type: array
items:
type: string
format: email
text:
type: string
#########################################################################################
##
@@ -365,6 +382,34 @@ components:
- $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList'
SystemInfoResults:
type: object
properties:
version:
type: string
uptime:
type: integer
format: integer64
start:
type: integer
format: integer64
os:
type: string
processors:
type: integer
hostname:
type: string
certificates:
type: array
items:
type: object
properties:
filename:
type: string
expires:
type: integer
format: int64
ProfileAction:
type: object
properties:
@@ -439,6 +484,80 @@ components:
$ref: '#/components/schemas/UserInfo'
tokenInfo:
$ref: '#/components/schemas/WebTokenResult'
SystemCommandSetLogLevel:
type: object
properties:
command:
type: string
enum:
- setloglevel
subsystems:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandReload:
type: object
properties:
command:
type: string
enum:
- reload
subsystems:
type: array
items:
type: string
example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult.
SystemCommandGetLogLevels:
type: object
properties:
command:
type: string
enum:
- getloglevels
SystemGetLogLevelsResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandGetLogLevelNames:
type: object
properties:
command:
type: string
enum:
- getloglevelnames
SystemCommandGetSubsystemNames:
type: object
properties:
command:
type: string
enum:
- getsubsystemnames
SystemCommandGetLogLevelNamesResult:
type: object
properties:
list:
type: array
items:
type: string
SystemGetSubSystemNemesResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
#########################################################################################
##
## End of uCentral system wide values
@@ -775,63 +894,42 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/email:
post:
tags:
- EMail
summary: Send test email with the system
operationId: Send a test email
requestBody:
description: The requested message
content:
application/json:
schema:
$ref: '#/components/schemas/EMailInfo'
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
500:
description: Error description
content:
application/json:
schema:
type: object
properties:
errors:
type: array
items:
type: string
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
##
#########################################################################################
/system:
post:
tags:
- System Commands
summary: Perform some systeme wide commands
operationId: systemCommand
requestBody:
description: Command details
content:
application/json:
schema:
$ref: '#/components/schemas/SystemCommandDetails'
responses:
200:
description: Successfull command execution
content:
application/json:
schema:
$ref: '#/components/schemas/SystemCommandResults'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
get:
tags:
- System Commands
summary: Retrieve different values from the running service.
operationId: getSystemCommand
parameters:
- in: query
description: Get a value
name: command
schema:
type: string
enum:
- version
- times
required: true
responses:
200:
description: Successfull command execution
content:
application/json:
schema:
$ref: '#/components/schemas/TagValuePair'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/securityProfiles:
get:
tags:
@@ -902,6 +1000,65 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/system:
post:
tags:
- System Commands
summary: Perform some systeme wide commands
operationId: systemCommand
requestBody:
description: Command details
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemCommandSetLogLevel'
- $ref: '#/components/schemas/SystemCommandReload'
- $ref: '#/components/schemas/SystemCommandGetLogLevels'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNames'
- $ref: '#/components/schemas/SystemCommandGetSubsystemNames'
responses:
200:
description: Successfull command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemGetLogLevelsResult'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult'
- $ref: '#/components/schemas/SystemGetSubSystemNemesResult'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
get:
tags:
- System Commands
summary: Retrieve different values from the running service.
operationId: getSystemCommand
parameters:
- in: query
description: Get a value
name: command
schema:
type: string
enum:
- info
required: true
responses:
200:
description: Successfull command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemInfoResults'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
#########################################################################################
##

View File

@@ -7,24 +7,24 @@
#
# REST API access
#
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16001
ucentral.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
ucentral.restapi.wwwassets = $UCENTRALSEC_ROOT/wwwassets
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = 16001
openwifi.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.key.password = mypassword
openwifi.restapi.wwwassets = $OWSEC_ROOT/wwwassets
ucentral.internal.restapi.host.0.backlog = 100
ucentral.internal.restapi.host.0.security = relaxed
ucentral.internal.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address = *
ucentral.internal.restapi.host.0.port = 17001
ucentral.internal.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.key.password = mypassword
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = 17001
openwifi.internal.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.internal.restapi.host.0.key.password = mypassword
#
# Generic section that all microservices must have
@@ -32,13 +32,13 @@ ucentral.internal.restapi.host.0.key.password = mypassword
authentication.enabled = true
authentication.default.username = tip@ucentral.com
authentication.default.password = 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf
ucentral.system.data = $UCENTRALSEC_ROOT/data
ucentral.system.uri.private = https://localhost:17001
ucentral.system.uri.public = https://local.dpaas.arilia.com:16001
ucentral.system.uri.ui = https://ucentral-ui.arilia.com
ucentral.system.commandchannel = /tmp/app.ucentralsec
ucentral.service.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.service.key.password = mypassword
openwifi.system.data = $OWSEC_ROOT/data
openwifi.system.uri.private = https://localhost:17001
openwifi.system.uri.public = https://local.dpaas.arilia.com:16001
openwifi.system.uri.ui = https://ucentral-ui.arilia.com
openwifi.system.commandchannel = /tmp/app.ucentralsec
openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.service.key.password = mypassword
#
# Security Microservice Specific Section
@@ -46,9 +46,10 @@ ucentral.service.key.password = mypassword
mailer.hostname = smtp.gmail.com
mailer.username = ************************
mailer.password = ************************
mailer.sender = OpenWIFI
mailer.loginmethod = login
mailer.port = 587
mailer.templates = $UCENTRALSEC_ROOT/templates
mailer.templates = $OWSEC_ROOT/templates
#############################
@@ -63,17 +64,16 @@ alb.port = 16101
#
# Kafka
#
ucentral.kafka.group.id = security
ucentral.kafka.client.id = security1
ucentral.kafka.enable = true
# ucentral.kafka.brokerlist = a1.arilia.com:9092
ucentral.kafka.brokerlist = debfarm1-node-c.arilia.com:9092
ucentral.kafka.auto.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
openwifi.kafka.group.id = security
openwifi.kafka.client.id = security1
openwifi.kafka.enable = true
openwifi.kafka.brokerlist = a1.arilia.com:9092
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
openwifi.document.policy.access = /wwwassets/access_policy.html
openwifi.document.policy.password = /wwwassets/password_policy.html
openwifi.avatar.maxsize = 2000000
ucentral.document.policy.access = /wwwassets/access_policy.html
ucentral.document.policy.password = /wwwassets/password_policy.html
ucentral.avatar.maxsize = 2000000
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
@@ -121,7 +121,7 @@ logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $UCENTRALSEC_ROOT/logs/log
logging.channels.c2.path = $OWSEC_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M

146
owsec.properties.tmpl Normal file
View File

@@ -0,0 +1,146 @@
#
# uCentral protocol server for devices. This is where you point
# all your devices. You can replace the * for address by the specific
# address of one of your interfaces
#
#
# REST API access
#
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = ${RESTAPI_HOST_ROOTCA}
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = ${RESTAPI_HOST_PORT}
openwifi.restapi.host.0.cert = ${RESTAPI_HOST_CERT}
openwifi.restapi.host.0.key = ${RESTAPI_HOST_KEY}
openwifi.restapi.host.0.key.password = ${RESTAPI_HOST_KEY_PASSWORD}
openwifi.restapi.wwwassets = ${RESTAPI_WWWASSETS}
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = ${INTERNAL_RESTAPI_HOST_ROOTCA}
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = ${INTERNAL_RESTAPI_HOST_PORT}
openwifi.internal.restapi.host.0.cert = ${INTERNAL_RESTAPI_HOST_CERT}
openwifi.internal.restapi.host.0.key = ${INTERNAL_RESTAPI_HOST_KEY}
openwifi.internal.restapi.host.0.key.password = ${INTERNAL_RESTAPI_HOST_KEY_PASSWORD}
#
# Generic section that all microservices must have
#
authentication.enabled = true
authentication.default.username = ${AUTHENTICATION_DEFAULT_USERNAME}
authentication.default.password = ${AUTHENTICATION_DEFAULT_PASSWORD}
openwifi.system.data = ${SYSTEM_DATA}
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.system.commandchannel = /tmp/app.ucentralsec
openwifi.service.key = ${SERVICE_KEY}
openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}
#
# Security Microservice Specific Section
#
mailer.hostname = ${MAILER_HOSTNAME}
mailer.username = ${MAILER_USERNAME}
mailer.password = ${MAILER_PASSWORD}
mailer.sender = ${MAILER_SENDER}
mailer.loginmethod = login
mailer.port = ${MAILER_PORT}
mailer.templates = $UCENTRALSEC_ROOT/templates
#############################
# Generic information for all micro services
#############################
#
# NLB Support
#
alb.enable = true
alb.port = 16101
#
# Kafka
#
openwifi.kafka.group.id = security
openwifi.kafka.client.id = security1
openwifi.kafka.enable = ${KAFKA_ENABLE}
openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST}
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
openwifi.document.policy.access = /wwwassets/access_policy.html
openwifi.document.policy.password = /wwwassets/password_policy.html
openwifi.avatar.maxsize = 2000000
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
# death and might make your beer flat.
#
storage.type = ${STORAGE_TYPE}
storage.type.sqlite.db = security.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
storage.type.postgresql.password = ${STORAGE_TYPE_POSTGRESQL_PASSWORD}
storage.type.postgresql.database = ${STORAGE_TYPE_POSTGRESQL_DATABASE}
storage.type.postgresql.port = ${STORAGE_TYPE_POSTGRESQL_PORT}
storage.type.postgresql.connectiontimeout = 60
storage.type.mysql.maxsessions = 64
storage.type.mysql.idletime = 60
storage.type.mysql.host = ${STORAGE_TYPE_MYSQL_HOST}
storage.type.mysql.username = ${STORAGE_TYPE_MYSQL_USERNAME}
storage.type.mysql.password = ${STORAGE_TYPE_MYSQL_PASSWORD}
storage.type.mysql.database = ${STORAGE_TYPE_MYSQL_DATABASE}
storage.type.mysql.port = ${STORAGE_TYPE_MYSQL_PORT}
storage.type.mysql.connectiontimeout = 60
########################################################################
########################################################################
#
# Logging: please leave as is for now.
#
########################################################################
logging.formatters.f1.class = PatternFormatter
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.formatters.f1.times = UTC
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $UCENTRALSEC_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -5,8 +5,8 @@ Wants=network-online.target
[Service]
Type=simple
Environment="UCENTRALSEC_ROOT=/home/admin/dev/wlan-cloud-ucentralsec"
ExecStart=/home/admin/dev/wlan-cloud-ucentralsec/cmake-build/ucentralsec
Environment="OWSEC_ROOT=/home/admin/dev/wlan-cloud-ucentralsec"
ExecStart=/home/admin/dev/wlan-cloud-ucentralsec/cmake-build/owsec
WorkingDirectory=/home/admin/dev/wlan-cloud-ucentralsec
# ExecReload=/bin/kill -s HUP $MAINPID
User=admin

View File

@@ -1,4 +1,4 @@
#!/bin/bash
export UCENTRALSEC_CONFIG=`pwd`
export UCENTRALSEC_ROOT=`pwd`
export OWSEC_CONFIG=`pwd`
export OWSEC_ROOT=`pwd`

View File

@@ -1,5 +1,9 @@
//
// Created by stephane bourque on 2021-06-04.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_ALBHEALTHCHECKSERVER_H
@@ -26,12 +30,12 @@ namespace OpenWifi {
/// Return a HTML document with the current date and time.
{
public:
ALBRequestHandler(Poco::Logger & L)
explicit ALBRequestHandler(Poco::Logger & L)
: Logger_(L)
{
}
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response)
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override
{
Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString()));
Response.setChunkedTransferEncoding(true);
@@ -83,7 +87,7 @@ namespace OpenWifi {
return instance_;
}
int Start() {
int Start() override {
if(Daemon()->ConfigGetBool("alb.enable",false)) {
Port_ = (int)Daemon()->ConfigGetInt("alb.port",15015);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
@@ -95,7 +99,7 @@ namespace OpenWifi {
return 0;
}
void Stop() {
void Stop() override {
if(Server_)
Server_->stop();
}

View File

@@ -1,6 +1,11 @@
//
// Created by stephane bourque on 2021-06-30.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <utility>
#include "AuthClient.h"
@@ -20,7 +25,7 @@ namespace OpenWifi {
}
void AuthClient::RemovedCachedToken(const std::string &Token) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
UserCache_.erase(Token);
}
@@ -29,7 +34,7 @@ namespace OpenWifi {
}
bool AuthClient::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {
@@ -58,7 +63,7 @@ namespace OpenWifi {
}
bool AuthClient::IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {

View File

@@ -67,7 +67,7 @@ namespace OpenWifi {
if(!Secure_)
return true;
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
std::string CallToken;
@@ -80,14 +80,10 @@ namespace OpenWifi {
} catch(const Poco::Exception &E) {
}
if(CallToken.empty())
CallToken = Request.get("X-API-KEY ", "");
if(CallToken.empty())
if(!CallToken.empty()) {
if(Storage()->IsTokenRevoked(CallToken))
return false;
auto Client = UserCache_.find(CallToken);
if( Client == UserCache_.end() )
return ValidateToken(CallToken, CallToken, UInfo);
@@ -97,15 +93,34 @@ namespace OpenWifi {
return true;
}
UserCache_.erase(CallToken);
Storage()->RevokeToken(CallToken);
return false;
}
return false;
}
bool AuthService::DeleteUserFromCache(const std::string &UserName) {
std::lock_guard Guard(Mutex_);
for(auto i=UserCache_.begin();i!=UserCache_.end();) {
if (i->second.userinfo.email==UserName) {
Logout(i->first);
i = UserCache_.erase(i);
} else {
++i;
}
}
return true;
}
bool AuthService::ValidatePassword(const std::string &Password) {
return std::regex_match(Password, PasswordValidation_);
}
void AuthService::Logout(const std::string &token) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
UserCache_.erase(token);
try {
@@ -115,6 +130,8 @@ namespace OpenWifi {
Obj.set("token", token);
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Obj, ResultText);
std::string Tmp{token};
Storage()->RevokeToken(Tmp);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, Daemon()->PrivateEndPoint(), ResultText.str(),
false);
} catch (const Poco::Exception &E) {
@@ -123,7 +140,7 @@ namespace OpenWifi {
}
std::string AuthService::GenerateToken(const std::string & Identity, ACCESS_TYPE Type) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
Poco::JWT::Token T;
@@ -143,37 +160,22 @@ namespace OpenWifi {
}
bool AuthService::ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
Poco::JWT::Token DecryptedToken;
try {
auto E = UserCache_.find(SessionToken);
if(E == UserCache_.end()) {
if (Signer_.tryVerify(Token, DecryptedToken)) {
auto Expires = DecryptedToken.getExpiration();
if (Expires > Poco::Timestamp()) {
auto Identity = DecryptedToken.payload().get("identity").toString();
if(Storage()->GetUserById(Identity,UInfo.userinfo)) {
auto IssuedAt = DecryptedToken.getIssuedAt();
auto Subject = DecryptedToken.getSubject();
UInfo.webtoken.access_token_ = Token;
UInfo.webtoken.refresh_token_ = Token;
UInfo.webtoken.username_ = Identity;
UInfo.webtoken.id_token_ = Token;
UInfo.webtoken.token_type_ = "Bearer";
UInfo.webtoken.created_ = IssuedAt.epochTime();
UInfo.webtoken.expires_in_ = Expires.epochTime() - IssuedAt.epochTime();
UInfo.webtoken.idle_timeout_ = 5 * 60;
if(Storage()->GetToken(SessionToken,UInfo)) {
if(Storage()->GetUserById(UInfo.userinfo.email,UInfo.userinfo)) {
UserCache_[UInfo.webtoken.access_token_] = UInfo;
return true;
}
}
}
} else {
UInfo = E->second;
return true;
}
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
@@ -182,24 +184,26 @@ namespace OpenWifi {
void AuthService::CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo)
{
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
std::string Token = GenerateToken(UInfo.userinfo.Id,USERNAME);
SecurityObjects::AclTemplate ACL;
ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true;
UInfo.webtoken.acl_template_ = ACL;
UInfo.webtoken.expires_in_ = TokenAging_ ;
UInfo.webtoken.idle_timeout_ = 5 * 60;
UInfo.webtoken.token_type_ = "Bearer";
UInfo.webtoken.access_token_ = Token;
UInfo.webtoken.id_token_ = Token;
UInfo.webtoken.refresh_token_ = Token;
UInfo.webtoken.access_token_ = GenerateToken(UInfo.userinfo.Id,USERNAME);
UInfo.webtoken.id_token_ = GenerateToken(UInfo.userinfo.Id,USERNAME);
UInfo.webtoken.refresh_token_ = GenerateToken(UInfo.userinfo.Id,CUSTOM);
UInfo.webtoken.created_ = time(nullptr);
UInfo.webtoken.username_ = UserName;
UInfo.webtoken.errorCode = 0;
UInfo.webtoken.userMustChangePassword = false;
UserCache_[Token] = UInfo;
UserCache_[UInfo.webtoken.access_token_] = UInfo;
Storage()->SetLastLogin(UInfo.userinfo.Id);
Storage()->AddToken(UInfo.webtoken.username_, UInfo.webtoken.access_token_,
UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
}
bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
@@ -220,7 +224,7 @@ namespace OpenWifi {
AuthService::AUTH_ERROR AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo )
{
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
SecurityObjects::AclTemplate ACL;
Poco::toLowerInPlace(UserName);
@@ -331,6 +335,13 @@ namespace OpenWifi {
}
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) {
std::lock_guard G(Mutex_);
auto It = UserCache_.find(Token);
if(It==UserCache_.end())
return false;
WebToken = It->second.webtoken;
UserInfo = It->second.userinfo;
return true;
}

View File

@@ -82,6 +82,7 @@ namespace OpenWifi{
[[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
[[nodiscard]] static bool SendEmailToUser(std::string &Email, EMAIL_REASON Reason);
[[nodiscard]] bool DeleteUserFromCache(const std::string &UserName);
private:
static AuthService *instance_;

View File

@@ -26,23 +26,23 @@
namespace OpenWifi {
static const char * vDAEMON_PROPERTIES_FILENAME = "ucentralsec.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALSEC_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "UCENTRALSEC_CONFIG";
static const char * vDAEMON_PROPERTIES_FILENAME = "owsec.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "OWSEC_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "OWSEC_CONFIG";
static const char * vDAEMON_APP_NAME = uSERVICE_SECURITY.c_str();
static const uint64_t vDAEMON_BUS_TIMER = 5000;
class Daemon : public MicroService {
public:
explicit Daemon(std::string PropFile,
std::string RootEnv,
std::string ConfigEnv,
std::string AppName,
explicit Daemon(const std::string & PropFile,
const std::string & RootEnv,
const std::string & ConfigEnv,
const std::string & AppName,
uint64_t BusTimer,
Types::SubSystemVec SubSystems) :
const Types::SubSystemVec & SubSystems) :
MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {};
void initialize(Poco::Util::Application &self);
void initialize(Poco::Util::Application &self) override;
static Daemon *instance();
private:
static Daemon *instance_;

View File

@@ -17,13 +17,13 @@ namespace OpenWifi {
class KafkaManager *KafkaManager::instance_ = nullptr;
KafkaManager::KafkaManager() noexcept:
SubSystemServer("KafkaManager", "KAFKA-SVR", "ucentral.kafka")
SubSystemServer("KafkaManager", "KAFKA-SVR", "openwifi.kafka")
{
}
void KafkaManager::initialize(Poco::Util::Application & self) {
SubSystemServer::initialize(self);
KafkaEnabled_ = Daemon()->ConfigGetBool("ucentral.kafka.enable",false);
KafkaEnabled_ = Daemon()->ConfigGetBool("openwifi.kafka.enable",false);
}
#ifdef SMALL_BUILD
@@ -55,8 +55,8 @@ namespace OpenWifi {
void KafkaManager::ProducerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") }
{ "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") }
});
SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" +
std::to_string(Daemon()->ID()) +
@@ -68,7 +68,7 @@ namespace OpenWifi {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
try
{
SubMutexGuard G(ProducerMutex_);
std::lock_guard G(ProducerMutex_);
auto Num=0;
while (!Queue_.empty()) {
const auto M = Queue_.front();
@@ -96,10 +96,10 @@ namespace OpenWifi {
void KafkaManager::ConsumerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") },
{ "group.id", Daemon()->ConfigGetString("ucentral.kafka.group.id") },
{ "enable.auto.commit", Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false) },
{ "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") },
{ "group.id", Daemon()->ConfigGetString("openwifi.kafka.group.id") },
{ "enable.auto.commit", Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false) },
{ "auto.offset.reset", "latest" } ,
{ "enable.partition.eof", false }
});
@@ -125,8 +125,8 @@ namespace OpenWifi {
}
});
bool AutoCommit = Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false);
auto BatchSize = Daemon()->ConfigGetInt("ucentral.kafka.consumer.batchsize",20);
bool AutoCommit = Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false);
auto BatchSize = Daemon()->ConfigGetInt("openwifi.kafka.consumer.batchsize",20);
Types::StringVec Topics;
for(const auto &i:Notifiers_)
@@ -148,7 +148,7 @@ namespace OpenWifi {
Consumer.async_commit(Msg);
continue;
}
SubMutexGuard G(ConsumerMutex_);
std::lock_guard G(ConsumerMutex_);
auto It = Notifiers_.find(Msg.get_topic());
if (It != Notifiers_.end()) {
Types::TopicNotifyFunctionList &FL = It->second;
@@ -174,9 +174,9 @@ namespace OpenWifi {
return std::move( SystemInfoWrapper_ + PayLoad + "}");
}
void KafkaManager::PostMessage(std::string topic, std::string key, std::string PayLoad, bool WrapMessage ) {
void KafkaManager::PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage ) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
KMessage M{
.Topic = topic,
.Key = key,
@@ -187,7 +187,7 @@ namespace OpenWifi {
int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It == Notifiers_.end()) {
Types::TopicNotifyFunctionList L;
@@ -204,7 +204,7 @@ namespace OpenWifi {
void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It != Notifiers_.end()) {
Types::TopicNotifyFunctionList & L = It->second;

View File

@@ -41,7 +41,7 @@ namespace OpenWifi {
int Start() override;
void Stop() override;
void PostMessage(std::string topic, std::string key, std::string payload, bool WrapMessage = true);
void PostMessage(const std::string &topic, const std::string & key, const std::string &payload, bool WrapMessage = true);
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad);
[[nodiscard]] bool Enabled() { return KafkaEnabled_; }
int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F);
@@ -52,8 +52,8 @@ namespace OpenWifi {
private:
static KafkaManager *instance_;
SubMutex ProducerMutex_;
SubMutex ConsumerMutex_;
std::mutex ProducerMutex_;
std::mutex ConsumerMutex_;
bool KafkaEnabled_ = false;
std::atomic_bool ProducerRunning_ = false;
std::atomic_bool ConsumerRunning_ = false;

View File

@@ -1,6 +1,11 @@
//
// Created by stephane bourque on 2021-06-22.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <cstdlib>
#include <boost/algorithm/string.hpp>
@@ -57,7 +62,7 @@ namespace OpenWifi {
}
void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) {
SubMutexGuard G(InfraMutex_);
std::lock_guard G(InfraMutex_);
try {
Poco::JSON::Parser P;
auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>();
@@ -128,7 +133,7 @@ namespace OpenWifi {
}
MicroServiceMetaVec MicroService::GetServices(const std::string & Type) {
SubMutexGuard G(InfraMutex_);
std::lock_guard G(InfraMutex_);
auto T = Poco::toLower(Type);
MicroServiceMetaVec Res;
@@ -140,7 +145,7 @@ namespace OpenWifi {
}
MicroServiceMetaVec MicroService::GetServices() {
SubMutexGuard G(InfraMutex_);
std::lock_guard G(InfraMutex_);
MicroServiceMetaVec Res;
for(const auto &[Id,ServiceRec]:Services_) {
@@ -149,16 +154,7 @@ namespace OpenWifi {
return Res;
}
void MicroService::initialize(Poco::Util::Application &self) {
// add the default services
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
void MicroService::LoadConfigurationFile() {
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,".");
Poco::Path ConfigFile;
@@ -172,9 +168,42 @@ namespace OpenWifi {
std::exit(Poco::Util::Application::EXIT_CONFIG);
}
static const char * LogFilePathKey = "logging.channels.c2.path";
loadConfiguration(ConfigFile.toString());
}
void MicroService::Reload() {
LoadConfigurationFile();
LoadMyConfig();
}
void MicroService::LoadMyConfig() {
std::string KeyFile = ConfigPath("openwifi.service.key");
std::string KeyFilePassword = ConfigPath("openwifi.service.key.password" , "" );
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
Cipher_ = CipherFactory_.createCipher(*AppKey_);
ID_ = Utils::GetSystemId();
if(!DebugMode_)
DebugMode_ = ConfigGetBool("openwifi.system.debug",false);
MyPrivateEndPoint_ = ConfigGetString("openwifi.system.uri.private");
MyPublicEndPoint_ = ConfigGetString("openwifi.system.uri.public");
UIURI_ = ConfigGetString("openwifi.system.uri.ui");
MyHash_ = CreateHash(MyPublicEndPoint_);
}
void MicroService::initialize(Poco::Util::Application &self) {
// add the default services
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
LoadConfigurationFile();
static const char * LogFilePathKey = "logging.channels.c2.path";
if(LogDir_.empty()) {
std::string OriginalLogFileValue = ConfigPath(LogFilePathKey);
@@ -182,7 +211,8 @@ namespace OpenWifi {
} else {
config().setString(LogFilePathKey, LogDir_);
}
Poco::File DataDir(ConfigPath("ucentral.system.data"));
Poco::File DataDir(ConfigPath("openwifi.system.data"));
DataDir_ = DataDir.path();
if(!DataDir.exists()) {
try {
@@ -191,17 +221,9 @@ namespace OpenWifi {
logger().log(E);
}
}
std::string KeyFile = ConfigPath("ucentral.service.key");
std::string KeyFilePassword = ConfigPath("ucentral.service.key.password" , "" );
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
Cipher_ = CipherFactory_.createCipher(*AppKey_);
ID_ = Utils::GetSystemId();
if(!DebugMode_)
DebugMode_ = ConfigGetBool("ucentral.system.debug",false);
MyPrivateEndPoint_ = ConfigGetString("ucentral.system.uri.private");
MyPublicEndPoint_ = ConfigGetString("ucentral.system.uri.public");
UIURI_ = ConfigGetString("ucentral.system.uri.ui");
MyHash_ = CreateHash(MyPublicEndPoint_);
LoadMyConfig();
InitializeSubSystemServers();
ServerApplication::initialize(self);
@@ -336,14 +358,23 @@ namespace OpenWifi {
return false;
}
void MicroService::Reload(const std::string &Sub) {
for (auto i : SubSystems_) {
if (Poco::toLower(Sub) == Poco::toLower(i->Name())) {
i->reinitialize(Poco::Util::Application::instance());
return;
}
}
}
Types::StringVec MicroService::GetSubSystems() const {
Types::StringVec Result;
for(auto i:SubSystems_)
Result.push_back(i->Name());
Result.push_back(Poco::toLower(i->Name()));
return Result;
}
Types::StringPairVec MicroService::GetLogLevels() const {
Types::StringPairVec MicroService::GetLogLevels() {
Types::StringPairVec Result;
for(auto &i:SubSystems_) {
@@ -353,7 +384,7 @@ namespace OpenWifi {
return Result;
}
const Types::StringVec & MicroService::GetLogLevelNames() const {
const Types::StringVec & MicroService::GetLogLevelNames() {
static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" };
return LevelNames;
}
@@ -427,7 +458,7 @@ namespace OpenWifi {
Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer());
if(!Running_)
break;
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE);
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
}
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE);

View File

@@ -1,5 +1,9 @@
//
// Created by stephane bourque on 2021-06-22.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_MICROSERVICE_H
@@ -29,11 +33,12 @@
namespace OpenWifi {
static const std::string uSERVICE_SECURITY{"ucentralsec"};
static const std::string uSERVICE_GATEWAY{"ucentralgw"};
static const std::string uSERVICE_FIRMWARE{ "ucentralfms"};
static const std::string uSERVICE_SECURITY{"owsec"};
static const std::string uSERVICE_GATEWAY{"owgw"};
static const std::string uSERVICE_FIRMWARE{ "owfms"};
static const std::string uSERVICE_TOPOLOGY{ "owtopo"};
static const std::string uSERVICE_PROVISIONING{ "owprov"};
static const std::string uSERVICE_OWLS{ "owls"};
class MyErrorHandler : public Poco::ErrorHandler {
public:
@@ -82,9 +87,6 @@ namespace OpenWifi {
DAEMON_APP_NAME(std::move(AppName)),
DAEMON_BUS_TIMER(BusTimer),
SubSystems_(std::move(Subsystems)) {
std::string V{APP_VERSION};
std::string B{BUILD_NUMBER};
Version_ = V + "(" + B + ")";
}
int main(const ArgVec &args) override;
@@ -111,8 +113,8 @@ namespace OpenWifi {
[[nodiscard]] bool Debug() const { return DebugMode_; }
[[nodiscard]] uint64_t ID() const { return ID_; }
[[nodiscard]] Types::StringVec GetSubSystems() const;
[[nodiscard]] Types::StringPairVec GetLogLevels() const;
[[nodiscard]] const Types::StringVec & GetLogLevelNames() const;
[[nodiscard]] Types::StringPairVec GetLogLevels() ;
[[nodiscard]] static const Types::StringVec & GetLogLevelNames();
[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default);
[[nodiscard]] std::string ConfigGetString(const std::string &Key);
[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default);
@@ -129,6 +131,7 @@ namespace OpenWifi {
[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; };
[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; };
[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ;
[[nodiscard]] const Types::SubSystemVec & GetFullSubSystems() { return SubSystems_; }
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
void BusMessageReceived( const std::string & Key, const std::string & Message);
@@ -136,11 +139,17 @@ namespace OpenWifi {
[[nodiscard]] MicroServiceMetaVec GetServices();
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
void SavePID();
inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() const { return MyPublicEndPoint_ + "/api/v1"; };
static void SavePID();
static inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; };
[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;};
void Reload(const std::string &Name); // reload a subsystem
void Reload(); // reload the daemon itself
void LoadMyConfig();
void LoadConfigurationFile();
private:
bool HelpRequested_ = false;
std::string LogDir_;
@@ -159,9 +168,9 @@ namespace OpenWifi {
std::string MyPrivateEndPoint_;
std::string MyPublicEndPoint_;
std::string UIURI_;
std::string Version_;
std::string Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"};
BusEventManager BusEventManager_;
SubMutex InfraMutex_;
std::mutex InfraMutex_;
std::string DAEMON_PROPERTIES_FILENAME;
std::string DAEMON_ROOT_ENV_VAR;

View File

@@ -1,17 +1,20 @@
//
// Created by stephane bourque on 2021-07-01.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
//
#include <iostream>
#include "OpenAPIRequest.h"
#include "Poco/Net/HTTPSClientSession.h"
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include "Utils.h"
@@ -19,12 +22,12 @@
namespace OpenWifi {
OpenAPIRequestGet::OpenAPIRequestGet( const std::string & ServiceType,
const std::string & EndPoint,
OpenAPIRequestGet::OpenAPIRequestGet( std::string ServiceType,
std::string EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout):
Type_(ServiceType),
EndPoint_(EndPoint),
Type_(std::move(ServiceType)),
EndPoint_(std::move(EndPoint)),
QueryData_(QueryData),
msTimeout_(msTimeout) {

View File

@@ -1,5 +1,9 @@
//
// Created by stephane bourque on 2021-07-01.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_OPENAPIREQUEST_H
@@ -13,8 +17,8 @@ namespace OpenWifi {
class OpenAPIRequestGet {
public:
explicit OpenAPIRequestGet( const std::string & Type,
const std::string & EndPoint,
explicit OpenAPIRequestGet( std::string Type,
std::string EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout);
int Do(Poco::JSON::Object::Ptr &ResponseObject);

View File

@@ -1,5 +1,9 @@
//
// Created by stephane bourque on 2021-06-13.
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_UCENTRALTYPES_H
@@ -16,6 +20,8 @@
#include <queue>
#include "Poco/StringTokenizer.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
namespace OpenWifi::Types {
typedef std::pair<std::string,std::string> StringPair;
@@ -42,26 +48,58 @@ namespace OpenWifi::Types {
}
inline std::string to_string( const StringVec &V) {
std::string Result;
bool first=true;
Poco::JSON::Array O;
for(const auto &i:V) {
if(first) {
Result += i;
first = false;
} else {
Result += ",";
Result += i;
O.add(i);
}
std::stringstream SS;
Poco::JSON::Stringifier::stringify(O,SS);
return SS.str();
}
inline std::string to_string( const StringPairVec &V) {
Poco::JSON::Array O;
for(const auto &i:V) {
Poco::JSON::Array OO;
OO.add(i.first);
OO.add(i.second);
O.add(OO);
}
std::stringstream SS;
Poco::JSON::Stringifier::stringify(O,SS);
return SS.str();
}
inline void from_string(const std::string &S, StringPairVec &V) {
try {
Poco::JSON::Parser P;
auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
for(const auto &i:*O) {
auto Inner = i.extract<Poco::JSON::Array::Ptr>();
for(const auto &j:*Inner) {
auto S1 = i[0].toString();
auto S2 = i[1].toString();
V.push_back(std::make_pair(S1,S2));
}
}
return Result;
} catch (...) {
}
}
inline void from_string(const std::string &S, StringVec &V) {
Poco::StringTokenizer Tokens(S,",",Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
try {
Poco::JSON::Parser P;
auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
for(auto const &i:Tokens)
V.emplace_back(i);
for(auto const &i:*O) {
V.push_back(i.toString());
}
} catch (...) {
}
}
};

View File

@@ -10,26 +10,19 @@
#include "RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_AssetServer::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else
NotFound(Request, Response);
}
void RESTAPI_AssetServer::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
void RESTAPI_AssetServer::DoGet() {
Poco::File AssetFile;
if(Request.getURI().find("/favicon.ico") != std::string::npos) {
if(Request->getURI().find("/favicon.ico") != std::string::npos) {
AssetFile = RESTAPI_Server()->AssetDir() + "/favicon.ico";
} else {
std::string AssetName = GetBinding(RESTAPI::Protocol::ID, "");
AssetFile = RESTAPI_Server()->AssetDir() + "/" + AssetName;
}
if(!AssetFile.isFile()) {
NotFound(Request, Response);
NotFound();
return;
}
SendFile(AssetFile,Request, Response);
SendFile(AssetFile);
}
}

View File

@@ -10,7 +10,7 @@
namespace OpenWifi {
class RESTAPI_AssetServer : public RESTAPIHandler {
public:
RESTAPI_AssetServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_AssetServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_POST,
@@ -18,11 +18,15 @@ namespace OpenWifi {
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/wwwassets/{id}" ,
"/favicon.ico"}; };
void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoPost() final {};
void DoDelete() final {};
void DoPut() final {};
private:
};

View File

@@ -0,0 +1,5 @@
//
// Created by stephane bourque on 2021-09-15.
//
#include "RESTAPI_GenericServer.h"

View File

@@ -0,0 +1,78 @@
//
// Created by stephane bourque on 2021-09-15.
//
#ifndef OWPROV_RESTAPI_GENERICSERVER_H
#define OWPROV_RESTAPI_GENERICSERVER_H
#include <vector>
#include <string>
#include "Daemon.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Net/HTTPRequest.h"
namespace OpenWifi {
class RESTAPI_GenericServer {
public:
enum {
LOG_GET=0,
LOG_DELETE,
LOG_PUT,
LOG_POST
};
void inline SetFlags(bool External, const std::string &Methods) {
Poco::StringTokenizer Tokens(Methods,",");
auto Offset = (External ? 0 : 4);
for(const auto &i:Tokens) {
if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_DELETE)==0)
LogFlags_[Offset+LOG_DELETE]=true;
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_PUT)==0)
LogFlags_[Offset+LOG_PUT]=true;
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_POST)==0)
LogFlags_[Offset+LOG_POST]=true;
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_GET)==0)
LogFlags_[Offset+LOG_GET]=true;
}
}
inline void InitLogging() {
std::string Public = Daemon()->ConfigGetString("apilogging.public.methods","PUT,POST,DELETE");
SetFlags(true, Public);
std::string Private = Daemon()->ConfigGetString("apilogging.private.methods","PUT,POST,DELETE");
SetFlags(false, Private);
std::string PublicBadTokens = Daemon()->ConfigGetString("apilogging.public.badtokens.methods","");
LogBadTokens_[0] = (Poco::icompare(PublicBadTokens,"true")==0);
std::string PrivateBadTokens = Daemon()->ConfigGetString("apilogging.private.badtokens.methods","");
LogBadTokens_[1] = (Poco::icompare(PrivateBadTokens,"true")==0);
}
[[nodiscard]] inline bool LogIt(const std::string &Method, bool External) const {
auto Offset = (External ? 0 : 4);
if(Method == Poco::Net::HTTPRequest::HTTP_GET)
return LogFlags_[Offset+LOG_GET];
if(Method == Poco::Net::HTTPRequest::HTTP_POST)
return LogFlags_[Offset+LOG_POST];
if(Method == Poco::Net::HTTPRequest::HTTP_PUT)
return LogFlags_[Offset+LOG_PUT];
if(Method == Poco::Net::HTTPRequest::HTTP_DELETE)
return LogFlags_[Offset+LOG_DELETE];
return false;
};
[[nodiscard]] inline bool LogBadTokens(bool External) const {
return LogBadTokens_[ (External ? 0 : 1) ];
};
private:
std::array<bool,8> LogFlags_{false};
std::array<bool,2> LogBadTokens_{false};
};
}
#endif //OWPROV_RESTAPI_GENERICSERVER_H

View File

@@ -19,12 +19,13 @@ namespace OpenWifi {
class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr;
RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept:
SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "ucentral.internal.restapi")
SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi")
{
}
int RESTAPI_InternalServer::Start() {
Logger_.information("Starting.");
Server_.InitLogging();
for(const auto & Svr: ConfigServersList_) {
Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
@@ -41,7 +42,7 @@ namespace OpenWifi {
Params->setMaxQueued(200);
Params->setKeepAlive(true);
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory, Pool_, Sock, Params);
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory(Server_), Pool_, Sock, Params);
NewServer->start();
RESTServers_.push_back(std::move(NewServer));
}
@@ -53,14 +54,17 @@ namespace OpenWifi {
Logger_.information("Stopping ");
for( const auto & svr : RESTServers_ )
svr->stop();
RESTServers_.clear();
}
void RESTAPI_InternalServer::reinitialize(Poco::Util::Application &self) {
Daemon()->LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s",
Utils::FormatIPv6(Request.clientAddress().toString()),
Request.getMethod(), Request.getURI()));
Poco::URI uri(Request.getURI());
const auto & Path = uri.getPath();
RESTAPIHandler::BindingMap Bindings;
@@ -70,7 +74,7 @@ namespace OpenWifi {
RESTAPI_system_command,
RESTAPI_action_links,
RESTAPI_validateToken_handler
>(Path,Bindings,Logger_);
>(Path,Bindings,Logger_, Server_);
}
}

View File

@@ -11,6 +11,7 @@
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/NetException.h"
#include "RESTAPI_GenericServer.h"
namespace OpenWifi {
@@ -27,23 +28,27 @@ namespace OpenWifi {
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
private:
static RESTAPI_InternalServer *instance_;
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_;
RESTAPI_GenericServer Server_;
};
inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); };
class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
InternalRequestHandlerFactory() :
Logger_(RESTAPI_InternalServer()->Logger()){}
explicit InternalRequestHandlerFactory(RESTAPI_GenericServer & Server) :
Logger_(RESTAPI_InternalServer()->Logger()),
Server_(Server){}
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
private:
Poco::Logger & Logger_;
RESTAPI_GenericServer & Server_;
};

View File

@@ -160,7 +160,7 @@ namespace OpenWifi::SecurityObjects {
typedef std::vector<ProfileAction> ProfileActionVec;
struct SecurityProfile {
uint64_t id;
uint64_t id=0;
std::string name;
std::string description;
ProfileActionVec policy;

View File

@@ -13,36 +13,42 @@
#include "Daemon.h"
namespace OpenWifi {
void RESTAPI_action_links::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
// there is no authentication here, this is just someone clicking on a link
// and arriving here. There should be a UUID in the link and this is all we need to know
// what we need to do.
ParseParameters(Request);
void RESTAPI_action_links::DoGet() {
auto Action = GetParameter("action","");
auto Id = GetParameter("id","");
if(Action=="password_reset")
DoResetPassword(Id, Request, Response);
RequestResetPassword(Id);
else if(Action=="email_verification")
DoEmailVerification(Id, Request, Response);
DoEmailVerification(Id);
else
DoReturnA404(Request, Response);
DoReturnA404();
}
void RESTAPI_action_links::DoResetPassword(std::string &Id,Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
void RESTAPI_action_links::DoPost() {
auto Action = GetParameter("action","");
auto Id = GetParameter("id","");
if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_GET) {
Logger_.information(Poco::format("COMPLETE-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id));
if(Action=="password_reset")
CompleteResetPassword(Id);
else
DoReturnA404();
}
void RESTAPI_action_links::RequestResetPassword(std::string &Id) {
Logger_.information(Poco::format("REQUEST-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id));
Poco::File FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset.html"};
Types::StringPairVec FormVars{ {"UUID", Id},
{"PASSWORD_VALIDATION", AuthService()->PasswordValidationExpression()}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
} else if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_POST) {
SendHTMLFileBack(FormFile,FormVars);
}
void RESTAPI_action_links::CompleteResetPassword(std::string &Id) {
// form has been posted...
RESTAPI_PartHandler PartHandler;
Poco::Net::HTMLForm Form(Request, Request.stream(), PartHandler);
Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler);
if (!Form.empty()) {
auto Password1 = Form.get("password1","bla");
auto Password2 = Form.get("password1","blu");
@@ -54,7 +60,7 @@ namespace OpenWifi {
" accepted password creation restrictions. Please consult our on-line help"
" to look at the our password policy. If you would like to contact us, please mention"
" id(" + Id + ")"}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
SendHTMLFileBack(FormFile,FormVars);
return;
}
@@ -63,7 +69,7 @@ namespace OpenWifi {
Poco::File FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"};
Types::StringPairVec FormVars{ {"UUID", Id},
{"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
SendHTMLFileBack(FormFile,FormVars);
return;
}
@@ -71,7 +77,7 @@ namespace OpenWifi {
Poco::File FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"};
Types::StringPairVec FormVars{ {"UUID", Id},
{"ERROR_TEXT", "Please contact our system administrators. We have identified an error in your account that must be resolved first."}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
SendHTMLFileBack(FormFile,FormVars);
return;
}
@@ -79,7 +85,7 @@ namespace OpenWifi {
Poco::File FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"};
Types::StringPairVec FormVars{ {"UUID", Id},
{"ERROR_TEXT", "You cannot reuse one of your recent passwords."}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
SendHTMLFileBack(FormFile,FormVars);
return;
}
Storage()->UpdateUserInfo(UInfo.email,Id,UInfo);
@@ -87,23 +93,21 @@ namespace OpenWifi {
Types::StringPairVec FormVars{ {"UUID", Id},
{"USERNAME", UInfo.email},
{"ACTION_LINK",Daemon()->GetUIURI()}};
SendHTMLFileBack(FormFile,Request, Response, FormVars);
}
SendHTMLFileBack(FormFile,FormVars);
} else {
DoReturnA404(Request, Response);
DoReturnA404();
}
}
void RESTAPI_action_links::DoEmailVerification(std::string &Id,Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_GET) {
void RESTAPI_action_links::DoEmailVerification(std::string &Id) {
SecurityObjects::UserInfo UInfo;
Logger_.information(Poco::format("EMAIL-VERIFICATION(%s): For ID=%s", Request->clientAddress().toString(), Id));
if (!Storage()->GetUserById(Id, UInfo)) {
Types::StringPairVec FormVars{{"UUID", Id},
{"ERROR_TEXT", "This does not appear to be a valid email verification link.."}};
Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_error.html"};
SendHTMLFileBack(FormFile, Request, Response, FormVars);
SendHTMLFileBack(FormFile, FormVars);
return;
}
@@ -116,18 +120,13 @@ namespace OpenWifi {
{"USERNAME", UInfo.email},
{"ACTION_LINK",Daemon()->GetUIURI()}};
Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_success.html"};
SendHTMLFileBack(FormFile, Request, Response, FormVars);
return;
} else {
DoReturnA404(Request, Response);
}
SendHTMLFileBack(FormFile, FormVars);
}
void RESTAPI_action_links::DoReturnA404(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
void RESTAPI_action_links::DoReturnA404() {
Types::StringPairVec FormVars;
Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/404_error.html"};
SendHTMLFileBack(FormFile, Request, Response, FormVars);
SendHTMLFileBack(FormFile, FormVars);
}
}

View File

@@ -18,22 +18,25 @@
namespace OpenWifi {
class RESTAPI_action_links : public RESTAPIHandler {
public:
RESTAPI_action_links(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_action_links(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override;
Server,
Internal,
false) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; };
void DoResetPassword(std::string &Id,Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoEmailVerification(std::string &Id,Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoReturnA404(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void RequestResetPassword(std::string &Id);
void CompleteResetPassword(std::string &Id);
void DoEmailVerification(std::string &Id);
void DoReturnA404();
void DoGet() final;
void DoPost() final;
void DoDelete() final {};
void DoPut() final {};
};
}

View File

@@ -28,32 +28,12 @@ namespace OpenWifi {
Length_ = InputStream.chars();
};
void RESTAPI_avatarHandler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
DoPost(Request, Response);
else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE)
DoDelete(Request, Response);
else
BadRequest(Request, Response);
}
void RESTAPI_avatarHandler::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_avatarHandler::DoPost() {
std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
SecurityObjects::UserInfo UInfo;
if (Id.empty() || !Storage()->GetUserById(Id, UInfo)) {
NotFound(Request, Response);
NotFound();
return;
}
@@ -63,9 +43,9 @@ namespace OpenWifi {
Poco::TemporaryFile TmpFile;
AvatarPartHandler partHandler(Id, Logger_, TmpFile);
Poco::Net::HTMLForm form(Request, Request.stream(), partHandler);
Poco::Net::HTMLForm form(*Request, Request->stream(), partHandler);
Poco::JSON::Object Answer;
if (!partHandler.Name().empty() && partHandler.Length()<Daemon()->ConfigGetInt("ucentral.avatar.maxsize",2000000)) {
if (!partHandler.Name().empty() && partHandler.Length()<Daemon()->ConfigGetInt("openwifi.avatar.maxsize",2000000)) {
Answer.set(RESTAPI::Protocol::AVATARID, Id);
Answer.set(RESTAPI::Protocol::ERRORCODE, 0);
Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType()));
@@ -76,50 +56,34 @@ namespace OpenWifi {
Answer.set(RESTAPI::Protocol::ERRORCODE, 13);
Answer.set(RESTAPI::Protocol::ERRORTEXT, "Avatar upload could not complete.");
}
ReturnObject(Request, Answer, Response);
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
ReturnObject(Answer);
}
void RESTAPI_avatarHandler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_avatarHandler::DoGet() {
std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
if (Id.empty()) {
NotFound(Request, Response);
NotFound();
return;
}
Poco::TemporaryFile TempAvatar;
std::string Type, Name;
if (!Storage()->GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) {
NotFound(Request, Response);
NotFound();
return;
}
SendFile(TempAvatar, Type, Name, Request, Response);
return;
} catch (const Poco::Exception&E) {
Logger_.log(E);
}
BadRequest(Request, Response);
SendFile(TempAvatar, Type, Name);
}
void RESTAPI_avatarHandler::DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_avatarHandler::DoDelete() {
std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
if (Id.empty()) {
NotFound(Request, Response);
NotFound();
return;
}
if (!Storage()->DeleteAvatar(UserInfo_.userinfo.email, Id)) {
NotFound(Request, Response);
NotFound();
return;
}
OK(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
OK();
}
}

View File

@@ -33,26 +33,22 @@ namespace OpenWifi {
class RESTAPI_avatarHandler : public RESTAPIHandler {
public:
RESTAPI_avatarHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_avatarHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/avatar/{id}"}; };
void DoGet( Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoPost( Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoDelete( Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoPost() final;
void DoDelete() final;
void DoPut() final {};
};
}
#endif //UCENTRALSEC_RESTAPI_AVATARHANDLER_H

View File

@@ -0,0 +1,36 @@
//
// Created by stephane bourque on 2021-09-02.
//
#include "RESTAPI_email_handler.h"
#include "Poco/Exception.h"
#include "Poco/JSON/Parser.h"
#include "Daemon.h"
#include "SMTPMailerService.h"
#include "RESTAPI_errors.h"
namespace OpenWifi {
void RESTAPI_email_handler::DoPost() {
auto Obj = ParseStream();
if (Obj->has("subject") &&
Obj->has("from") &&
Obj->has("text") &&
Obj->has("recipients")) {
auto Recipients = Obj->getArray("recipients");
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = Recipients->get(0).toString();
Attrs[SUBJECT] = Obj->get("subject").toString();
Attrs[TEXT] = Obj->get("text").toString();
if(SMTPMailerService()->SendMessage(Recipients->get(0).toString(), "password_reset.txt", Attrs)) {
OK();
return;
}
ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
return;
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
}

View File

@@ -0,0 +1,28 @@
//
// Created by stephane bourque on 2021-09-02.
//
#ifndef OWSEC_RESTAPI_EMAIL_HANDLER_H
#define OWSEC_RESTAPI_EMAIL_HANDLER_H
#include "RESTAPI_handler.h"
namespace OpenWifi {
class RESTAPI_email_handler : public RESTAPIHandler {
public:
RESTAPI_email_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/email"};}
void DoGet() final {};
void DoPost() final;
void DoDelete() final {};
void DoPut() final {};
};
}
#endif //OWSEC_RESTAPI_EMAIL_HANDLER_H

55
src/RESTAPI_errors.h Normal file
View File

@@ -0,0 +1,55 @@
//
// Created by stephane bourque on 2021-09-12.
//
#ifndef OWPROV_RESTAPI_ERRORS_H
#define OWPROV_RESTAPI_ERRORS_H
namespace OpenWifi::RESTAPI::Errors {
static const std::string MissingUUID{"Missing UUID."};
static const std::string MissingSerialNumber{"Missing Serial Number."};
static const std::string InternalError{"Internal error. Please try later."};
static const std::string InvalidJSONDocument{"Invalid JSON document."};
static const std::string UnsupportedHTTPMethod{"Unsupported HTTP Method"};
static const std::string StillInUse{"Element still in use."};
static const std::string CouldNotBeDeleted{"Element could not be deleted."};
static const std::string NameMustBeSet{"The name property must be set."};
static const std::string ConfigBlockInvalid{"Configuration block type invalid."};
static const std::string UnknownId{"Unknown management policy."};
static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."};
static const std::string RecordNotCreated{"Record could not be created."};
static const std::string RecordNotUpdated{"Record could not be updated."};
static const std::string UnknownManagementPolicyUUID{"Unknown management policy UUID."};
static const std::string CannotDeleteRoot{"Root Entity cannot be removed, only modified."};
static const std::string MustCreateRootFirst{"Root entity must be created first."};
static const std::string ParentUUIDMustExist{"Parent UUID must exist."};
static const std::string ConfigurationMustExist{"Configuration must exist."};
static const std::string MissingOrInvalidParameters{"Invalid or missing parameters."};
static const std::string UnknownSerialNumber{"Unknown Serial Number."};
static const std::string InvalidSerialNumber{"Invalid Serial Number."};
static const std::string SerialNumberExists{"Serial Number already exists."};
static const std::string ValidNonRootUUID{"Must be a non-root, and valid UUID."};
static const std::string VenueMustExist{"Venue does not exist."};
static const std::string NotBoth{"You cannot specify both Entity and Venue"};
static const std::string EntityMustExist{"Entity must exist."};
static const std::string ParentOrEntityMustBeSet{"Parent or Entity must be set."};
static const std::string ContactMustExist{"Contact must exist."};
static const std::string LocationMustExist{"Location must exist."};
static const std::string OnlyWSSupported{"This endpoint only supports WebSocket."};
static const std::string SerialNumberMismatch{"Serial Number mismatch."};
static const std::string InvalidCommand{"Invalid command."};
static const std::string NoRecordsDeleted{"No records deleted."};
static const std::string DeviceNotConnected{"Device is not currently connected."};
static const std::string CannotCreateWS{"Telemetry system could not create WS endpoint. Please try again."};
static const std::string BothDeviceTypeRevision{"Both deviceType and revision must be set."};
static const std::string IdOrSerialEmpty{"SerialNumber and Id must not be empty."};
static const std::string MissingUserID{"Missing user ID."};
static const std::string IdMustBe0{"To create a user, you must set the ID to 0"};
static const std::string InvalidUserRole{"Invalid userRole."};
static const std::string InvalidEmailAddress{"Invalid email address."};
static const std::string InvalidPassword{"Invalid password."};
static const std::string PasswordRejected{"Password was rejected. This maybe an old password."};
static const std::string InvalidIPRanges{"Invalid IP range specifications."};
}
#endif //OWPROV_RESTAPI_ERRORS_H

View File

@@ -8,6 +8,7 @@
#include <cctype>
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <future>
@@ -16,6 +17,8 @@
#include "Poco/URI.h"
#include "Poco/Net/OAuth20Credentials.h"
#include "RESTAPI_errors.h"
#ifdef TIP_SECURITY_SERVICE
#include "AuthService.h"
#else
@@ -29,9 +32,41 @@
namespace OpenWifi {
bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) {
std::string Param, Value;
void RESTAPIHandler::handleRequest(Poco::Net::HTTPServerRequest &RequestIn,
Poco::Net::HTTPServerResponse &ResponseIn) {
try {
Request = &RequestIn;
Response = &ResponseIn;
if (!ContinueProcessing())
return;
if (AlwaysAuthorize_ && !IsAuthorized())
return;
ParseParameters();
if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
DoGet();
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
DoPost();
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE)
DoDelete();
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_PUT)
DoPut();
else
BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod);
return;
} catch (const Poco::Exception &E) {
Logger_.log(E);
BadRequest(RESTAPI::Errors::InternalError);
}
}
const Poco::JSON::Object::Ptr &RESTAPIHandler::ParseStream() {
return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
}
bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) {
bindings.clear();
std::vector<std::string> PathItems = Utils::Split(Request, '/');
@@ -42,7 +77,6 @@ namespace OpenWifi {
bool Matched = true;
for (auto i = 0; i != PathItems.size() && Matched; i++) {
// std::cout << "PATH:" << PathItems[i] << " ENDPOINT:" << ParamItems[i] << std::endl;
if (PathItems[i] != ParamItems[i]) {
if (ParamItems[i][0] == '{') {
auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2);
@@ -59,14 +93,14 @@ namespace OpenWifi {
}
void RESTAPIHandler::PrintBindings() {
for (auto &[key, value] : Bindings_)
for (const auto &[key, value] : Bindings_)
std::cout << "Key = " << key << " Value= " << value << std::endl;
}
void RESTAPIHandler::ParseParameters(Poco::Net::HTTPServerRequest &request) {
Poco::URI uri(request.getURI());
void RESTAPIHandler::ParseParameters() {
Poco::URI uri(Request->getURI());
Parameters_ = uri.getQueryParameters();
InitQueryBlock();
}
static bool is_number(const std::string &s) {
@@ -80,35 +114,40 @@ namespace OpenWifi {
}
uint64_t RESTAPIHandler::GetParameter(const std::string &Name, const uint64_t Default) {
for (const auto &i : Parameters_) {
if (i.first == Name) {
if (!is_number(i.second))
return Default;
return std::stoi(i.second);
}
}
auto Hint = std::find_if(Parameters_.begin(),Parameters_.end(),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==Parameters_.end() || !is_number(Hint->second))
return Default;
return std::stoull(Hint->second);
}
bool RESTAPIHandler::GetBoolParameter(const std::string &Name, bool Default) {
for (const auto &i : Parameters_) {
if (i.first == Name) {
if (!is_bool(i.second))
return Default;
return i.second == "true";
}
}
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_) || !is_bool(Hint->second))
return Default;
return Hint->second=="true";
}
std::string RESTAPIHandler::GetParameter(const std::string &Name, const std::string &Default) {
for (const auto &i : Parameters_) {
if (i.first == Name)
return i.second;
}
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_))
return Default;
return Hint->second;
}
bool RESTAPIHandler::HasParameter(const std::string &Name, std::string &Value) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_))
return false;
Value = Hint->second;
return true;
}
bool RESTAPIHandler::HasParameter(const std::string &Name, uint64_t & Value) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_))
return false;
Value = std::stoull(Hint->second);
return true;
}
const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) {
@@ -130,202 +169,225 @@ namespace OpenWifi {
return Return;
}
void RESTAPIHandler::AddCORS(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
auto Origin = Request.find("Origin");
if (Origin != Request.end()) {
Response.set("Access-Control-Allow-Origin", Origin->second);
Response.set("Vary", "Origin");
} else {
Response.set("Access-Control-Allow-Origin", "*");
bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value) {
if(O->has(Field)) {
Value = O->get(Field).toString();
return true;
}
Response.set("Access-Control-Allow-Headers", "*");
Response.set("Access-Control-Allow-Methods", MakeList(Methods_));
Response.set("Access-Control-Max-Age", "86400");
return false;
}
void RESTAPIHandler::SetCommonHeaders(Poco::Net::HTTPServerResponse &Response, bool CloseConnection) {
Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
Response.setChunkedTransferEncoding(true);
Response.setContentType("application/json");
bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value) {
if(O->has(Field)) {
Value = O->get(Field);
return true;
}
return false;
}
void RESTAPIHandler::AddCORS() {
auto Origin = Request->find("Origin");
if (Origin != Request->end()) {
Response->set("Access-Control-Allow-Origin", Origin->second);
Response->set("Vary", "Origin");
} else {
Response->set("Access-Control-Allow-Origin", "*");
}
Response->set("Access-Control-Allow-Headers", "*");
Response->set("Access-Control-Allow-Methods", MakeList(Methods_));
Response->set("Access-Control-Max-Age", "86400");
}
void RESTAPIHandler::SetCommonHeaders(bool CloseConnection) {
Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
Response->setChunkedTransferEncoding(true);
Response->setContentType("application/json");
if(CloseConnection) {
Response.set("Connection", "close");
Response.setKeepAlive(false);
Response->set("Connection", "close");
Response->setKeepAlive(false);
} else {
Response.setKeepAlive(true);
Response.set("Connection", "Keep-Alive");
Response.set("Keep-Alive", "timeout=5, max=1000");
Response->setKeepAlive(true);
Response->set("Connection", "Keep-Alive");
Response->set("Keep-Alive", "timeout=5, max=1000");
}
}
void RESTAPIHandler::ProcessOptions(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
AddCORS(Request, Response);
SetCommonHeaders(Response);
Response.setContentLength(0);
Response.set("Access-Control-Allow-Credentials", "true");
Response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
Response.set("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method");
/* std::cout << "RESPONSE:" << std::endl;
for(const auto &[f,s]:Response)
std::cout << "First: " << f << " second:" << s << std::endl;
*/
Response.send();
void RESTAPIHandler::ProcessOptions() {
AddCORS();
SetCommonHeaders();
Response->setContentLength(0);
Response->set("Access-Control-Allow-Credentials", "true");
Response->setStatus(Poco::Net::HTTPResponse::HTTP_OK);
Response->set("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method");
Response->send();
}
void RESTAPIHandler::PrepareResponse(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
Poco::Net::HTTPResponse::HTTPStatus Status,
void RESTAPIHandler::PrepareResponse( Poco::Net::HTTPResponse::HTTPStatus Status,
bool CloseConnection) {
Response.setStatus(Status);
AddCORS(Request, Response);
SetCommonHeaders(Response, CloseConnection);
Response->setStatus(Status);
AddCORS();
SetCommonHeaders(CloseConnection);
}
void RESTAPIHandler::BadRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
const std::string & Reason) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
void RESTAPIHandler::BadRequest(const std::string & Reason) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",400);
ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ;
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::InternalError(const std::string & Reason) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",500);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ;
std::ostream &Answer = Response.send();
ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Please try later or review the data submitted." : Reason) ;
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::UnAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
const std::string & Reason) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_FORBIDDEN);
void RESTAPIHandler::UnAuthorized(const std::string & Reason) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN);
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",403);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ;
std::ostream &Answer = Response.send();
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::NotFound(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
void RESTAPIHandler::NotFound() {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",404);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription","This resource does not exist.");
std::ostream &Answer = Response.send();
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
Logger_.debug(Poco::format("RES-NOTFOUND: User='%s' Method='%s' Path='%s",
Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(),
Request->getURI()));
}
void RESTAPIHandler::OK(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response);
if( Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE ||
Request.getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) {
Response.send();
void RESTAPIHandler::OK() {
PrepareResponse();
if( Request->getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE ||
Request->getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) {
Response->send();
} else {
Poco::JSON::Object ErrorObject;
ErrorObject.set("Code", 0);
ErrorObject.set("Operation", Request.getMethod());
ErrorObject.set("Operation", Request->getMethod());
ErrorObject.set("Details", "Command completed.");
std::ostream &Answer = Response.send();
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
}
void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
Response.set("Content-Type","application/octet-stream");
Response.set("Content-Disposition", "attachment; filename=" + UUID );
Response.set("Content-Transfer-Encoding","binary");
Response.set("Accept-Ranges", "bytes");
Response.set("Cache-Control", "private");
Response.set("Pragma", "private");
Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
Response.set("Content-Length", std::to_string(File.getSize()));
AddCORS(Request, Response);
Response.sendFile(File.path(),"application/octet-stream");
void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID) {
Response->set("Content-Type","application/octet-stream");
Response->set("Content-Disposition", "attachment; filename=" + UUID );
Response->set("Content-Transfer-Encoding","binary");
Response->set("Accept-Ranges", "bytes");
Response->set("Cache-Control", "private");
Response->set("Pragma", "private");
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
Response->set("Content-Length", std::to_string(File.getSize()));
AddCORS();
Response->sendFile(File.path(),"application/octet-stream");
}
void RESTAPIHandler::SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
void RESTAPIHandler::SendFile(Poco::File & File) {
Poco::Path P(File.path());
auto MT = Utils::FindMediaType(File);
if(MT.Encoding==Utils::BINARY) {
Response.set("Content-Transfer-Encoding","binary");
Response.set("Accept-Ranges", "bytes");
Response->set("Content-Transfer-Encoding","binary");
Response->set("Accept-Ranges", "bytes");
}
Response.set("Cache-Control", "private");
Response.set("Pragma", "private");
Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
AddCORS(Request, Response);
Response.sendFile(File.path(),MT.ContentType);
Response->set("Cache-Control", "private");
Response->set("Pragma", "private");
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
AddCORS();
Response->sendFile(File.path(),MT.ContentType);
}
void RESTAPIHandler::SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
void RESTAPIHandler::SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name) {
auto MT = Utils::FindMediaType(Name);
if(MT.Encoding==Utils::BINARY) {
Response.set("Content-Transfer-Encoding","binary");
Response.set("Accept-Ranges", "bytes");
Response->set("Content-Transfer-Encoding","binary");
Response->set("Accept-Ranges", "bytes");
}
Response.set("Content-Disposition", "attachment; filename=" + Name );
Response.set("Accept-Ranges", "bytes");
Response.set("Cache-Control", "private");
Response.set("Pragma", "private");
Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
AddCORS(Request, Response);
Response.sendFile(TempAvatar.path(),MT.ContentType);
Response->set("Content-Disposition", "attachment; filename=" + Name );
Response->set("Accept-Ranges", "bytes");
Response->set("Cache-Control", "private");
Response->set("Pragma", "private");
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
AddCORS();
Response->sendFile(TempAvatar.path(),MT.ContentType);
}
void RESTAPIHandler::SendHTMLFileBack(Poco::File & File,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response ,
const Types::StringPairVec & FormVars) {
Response.set("Pragma", "private");
Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
Response.set("Content-Length", std::to_string(File.getSize()));
AddCORS(Request, Response);
Response->set("Pragma", "private");
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
Response->set("Content-Length", std::to_string(File.getSize()));
AddCORS();
auto FormContent = Utils::LoadFile(File.path());
Utils::ReplaceVariables(FormContent, FormVars);
Response.setChunkedTransferEncoding(true);
Response.setContentType("text/html");
std::ostream& ostr = Response.send();
Response->setChunkedTransferEncoding(true);
Response->setContentType("text/html");
std::ostream& ostr = Response->send();
ostr << FormContent;
}
void RESTAPIHandler::ReturnStatus(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
Poco::Net::HTTPResponse::HTTPStatus Status,
bool CloseConnection) {
PrepareResponse(Request, Response, Status, CloseConnection);
void RESTAPIHandler::ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status, bool CloseConnection) {
PrepareResponse(Status, CloseConnection);
if(Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) {
Response.setContentLength(0);
Response.erase("Content-Type");
Response.setChunkedTransferEncoding(false);
Response->setContentLength(0);
Response->erase("Content-Type");
Response->setChunkedTransferEncoding(false);
}
Response.send();
Response->send();
}
bool RESTAPIHandler::ContinueProcessing(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) {
ProcessOptions(Request, Response);
bool RESTAPIHandler::ContinueProcessing() {
if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) {
ProcessOptions();
return false;
} else if (std::find(Methods_.begin(), Methods_.end(), Request.getMethod()) == Methods_.end()) {
BadRequest(Request, Response);
} else if (std::find(Methods_.begin(), Methods_.end(), Request->getMethod()) == Methods_.end()) {
BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod);
return false;
}
return true;
}
bool RESTAPIHandler::IsAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
bool RESTAPIHandler::IsAuthorized() {
if(Internal_) {
return Daemon()->IsValidAPIKEY(Request);
auto Allowed = Daemon()->IsValidAPIKEY(*Request);
if(!Allowed) {
if(Server_.LogBadTokens(false)) {
Logger_.debug(Poco::format("I-REQ-DENIED(%s): Method='%s' Path='%s",
Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI()));
}
} else {
auto Id = Request->get("X-INTERNAL-NAME", "unknown");
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(Poco::format("I-REQ-ALLOWED(%s): User='%s' Method='%s' Path='%s",
Utils::FormatIPv6(Request->clientAddress().toString()), Id,
Request->getMethod(), Request->getURI()));
}
}
return Allowed;
} else {
if (SessionToken_.empty()) {
try {
Poco::Net::OAuth20Credentials Auth(Request);
Poco::Net::OAuth20Credentials Auth(*Request);
if (Auth.getScheme() == "Bearer") {
SessionToken_ = Auth.getBearerToken();
}
@@ -334,37 +396,47 @@ namespace OpenWifi {
}
}
#ifdef TIP_SECURITY_SERVICE
if (AuthService()->IsAuthorized(Request, SessionToken_, UserInfo_)) {
if (AuthService()->IsAuthorized(*Request, SessionToken_, UserInfo_)) {
#else
if (AuthClient()->IsAuthorized(Request, SessionToken_, UserInfo_)) {
if (AuthClient()->IsAuthorized(*Request, SessionToken_, UserInfo_)) {
#endif
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s",
Utils::FormatIPv6(Request->clientAddress().toString()),
UserInfo_.userinfo.email,
Request->clientAddress().toString(),
Request->getMethod(),
Request->getURI()));
}
return true;
} else {
UnAuthorized(Request, Response);
if(Server_.LogBadTokens(true)) {
Logger_.debug(Poco::format("X-REQ-DENIED(%s): Method='%s' Path='%s",
Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI()));
}
UnAuthorized();
}
return false;
}
}
/*
bool RESTAPIHandler::ValidateAPIKey(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
auto Key = Request.get("X-API-KEY", "");
if (Key.empty())
return false;
return true;
}
*/
void RESTAPIHandler::ReturnObject(Poco::Net::HTTPServerRequest &Request, Poco::JSON::Object &Object,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response);
std::ostream &Answer = Response.send();
void RESTAPIHandler::ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse();
std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(Object, Answer);
}
void RESTAPIHandler::ReturnCountOnly(uint64_t Count) {
Poco::JSON::Object Answer;
Answer.set("count", Count);
ReturnObject(Answer);
}
bool RESTAPIHandler::InitQueryBlock() {
if(QueryBlockInitialized_)
return true;
QueryBlockInitialized_=true;
QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0);
QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0);
@@ -376,8 +448,10 @@ namespace OpenWifi {
QB_.LogType = GetParameter(RESTAPI::Protocol::LOGTYPE,0);
QB_.LastOnly = GetBoolParameter(RESTAPI::Protocol::LASTONLY,false);
QB_.Newest = GetBoolParameter(RESTAPI::Protocol::NEWEST,false);
QB_.CountOnly = GetBoolParameter(RESTAPI::Protocol::COUNTONLY,false);
if(QB_.Offset<1) return false;
if(QB_.Offset<1)
QB_.Offset=1;
return true;
}
@@ -402,6 +476,4 @@ namespace OpenWifi {
[[nodiscard]] uint64_t RESTAPIHandler::GetWhen(const Poco::JSON::Object::Ptr &Obj) {
return RESTAPIHandler::Get(RESTAPI::Protocol::WHEN, Obj);
}
}

View File

@@ -25,6 +25,8 @@
#include "Poco/NullStream.h"
#include "RESTAPI_SecurityObjects.h"
#include "RESTAPI_utils.h"
#include "RESTAPI_GenericServer.h"
namespace OpenWifi {
@@ -86,66 +88,78 @@ namespace OpenWifi {
struct QueryBlock {
uint64_t StartDate = 0 , EndDate = 0 , Offset = 0 , Limit = 0, LogType = 0 ;
std::string SerialNumber, Filter, Select;
bool Lifetime=false, LastOnly=false, Newest=false;
bool Lifetime=false, LastOnly=false, Newest=false, CountOnly=false;
};
typedef std::map<std::string, std::string> BindingMap;
RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods, bool Internal=false)
: Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)), Internal_(Internal) {}
RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods, RESTAPI_GenericServer & Server, bool Internal=false, bool AlwaysAuthorize=true)
: Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)), Server_(Server), Internal_(Internal), AlwaysAuthorize_(AlwaysAuthorize) {}
static bool ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &Keys);
void PrintBindings();
void ParseParameters(Poco::Net::HTTPServerRequest &request);
void ParseParameters();
void AddCORS(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &response);
void SetCommonHeaders(Poco::Net::HTTPServerResponse &response, bool CloseConnection=false);
void ProcessOptions(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &response);
void AddCORS();
void SetCommonHeaders(bool CloseConnection=false);
void ProcessOptions();
void
PrepareResponse(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &response,
Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK,
PrepareResponse(Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK,
bool CloseConnection = false);
bool ContinueProcessing(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
bool IsAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
/* bool ValidateAPIKey(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response); */
bool ContinueProcessing();
bool IsAuthorized();
uint64_t GetParameter(const std::string &Name, uint64_t Default);
std::string GetParameter(const std::string &Name, const std::string &Default);
bool GetBoolParameter(const std::string &Name, bool Default);
void BadRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response, const std::string &Reason = "");
void UnAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, const std::string &Reason = "");
void ReturnObject(Poco::Net::HTTPServerRequest &Request, Poco::JSON::Object &Object,
Poco::Net::HTTPServerResponse &Response);
void NotFound(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void OK(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void ReturnStatus(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
Poco::Net::HTTPResponse::HTTPStatus Status,
void BadRequest(const std::string &Reason );
void InternalError(const std::string &Reason = "");
void UnAuthorized(const std::string &Reason = "");
void ReturnObject(Poco::JSON::Object &Object);
void NotFound();
void OK();
void ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status,
bool CloseConnection=false);
void SendFile(Poco::File & File, const std::string & UUID,
Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void SendFile(Poco::File & File, const std::string & UUID);
void SendHTMLFileBack(Poco::File & File,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response ,
const Types::StringPairVec & FormVars);
void SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name);
void SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void SendFile(Poco::File & File);
const std::string &GetBinding(const std::string &Name, const std::string &Default);
bool InitQueryBlock();
void ReturnCountOnly(uint64_t Count);
[[nodiscard]] static uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0);
[[nodiscard]] static std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default="");
[[nodiscard]] static bool GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default=false);
[[nodiscard]] static uint64_t GetWhen(const Poco::JSON::Object::Ptr &Obj);
bool HasParameter(const std::string &QueryParameter, std::string &Value);
bool HasParameter(const std::string &QueryParameter, uint64_t & Value);
static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value);
static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value);
template<typename T> void ReturnObject(const char *Name, const std::vector<T> & Objects) {
Poco::JSON::Object Answer;
RESTAPI_utils::field_to_json(Answer,Name,Objects);
ReturnObject(Answer);
}
Poco::Logger & Logger() { return Logger_; }
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) final;
virtual void DoGet() = 0 ;
virtual void DoDelete() = 0 ;
virtual void DoPost() = 0 ;
virtual void DoPut() = 0 ;
const Poco::JSON::Object::Ptr & ParseStream();
protected:
BindingMap Bindings_;
@@ -156,18 +170,22 @@ namespace OpenWifi {
std::vector<std::string> Methods_;
QueryBlock QB_;
bool Internal_=false;
bool QueryBlockInitialized_=false;
Poco::Net::HTTPServerRequest *Request= nullptr;
Poco::Net::HTTPServerResponse *Response= nullptr;
bool AlwaysAuthorize_=true;
Poco::JSON::Parser IncomingParser_;
RESTAPI_GenericServer & Server_;
};
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
public:
RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L)
: RESTAPIHandler(bindings, L, std::vector<std::string>{}) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override {
if (!IsAuthorized(Request, Response))
return;
BadRequest(Request, Response, "Unknown API endpoint");
}
RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server)
: RESTAPIHandler(bindings, L, std::vector<std::string>{}, Server) {}
inline void DoGet() override {};
inline void DoPost() override {};
inline void DoPut() override {};
inline void DoDelete() override {};
};
template<class T>
@@ -182,30 +200,30 @@ namespace OpenWifi {
}
template<typename T, typename... Args>
RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger ) {
RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) {
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method.");
if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) {
return new T(Bindings, Logger, false);
return new T(Bindings, Logger, Server, false);
}
if constexpr (sizeof...(Args) == 0) {
return new RESTAPI_UnknownRequestHandler(Bindings,Logger);
return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server);
} else {
return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger);
return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger, Server);
}
}
template<typename T, typename... Args>
RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger) {
RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) {
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method.");
if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) {
return new T(Bindings, Logger, true);
return new T(Bindings, Logger, Server, true);
}
if constexpr (sizeof...(Args) == 0) {
return new RESTAPI_UnknownRequestHandler(Bindings,Logger);
return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server);
} else {
return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger);
return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger, Server);
}
}

View File

@@ -16,97 +16,85 @@
#include "Utils.h"
namespace OpenWifi {
void RESTAPI_oauth2Handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
void RESTAPI_oauth2Handler::DoGet() {
if (!IsAuthorized()) {
UnAuthorized("Not authorized.");
return;
}
bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
if(GetMe) {
Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
Poco::JSON::Object Me;
UserInfo_.userinfo.to_json(Me);
ReturnObject(Me);
return;
}
BadRequest("Ill-formed request. Please consult documentation.");
}
try {
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
// Extract the info for login...
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
void RESTAPI_oauth2Handler::DoDelete() {
if (!IsAuthorized()) {
UnAuthorized("Not authorized.");
return;
}
auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
if (Token == SessionToken_) {
AuthService()->Logout(Token);
ReturnStatus(Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true);
} else {
Logger_.information(Poco::format("BAD-LOGOUT(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
NotFound();
}
}
void RESTAPI_oauth2Handler::DoPost() {
auto Obj = ParseStream();
auto userId = GetS(RESTAPI::Protocol::USERID, Obj);
auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj);
auto newPassword = GetS(RESTAPI::Protocol::NEWPASSWORD, Obj);
Poco::toLowerInPlace(userId);
if(GetBoolParameter(RESTAPI::Protocol::REQUIREMENTS, false)) {
Logger_.information(Poco::format("POLICY-REQUEST(%s): Request.", Request->clientAddress().toString()));
Poco::JSON::Object Answer;
Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->PasswordValidationExpression());
Answer.set(RESTAPI::Protocol::ACCESSPOLICY, RESTAPI_Server()->GetAccessPolicy());
Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, RESTAPI_Server()->GetPasswordPolicy());
ReturnObject(Request, Answer, Response);
ReturnObject(Answer);
return;
}
if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
// Send an email to the userId
Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
SecurityObjects::UserInfoAndPolicy UInfo;
if(AuthService::SendEmailToUser(userId,AuthService::FORGOT_PASSWORD))
Logger_.information(Poco::format("Send password reset link to %s",userId));
UInfo.webtoken.userMustChangePassword=true;
Poco::JSON::Object ReturnObj;
UInfo.webtoken.to_json(ReturnObj);
ReturnObject(Request, ReturnObj, Response);
ReturnObject(ReturnObj);
return;
}
Poco::toLowerInPlace(userId);
SecurityObjects::UserInfoAndPolicy UInfo;
auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo);
if (Code==AuthService::SUCCESS) {
Poco::JSON::Object ReturnObj;
UInfo.webtoken.to_json(ReturnObj);
ReturnObject(Request, ReturnObj, Response);
ReturnObject(ReturnObj);
return;
} else {
switch(Code) {
case AuthService::INVALID_CREDENTIALS: UnAuthorized(Request, Response, "Unrecognized credentials (username/password)."); break;
case AuthService::PASSWORD_INVALID: UnAuthorized(Request, Response, "Invalid password."); break;
case AuthService::PASSWORD_ALREADY_USED: UnAuthorized(Request, Response, "Password already used previously."); break;
case AuthService::USERNAME_PENDING_VERIFICATION: UnAuthorized(Request, Response, "User access pending email verification."); break;
case AuthService::PASSWORD_CHANGE_REQUIRED: UnAuthorized(Request, Response, "Password change expected."); break;
default: UnAuthorized(Request, Response, "Unrecognized credentials (username/password)."); break;
case AuthService::INVALID_CREDENTIALS: UnAuthorized("Unrecognized credentials (username/password)."); break;
case AuthService::PASSWORD_INVALID: UnAuthorized("Invalid password."); break;
case AuthService::PASSWORD_ALREADY_USED: UnAuthorized("Password already used previously."); break;
case AuthService::USERNAME_PENDING_VERIFICATION: UnAuthorized("User access pending email verification."); break;
case AuthService::PASSWORD_CHANGE_REQUIRED: UnAuthorized("Password change expected."); break;
default: UnAuthorized("Unrecognized credentials (username/password)."); break;
}
return;
}
} else if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) {
if (!IsAuthorized(Request, Response)) {
UnAuthorized(Request, Response, "Not authorized.");
return;
}
auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
if (Token == SessionToken_) {
AuthService()->Logout(Token);
ReturnStatus(Request, Response, Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true);
} else {
NotFound(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
if (!IsAuthorized(Request, Response)) {
UnAuthorized(Request, Response, "Not authorized.");
return;
}
bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
if(GetMe) {
Poco::JSON::Object Me;
UserInfo_.userinfo.to_json(Me);
ReturnObject(Request, Me, Response);
return;
}
BadRequest(Request, Response);
} else {
BadRequest(Request, Response, "Unsupported HTTP method.");
}
return;
} catch (const Poco::Exception &E) {
Logger_.warning(
Poco::format("%s: Failed with: %s", std::string(__func__), E.displayText()));
}
BadRequest(Request, Response);
}
}

View File

@@ -14,16 +14,19 @@
namespace OpenWifi {
class RESTAPI_oauth2Handler : public RESTAPIHandler {
public:
RESTAPI_oauth2Handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_oauth2Handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
Server,
Internal, false) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; };
void DoGet() final;
void DoPost() final;
void DoDelete() final;
void DoPut() final {};
};
}
#endif //UCENTRAL_RESTAPI_OAUTH2HANDLER_H

View File

@@ -69,7 +69,13 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char * COMMANDUUID = "commandUUID";
static const char * FIRMWARES = "firmwares";
static const char * TOPIC = "topic";
static const char * HOST = "host";
static const char * OS = "os";
static const char * HOSTNAME = "hostname";
static const char * PROCESSORS = "processors";
static const char * REASON = "reason";
static const char * RELOAD = "reload";
static const char * SUBSYSTEMS = "subsystems";
static const char * FILEUUID = "uuid";
static const char * USERID = "userId";
static const char * PASSWORD = "password";
@@ -122,6 +128,8 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char * PASSWORDPOLICY = "passwordPolicy";
static const char * FORGOTPASSWORD = "forgotPassword";
static const char * ME = "me";
static const char * TELEMETRY = "telemetry";
static const char * INTERVAL = "interval";
}

View File

@@ -19,6 +19,7 @@
#include "RESTAPI_systemEndpoints_handler.h"
#include "RESTAPI_AssetServer.h"
#include "RESTAPI_avatarHandler.h"
#include "RESTAPI_email_handler.h"
#include "Daemon.h"
#include "Utils.h"
@@ -29,10 +30,11 @@ namespace OpenWifi {
int RESTAPI_Server::Start() {
Logger_.information("Starting.");
Server_.InitLogging();
AsserDir_ = Daemon()->ConfigPath("ucentral.restapi.wwwassets");
AccessPolicy_ = Daemon()->ConfigGetString("ucentral.document.policy.access", "/wwwassets/access_policy.html");
PasswordPolicy_ = Daemon()->ConfigGetString("ucentral.document.policy.password", "/wwwassets/possword_policy.html");
AsserDir_ = Daemon()->ConfigPath("openwifi.restapi.wwwassets");
AccessPolicy_ = Daemon()->ConfigGetString("openwifi.document.policy.access", "/wwwassets/access_policy.html");
PasswordPolicy_ = Daemon()->ConfigGetString("openwifi.document.policy.password", "/wwwassets/possword_policy.html");
for(const auto & Svr: ConfigServersList_) {
Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
@@ -49,18 +51,14 @@ namespace OpenWifi {
Params->setMaxQueued(200);
Params->setKeepAlive(true);
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RequestHandlerFactory, Pool_, Sock, Params);
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RequestHandlerFactory(Server_), Pool_, Sock, Params);
NewServer->start();
RESTServers_.push_back(std::move(NewServer));
}
return 0;
}
Poco::Net::HTTPRequestHandler *RequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Poco::URI uri(Request.getURI());
const auto & Path = uri.getPath();
RESTAPIHandler::BindingMap Bindings;
@@ -72,14 +70,23 @@ namespace OpenWifi {
RESTAPI_AssetServer,
RESTAPI_systemEndpoints_handler,
RESTAPI_action_links,
RESTAPI_avatarHandler
>(Path,Bindings,Logger_);
RESTAPI_avatarHandler,
RESTAPI_email_handler
>(Path,Bindings,Logger_,Server_);
}
void RESTAPI_Server::Stop() {
Logger_.information("Stopping ");
for( const auto & svr : RESTServers_ )
svr->stop();
RESTServers_.clear();
}
void RESTAPI_Server::reinitialize(Poco::Util::Application &self) {
Daemon()->LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
} // namespace

View File

@@ -15,6 +15,7 @@
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/NetException.h"
#include "RESTAPI_GenericServer.h"
namespace OpenWifi {
@@ -30,6 +31,8 @@ namespace OpenWifi {
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
inline const std::string & AssetDir() { return AsserDir_; }
inline const std::string & GetPasswordPolicy() const { return PasswordPolicy_; }
inline const std::string & GetAccessPolicy() const { return AccessPolicy_; }
@@ -40,9 +43,10 @@ namespace OpenWifi {
std::string AsserDir_;
std::string PasswordPolicy_;
std::string AccessPolicy_;
RESTAPI_GenericServer Server_;
RESTAPI_Server() noexcept:
SubSystemServer("RESTAPIServer", "REST-SRV", "ucentral.restapi")
SubSystemServer("RESTAPIServer", "REST-SRV", "openwifi.restapi")
{
}
};
@@ -51,12 +55,14 @@ namespace OpenWifi {
class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
RequestHandlerFactory() :
Logger_(RESTAPI_Server()->Logger()){}
RequestHandlerFactory(RESTAPI_GenericServer &Server) :
Logger_(RESTAPI_Server()->Logger()),
Server_(Server){}
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
private:
Poco::Logger & Logger_;
RESTAPI_GenericServer &Server_;
};

View File

@@ -7,21 +7,10 @@
#include "RESTAPI_SecurityObjects.h"
namespace OpenWifi {
void RESTAPI_systemEndpoints_handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
try {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
void RESTAPI_systemEndpoints_handler::DoGet() {
auto Services = Daemon()->GetServices();
SecurityObjects::SystemEndpointList L;
for(const auto &i:Services) {
SecurityObjects::SystemEndpoint S{
.type = i.Type,
@@ -31,14 +20,6 @@ namespace OpenWifi {
}
Poco::JSON::Object Obj;
L.to_json(Obj);
ReturnObject(Request, Obj, Response);
return;
ReturnObject(Obj);
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
}

View File

@@ -9,14 +9,17 @@
namespace OpenWifi {
class RESTAPI_systemEndpoints_handler : public RESTAPIHandler {
public:
RESTAPI_systemEndpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_systemEndpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/systemEndpoints"}; };
void DoGet() final;
void DoPost() final {};
void DoDelete() final {};
void DoPut() final {};
};
}

View File

@@ -9,39 +9,26 @@
#include "Poco/Exception.h"
#include "Poco/JSON/Parser.h"
#include "Poco/DateTime.h"
#include "Poco/DateTimeFormat.h"
#include "Daemon.h"
#include "RESTAPI_protocol.h"
#include "RESTAPI_errors.h"
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
namespace OpenWifi {
void RESTAPI_system_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
DoPost(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else
BadRequest(Request, Response, "Unsupported method.");
}
void RESTAPI_system_command::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
Poco::JSON::Parser parser;
auto Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
void RESTAPI_system_command::DoPost() {
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::COMMAND)) {
auto Command = Poco::toLower(Obj->get(RESTAPI::Protocol::COMMAND).toString());
if (Command == RESTAPI::Protocol::SETLOGLEVEL) {
if (Obj->has(RESTAPI::Protocol::PARAMETERS) &&
Obj->isArray(RESTAPI::Protocol::PARAMETERS)) {
auto ParametersBlock = Obj->getArray(RESTAPI::Protocol::PARAMETERS);
if (Obj->has(RESTAPI::Protocol::SUBSYSTEMS) &&
Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) {
auto ParametersBlock = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS);
for (const auto &i : *ParametersBlock) {
Poco::JSON::Parser pp;
auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>();
@@ -50,10 +37,11 @@ namespace OpenWifi {
auto Name = GetS(RESTAPI::Protocol::TAG, InnerObj);
auto Value = GetS(RESTAPI::Protocol::VALUE, InnerObj);
Daemon()->SetSubsystemLogLevel(Name, Value);
Logger_.information(Poco::format("Setting log level for %s at %s", Name, Value));
Logger_.information(
Poco::format("Setting log level for %s at %s", Name, Value));
}
}
OK(Request, Response);
OK();
return;
}
} else if (Command == RESTAPI::Protocol::GETLOGLEVELS) {
@@ -67,7 +55,7 @@ namespace OpenWifi {
Array.add(Pair);
}
Result.set(RESTAPI::Protocol::TAGLIST, Array);
ReturnObject(Request,Result,Response);
ReturnObject(Result);
return;
} else if (Command == RESTAPI::Protocol::GETLOGLEVELNAMES) {
Poco::JSON::Object Result;
@@ -76,7 +64,7 @@ namespace OpenWifi {
for (const auto &i : LevelNames)
LevelNamesArray.add(i);
Result.set(RESTAPI::Protocol::LIST, LevelNamesArray);
ReturnObject(Request,Result,Response);
ReturnObject(Result);
return;
} else if (Command == RESTAPI::Protocol::GETSUBSYSTEMNAMES) {
Poco::JSON::Object Result;
@@ -85,48 +73,74 @@ namespace OpenWifi {
for (const auto &i : SubSystemNames)
LevelNamesArray.add(i);
Result.set(RESTAPI::Protocol::LIST, LevelNamesArray);
ReturnObject(Request,Result,Response);
ReturnObject(Result);
return;
} else if (Command == RESTAPI::Protocol::STATS) {
} else if (Command == RESTAPI::Protocol::RELOAD) {
if (Obj->has(RESTAPI::Protocol::SUBSYSTEMS) &&
Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) {
auto SubSystems = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS);
std::vector<std::string> Names;
for (const auto &i : *SubSystems)
Names.push_back(i.toString());
std::thread ReloadThread([Names](){
std::this_thread::sleep_for(10000ms);
for(const auto &i:Names) {
if(i=="daemon")
Daemon()->Reload();
else
Daemon()->Reload(i);
}
});
ReloadThread.detach();
}
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response, "Unsupported or missing parameters.");
}
void RESTAPI_system_command::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
ParseParameters(Request);
auto Command = GetParameter(RESTAPI::Protocol::COMMAND, "");
if (!Poco::icompare(Command, RESTAPI::Protocol::VERSION)) {
Poco::JSON::Object Answer;
Answer.set(RESTAPI::Protocol::TAG, RESTAPI::Protocol::VERSION);
Answer.set(RESTAPI::Protocol::VALUE, Daemon()->Version());
ReturnObject(Request, Answer, Response);
OK();
return;
}
if (!Poco::icompare(Command, RESTAPI::Protocol::TIMES)) {
Poco::JSON::Array Array;
Poco::JSON::Object Answer;
Poco::JSON::Object UpTimeObj;
UpTimeObj.set(RESTAPI::Protocol::TAG,RESTAPI::Protocol::UPTIME);
UpTimeObj.set(RESTAPI::Protocol::VALUE, Daemon()->uptime().totalSeconds());
Poco::JSON::Object StartObj;
StartObj.set(RESTAPI::Protocol::TAG,RESTAPI::Protocol::START);
StartObj.set(RESTAPI::Protocol::VALUE, Daemon()->startTime().epochTime());
Array.add(UpTimeObj);
Array.add(StartObj);
Answer.set(RESTAPI::Protocol::TIMES, Array);
ReturnObject(Request, Answer, Response);
} else {
BadRequest(RESTAPI::Errors::InvalidCommand);
return;
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response, "Unsupported or missing parameters.");
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_system_command::DoGet() {
std::string Arg;
if(HasParameter("command",Arg) && Arg=="info") {
Poco::JSON::Object Answer;
Answer.set(RESTAPI::Protocol::VERSION, Daemon()->Version());
Answer.set(RESTAPI::Protocol::UPTIME, Daemon()->uptime().totalSeconds());
Answer.set(RESTAPI::Protocol::START, Daemon()->startTime().epochTime());
Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName());
Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount());
Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName());
Poco::JSON::Array Certificates;
auto SubSystems = Daemon()->GetFullSubSystems();
std::set<std::string> CertNames;
for(const auto &i:SubSystems) {
auto Hosts=i->HostSize();
for(uint64_t j=0;j<Hosts;++j) {
auto CertFileName = i->Host(j).CertFile();
if(!CertFileName.empty()) {
auto InsertResult = CertNames.insert(CertFileName);
if(InsertResult.second) {
Poco::JSON::Object Inner;
Inner.set("filename", CertFileName);
Poco::Crypto::X509Certificate C(CertFileName);
auto ExpiresOn = C.expiresOn();
Inner.set("expiresOn",ExpiresOn.timestamp().epochTime());
Certificates.add(Inner);
}
}
}
}
Answer.set("certificates", Certificates);
ReturnObject(Answer);
return;
}
BadRequest(RESTAPI::Errors::InvalidCommand);
}
}

View File

@@ -14,19 +14,19 @@
namespace OpenWifi {
class RESTAPI_system_command : public RESTAPIHandler {
public:
RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/system"};}
void DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoPost(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoPost() final;
void DoPut() final {};
void DoDelete() final {};
};
}
#endif // UCENTRALGW_RESTAPI_SYSTEM_COMMAND_H

View File

@@ -7,99 +7,76 @@
#include "Poco/JSON/Parser.h"
#include "Utils.h"
#include "RESTAPI_utils.h"
#include "RESTAPI_errors.h"
namespace OpenWifi {
void RESTAPI_user_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_POST)
DoPost(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE)
DoDelete(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_PUT)
DoPut(Request, Response);
else
BadRequest(Request, Response, "Unimplemented HTTP Operation.");
}
void RESTAPI_user_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_user_handler::DoGet() {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
BadRequest(RESTAPI::Errors::MissingUserID);
return;
}
SecurityObjects::UserInfo UInfo;
if(!Storage()->GetUserById(Id,UInfo)) {
NotFound(Request, Response);
NotFound();
return;
}
Poco::JSON::Object UserInfoObject;
UInfo.to_json(UserInfoObject);
ReturnObject(Request, UserInfoObject, Response);
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
ReturnObject(UserInfoObject);
}
void RESTAPI_user_handler::DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_user_handler::DoDelete() {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
return;
}
if(!Storage()->DeleteUser(UserInfo_.userinfo.name,Id)) {
NotFound(Request, Response);
return;
}
Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
OK(Request, Response);
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_user_handler::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::string Id = GetBinding("id", "");
if(Id!="0") {
BadRequest(Request, Response, "To create a user, you must set the ID to 0");
BadRequest(RESTAPI::Errors::MissingUserID);
return;
}
SecurityObjects::UserInfo UInfo;
RESTAPI_utils::from_request(UInfo,Request);
if(!Storage()->GetUserById(Id,UInfo)) {
NotFound();
return;
}
if(!Storage()->DeleteUser(UserInfo_.userinfo.email,Id)) {
NotFound();
return;
}
if(AuthService()->DeleteUserFromCache(UInfo.email))
;
Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email));
Storage()->RevokeAllTokens(UInfo.email);
Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
OK();
}
void RESTAPI_user_handler::DoPost() {
std::string Id = GetBinding("id", "");
if(Id!="0") {
BadRequest(RESTAPI::Errors::IdMustBe0);
return;
}
SecurityObjects::UserInfo UInfo;
RESTAPI_utils::from_request(UInfo,*Request);
if(UInfo.userRole == SecurityObjects::UNKNOWN) {
BadRequest(Request, Response, "Invalid userRole.");
BadRequest(RESTAPI::Errors::InvalidUserRole);
return;
}
Poco::toLowerInPlace(UInfo.email);
if(!Utils::ValidEMailAddress(UInfo.email)) {
BadRequest(Request, Response, "Invalid email address.");
BadRequest(RESTAPI::Errors::InvalidEmailAddress);
return;
}
if(!UInfo.currentPassword.empty()) {
if(!AuthService()->ValidatePassword(UInfo.currentPassword)) {
BadRequest(Request, Response, "Invalid password.");
BadRequest(RESTAPI::Errors::InvalidPassword);
return;
}
}
@@ -107,9 +84,9 @@ namespace OpenWifi {
if(UInfo.name.empty())
UInfo.name = UInfo.email;
if(!Storage()->CreateUser(UserInfo_.userinfo.name,UInfo)) {
if(!Storage()->CreateUser(UInfo.email,UInfo)) {
Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email));
BadRequest(Request, Response);
BadRequest(RESTAPI::Errors::RecordNotCreated);
return;
}
@@ -121,43 +98,35 @@ namespace OpenWifi {
if(!Storage()->GetUserByEmail(UInfo.email, UInfo)) {
Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email));
BadRequest(Request, Response);
NotFound();
return;
}
Poco::JSON::Object UserInfoObject;
UInfo.to_json(UserInfoObject);
ReturnObject(Request, UserInfoObject, Response);
ReturnObject(UserInfoObject);
Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email));
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_user_handler::DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_user_handler::DoPut() {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
BadRequest(RESTAPI::Errors::MissingUserID);
return;
}
SecurityObjects::UserInfo LocalObject;
if(!Storage()->GetUserById(Id,LocalObject)) {
NotFound(Request, Response);
NotFound();
return;
}
// some basic validations
Poco::JSON::Parser IncomingParser;
auto RawObject = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
auto RawObject = ParseStream();
if(RawObject->has("userRole") && SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString())==SecurityObjects::UNKNOWN) {
BadRequest(Request, Response, "Bad userRole value.");
BadRequest(RESTAPI::Errors::InvalidUserRole);
return;
}
@@ -192,11 +161,11 @@ namespace OpenWifi {
}
if(RawObject->has("currentPassword")) {
if(!AuthService()->ValidatePassword(RawObject->get("currentPassword").toString())) {
BadRequest(Request, Response, "Invalid password.");
BadRequest(RESTAPI::Errors::InvalidPassword);
return;
}
if(!AuthService()->SetPassword(RawObject->get("currentPassword").toString(),LocalObject)) {
BadRequest(Request, Response, "Password was rejected. This maybe an old password.");
BadRequest(RESTAPI::Errors::PasswordRejected);
return;
}
}
@@ -209,12 +178,9 @@ namespace OpenWifi {
if(Storage()->UpdateUserInfo(UserInfo_.userinfo.email,Id,LocalObject)) {
Poco::JSON::Object ModifiedObject;
LocalObject.to_json(ModifiedObject);
ReturnObject(Request, ModifiedObject, Response);
ReturnObject(ModifiedObject);
return;
}
} catch( const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response, "Request rejected.");
BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
}

View File

@@ -10,7 +10,7 @@
namespace OpenWifi {
class RESTAPI_user_handler : public RESTAPIHandler {
public:
RESTAPI_user_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_user_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_POST,
@@ -18,13 +18,13 @@ namespace OpenWifi {
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; };
void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoPost() final;
void DoDelete() final;
void DoPut() final;
private:
};

View File

@@ -8,29 +8,14 @@
#include "Utils.h"
namespace OpenWifi {
void RESTAPI_users_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else
BadRequest(Request, Response);
}
void RESTAPI_users_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
void RESTAPI_users_handler::DoGet() {
std::vector<SecurityObjects::UserInfo> Users;
InitQueryBlock();
bool IdOnly = (GetParameter("idOnly","false")=="true");
if(QB_.Select.empty()) {
if (Storage()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
Poco::JSON::Array ArrayObj;
Poco::JSON::Object Answer;
if (Storage()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
for (const auto &i : Users) {
Poco::JSON::Object Obj;
if (IdOnly) {
@@ -40,11 +25,10 @@ namespace OpenWifi {
ArrayObj.add(Obj);
}
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::USERS, ArrayObj);
ReturnObject(Request, RetObj, Response);
return;
Answer.set(RESTAPI::Protocol::USERS, ArrayObj);
}
ReturnObject(Answer);
return;
} else {
Types::StringVec IDs = Utils::Split(QB_.Select);
Poco::JSON::Array ArrayObj;
@@ -62,12 +46,8 @@ namespace OpenWifi {
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::USERS, ArrayObj);
ReturnObject(Request, RetObj, Response);
ReturnObject(RetObj);
return;
}
} catch ( const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
}

View File

@@ -10,15 +10,18 @@
namespace OpenWifi {
class RESTAPI_users_handler : public RESTAPIHandler {
public:
RESTAPI_users_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_users_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; };
void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoPost() final {};
void DoDelete() final {};
void DoPut() final {};
};
};

View File

@@ -8,35 +8,21 @@
#include "Utils.h"
namespace OpenWifi {
void RESTAPI_validateToken_handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
try {
Poco::URI URI(Request.getURI());
void RESTAPI_validateToken_handler::DoGet() {
Poco::URI URI(Request->getURI());
auto Parameters = URI.getQueryParameters();
for(auto const &i:Parameters) {
if (i.first == "token") {
// can we find this token?
SecurityObjects::UserInfoAndPolicy SecObj;
if (AuthService()->IsValidToken(i.first, SecObj.webtoken, SecObj.userinfo)) {
if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo)) {
Poco::JSON::Object Obj;
SecObj.to_json(Obj);
ReturnObject(Request, Obj, Response);
ReturnObject(Obj);
return;
}
}
}
NotFound(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.log(E);
NotFound();
}
BadRequest(Request, Response);
};
}

View File

@@ -10,15 +10,18 @@
namespace OpenWifi {
class RESTAPI_validateToken_handler : public RESTAPIHandler {
public:
RESTAPI_validateToken_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_validateToken_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {};
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateToken"}; };
void DoGet() final;
void DoPost() final {};
void DoDelete() final {};
void DoPut() final {};
};
}

View File

@@ -24,13 +24,18 @@ namespace OpenWifi {
class SMTPMailerService * SMTPMailerService::instance_ = nullptr;
int SMTPMailerService::Start() {
void SMTPMailerService::LoadMyConfig() {
MailHost_ = Daemon()->ConfigGetString("mailer.hostname");
SenderLoginUserName_ = Daemon()->ConfigGetString("mailer.username");
SenderLoginPassword_ = Daemon()->ConfigGetString("mailer.password");
Sender_ = Daemon()->ConfigGetString("mailer.sender");
LoginMethod_ = Daemon()->ConfigGetString("mailer.loginmethod");
MailHostPort_ = (int)Daemon()->ConfigGetInt("mailer.port");
TemplateDir_ = Daemon()->ConfigPath("mailer.templates", Daemon()->DataDir());
}
int SMTPMailerService::Start() {
LoadMyConfig();
SenderThr_.start(*this);
return 0;
}
@@ -41,8 +46,14 @@ namespace OpenWifi {
SenderThr_.join();
}
void SMTPMailerService::reinitialize(Poco::Util::Application &self) {
Daemon()->LoadConfigurationFile();
Logger_.information("Reinitializing.");
LoadMyConfig();
}
bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
uint64_t Now = std::time(nullptr);
auto CE = Cache_.find(Poco::toLower(Recipient));
@@ -60,17 +71,18 @@ namespace OpenWifi {
.File=Poco::File(TemplateDir_ + "/" +Name),
.Attrs=Attrs});
return false;
return true;
}
void SMTPMailerService::run() {
Running_ = true;
while(Running_) {
Poco::Thread::trySleep(2000);
Poco::Thread::trySleep(10000);
if(!Running_)
break;
{
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
uint64_t Now = std::time(nullptr);
@@ -106,11 +118,16 @@ namespace OpenWifi {
Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
Message.setSubject(Msg.Attrs.find(SUBJECT)->second);
if(Msg.Attrs.find(TEXT) != Msg.Attrs.end()) {
std::string Content = Msg.Attrs.find(TEXT)->second;
Message.addContent(new Poco::Net::StringPartSource(Content));
} else {
std::string Content = Utils::LoadFile(Msg.File);
Types::StringPairVec Variables;
FillVariables(Msg.Attrs, Variables);
Utils::ReplaceVariables(Content, Variables);
Message.addContent(new Poco::Net::StringPartSource(Content));
}
auto Logo = Msg.Attrs.find(LOGO);
if(Logo!=Msg.Attrs.end()) {

View File

@@ -22,7 +22,8 @@ namespace OpenWifi {
SUBJECT,
TEMPLATE_TXT,
TEMPLATE_HTML,
LOGO
LOGO,
TEXT
};
static const std::map<MESSAGE_ATTRIBUTES,const std::string>
@@ -36,7 +37,9 @@ namespace OpenWifi {
{ SUBJECT, "SUBJECT"},
{ TEMPLATE_TXT, "TEMPLATE_TXT"},
{ TEMPLATE_HTML, "TEMPLATE_HTML"},
{ LOGO, "LOGO"}};
{ LOGO, "LOGO"},
{ TEXT, "TEXT"}
};
inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) {
static const std::string EmptyString{};
@@ -75,7 +78,8 @@ namespace OpenWifi {
void Stop() override;
bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs);
bool SendIt(const MessageEvent &Msg);
void LoadMyConfig();
void reinitialize(Poco::Util::Application &self) override;
private:
static SMTPMailerService * instance_;
std::string MailHost_;

View File

@@ -15,11 +15,6 @@ namespace OpenWifi {
class Storage *Storage::instance_ = nullptr;
Storage::Storage() noexcept:
SubSystemServer("Storage", "STORAGE-SVR", "storage")
{
}
std::string Storage::ConvertParams(const std::string & S) const {
std::string R;
@@ -43,7 +38,7 @@ namespace OpenWifi {
}
int Storage::Start() {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
Logger_.setLevel(Poco::Message::PRIO_NOTICE);
Logger_.notice("Starting.");

View File

@@ -154,6 +154,13 @@ namespace OpenWifi {
bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
bool DeleteAvatar(const std::string & Admin, std::string &Id);
bool AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut);
bool RevokeToken( std::string & Token );
bool IsTokenRevoked( std::string & Token );
bool CleanRevokedTokens( uint64_t Oldest );
bool RevokeAllTokens( std::string & UserName );
bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo);
/*
* All ActionLinks functions
*/
@@ -176,8 +183,8 @@ namespace OpenWifi {
int Create_Tables();
int Create_UserTable();
int Create_AvatarTable();
int Create_TokensTable();
int Setup_SQLite();
[[nodiscard]] std::string ConvertParams(const std::string &S) const;
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(dbType_==sqlite) {
@@ -190,11 +197,15 @@ namespace OpenWifi {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
}
#ifndef SMALL_BUILD
Storage() noexcept:
SubSystemServer("Storage", "STORAGE-SVR", "storage")
{
}
int Setup_SQLite();
int Setup_MySQL();
int Setup_PostgreSQL();
#endif
Storage() noexcept;
};
inline Storage * Storage() { return Storage::instance(); };

View File

@@ -32,6 +32,7 @@ void SubSystemServer::initialize(Poco::Util::Application &self) {
auto i = 0;
bool good = true;
ConfigServersList_.clear();
while (good) {
std::string root{SubSystemConfigPrefix_ + ".host." + std::to_string(i) + "."};
@@ -81,10 +82,11 @@ void SubSystemServer::initialize(Poco::Util::Application &self) {
}
}
void SubSystemServer::uninitialize() {}
void SubSystemServer::uninitialize() {
}
void SubSystemServer::reinitialize(Poco::Util::Application &self) {
// add your own reinitialization code here
Logger_.information("Reloading of this subsystem is not supported.");
}
void SubSystemServer::defineOptions(Poco::Util::OptionSet &options) {}

View File

@@ -20,9 +20,6 @@
#include "Poco/Net/X509Certificate.h"
using SubMutex = std::recursive_mutex;
using SubMutexGuard = std::lock_guard<SubMutex>;
namespace OpenWifi {
class PropertiesFileServerEntry {
public:
@@ -79,7 +76,8 @@ class SubSystemServer : public Poco::Util::Application::Subsystem {
inline const std::string & Name() const { return Name_; };
const char * name() const override { return Name_.c_str(); }
const PropertiesFileServerEntry &Host(int index) { return ConfigServersList_[index]; };
const PropertiesFileServerEntry & Host(uint64_t index) { return ConfigServersList_[index]; };
uint64_t HostSize() const { return ConfigServersList_.size(); }
Poco::Logger &Logger() { return Logger_; };
void SetLoggingLevel(Poco::Message::Priority NewPriority) { Logger_.setLevel(NewPriority); }
int GetLoggingLevel() { return Logger_.getLevel(); }
@@ -87,7 +85,7 @@ class SubSystemServer : public Poco::Util::Application::Subsystem {
virtual void Stop() = 0;
protected:
SubMutex Mutex_{};
std::recursive_mutex Mutex_;
Poco::Logger &Logger_;
std::string Name_;
std::vector<PropertiesFileServerEntry> ConfigServersList_;

View File

@@ -151,7 +151,7 @@ namespace OpenWifi::Utils {
if(input.length() % 4)
throw std::runtime_error("Invalid base64 length!");
std::size_t padding{};
std::size_t padding=0;
if(input.length())
{
@@ -162,7 +162,7 @@ namespace OpenWifi::Utils {
std::vector<byte> decoded;
decoded.reserve(((input.length() / 4) * 3) - padding);
std::uint32_t temp{};
std::uint32_t temp=0;
auto it = input.begin();
while(it < input.end())
@@ -488,67 +488,4 @@ namespace OpenWifi::Utils {
return Result;
}
static bool cidr_match(const in_addr &addr, const in_addr &net, uint8_t bits) {
if (bits == 0) {
return true;
}
return !((addr.s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits)));
}
static bool cidr6_match(const in6_addr &address, const in6_addr &network, uint8_t bits) {
#ifdef __linux__
const uint32_t *a = address.s6_addr32;
const uint32_t *n = network.s6_addr32;
#else
const uint32_t *a = address.__u6_addr.__u6_addr32;
const uint32_t *n = network.__u6_addr.__u6_addr32;
#endif
int bits_whole, bits_incomplete;
bits_whole = bits >> 5; // number of whole u32
bits_incomplete = bits & 0x1F; // number of bits in incomplete u32
if (bits_whole) {
if (memcmp(a, n, bits_whole << 2)!=0) {
return false;
}
}
if (bits_incomplete) {
uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete));
if ((a[bits_whole] ^ n[bits_whole]) & mask) {
return false;
}
}
return true;
}
static bool ConvertStringToLong(const char *S, unsigned long &L) {
char *end;
L = std::strtol(S,&end,10);
return end != S;
}
bool IPinRange(const std::string &Range, const Poco::Net::IPAddress &IP) {
Poco::StringTokenizer TimeTokens(Range,"/",Poco::StringTokenizer::TOK_TRIM);
Poco::Net::IPAddress RangeIP;
if(Poco::Net::IPAddress::tryParse(TimeTokens[0],RangeIP)) {
if(TimeTokens.count()==2) {
if (RangeIP.family() == Poco::Net::IPAddress::IPv4) {
unsigned long MaskLength;
if (ConvertStringToLong(TimeTokens[1].c_str(), MaskLength)) {
return cidr_match(*static_cast<const in_addr *>(RangeIP.addr()),
*static_cast<const in_addr *>(IP.addr()), MaskLength);
}
} else if (RangeIP.family() == Poco::Net::IPAddress::IPv6) {
unsigned long MaskLength;
if (ConvertStringToLong(TimeTokens[1].c_str(), MaskLength)) {
return cidr6_match(*static_cast<const in6_addr *>(RangeIP.addr()),
*static_cast<const in6_addr *>(IP.addr()), MaskLength);
}
}
}
return false;
}
return false;
}
}

View File

@@ -71,11 +71,8 @@ namespace OpenWifi::Utils {
[[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F);
[[nodiscard]] std::string BinaryFileToHexString( const Poco::File &F);
[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
[[nodiscard]] bool IPinRange(const std::string &Range, const Poco::Net::IPAddress &IP);
template< typename T >
std::string int_to_hex( T i )
{

View File

@@ -12,6 +12,7 @@ namespace OpenWifi {
int Storage::Create_Tables() {
Create_UserTable();
Create_AvatarTable();
Create_TokensTable();
return 0;
}
@@ -75,4 +76,48 @@ namespace OpenWifi {
}
return 0;
}
int Storage::Create_TokensTable() {
try {
Poco::Data::Session Sess = Pool_->get();
if(dbType_==sqlite) {
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
"Token TEXT PRIMARY KEY, "
"RefreshToken TEXT, "
"TokenType TEXT, "
"UserName TEXT, "
"Created BIGINT, "
"Expires BIGINT, "
"IdleTimeOut BIGINT, "
"RevocationDate BIGINT "
") ", Poco::Data::Keywords::now;
} else if(dbType_==mysql) {
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
"Token TEXT PRIMARY KEY, "
"RefreshToken TEXT, "
"TokenType TEXT, "
"UserName TEXT, "
"Created BIGINT, "
"Expires BIGINT, "
"IdleTimeOut BIGINT, "
"RevocationDate BIGINT "
") ", Poco::Data::Keywords::now;
} else if(dbType_==pgsql) {
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
"Token TEXT PRIMARY KEY, "
"RefreshToken TEXT, "
"TokenType TEXT, "
"UserName TEXT, "
"Created BIGINT, "
"Expires BIGINT, "
"IdleTimeOut BIGINT, "
"RevocationDate BIGINT "
") ", Poco::Data::Keywords::now;
}
return 0;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return 0;
}
}

152
src/storage_tokens.cpp Normal file
View File

@@ -0,0 +1,152 @@
#include "StorageService.h"
namespace OpenWifi {
/*
"Token TEXT PRIMARY KEY, "
"RefreshToken TEXT, "
"TokenType TEXT, "
"UserName TEXT, "
"Created BIGINT, "
"Expires BIGINT, "
"IdleTimeOut BIGINT, "
"RevocationDate BIGINT "
*/
bool Storage::AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
uint64_t Now = std::time(nullptr);
uint64_t Z = 0;
std::string St2{
"INSERT INTO Tokens (Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate) VALUES(?,?,?,?,?,?,?,?)"};
Insert << ConvertParams(St2),
Poco::Data::Keywords::use(Token),
Poco::Data::Keywords::use(RefreshToken),
Poco::Data::Keywords::use(TokenType),
Poco::Data::Keywords::use(UserName),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Expires),
Poco::Data::Keywords::use(TimeOut),
Poco::Data::Keywords::use(Z);
Insert.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
uint32_t RevocationDate = 0 ;
std::string St2{"SELECT Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate From Tokens WHERE Token=?"};
Select << ConvertParams(St2),
Poco::Data::Keywords::into(UInfo.webtoken.access_token_),
Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_),
Poco::Data::Keywords::into(UInfo.webtoken.token_type_),
Poco::Data::Keywords::into(UInfo.userinfo.email),
Poco::Data::Keywords::into(UInfo.webtoken.created_),
Poco::Data::Keywords::into(UInfo.webtoken.expires_in_),
Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_),
Poco::Data::Keywords::into(RevocationDate),
Poco::Data::Keywords::use(Token);
Select.execute();
if(RevocationDate>0)
return false;
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::IsTokenRevoked(std::string &Token) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
uint32_t RevocationDate = 0 ;
std::string St2{"SELECT Revoked From Tokens WHERE Token=?"};
Select << ConvertParams(St2),
Poco::Data::Keywords::into(RevocationDate),
Poco::Data::Keywords::use(Token);
Select.execute();
if(Select.columnsExtracted()==0)
return false;
return RevocationDate>0 ;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::RevokeToken(std::string &Token) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
uint32_t Revoked = 1 ;
uint64_t Now = std::time(nullptr);
// update users set lastLogin=? where id=?
std::string St2{"UPDATE Tokens Set RevocationDate=? WHERE Token=?"};
Update << ConvertParams(St2),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Token);
Update.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::CleanRevokedTokens(uint64_t Oldest) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
uint64_t Now = std::time(nullptr);
std::string St2{"DELETE From Tokens WHERE Created <= ?"};
Delete << ConvertParams(St2),
Poco::Data::Keywords::use(Oldest);
Delete.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::RevokeAllTokens(std::string & username) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string St2{"DELETE From Tokens WHERE Username=?"};
Delete << ConvertParams(St2),
Poco::Data::Keywords::use(username);
Delete.execute();
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

View File

@@ -88,6 +88,8 @@ namespace OpenWifi::uCentralProtocol {
static const char * TIMESTAMP = "timestamp";
static const char * SYSTEM = "system";
static const char * HOST = "host";
static const char * CONNECTIONIP = "connectionIp";
static const char * TELEMETRY = "telemetry";
enum EVENT_MSG {
ET_UNKNOWN,
@@ -99,7 +101,8 @@ namespace OpenWifi::uCentralProtocol {
ET_PING,
ET_CFGPENDING,
ET_RECOVERY,
ET_DEVICEUPDATE
ET_DEVICEUPDATE,
ET_TELEMETRY
};
static EVENT_MSG EventFromString(const std::string & Method) {
@@ -121,6 +124,8 @@ namespace OpenWifi::uCentralProtocol {
return ET_RECOVERY;
} else if (!Poco::icompare(Method, DEVICEUPDATE)) {
return ET_DEVICEUPDATE;
} else if (!Poco::icompare(Method, TELEMETRY)) {
return ET_TELEMETRY;
} else
return ET_UNKNOWN;
};

View File

@@ -20,10 +20,10 @@ then
exit 1
fi
if [[ "${UCENTRALSEC}" == "" ]]
if [[ "${OWSEC}" == "" ]]
then
echo "You must set the variable UCENTRALSEC in order to use this script. Something like"
echo "UCENTRALSEC=myauthgateway.isp.com:16001"
echo "You must set the variable OWSEC in order to use this script. Something like"
echo "OWSEC=myauthgateway.isp.com:16001"
exit 1
fi
@@ -43,7 +43,7 @@ browser=""
login() {
payload="{ \"userId\" : \"$username\" , \"password\" : \"$password\" }"
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${UCENTRALSEC}/api/v1/oauth2" | jq -r '.access_token')
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
if [[ "${token}" == "" ]]
then
@@ -55,7 +55,7 @@ login() {
testlogin() {
payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
-H "Content-Type: application/json" \
-d "$payload" > ${result_file}
userMustChangePassword=$(cat ${result_file} | jq -r '.userMustChangePassword')
@@ -68,14 +68,14 @@ testlogin() {
exit 1
fi
payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
-H "Content-Type: application/json" \
-d "$payload" > ${result_file}
jq < ${result_file}
elif [[ "$3" != "" ]]
then
payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
-H "Content-Type: application/json" \
-d "$payload" > ${result_file}
jq < ${result_file}
@@ -85,7 +85,7 @@ testlogin() {
emailtest() {
payload="{ \"userId\" : \"$1\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2?forgotPassword=true" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2?forgotPassword=true" \
-H "Content-Type: application/json" \
-d "$payload" > ${result_file}
jq < ${result_file}
@@ -114,18 +114,19 @@ findbrowser() {
logout() {
curl ${FLAGS} -X DELETE -H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
"https://${UCENTRALSEC}/api/v1/oauth2/${token}"
"https://${OWSEC}/api/v1/oauth2/${token}"
token=""
rm -rf token.json
}
me() {
curl ${FLAGS} -X GET -H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
"https://${UCENTRALSEC}/api/v1/oauth2?me=true"
"https://${OWSEC}/api/v1/oauth2?me=true"
}
listendpoints() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/systemEndpoints" \
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/systemEndpoints" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
@@ -161,12 +162,12 @@ listendpoints() {
}
getlogo() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/wwwassets/open-wifi.svg"
curl ${FLAGS} -X GET "https://${OWSEC}/wwwassets/open-wifi.svg"
}
createuser() {
payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/user/0" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/user/0" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
@@ -175,7 +176,7 @@ createuser() {
createuser_v() {
payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/user/0?email_verification=true" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/user/0?email_verification=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
@@ -183,7 +184,7 @@ createuser_v() {
}
deleteuser() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/user/$1" \
curl ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/user/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
@@ -191,7 +192,7 @@ deleteuser() {
}
getuser() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/user/$1" \
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/user/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
@@ -199,7 +200,7 @@ getuser() {
}
listusers() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/users" \
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/users" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
@@ -208,53 +209,127 @@ listusers() {
policies() {
payload="{}"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2?requirements=true" \
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2?requirements=true" \
-H "Content-Type: application/json" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
setavatar() {
curl ${FLAGS} -F 'data=@open-wifi.svg' "https://${UCENTRALSEC}/api/v1/avatar/$1" \
curl ${FLAGS} -F 'data=@$2' "https://${OWSEC}/api/v1/avatar/$1" \
-H "Authorization: Bearer ${token}" > ${result_file};
jq < ${result_file}
}
getavatar() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/avatar/$1" \
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/avatar/$1" \
-H "accept: application/octet-stream" \
-H "Authorization: Bearer ${token}" \
-o "user.svg"
}
deleteavatar() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/avatar/$1" \
curl ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/avatar/$1" \
-H "Authorization: Bearer ${token}" \
-H "Content-Type: application/json" > ${result_file}
jq < ${result_file}
}
secversion() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/system?command=version" \
sendemail() {
payload="{ \"recipients\" : [ \"$1\" ] , \"subject\" : \"test1\" , \"from\" : \"$2\" , \"text\" : \"This is a test from SES.\" }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/email" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
testlogout() {
echo "Logged in..."
oldtoken=${token}
listusers
logout
echo "Logged out..."
token=${oldtoken}
echo "This should be en error"
listusers
}
setloglevel() {
payload="{ \"command\" : \"setloglevel\" , \"subsystems\" : [ { \"tag\" : \"$1\" , \"value\" : \"$2\" } ] }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getloglevels() {
payload="{ \"command\" : \"getloglevels\" }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getloglevelnames() {
payload="{ \"command\" : \"getloglevelnames\" }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getsubsystemnames() {
payload="{ \"command\" : \"getsubsystemnames\" }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
systeminfo() {
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/system?command=info" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
sectimes() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/system?command=times" \
reloadsubsystem() {
payload="{ \"command\" : \"reload\", \"subsystems\" : [ \"$1\" ] }"
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
help() {
echo
echo "Usage: cli <cmd> [args]"
echo
echo "listendpoints Get all the system endpoints."
echo "emailtest Generate a forgot Password e-amil to the logged in user."
echo "me Show information about the logged user."
echo "createuser <email> <password> Create a user with an initial password and force the user to change password."
echo "createuser_v <email> <password> Same as create user but also force an e-mail verification."
echo "deleteuser <user UUID> Delete the user."
echo "getuser <user UUID> Get the user information."
echo "listusers List users."
echo "policies List the login and access policies."
echo "setavatar <user UUID> <filename> Sets the avatar for user to the image in filename."
echo "getavatar <user UUID> Get the avatar for the user."
echo "deleteavatar <user UUID> Remove the avatar for a user."
echo "sendemail <recipient> <from> Sends a test email to see if the e-mail system is working."
echo "setloglevel <subsystem> <loglevel> Set the log level for s specific subsystem."
echo "getloglevels Get the current log levels for all subsystems."
echo "getloglevelnames Get the log level names available."
echo "getsubsystemnames Get the list of subsystems."
echo "systeminfo Get basic system information."
echo "reloadsubsystem <subsystem name> Reload the configuration for a subsystem."
echo
}
shopt -s nocasematch
case "$1" in
"createuser") login; createuser "$2" "$3"; logout;;
"createuser_v") login; createuser_v "$2" "$3"; logout;;
@@ -270,8 +345,14 @@ case "$1" in
"setavatar") login; setavatar "$2"; logout;;
"getavatar") login; getavatar "$2"; logout;;
"deleteavatar") login; deleteavatar "$2"; logout;;
"secversion") login; secversion ; logout;;
"sectimes") login; sectimes ; logout;;
"sendemail") login; sendemail ; logout;;
"testlogout") login; testlogout ;;
"setloglevel") login; setloglevel "$2" "$3" ; logout ;;
"getloglevels") login; getloglevels; logout ;;
"getloglevelnames") login; getloglevelnames; logout ;;
"getsubsystemnames") login; getsubsystemnames; logout ;;
"reloadsubsystem") login; reloadsubsystem "$2"; logout ;;
"systeminfo") login; systeminfo ; logout;;
"help") login; help ; logout ;;
*) help ;;
esac