mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-12-24 22:37:04 +00:00
Compare commits
93 Commits
kv3.0.9
...
version_up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6f0f113e2 | ||
|
|
6542726ac3 | ||
|
|
4bc753f8b5 | ||
|
|
e3a513fa6a | ||
|
|
b151239a5c | ||
|
|
862dab38d1 | ||
|
|
ee2e9a19c0 | ||
|
|
8b28fa0435 | ||
|
|
aeef70a121 | ||
|
|
42c421ec12 | ||
|
|
98bfb4b24d | ||
|
|
6b64089f55 | ||
|
|
1f6e42b57c | ||
|
|
f857d61377 | ||
|
|
66d580d047 | ||
|
|
567c671c22 | ||
|
|
9e3735ced8 | ||
|
|
18b169e517 | ||
|
|
cab0d8aee6 | ||
|
|
680b6a16e3 | ||
|
|
218694872f | ||
|
|
6ae1eeb2ea | ||
|
|
f537e701a0 | ||
|
|
d4dfb7b620 | ||
|
|
446cbf270f | ||
|
|
06ffee27b1 | ||
|
|
fa3c325bfa | ||
|
|
182a442582 | ||
|
|
3b7a24ea30 | ||
|
|
1c5909613f | ||
|
|
8e5e51a52a | ||
|
|
b4699e9178 | ||
|
|
438309714f | ||
|
|
a9130eeb75 | ||
|
|
33068fca9e | ||
|
|
d329151f6c | ||
|
|
ec846006bb | ||
|
|
bd48079a8d | ||
|
|
242261de0a | ||
|
|
31a4edead5 | ||
|
|
f7b697f219 | ||
|
|
e020da75fc | ||
|
|
89702f56e0 | ||
|
|
0ac97442c0 | ||
|
|
e38b4c8a13 | ||
|
|
9c5bbee834 | ||
|
|
a5d1eebe6d | ||
|
|
ee14f064c8 | ||
|
|
dbf52c1f23 | ||
|
|
9dc6a6bf97 | ||
|
|
1c0556f8bf | ||
|
|
d298139525 | ||
|
|
a37c961f5b | ||
|
|
75bcbd748c | ||
|
|
b6eba2a96d | ||
|
|
17082803d4 | ||
|
|
26b9a96506 | ||
|
|
5ce8dae9ec | ||
|
|
7da135c1e5 | ||
|
|
50ee4ba5cb | ||
|
|
3a8109d7ad | ||
|
|
56232966ec | ||
|
|
1ecf98d712 | ||
|
|
f5b60ced61 | ||
|
|
e4d141bb8e | ||
|
|
25b4288050 | ||
|
|
82430c2d5d | ||
|
|
7b68ec0536 | ||
|
|
839f4fec44 | ||
|
|
c4178209bb | ||
|
|
79ab67db50 | ||
|
|
00bc77feea | ||
|
|
4f00d77d2b | ||
|
|
c679d4ac40 | ||
|
|
4a150a9fcb | ||
|
|
83eb603f0a | ||
|
|
38bc0f0d69 | ||
|
|
e7362c2020 | ||
|
|
9c9987e190 | ||
|
|
4ac7b6ba0b | ||
|
|
f9ee19af91 | ||
|
|
cd2ab8660f | ||
|
|
b9f00f6603 | ||
|
|
596cfd49e1 | ||
|
|
b3deba5606 | ||
|
|
a97d49a06b | ||
|
|
b1be0604d6 | ||
|
|
b29f7f7dc4 | ||
|
|
132b31b06b | ||
|
|
3114ff8a32 | ||
|
|
9c5aeda5dd | ||
|
|
783ec99930 | ||
|
|
0c661b8b93 |
169
.github/workflows/ci.yml
vendored
169
.github/workflows/ci.yml
vendored
@@ -1,19 +1,19 @@
|
||||
name: Build Docker image
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'openapi/**'
|
||||
- '**.md'
|
||||
- 'version'
|
||||
- 'package*.json'
|
||||
- 'helm/*.yaml'
|
||||
- 'CMakeLists.txt'
|
||||
branches:
|
||||
- kinara
|
||||
- master
|
||||
- 'release/*'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- kinara
|
||||
- master
|
||||
- 'release/*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -23,100 +23,79 @@ jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ECR_REGISTRY: 471112855615.dkr.ecr.us-east-1.amazonaws.com
|
||||
ECR_REPOSITORY: owgw
|
||||
AWS_REGION: us-east-1
|
||||
|
||||
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
DOCKER_REGISTRY_USERNAME: ucentral
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: build
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
persist-credentials: true
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Checkout dot github repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: kinarasystems/.github
|
||||
ref: main
|
||||
path: tools
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
- name: Build and push Docker image
|
||||
uses: ./github/composite-actions/docker-image-build
|
||||
with:
|
||||
image_name: owgw
|
||||
registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
registry_user: ucentral
|
||||
registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Bump version and checkin
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
id: bump-version
|
||||
run: |
|
||||
cd build
|
||||
../tools/utils/setup-git-credentials "${{ secrets.GIT_PUSH_PAT}}"
|
||||
../tools/utils/ver-bump -b -a -p -V kv -y helm/Chart.yaml -Y helm/values.yaml -M CMakeLists.txt
|
||||
- name: Notify on failure via Slack
|
||||
if: failure() && github.ref == 'refs/heads/master'
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_USERNAME: GitHub Actions failure notifier
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
SLACK_COLOR: "${{ job.status }}"
|
||||
SLACK_ICON: https://raw.githubusercontent.com/quintessence/slack-icons/master/images/github-logo-slack-icon.png
|
||||
SLACK_TITLE: Docker build failed for OWGW service
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
cd build
|
||||
version=$(cat version)
|
||||
../tools/utils/docker_build \
|
||||
-m kinara \
|
||||
-b "$GITHUB_REF" \
|
||||
-t "$IMAGE_TAG" \
|
||||
-r "$ECR_REGISTRY/$ECR_REPOSITORY" \
|
||||
-v "kv${version}"
|
||||
|
||||
- name: Notify via Teams
|
||||
#if: failure() && github.ref == 'refs/heads/kinara'
|
||||
if: always()
|
||||
uses: skitionek/notify-microsoft-teams@master
|
||||
with:
|
||||
webhook_url: ${{ secrets.MS_TEAMS_WEBHOOK }}
|
||||
needs: ${{ toJson(needs) }}
|
||||
job: ${{ toJson(job) }}
|
||||
steps: ${{ toJson(steps) }}
|
||||
dry_run: False
|
||||
|
||||
deploy-to-dev:
|
||||
trigger-testing:
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
env:
|
||||
DEPLOY_NAME: owgw
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_NAMESPACE: kic-dev1
|
||||
AWS_EKS_NAME: kinara-dev
|
||||
KUBECTL_VERSION: "v1.27.14"
|
||||
needs: docker
|
||||
steps:
|
||||
- name: Get base branch name and set as output
|
||||
id: get_base_branch
|
||||
run: |
|
||||
echo "branch=$(echo ${GITHUB_BASE_REF##*/} | sed 's/master/main/g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Trigger testing of OpenWifi Docker Compose deployment and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
env:
|
||||
BASE_BRANCH: ${{ steps.get_base_branch.outputs.branch }}
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ow_docker-compose.yml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"deployment_version": "${{ env.BASE_BRANCH }}", "owgw_version": "${{ github.sha }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "${{ env.BASE_BRANCH }}", "owanalytics_version": "${{ env.BASE_BRANCH }}", "owsub_version": "${{ env.BASE_BRANCH }}", "microservice": "owgw"}'
|
||||
|
||||
trigger-deploy-to-dev:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
needs:
|
||||
- docker
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_DEFAULT_REGION }}
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Fetch kubeconfig
|
||||
run: |
|
||||
aws eks update-kubeconfig --name ${{ env.AWS_EKS_NAME }} --region ${{ env.AWS_DEFAULT_REGION }}
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
curl -s -LO "https://dl.k8s.io/release/${{ env.KUBECTL_VERSION }}/bin/linux/amd64/kubectl"
|
||||
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Rolling update of deployment
|
||||
run: |
|
||||
kubectl rollout restart deployment/${{ env.DEPLOY_NAME }} -n ${{ env.AWS_NAMESPACE }}
|
||||
- name: Trigger deployment of the latest version to dev instance and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ucentralgw-dev-deployment.yaml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"force_latest": "true"}'
|
||||
|
||||
26
.github/workflows/cleanup.yml
vendored
Normal file
26
.github/workflows/cleanup.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Clean up PR Docker images
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types: [ closed ]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup Docker image with PR branch tag
|
||||
run: |
|
||||
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
|
||||
|
||||
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
|
||||
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
|
||||
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owgw/$PR_BRANCH_TAG"
|
||||
else
|
||||
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
|
||||
fi
|
||||
24
.github/workflows/enforce-jira-issue-key.yml
vendored
Normal file
24
.github/workflows/enforce-jira-issue-key.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Ensure Jira issue is linked
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
branches:
|
||||
- 'release/*'
|
||||
|
||||
jobs:
|
||||
check_for_issue_key:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Run JIRA check
|
||||
uses: ./github/composite-actions/enforce-jira-issue-key
|
||||
with:
|
||||
jira_base_url: ${{ secrets.TIP_JIRA_URL }}
|
||||
jira_user_email: ${{ secrets.TIP_JIRA_USER_EMAIL }}
|
||||
jira_api_token: ${{ secrets.TIP_JIRA_API_TOKEN }}
|
||||
41
.github/workflows/openapi-pages.yml
vendored
Normal file
41
.github/workflows/openapi-pages.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Update OpenAPI docs on GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'openapi/**'
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
docsgen:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Generate static HTML page with docs from OpenAPI definition
|
||||
run: |
|
||||
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v6.2.1 generate -i https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentralgw/master/openapi/owgw.yaml -g html2 --skip-validate-spec -o /local/
|
||||
|
||||
- name: Update OpenAPI docs
|
||||
run: |
|
||||
mkdir tmp-docs
|
||||
mv index.html tmp-docs/index.html
|
||||
mkdir -p ~/.ssh
|
||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||
echo https://tip-automation:${{ secrets.GIT_PUSH_PAT }}@github.com > ~/.git-credentials
|
||||
git config --global credential.helper store
|
||||
git config --global user.email "tip-automation@telecominfraproject.com"
|
||||
git config --global user.name "TIP Automation User"
|
||||
git pull
|
||||
git checkout gh-pages || git checkout -b gh-pages
|
||||
rm -rf docs
|
||||
mv tmp-docs docs
|
||||
git add docs
|
||||
git commit -m'Update OpenAPI docs for GitHub pages'
|
||||
git push --set-upstream origin gh-pages
|
||||
46
.github/workflows/release.yml
vendored
Normal file
46
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Release chart package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
helm-package:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
HELM_REPO_USERNAME: ucentral
|
||||
steps:
|
||||
- name: Checkout uCentral assembly chart repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: wlan-cloud-ucentralgw
|
||||
|
||||
- name: Build package
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
helm plugin install https://github.com/aslafy-z/helm-git --version 0.10.0
|
||||
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
helm repo update
|
||||
helm dependency update
|
||||
mkdir dist
|
||||
helm package . -d dist
|
||||
|
||||
- name: Generate GitHub release body
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
pip3 install yq -q
|
||||
echo "Docker image - tip-tip-wlan-cloud-ucentral.jfrog.io/owgw:$GITHUB_REF_NAME" > release.txt
|
||||
echo "Helm charted may be attached to this release" >> release.txt
|
||||
echo "Deployment artifacts may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/$GITHUB_REF_NAME" >> release.txt
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: wlan-cloud-ucentralgw/helm/release.txt
|
||||
files: wlan-cloud-ucentralgw/helm/dist/*
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,3 +29,4 @@ helm/charts/*
|
||||
!helm/charts/.gitkeep
|
||||
/portal-test/
|
||||
/src/ow_version.h
|
||||
.vscode/*
|
||||
|
||||
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,28 +0,0 @@
|
||||
## 3.0.9 (August 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.8 -> 3.0.9
|
||||
- Merge pull request #11 from kinarasystems/fixedconfig
|
||||
|
||||
## 3.0.8 (August 08, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.7 -> 3.0.8
|
||||
- Merge pull request #10 from kinarasystems/WIFI-13875-fix-use-dns
|
||||
|
||||
## 3.0.7 (August 07, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.6 -> 3.0.7
|
||||
- Merge branch 'Telecominfraproject:master' into kinara
|
||||
|
||||
## 3.0.6 (July 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.5 -> 3.0.6
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
|
||||
## 3.0.5 (July 22, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
- Merge pull request #8 from kinarasystems/command
|
||||
|
||||
## 3.0.4 (July 17, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.3 -> 3.0.4
|
||||
- Merge pull request #7 from kinarasystems/fix_uptime_update_after_reboot
|
||||
|
||||
## 3.0.3 (June 19, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, created CHANGELOG.md, bumped 3.0.2 -> 3.0.3
|
||||
- Merge pull request #6 from kinarasystems/devices
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owgw VERSION 3.0.9)
|
||||
project(owgw VERSION 4.2.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ARG DEBIAN_VERSION=11.5-slim
|
||||
ARG POCO_VERSION=poco-tip-v2
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG POCO_VERSION=poco-tip-v4-tag
|
||||
ARG CPPKAFKA_VERSION=tip-v1
|
||||
ARG VALIJASON_VERSION=tip-v1.0.2
|
||||
ARG APP_NAME=owgw
|
||||
@@ -100,7 +100,7 @@ RUN mkdir -p $APP_ROOT $APP_CONFIG && \
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
|
||||
libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt7 sqlite3
|
||||
libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt9 sqlite3
|
||||
|
||||
COPY readiness_check /readiness_check
|
||||
COPY test_scripts/curl/cli /cli
|
||||
|
||||
72
PROTOCOL.md
72
PROTOCOL.md
@@ -306,8 +306,54 @@ The device should answer:
|
||||
},
|
||||
"id" : <same number>
|
||||
}
|
||||
```
|
||||
|
||||
#### Controller wants the device to apply a given fixed configuration
|
||||
|
||||
Controller sends this command when it requires the device to apply fixed configuration, eg. country code. The device
|
||||
should respond with message indicating failure or success.
|
||||
|
||||
```json
|
||||
{ "jsonrpc" : "2.0",
|
||||
"method" : "fixedconfig",
|
||||
"params" : {
|
||||
"serial" : <serial number>,
|
||||
"when" : Optional - <UTC time when to apply this config, 0 means immediate, this is a suggestion>
|
||||
"country" : "<country-code>"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller
|
||||
will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed
|
||||
and encoded in base64 format:
|
||||
```json
|
||||
{ "jsonrpc" : "2.0",
|
||||
"method" : "configure",
|
||||
"params" : {
|
||||
"compress_64" : "<b64 encoded zlib compressed payload>",
|
||||
"compress_sz" : "<size of uncompressed data in bytes>"
|
||||
},
|
||||
"id" : <some number>
|
||||
}
|
||||
```
|
||||
|
||||
The device should answer:
|
||||
```json
|
||||
{ "jsonrpc" : "2.0",
|
||||
"result" : {
|
||||
"serial": <serial number>,
|
||||
"status": {
|
||||
"error": 0 or an error number,
|
||||
"text": <description of the error or success, eg. "Applied fixed config, rebooting">
|
||||
},
|
||||
"uuid": <UUID>
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
##### The Answer
|
||||
The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
|
||||
appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device
|
||||
@@ -834,6 +880,32 @@ The device should answer:
|
||||
}
|
||||
```
|
||||
|
||||
#### Controller wants the device to perform re-enrollment
|
||||
Controller sends this command to trigger re-enrollment, i.e. update of operational certificate. Extreme care must be taken.
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "reenroll" ,
|
||||
"params" : {
|
||||
"serial" : <serial number>,
|
||||
"when" : Optional - <UTC time when to apply this config, 0 mean immediate, this is a suggestion>
|
||||
},
|
||||
"id" : <some number>
|
||||
}
|
||||
```
|
||||
|
||||
The device should answer:
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"result" : {
|
||||
"serial" : <serial number> ,
|
||||
"status" : {
|
||||
"error" : <0 or the value of $? from the shell running the command, 255 signifies a timeout>,
|
||||
"txt" : <text describing the error or success>
|
||||
},
|
||||
"id" : <same number as request>
|
||||
}
|
||||
```
|
||||
|
||||
#### Controller wants the device to switch to another controller
|
||||
Controller sends this when the device should change the controller it connects to without looking up a new redirector.
|
||||
|
||||
|
||||
21
buildaws
21
buildaws
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
[ -z "$AWS_PROFILE" ] && echo "Please set AWS_PROFILE" && exit 1
|
||||
registry="471112855615.dkr.ecr.us-east-1.amazonaws.com"
|
||||
repo="owgw"
|
||||
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin "$registry"
|
||||
img="$registry/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
20
buildit
20
buildit
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
repo="owgw"
|
||||
[ -z "$REMOTE_DOCKER_HOST" ] && echo "Please set DOCKER_HOST" && exit 1
|
||||
[ -z "$REMOTE_DOCKER_PASSWORD" ] && echo "Please set DOCKER_PASSWORD" && exit 1
|
||||
img="$REMOTE_DOCKER_HOST/kinara/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
@@ -32,6 +32,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\${APP_ROOT}/uploads"} \
|
||||
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
|
||||
FILEUPLOADER_MAXSIZE=${FILEUPLOADER_MAXSIZE:-"10000"} \
|
||||
SERVICE_KEY=${SERVICE_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
|
||||
SYSTEM_DATA=${SYSTEM_DATA:-"\${APP_ROOT}/data"} \
|
||||
@@ -76,6 +77,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
|
||||
IPINFO_DEFAULT_COUNTRY=${IPINFO_DEFAULT_COUNTRY:-"US"} \
|
||||
DEVICE_SESSION_TIMEOUT=${DEVICE_SESSION_TIMEOUT:-"600"} \
|
||||
LOGGING_LEVEL=${LOGGING_LEVEL:-"information"} \
|
||||
envsubst < /"${APP_NAME}".properties.tmpl > "${APP_CONFIG}"/"${APP_NAME}".properties
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
apiVersion: v2
|
||||
appVersion: "3.0.9"
|
||||
appVersion: "1.0"
|
||||
description: A Helm chart for Kubernetes
|
||||
name: owgw
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
|
||||
@@ -2,21 +2,24 @@
|
||||
replicaCount: 1
|
||||
strategyType: Recreate
|
||||
revisionHistoryLimit: 2
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
images:
|
||||
owgw:
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/owgw
|
||||
tag: kv3.0.9
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
dockerize:
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/wait-ready
|
||||
tag: latest
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
|
||||
tag: 0.16.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
services:
|
||||
owgw:
|
||||
type: ClusterIP
|
||||
@@ -59,6 +62,7 @@ services:
|
||||
servicePort: 3799
|
||||
targetPort: 3799
|
||||
protocol: UDP
|
||||
|
||||
checks:
|
||||
owgw:
|
||||
liveness:
|
||||
@@ -69,31 +73,33 @@ checks:
|
||||
exec:
|
||||
command:
|
||||
- /readiness_check
|
||||
|
||||
ingresses:
|
||||
restapi:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- restapi.chart-example.local
|
||||
- restapi.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
fileuploader:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- fileuploader.chart-example.local
|
||||
- fileuploader.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
|
||||
volumes:
|
||||
owgw:
|
||||
- name: config
|
||||
@@ -119,17 +125,18 @@ volumes:
|
||||
volumeDefinition: |
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ template "owgw.fullname" . }}-pvc
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
@@ -144,12 +151,18 @@ securityContext:
|
||||
# value: "2"
|
||||
#- name: net.ipv4.tcp_keepalive_time
|
||||
# value: "45"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityPolicy:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# storageClassName: "-"
|
||||
@@ -157,6 +170,7 @@ persistence:
|
||||
- ReadWriteOnce
|
||||
size: 10Gi
|
||||
annotations: {}
|
||||
|
||||
# Application
|
||||
public_env_variables:
|
||||
OWGW_ROOT: /owgw-data
|
||||
@@ -166,10 +180,12 @@ public_env_variables:
|
||||
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
|
||||
#READINESS_METHOD: systeminfo
|
||||
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
|
||||
|
||||
secret_env_variables:
|
||||
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
|
||||
OWSEC_USERNAME: tip@ucentral.com
|
||||
OWSEC_PASSWORD: openwifi
|
||||
|
||||
configProperties:
|
||||
# -> Public part
|
||||
# Websocket
|
||||
@@ -294,6 +310,7 @@ configProperties:
|
||||
archiver.db.2.keep: 7
|
||||
archiver.db.3.name: commandlist
|
||||
archiver.db.3.keep: 7
|
||||
|
||||
# -> Secret part
|
||||
# Websocket
|
||||
ucentral.websocket.host.0.key.password: mypassword
|
||||
@@ -315,8 +332,10 @@ configProperties:
|
||||
## MySQL
|
||||
storage.type.mysql.username: stephb
|
||||
storage.type.mysql.password: snoopy99
|
||||
|
||||
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
|
||||
existingCertsSecret: ""
|
||||
|
||||
certs:
|
||||
clientcas.pem: ""
|
||||
issuer.pem: ""
|
||||
@@ -326,53 +345,66 @@ certs:
|
||||
root.pem: ""
|
||||
websocket-cert.pem: ""
|
||||
websocket-key.pem: ""
|
||||
|
||||
certsCAs:
|
||||
issuer.pem: ""
|
||||
root.pem: ""
|
||||
|
||||
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/postgresql
|
||||
tag: 11.13.0-debian-10-r0
|
||||
|
||||
postgresqlPostgresPassword: "rootPassword"
|
||||
postgresqlUsername: stephb
|
||||
postgresqlPassword: snoopy99
|
||||
postgresqlDatabase: owgw
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
|
||||
mysql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mysql
|
||||
tag: 8.0.26-debian-10-r10
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
|
||||
mariadb:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mariadb
|
||||
tag: 10.5.12-debian-10-r0
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
|
||||
@@ -12,7 +12,7 @@ info:
|
||||
url: https://www.ucentral.info/support
|
||||
|
||||
servers:
|
||||
- url: 'https://localhost:16001/api/v1'
|
||||
- url: 'https://localhost:16002/api/v1'
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@@ -1576,6 +1576,15 @@ components:
|
||||
format: base64
|
||||
description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
|
||||
|
||||
ReenrollRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
when:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
PowerCycleRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1600,6 +1609,74 @@ components:
|
||||
maximum: 60000
|
||||
description: off time in milliseconds
|
||||
|
||||
PackageGetResponse:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
package:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
uuid:
|
||||
type: number
|
||||
|
||||
|
||||
PackageInstallRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
|
||||
PackageInstallResponse:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: number
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
result:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
uuid:
|
||||
type: number
|
||||
|
||||
PackageRemoveRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
|
||||
paths:
|
||||
/devices:
|
||||
get:
|
||||
@@ -3056,6 +3133,32 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/reenroll:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Reenroll operational certificate for the device.
|
||||
operationId: reenrollCertificate
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Reenroll operational certificate for the device
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReenrollRequest'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/powercycle:
|
||||
post:
|
||||
tags:
|
||||
@@ -3084,6 +3187,98 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/package:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get package installed on the remote device.
|
||||
operationId: getDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
- in: query
|
||||
name: pkgName
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The name or identifier of the package to retrieve.
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageGetResponse'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Install IPK files to remote device.
|
||||
operationId: postDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Packages to be installed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallRequest'
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallResponse'
|
||||
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Remove install packages from remote device.
|
||||
operationId: deleteDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Packages to be removed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageRemoveRequest'
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallResponse'
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/ouis:
|
||||
get:
|
||||
tags:
|
||||
|
||||
@@ -52,7 +52,8 @@ openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
|
||||
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
|
||||
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
|
||||
openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
|
||||
openwifi.fileuploader.maxsize = 10000
|
||||
# maxsize in KB
|
||||
openwifi.fileuploader.maxsize = ${FILEUPLOADER_MAXSIZE}
|
||||
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
|
||||
|
||||
#
|
||||
@@ -182,4 +183,4 @@ archiver.db.3.keep = 7
|
||||
########################################################################
|
||||
logging.type = console
|
||||
logging.path = $OWGW_ROOT/logs
|
||||
logging.level = information
|
||||
logging.level = ${LOGGING_LEVEL}
|
||||
|
||||
15
package.json
15
package.json
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "owgw",
|
||||
"version": "3.0.9",
|
||||
"description": "This is the Kinara version of OpenWifi OWGW",
|
||||
"author": "Kinara Systems",
|
||||
"homepage": "https://kinarasystems.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kinarasystems/wlan-cloud-ucentralgw"
|
||||
},
|
||||
"keywords": [
|
||||
"owgw",
|
||||
"gateway"
|
||||
]
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/HTTPServerRequestImpl.h>
|
||||
#include <Poco/Net/HTTPServerResponseImpl.h>
|
||||
#include <Poco/JSON/JSONException.h>
|
||||
#include <Poco/Net/NetException.h>
|
||||
#include <Poco/Net/SSLException.h>
|
||||
#include <Poco/Net/SecureStreamSocketImpl.h>
|
||||
@@ -39,7 +40,7 @@ namespace OpenWifi {
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
uint64_t session_id, Poco::Logger &L,
|
||||
std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
|
||||
: Logger_(L) {
|
||||
: Logger_(L), IncomingFrame_(0) {
|
||||
|
||||
Reactor_ = R.first;
|
||||
DbSession_ = R.second;
|
||||
@@ -54,6 +55,7 @@ namespace OpenWifi {
|
||||
WS_->setNoDelay(false);
|
||||
WS_->setKeepAlive(true);
|
||||
WS_->setBlocking(false);
|
||||
IncomingFrame_.resize(0);
|
||||
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
|
||||
|
||||
AP_WS_Server()->IncrementConnectionCount();
|
||||
@@ -213,6 +215,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
|
||||
State_.certificateIssuerName = PeerCert.issuerName();
|
||||
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
|
||||
@@ -599,36 +602,95 @@ namespace OpenWifi {
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::ProcessIncomingFrame() {
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
void AP_WS_Connection::ProcessWSFinalPayload() {
|
||||
auto IncomingSize = IncomingFrame_.size();
|
||||
|
||||
if (IncomingSize == 0) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("ProcessWSFrame({}): Final Acc. Frame received but empty",
|
||||
CId_));
|
||||
return;
|
||||
}
|
||||
IncomingFrame_.append(0);
|
||||
|
||||
poco_trace(Logger_,
|
||||
fmt::format("ProcessWSFrame({}): Final Acc. Frame received (len={}, Msg={}",
|
||||
CId_, IncomingSize, IncomingFrame_.begin()));
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
auto ParsedMessage = parser.parse(IncomingFrame_.begin());
|
||||
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
|
||||
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
|
||||
IncomingJSON->has(uCentralProtocol::PARAMS)) {
|
||||
ProcessJSONRPCEvent(IncomingJSON);
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
|
||||
IncomingJSON->has(uCentralProtocol::ID)) {
|
||||
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
|
||||
IncomingFrame_.begin()));
|
||||
ProcessJSONRPCResult(IncomingJSON);
|
||||
} else {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
|
||||
CId_, IncomingFrame_.begin()));
|
||||
}
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
|
||||
ProcessIncomingRadiusData(IncomingJSON);
|
||||
} else {
|
||||
std::ostringstream iS;
|
||||
IncomingJSON->stringify(iS);
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
|
||||
CId_, iS.str()));
|
||||
Errors_++;
|
||||
}
|
||||
IncomingFrame_.clear();
|
||||
IncomingFrame_.resize(0);
|
||||
}
|
||||
|
||||
void AP_WS_Connection::ProcessIncomingFrame() {
|
||||
Poco::Buffer<char> CurrentFrame(0);
|
||||
bool KillConnection = false;
|
||||
int flags = 0;
|
||||
int IncomingSize = 0;
|
||||
|
||||
bool KillConnection=false;
|
||||
try {
|
||||
int Op, flags;
|
||||
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
|
||||
IncomingSize = WS_->receiveFrame(CurrentFrame, flags);
|
||||
int Op;
|
||||
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
if (IncomingSize < 0 && flags == 0) {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("EMPTY({}): Non-blocking try-again empty frame (len={}, flags={})",
|
||||
CId_, IncomingSize, flags));
|
||||
} else if (IncomingSize == 0 && flags == 0) {
|
||||
poco_information(Logger_,
|
||||
fmt::format("DISCONNECT({}): device has disconnected. Session={}",
|
||||
CId_, State_.sessionId));
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
IncomingFrame.append(0);
|
||||
|
||||
State_.RX += IncomingSize;
|
||||
AP_WS_Server()->AddRX(IncomingSize);
|
||||
if (IncomingSize > 0) {
|
||||
State_.RX += IncomingSize;
|
||||
AP_WS_Server()->AddRX(IncomingSize);
|
||||
IncomingFrame_.append(CurrentFrame);
|
||||
}
|
||||
State_.MessageCount++;
|
||||
State_.LastContact = Utils::Now();
|
||||
poco_trace(Logger_,
|
||||
fmt::format("FRAME({}): Frame rx (op={} len={}, flags={}, acc.len={})",
|
||||
CId_, Op, IncomingSize, flags, IncomingFrame_.size()));
|
||||
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
|
||||
poco_trace(Logger_, fmt::format("PING({}): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Object PingObject;
|
||||
@@ -642,49 +704,32 @@ namespace OpenWifi {
|
||||
PingDetails.set("locale", State_.locale);
|
||||
PingObject.set(uCentralProtocol::PING, PingDetails);
|
||||
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,
|
||||
PingObject);
|
||||
}
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
poco_trace(Logger_, fmt::format("CONTINUATION({}): registered.", CId_));
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
poco_trace(Logger_, fmt::format("BINARY({}): Invalid frame type.", CId_));
|
||||
KillConnection=true;
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
|
||||
CId_, IncomingSize, flags, IncomingFrame.begin()));
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
auto ParsedMessage = parser.parse(IncomingFrame.begin());
|
||||
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
|
||||
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
|
||||
IncomingJSON->has(uCentralProtocol::PARAMS)) {
|
||||
ProcessJSONRPCEvent(IncomingJSON);
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
|
||||
IncomingJSON->has(uCentralProtocol::ID)) {
|
||||
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
|
||||
IncomingFrame.begin()));
|
||||
ProcessJSONRPCResult(IncomingJSON);
|
||||
} else {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
|
||||
CId_, IncomingFrame.begin()));
|
||||
}
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
|
||||
ProcessIncomingRadiusData(IncomingJSON);
|
||||
} else {
|
||||
std::ostringstream iS;
|
||||
IncomingJSON->stringify(iS);
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
|
||||
CId_, iS.str()));
|
||||
Errors_++;
|
||||
}
|
||||
fmt::format("TEXT({}): Frame received (len={}, flags={}). Msg={}",
|
||||
CId_, IncomingSize, flags,
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin()));
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
@@ -700,25 +745,31 @@ namespace OpenWifi {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for final frame and process accumulated payload
|
||||
if (!KillConnection && (flags & Poco::Net::WebSocket::FRAME_FLAG_FIN) != 0) {
|
||||
ProcessWSFinalPayload();
|
||||
}
|
||||
|
||||
} catch (const Poco::Net::ConnectionResetException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("ConnectionResetException({}): Text:{} Payload:{} Session:{}",
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::JSON::JSONException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::WebSocketException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
|
||||
@@ -727,42 +778,42 @@ namespace OpenWifi {
|
||||
fmt::format(
|
||||
"SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}",
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::SSLException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::IOException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (const std::exception &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.what(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
KillConnection=true;
|
||||
} catch (...) {
|
||||
@@ -775,7 +826,9 @@ namespace OpenWifi {
|
||||
if (!KillConnection && Errors_ < 10)
|
||||
return;
|
||||
|
||||
poco_warning(Logger_, fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}", CId_, KillConnection, Errors_ ));
|
||||
poco_warning(Logger_,
|
||||
fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}",
|
||||
CId_, KillConnection, Errors_ ));
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
@@ -920,4 +973,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
class AP_WS_Connection {
|
||||
static constexpr int BufSize = 256000;
|
||||
static constexpr int BufSize = 512000;
|
||||
|
||||
public:
|
||||
explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
|
||||
@@ -33,6 +33,7 @@ namespace OpenWifi {
|
||||
void EndConnection();
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
|
||||
void ProcessWSFinalPayload();
|
||||
void ProcessIncomingFrame();
|
||||
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
|
||||
|
||||
@@ -145,6 +146,7 @@ namespace OpenWifi {
|
||||
std::uint64_t uuid_=0;
|
||||
bool Simulated_=false;
|
||||
std::atomic_uint64_t LastContact_=0;
|
||||
Poco::Buffer<char> IncomingFrame_;
|
||||
|
||||
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
|
||||
|
||||
@@ -175,4 +177,4 @@ namespace OpenWifi {
|
||||
|
||||
};
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace OpenWifi {
|
||||
Restrictions_.developer = Capabilities->getValue<bool>("developer");
|
||||
}
|
||||
|
||||
if(Capabilities->has("secure-rtty")) {
|
||||
if (Capabilities->has("secure-rtty")) {
|
||||
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
|
||||
}
|
||||
|
||||
|
||||
@@ -71,14 +71,18 @@ namespace OpenWifi {
|
||||
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
|
||||
const Poco::Crypto::X509Certificate &Certificate) {
|
||||
if (IsCertOk()) {
|
||||
if (!Certificate.issuedBy(*IssuerCert_)) {
|
||||
poco_warning(
|
||||
Logger(),
|
||||
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
|
||||
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
||||
return false;
|
||||
// validate certificate agains trusted chain
|
||||
for (const auto &cert : ClientCasCerts_) {
|
||||
if (Certificate.issuedBy(cert)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
poco_warning(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
|
||||
ConnectionId)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -116,7 +120,6 @@ namespace OpenWifi {
|
||||
P.verificationDepth = 9;
|
||||
P.loadDefaultCAs = Svr.RootCA().empty();
|
||||
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
||||
P.dhUse2048Bits = true;
|
||||
P.caLocation = Svr.Cas();
|
||||
|
||||
auto Context = Poco::AutoPtr<Poco::Net::Context>(
|
||||
@@ -133,6 +136,13 @@ namespace OpenWifi {
|
||||
Context->addChainCertificate(Issuing);
|
||||
Context->addCertificateAuthority(Issuing);
|
||||
|
||||
// add certificates from clientcas to trust chain
|
||||
ClientCasCerts_ = Poco::Net::X509Certificate::readPEM(Svr.ClientCas());
|
||||
for (const auto &cert : ClientCasCerts_) {
|
||||
Context->addChainCertificate(cert);
|
||||
Context->addCertificateAuthority(cert);
|
||||
}
|
||||
|
||||
Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
|
||||
Context->usePrivateKey(Key);
|
||||
|
||||
@@ -784,4 +794,4 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -223,6 +223,7 @@ namespace OpenWifi {
|
||||
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
|
||||
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
|
||||
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
||||
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace OpenWifi {
|
||||
i >> cache;
|
||||
|
||||
for (const auto &[Type, Platform] : cache.items()) {
|
||||
Platforms_[Type] = Poco::toLower(to_string(Platform));
|
||||
Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@@ -315,4 +315,4 @@ namespace OpenWifi {
|
||||
poco_notice(Logger(), "Stopped...");
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -54,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
|
||||
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
|
||||
|
||||
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
|
||||
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
|
||||
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
|
||||
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
|
||||
Cmd.Submitted = Utils::Now();
|
||||
Cmd.Executed = 0;
|
||||
|
||||
|
||||
@@ -91,6 +91,31 @@ namespace OpenWifi {
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return Rtty(UUID, RPC, 60000ms, Restrictions);
|
||||
};
|
||||
case APCommands::Commands::package:{
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
std::string pkg_name = "";
|
||||
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
Poco::URI uri(Request->getURI());
|
||||
for (const auto ¶m : uri.getQueryParameters()) {
|
||||
if (param.first == "pkgName") {
|
||||
pkg_name = param.second;
|
||||
}
|
||||
}
|
||||
if (pkg_name.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Command Package TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return GetPackages(UUID, RPC, pkg_name, 300000ms, Restrictions);
|
||||
}
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
@@ -128,6 +153,21 @@ namespace OpenWifi {
|
||||
return DeleteChecks();
|
||||
case APCommands::Commands::statistics:
|
||||
return DeleteStatistics();
|
||||
case APCommands::Commands::package: {
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return DeletePackages(UUID, RPC, 300000ms, Restrictions);
|
||||
}
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
@@ -169,7 +209,9 @@ namespace OpenWifi {
|
||||
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms},
|
||||
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
|
||||
{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
|
||||
|
||||
{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
|
||||
{APCommands::Commands::reenroll, false, true, &RESTAPI_device_commandHandler::ReEnroll, 120000ms},
|
||||
{APCommands::Commands::package, false, true, &RESTAPI_device_commandHandler::PackageInstall, 120000ms},
|
||||
};
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
@@ -407,6 +449,210 @@ namespace OpenWifi {
|
||||
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::GetPackages(const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
const std::string pkg_name,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
poco_debug(Logger_, fmt::format("GET-PACKAGES: TID={}, user={} serial={}. thr_id={}",
|
||||
TransactionId_, Requester(), SerialNumber_,
|
||||
Poco::Thread::current()->id()));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "list");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGE, pkg_name);
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::PackageInstall(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
|
||||
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
|
||||
CallCanceled("INSTALLPACKAGE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("INSTALL-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
|
||||
poco_information(Logger_, fmt::format("INSTALL_OBJECT: {} for device {}", os.str(), SerialNumber_));
|
||||
|
||||
GWObjects::PackageInstall PI;
|
||||
if (!PI.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
|
||||
for (const auto &i : PI.pkgs) {
|
||||
Poco::JSON::Object::Ptr Obj =
|
||||
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
|
||||
i.to_json(*Obj);
|
||||
ArrayObj->add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "install");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
|
||||
|
||||
std::ostringstream os2;
|
||||
Params.stringify(os2);
|
||||
|
||||
poco_information(Logger_, fmt::format("INSTALL_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
|
||||
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::DeletePackages(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
|
||||
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
|
||||
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("DELETE-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
|
||||
poco_information(Logger_, fmt::format("DELETE_OBJECT: {} for device {}", os.str(), SerialNumber_));
|
||||
|
||||
GWObjects::PackageRemove PR;
|
||||
if (!PR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
|
||||
for (const auto &i : PR.pkgs) {
|
||||
Poco::JSON::Object::Ptr Obj =
|
||||
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
|
||||
i.to_json(*Obj);
|
||||
ArrayObj->add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "delete");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
|
||||
|
||||
std::ostringstream os2;
|
||||
Params.stringify(os2);
|
||||
|
||||
poco_information(Logger_, fmt::format("DELETE_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
|
||||
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Ping(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
@@ -693,9 +939,31 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
// retrieve capabilities and encode/compress parameters, if required
|
||||
Poco::JSON::Object ConfigParams = Params;
|
||||
GWObjects::Capabilities Caps;
|
||||
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
|
||||
Poco::JSON::Object CapsJson;
|
||||
Caps.to_json(CapsJson);
|
||||
auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES);
|
||||
if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) {
|
||||
// compressed command capability present and it is set, compress parameters
|
||||
Poco::JSON::Object CompressedParams;
|
||||
std::string CompressedBase64Data;
|
||||
std::uint64_t UncompressedDataLen = ParamStream.str().length();
|
||||
if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) {
|
||||
// set compressed, base 64 encoded data and length of uncompressed data
|
||||
CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data);
|
||||
CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen);
|
||||
ConfigParams = CompressedParams;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
|
||||
Cmd, Params, *Request, *Response, timeout,
|
||||
Cmd, ConfigParams, *Request, *Response, timeout,
|
||||
nullptr, this, Logger_);
|
||||
|
||||
if(!Cmd.Executed) {
|
||||
@@ -1550,21 +1818,26 @@ namespace OpenWifi {
|
||||
Logger_);
|
||||
}
|
||||
|
||||
// `fixedconfig` command is used set country propery on AP
|
||||
// This handler uses `fixedconfig` command definitions
|
||||
void RESTAPI_device_commandHandler::FixedConfig(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
poco_debug(Logger_, fmt::format("FIXEDCONFIG({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC,
|
||||
TransactionId_, Requester(), SerialNumber_));
|
||||
// do not allow `fixedconfig` command for simulated devices
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
// setup and validate fixedconfig object
|
||||
GWObjects::FixedConfig fixed_config;
|
||||
if(!fixed_config.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
// setup command message
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
@@ -1577,8 +1850,91 @@ namespace OpenWifi {
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
|
||||
// send fixedconfig command to device and return status
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::fixedconfig, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::CableDiagnostics(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
|
||||
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
|
||||
CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("CABLEDIAGNOSTICS({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
GWObjects::CableDiagnostics PR;
|
||||
if(!PR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.Command = uCentralProtocol::CABLEDIAGNOSTICS;
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
Cmd.Details = os.str();
|
||||
Cmd.RunAt = PR.when;
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::cablediagnostics, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::ReEnroll(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
|
||||
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
|
||||
CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("REENROLL({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
GWObjects::ReEnroll PR;
|
||||
if(!PR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.Command = uCentralProtocol::REENROLL;
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
Cmd.Details = os.str();
|
||||
Cmd.RunAt = PR.when;
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::reenroll, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -33,6 +33,13 @@ namespace OpenWifi {
|
||||
void GetStatus();
|
||||
void GetChecks();
|
||||
void DeleteChecks();
|
||||
void GetPackages(const std::string &UUID, uint64_t RPC,
|
||||
std::string pkg_name,
|
||||
std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void DeletePackages(const std::string &UUID, uint64_t RPC,
|
||||
std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
|
||||
bool IsDeviceSimulated(std::string &Serial);
|
||||
|
||||
@@ -72,6 +79,12 @@ namespace OpenWifi {
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void FixedConfig(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void ReEnroll(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void PackageInstall(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
|
||||
static auto PathName() {
|
||||
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace OpenWifi {
|
||||
|
||||
} else if (QB_.CountOnly) {
|
||||
uint64_t Count = 0;
|
||||
if (StorageService()->GetDeviceCount(Count, platform, includeProvisioned)) {
|
||||
if (StorageService()->GetDeviceCount(Count, platform)) {
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
} else if (serialOnly) {
|
||||
|
||||
@@ -22,9 +22,15 @@ namespace OpenWifi {
|
||||
|
||||
std::string FileType;
|
||||
std::string FileContent;
|
||||
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType) || FileContent.empty()) {
|
||||
int WaitingForFile = 0;
|
||||
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType, WaitingForFile) && !WaitingForFile) {
|
||||
return NotFound();
|
||||
}
|
||||
else if (WaitingForFile) {
|
||||
// waiting for file to be uploaded, return Accepted
|
||||
return Accepted();
|
||||
}
|
||||
|
||||
if (FileType == "pcap") {
|
||||
SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoDelete() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_DELETE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -40,8 +40,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPost() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_CREATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -86,8 +86,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPut() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_UPDATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#include "Daemon.h"
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StorageService.h"
|
||||
#include "CapabilitiesCache.h"
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#include "StorageService.h"
|
||||
#endif
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
@@ -31,7 +31,8 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "serialNumber", SerialNumber);
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
|
||||
field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
|
||||
field_to_json(Obj, "blackListed",
|
||||
StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
|
||||
#endif
|
||||
field_to_json(Obj, "macAddress", MACAddress);
|
||||
field_to_json(Obj, "manufacturer", Manufacturer);
|
||||
@@ -70,12 +71,12 @@ namespace OpenWifi::GWObjects {
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
ConnectionState ConState;
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
auto Res = GS()->GetState(SerialNumber);
|
||||
if (Res.has_value()) {
|
||||
Res.value().to_json(SerialNumber,Obj);
|
||||
auto Res = GS()->GetState(SerialNumber);
|
||||
if (Res.has_value()) {
|
||||
Res.value().to_json(SerialNumber, Obj);
|
||||
#else
|
||||
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
|
||||
ConState.to_json(SerialNumber,Obj);
|
||||
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
|
||||
ConState.to_json(SerialNumber, Obj);
|
||||
#endif
|
||||
} else {
|
||||
field_to_json(Obj, "ipAddress", "");
|
||||
@@ -172,17 +173,16 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "recorded", Recorded);
|
||||
}
|
||||
|
||||
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "sanity", Sanity);
|
||||
field_from_json(Obj, "recorded", Recorded);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "sanity", Sanity);
|
||||
field_from_json(Obj, "recorded", Recorded);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
@@ -275,7 +275,8 @@ namespace OpenWifi::GWObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) {
|
||||
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber,
|
||||
Poco::JSON::Object &Obj) {
|
||||
field_to_json(Obj, "ipAddress", Address);
|
||||
field_to_json(Obj, "txBytes", TX);
|
||||
field_to_json(Obj, "rxBytes", RX);
|
||||
@@ -295,16 +296,17 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "started", started);
|
||||
field_to_json(Obj, "sessionId", sessionId);
|
||||
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_to_json(Obj, "totalConnectionTime", started ? Utils::Now() - started : 0);
|
||||
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
|
||||
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_to_json(Obj, "certificateIssuerName", certificateIssuerName);
|
||||
field_to_json(Obj, "connectReason", connectReason);
|
||||
field_to_json(Obj, "uptime", uptime);
|
||||
field_to_json(Obj, "compatible", Compatible);
|
||||
field_to_json(Obj, "compatible", Compatible);
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
|
||||
#endif
|
||||
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
|
||||
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
|
||||
field_to_json(Obj, "hasGPS", hasGPS);
|
||||
field_to_json(Obj, "sanity", sanity);
|
||||
field_to_json(Obj, "memoryUsed", memoryUsed);
|
||||
@@ -334,44 +336,45 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "compatible", Compatible);
|
||||
field_from_json(Obj, "ipAddress", Address);
|
||||
field_from_json(Obj, "txBytes", TX);
|
||||
field_from_json(Obj, "rxBytes", RX);
|
||||
field_from_json(Obj, "messageCount", MessageCount);
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "connected", Connected);
|
||||
field_from_json(Obj, "firmware", Firmware);
|
||||
field_from_json(Obj, "lastContact", LastContact);
|
||||
field_from_json(Obj, "associations_2G", Associations_2G);
|
||||
field_from_json(Obj, "associations_5G", Associations_5G);
|
||||
field_from_json(Obj, "associations_6G", Associations_6G);
|
||||
field_from_json(Obj, "webSocketClients", webSocketClients);
|
||||
field_from_json(Obj, "websocketPackets", websocketPackets);
|
||||
field_from_json(Obj, "kafkaClients", kafkaClients);
|
||||
field_from_json(Obj, "kafkaPackets", kafkaPackets);
|
||||
field_from_json(Obj, "locale", locale);
|
||||
field_from_json(Obj, "started", started);
|
||||
field_from_json(Obj, "sessionId", sessionId);
|
||||
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
|
||||
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_from_json(Obj, "connectReason", connectReason);
|
||||
field_from_json(Obj, "uptime", uptime);
|
||||
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
|
||||
field_from_json(Obj, "hasGPS", hasGPS);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "memoryUsed", memoryUsed);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "load", load);
|
||||
field_from_json(Obj, "temperature", temperature);
|
||||
return true;
|
||||
} catch(const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "compatible", Compatible);
|
||||
field_from_json(Obj, "ipAddress", Address);
|
||||
field_from_json(Obj, "txBytes", TX);
|
||||
field_from_json(Obj, "rxBytes", RX);
|
||||
field_from_json(Obj, "messageCount", MessageCount);
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "connected", Connected);
|
||||
field_from_json(Obj, "firmware", Firmware);
|
||||
field_from_json(Obj, "lastContact", LastContact);
|
||||
field_from_json(Obj, "associations_2G", Associations_2G);
|
||||
field_from_json(Obj, "associations_5G", Associations_5G);
|
||||
field_from_json(Obj, "associations_6G", Associations_6G);
|
||||
field_from_json(Obj, "webSocketClients", webSocketClients);
|
||||
field_from_json(Obj, "websocketPackets", websocketPackets);
|
||||
field_from_json(Obj, "kafkaClients", kafkaClients);
|
||||
field_from_json(Obj, "kafkaPackets", kafkaPackets);
|
||||
field_from_json(Obj, "locale", locale);
|
||||
field_from_json(Obj, "started", started);
|
||||
field_from_json(Obj, "sessionId", sessionId);
|
||||
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
|
||||
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_from_json(Obj, "certificateIssuerName", certificateIssuerName);
|
||||
field_from_json(Obj, "connectReason", connectReason);
|
||||
field_from_json(Obj, "uptime", uptime);
|
||||
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
|
||||
field_from_json(Obj, "hasGPS", hasGPS);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "memoryUsed", memoryUsed);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "load", load);
|
||||
field_from_json(Obj, "temperature", temperature);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
|
||||
@@ -808,4 +811,114 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CableDiagnostics::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "when", when);
|
||||
field_from_json(Obj, "ports", ports);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReEnroll::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "when", when);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PackageInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "version", version);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PackageInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "name", name);
|
||||
field_to_json(Obj, "version", version);
|
||||
}
|
||||
|
||||
void PackageList::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("serialNumber", serialNumber);
|
||||
|
||||
Poco::JSON::Array packageJsonArray;
|
||||
for (const auto &pkg : packageArray) {
|
||||
Poco::JSON::Object pkgObj;
|
||||
pkg.to_json(pkgObj);
|
||||
packageJsonArray.add(pkgObj);
|
||||
}
|
||||
Obj.set("packageArray", packageJsonArray);
|
||||
|
||||
Obj.set("FirstUpdate", Poco::UInt64(FirstUpdate));
|
||||
Obj.set("LastUpdate", Poco::UInt64(LastUpdate));
|
||||
}
|
||||
|
||||
bool ToBeInstalled::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "url", url);
|
||||
|
||||
Poco::URI uri(url);
|
||||
std::string scheme = uri.getScheme();
|
||||
if (scheme != "http" && scheme != "https") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToBeInstalled::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("name", name);
|
||||
Obj.set("url", url);
|
||||
}
|
||||
|
||||
bool PackageInstall::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "when", when);
|
||||
field_from_json(Obj, "packages", pkgs);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToBeRemoved::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToBeRemoved::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("name", name);
|
||||
}
|
||||
|
||||
bool PackageRemove::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "packages", pkgs);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace OpenWifi::GWObjects {
|
||||
uint64_t sessionId = 0;
|
||||
double connectionCompletionTime = 0.0;
|
||||
std::uint64_t certificateExpiryDate = 0;
|
||||
std::string certificateIssuerName;
|
||||
std::uint64_t hasRADIUSSessions = 0;
|
||||
bool hasGPS = false;
|
||||
std::uint64_t sanity=0;
|
||||
@@ -538,6 +539,64 @@ namespace OpenWifi::GWObjects {
|
||||
std::string serialNumber;
|
||||
std::string country;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct CableDiagnostics {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<std::string> ports;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct ReEnroll {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct PackageInfo {
|
||||
std::string name;
|
||||
std::string version;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageList {
|
||||
std::string serialNumber;
|
||||
std::vector<PackageInfo> packageArray;
|
||||
uint64_t FirstUpdate = 0;
|
||||
uint64_t LastUpdate = 0;
|
||||
std::string packageStringArray;
|
||||
|
||||
bool from_json(const Poco::JSON::Array::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct ToBeInstalled {
|
||||
std::string name;
|
||||
std::string url;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageInstall {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<ToBeInstalled> pkgs;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct ToBeRemoved {
|
||||
std::string name;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageRemove {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<ToBeRemoved> pkgs;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "framework/RESTAPI_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
|
||||
@@ -284,7 +282,6 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_to_json(Obj, "modified", modified);
|
||||
field_to_json(Obj, "signingUp", signingUp);
|
||||
Obj.set("userPermissions", permissions_to_json(userPermissions));
|
||||
};
|
||||
|
||||
bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -321,7 +318,6 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_from_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_from_json(Obj, "modified", modified);
|
||||
field_from_json(Obj, "signingUp", signingUp);
|
||||
userPermissions = permissions_from_json(Obj->getObject("userPermissions"));
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
std::cout << "Cannot parse: UserInfo" << std::endl;
|
||||
@@ -741,218 +737,4 @@ namespace OpenWifi::SecurityObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "create"))
|
||||
return PT_CREATE;
|
||||
else if (!Poco::icompare(U, "update"))
|
||||
return PT_UPDATE;
|
||||
else if (!Poco::icompare(U, "delete"))
|
||||
return PT_DELETE;
|
||||
else if (!Poco::icompare(U, "readonly"))
|
||||
return PT_READ_ONLY;
|
||||
return PT_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermTypeToString(PERMISSION_TYPE U) {
|
||||
switch (U) {
|
||||
case PT_CREATE:
|
||||
return "create";
|
||||
case PT_UPDATE:
|
||||
return "update";
|
||||
case PT_DELETE:
|
||||
return "delete";
|
||||
case PT_READ_ONLY:
|
||||
return "readonly";
|
||||
case PT_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "permissions"))
|
||||
return PM_PERMISSIONS;
|
||||
else if (!Poco::icompare(U, "venues"))
|
||||
return PM_VENUES_PROV;
|
||||
else if (!Poco::icompare(U, "venues_list"))
|
||||
return PM_VENUES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "entities"))
|
||||
return PM_ENTITIES_PROV;
|
||||
else if (!Poco::icompare(U, "entities_list"))
|
||||
return PM_ENTITIES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "inventory"))
|
||||
return PM_INVENTORY_PROV;
|
||||
else if (!Poco::icompare(U, "inventory_list"))
|
||||
return PM_INVENTORY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy"))
|
||||
return PM_MANAGEMENTPOLICY_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy_list"))
|
||||
return PM_MANAGEMENTPOLICY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole"))
|
||||
return PM_MANAGEMENTROLE_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole_list"))
|
||||
return PM_MANAGEMENTROLE_LIST_PROV;
|
||||
//GW
|
||||
else if (!Poco::icompare(U, "scripts"))
|
||||
return PM_SCRIPTS_GW;
|
||||
else if (!Poco::icompare(U, "configure"))
|
||||
return PM_DEVICE_CONFIGURE_GW;
|
||||
else if (!Poco::icompare(U, "upgrade"))
|
||||
return PM_DEVICE_UPGRADE_GW;
|
||||
else if (!Poco::icompare(U, "factoryreset"))
|
||||
return PM_DEVICE_FACTORY_GW;
|
||||
else if (!Poco::icompare(U, "leds"))
|
||||
return PM_DEVICE_LEDS_GW;
|
||||
else if (!Poco::icompare(U, "trace"))
|
||||
return PM_DEVICE_TRACE_GW;
|
||||
else if (!Poco::icompare(U, "request"))
|
||||
return PM_DEVICE_REQUEST_GW;
|
||||
else if (!Poco::icompare(U, "wifiscan"))
|
||||
return PM_DEVICE_WIFISCAN_GW;
|
||||
else if (!Poco::icompare(U, "eventqueue"))
|
||||
return PM_DEVICE_EVENTQUEUE_GW;
|
||||
else if (!Poco::icompare(U, "telemetry"))
|
||||
return PM_DEVICE_TELEMETRY_GW;
|
||||
else if (!Poco::icompare(U, "ping"))
|
||||
return PM_DEVICE_PING_GW;
|
||||
else if (!Poco::icompare(U, "ap_script"))
|
||||
return PM_DEVICE_SCRIPT_GW;
|
||||
else if (!Poco::icompare(U, "rrm"))
|
||||
return PM_DEVICE_RRM_GW;
|
||||
else if (!Poco::icompare(U, "transfer"))
|
||||
return PM_DEVICE_TRANSFER_GW;
|
||||
else if (!Poco::icompare(U, "certupdate"))
|
||||
return PM_DEVICE_CERTUPDATE_GW;
|
||||
else if (!Poco::icompare(U, "powercycle"))
|
||||
return PM_DEVICE_POWERCYCLE_GW;
|
||||
else if (!Poco::icompare(U, "ap_logs"))
|
||||
return PM_DEVICE_LOGS_GW;
|
||||
else if (!Poco::icompare(U, "healthchecks"))
|
||||
return PM_DEVICE_HEALTHCHECKS_GW;
|
||||
else if (!Poco::icompare(U, "ap_capabilities"))
|
||||
return PM_DEVICE_CAPABILITIES_GW;
|
||||
else if (!Poco::icompare(U, "ap_statistics"))
|
||||
return PM_DEVICE_STATISTICS_GW;
|
||||
else if (!Poco::icompare(U, "ap_status"))
|
||||
return PM_DEVICE_STATUS_GW;
|
||||
else if (!Poco::icompare(U, "ap_rtty"))
|
||||
return PM_DEVICE_RTTY_GW;
|
||||
|
||||
return PM_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermModelToString(PERMISSION_MODEL U) {
|
||||
switch (U) {
|
||||
case PM_PERMISSIONS:
|
||||
return "permissions";
|
||||
case PM_VENUES_PROV:
|
||||
return "venues";
|
||||
case PM_VENUES_LIST_PROV:
|
||||
return "venues_list";
|
||||
case PM_ENTITIES_PROV:
|
||||
return "entities";
|
||||
case PM_ENTITIES_LIST_PROV:
|
||||
return "entities_list";
|
||||
case PM_INVENTORY_PROV:
|
||||
return "inventory";
|
||||
case PM_INVENTORY_LIST_PROV:
|
||||
return "inventory_list";
|
||||
case PM_MANAGEMENTPOLICY_PROV:
|
||||
return "managementpolicy";
|
||||
case PM_MANAGEMENTPOLICY_LIST_PROV:
|
||||
return "managementpolicy_list";
|
||||
case PM_MANAGEMENTROLE_PROV:
|
||||
return "managementrole";
|
||||
case PM_MANAGEMENTROLE_LIST_PROV:
|
||||
return "managementrole_list";
|
||||
|
||||
//Gateway
|
||||
case PM_SCRIPTS_GW:
|
||||
return "scripts";
|
||||
case PM_DEVICE_CONFIGURE_GW:
|
||||
return "configure";
|
||||
case PM_DEVICE_UPGRADE_GW:
|
||||
return "upgrade";
|
||||
case PM_DEVICE_FACTORY_GW:
|
||||
return "factoryreset";
|
||||
case PM_DEVICE_LEDS_GW:
|
||||
return "leds";
|
||||
case PM_DEVICE_TRACE_GW:
|
||||
return "trace";
|
||||
case PM_DEVICE_REQUEST_GW:
|
||||
return "request";
|
||||
case PM_DEVICE_WIFISCAN_GW:
|
||||
return "wifiscan";
|
||||
case PM_DEVICE_EVENTQUEUE_GW:
|
||||
return "eventqueue";
|
||||
case PM_DEVICE_TELEMETRY_GW:
|
||||
return "telemetry";
|
||||
case PM_DEVICE_PING_GW:
|
||||
return "ping";
|
||||
case PM_DEVICE_SCRIPT_GW:
|
||||
return "ap_script";
|
||||
case PM_DEVICE_RRM_GW:
|
||||
return "rrm";
|
||||
case PM_DEVICE_TRANSFER_GW:
|
||||
return "transfer";
|
||||
case PM_DEVICE_CERTUPDATE_GW:
|
||||
return "certupdate";
|
||||
case PM_DEVICE_POWERCYCLE_GW:
|
||||
return "powercycle";
|
||||
case PM_DEVICE_LOGS_GW:
|
||||
return "ap_logs";
|
||||
case PM_DEVICE_HEALTHCHECKS_GW:
|
||||
return "healthchecks";
|
||||
case PM_DEVICE_CAPABILITIES_GW:
|
||||
return "ap_capabilities";
|
||||
case PM_DEVICE_STATISTICS_GW:
|
||||
return "ap_statistics";
|
||||
case PM_DEVICE_STATUS_GW:
|
||||
return "ap_status";
|
||||
case PM_DEVICE_RTTY_GW:
|
||||
return "ap_rtty";
|
||||
case PM_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert PermissionMap into a JSON object and return it
|
||||
*/
|
||||
Poco::JSON::Object permissions_to_json(const PermissionMap &Map) {
|
||||
Poco::JSON::Object MapObj;
|
||||
for (auto &[Model, Permissions] : Map) {
|
||||
Poco::JSON::Object ModelObject;
|
||||
for (auto &[Permission, Allowed] : Permissions) {
|
||||
ModelObject.set(PermTypeToString(Permission), Allowed);
|
||||
}
|
||||
MapObj.set(PermModelToString(Model), ModelObject);
|
||||
}
|
||||
return MapObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON object into a PermissionMap and return it
|
||||
*/
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
PermissionMap permissions;
|
||||
if (Obj == nullptr) {
|
||||
return permissions;
|
||||
}
|
||||
Poco::JSON::Object::ConstIterator it1;
|
||||
for(it1 = Obj->begin(); it1 != Obj->end(); it1++) {
|
||||
std::string model = it1->first;
|
||||
Poco::JSON::Object::Ptr modelObj = it1->second.extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object::ConstIterator it2;
|
||||
for(it2 = modelObj->begin(); it2 != modelObj->end(); it2++) {
|
||||
std::string permission = it2->first;
|
||||
bool allowed = it2->second;
|
||||
permissions[PermModelFromString(model)]
|
||||
[PermTypeFromString(permission)] = allowed;
|
||||
}
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
} // namespace OpenWifi::SecurityObjects
|
||||
|
||||
@@ -11,15 +11,10 @@
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Data/LOBStream.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Net/HTTPRequest.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "framework/utils.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace OpenWifi {
|
||||
uint64_t Now();
|
||||
@@ -60,10 +55,6 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// example entry {"/api/v1/device", {Poco::Net::HTTPRequest::HTTP_POST, Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE}}
|
||||
const std::map<std::string, std::set<std::string>> API_WHITELIST = {
|
||||
};
|
||||
|
||||
enum USER_ROLE {
|
||||
UNKNOWN,
|
||||
ROOT,
|
||||
@@ -134,72 +125,6 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// Represents particular permissions, i.e. what are you doing do the model
|
||||
enum PERMISSION_TYPE {
|
||||
PT_CREATE,
|
||||
PT_DELETE,
|
||||
PT_UPDATE,
|
||||
PT_READ_ONLY,
|
||||
PT_UNKNOWN
|
||||
};
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U);
|
||||
std::string PermTypeToString(PERMISSION_TYPE U);
|
||||
|
||||
// Represents a model that can be operated on
|
||||
enum PERMISSION_MODEL {
|
||||
//Security
|
||||
PM_PERMISSIONS,
|
||||
|
||||
//Provisioning
|
||||
PM_VENUES_PROV,
|
||||
PM_VENUES_LIST_PROV,
|
||||
PM_ENTITIES_PROV,
|
||||
PM_ENTITIES_LIST_PROV,
|
||||
PM_INVENTORY_PROV,
|
||||
PM_INVENTORY_LIST_PROV,
|
||||
PM_MANAGEMENTPOLICY_PROV,
|
||||
PM_MANAGEMENTPOLICY_LIST_PROV,
|
||||
PM_MANAGEMENTROLE_PROV,
|
||||
PM_MANAGEMENTROLE_LIST_PROV,
|
||||
|
||||
//Gateway
|
||||
PM_DEVICE_CONFIGURE_GW,
|
||||
PM_DEVICE_UPGRADE_GW,
|
||||
PM_DEVICE_REBOOT_GW,
|
||||
PM_DEVICE_FACTORY_GW,
|
||||
PM_DEVICE_LEDS_GW,
|
||||
PM_DEVICE_TRACE_GW,
|
||||
PM_DEVICE_REQUEST_GW,
|
||||
PM_DEVICE_WIFISCAN_GW,
|
||||
PM_DEVICE_EVENTQUEUE_GW,
|
||||
PM_DEVICE_TELEMETRY_GW,
|
||||
PM_DEVICE_PING_GW,
|
||||
PM_DEVICE_SCRIPT_GW,
|
||||
PM_DEVICE_RRM_GW,
|
||||
PM_DEVICE_TRANSFER_GW,
|
||||
PM_DEVICE_CERTUPDATE_GW,
|
||||
PM_DEVICE_POWERCYCLE_GW,
|
||||
PM_DEVICE_LOGS_GW,
|
||||
PM_DEVICE_HEALTHCHECKS_GW,
|
||||
PM_DEVICE_CAPABILITIES_GW,
|
||||
PM_DEVICE_STATISTICS_GW,
|
||||
PM_DEVICE_STATUS_GW,
|
||||
PM_DEVICE_RTTY_GW,
|
||||
|
||||
PM_SCRIPTS_GW,
|
||||
|
||||
PM_UNKNOWN
|
||||
};
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U);
|
||||
std::string PermModelToString(PERMISSION_MODEL U);
|
||||
|
||||
// Map a permission (e.g. create, delete) to true/false
|
||||
typedef std::map<PERMISSION_TYPE, bool> ModelPermissionMap;
|
||||
// Map a model (e.g. venues, devices) to permissions
|
||||
typedef std::map<PERMISSION_MODEL, ModelPermissionMap> PermissionMap;
|
||||
Poco::JSON::Object permissions_to_json(const SecurityObjects::PermissionMap &Map);
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
|
||||
struct UserInfo {
|
||||
std::string id;
|
||||
std::string name;
|
||||
@@ -224,7 +149,6 @@ namespace OpenWifi {
|
||||
bool suspended = false;
|
||||
bool blackListed = false;
|
||||
USER_ROLE userRole;
|
||||
PermissionMap userPermissions;
|
||||
UserLoginLoginExtensions userTypeProprietaryInfo;
|
||||
std::string securityPolicy;
|
||||
uint64_t securityPolicyChange = 0;
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace OpenWifi {
|
||||
bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
|
||||
bool DeviceExists(std::string &SerialNumber);
|
||||
bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
|
||||
bool GetDeviceCount(uint64_t &Count, const std::string &platform = "", bool includeProvisioned = true);
|
||||
bool GetDeviceCount(uint64_t &Count, const std::string &platform = "");
|
||||
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||
std::vector<std::string> &SerialNumbers,
|
||||
const std::string &orderBy = "",
|
||||
@@ -243,7 +243,7 @@ namespace OpenWifi {
|
||||
const std::string &Type);
|
||||
bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
|
||||
bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
|
||||
std::string &FileContent, std::string &Type);
|
||||
std::string &FileContent, std::string &Type, int& WaitingForFile);
|
||||
bool RemoveAttachedFile(std::string &UUID);
|
||||
bool SetCommandResult(std::string &UUID, std::string &Result);
|
||||
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
|
||||
|
||||
@@ -120,14 +120,16 @@ namespace OpenWifi {
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
|
||||
try {
|
||||
int Op, flags;
|
||||
int IncomingSize;
|
||||
int Op, flags, IncomingSize;
|
||||
|
||||
IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
poco_information(
|
||||
Logger(),
|
||||
if (IncomingSize == -1) {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("TELEMETRY-EMPTY({}): Empty frame, non-blocking try-again.", CId_));
|
||||
} else if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_));
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
@@ -136,12 +138,14 @@ namespace OpenWifi {
|
||||
fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) {
|
||||
poco_information(
|
||||
Logger(),
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_));
|
||||
MustDisconnect = true;
|
||||
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CONT) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-CONT({}): rx {} bytes.", CId_, IncomingSize));
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
@@ -154,4 +158,4 @@ namespace OpenWifi {
|
||||
SendTelemetryShutdown();
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -129,26 +129,4 @@ namespace OpenWifi {
|
||||
return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted, Suspended);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a role, remove the cached user info for any user with that role
|
||||
*/
|
||||
void AuthClient::EmptyCacheForRole(const std::string &role) {
|
||||
SecurityObjects::USER_ROLE roleEnum = SecurityObjects::UserTypeFromString(role);
|
||||
Poco::JSON::Object::ConstIterator it;
|
||||
std::set<std::string> tokens = Cache_.getAllKeys();
|
||||
for(const std::string &token : tokens) {
|
||||
auto UInfo = Cache_.get(token);
|
||||
if (UInfo->userinfo.userRole == roleEnum) {
|
||||
Cache_.remove(token);
|
||||
}
|
||||
}
|
||||
|
||||
tokens = ApiKeyCache_.getAllKeys();
|
||||
for(const std::string &token : tokens) {
|
||||
auto UInfo = ApiKeyCache_.get(token);
|
||||
if (UInfo->UserInfo.userinfo.userRole == roleEnum) {
|
||||
ApiKeyCache_.remove(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
@@ -61,8 +61,6 @@ namespace OpenWifi {
|
||||
SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
|
||||
bool &Expired, bool &Contacted, bool &Suspended);
|
||||
|
||||
void EmptyCacheForRole(const std::string &role);
|
||||
|
||||
private:
|
||||
Poco::ExpireLRUCache<std::string, OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{
|
||||
512, 1200000};
|
||||
|
||||
@@ -276,7 +276,8 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"sae-mixed",
|
||||
"wpa3",
|
||||
"wpa3-192",
|
||||
"wpa3-mixed"
|
||||
"wpa3-mixed",
|
||||
"mpsk-radius"
|
||||
],
|
||||
"examples": [
|
||||
"psk2"
|
||||
@@ -376,18 +377,21 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"properties": {
|
||||
"port-mirror": {
|
||||
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"monitor-ports": {
|
||||
"description": "The list of ports that we want to mirror.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"monitor-ports": {
|
||||
"description": "The list of ports that we want to mirror.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"analysis-port": {
|
||||
"description": "The port that mirror'ed packets should be sent to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"analysis-port": {
|
||||
"description": "The port that mirror'ed packets should be sent to.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -549,7 +553,8 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
},
|
||||
"bandwidth": {
|
||||
@@ -622,6 +627,10 @@ static std::string DefaultAPSchema = R"foo(
|
||||
],
|
||||
"default": 80
|
||||
},
|
||||
"enable": {
|
||||
"description": "Specifies radio is enabled/disabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"require-mode": {
|
||||
"description": "Stations that do no fulfill these HT modes will be rejected.",
|
||||
"type": "string",
|
||||
@@ -2306,7 +2315,8 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -2410,12 +2420,24 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"encryption": {
|
||||
"$ref": "#/$defs/interface.ssid.encryption"
|
||||
},
|
||||
"multi-psk": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||
}
|
||||
"enhanced-mpsk": {
|
||||
"description": "Optionally disable MPSK",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"multi-psk": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rrm": {
|
||||
"$ref": "#/$defs/interface.ssid.rrm"
|
||||
},
|
||||
@@ -3732,7 +3754,8 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -3942,8 +3965,10 @@ static std::string DefaultAPSchema = R"foo(
|
||||
"inactive-deauth",
|
||||
"key-mismatch",
|
||||
"beacon-report",
|
||||
"radar-detected"
|
||||
]
|
||||
"radar-detected",
|
||||
"ft-finish",
|
||||
"sta-authorized"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4431,7 +4456,8 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"sae-mixed",
|
||||
"wpa3",
|
||||
"wpa3-192",
|
||||
"wpa3-mixed"
|
||||
"wpa3-mixed",
|
||||
"mpsk-radius"
|
||||
],
|
||||
"examples": [
|
||||
"psk2"
|
||||
@@ -4645,16 +4671,22 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"port-mirror": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"monitor-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"monitor-ports": {
|
||||
"description": "The list of ports that we want to mirror.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"analysis-port": {
|
||||
"description": "The port that mirror'ed packets should be sent to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"analysis-port": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4874,7 +4906,8 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
},
|
||||
"bandwidth": {
|
||||
@@ -4940,6 +4973,10 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
],
|
||||
"default": 80
|
||||
},
|
||||
"enable": {
|
||||
"description": "Specifies radio is enabled/disabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"require-mode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -6512,7 +6549,8 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -6602,11 +6640,23 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"encryption": {
|
||||
"$ref": "#/$defs/interface.ssid.encryption"
|
||||
},
|
||||
"enhanced-mpsk": {
|
||||
"description": "Optionally disable MPSK",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"multi-psk": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||
}
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rrm": {
|
||||
"$ref": "#/$defs/interface.ssid.rrm"
|
||||
@@ -7728,7 +7778,8 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"5G",
|
||||
"5G-lower",
|
||||
"5G-upper",
|
||||
"6G"
|
||||
"6G",
|
||||
"HaLow"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -7897,7 +7948,9 @@ static std::string DefaultSWITCHSchema = R"foo(
|
||||
"inactive-deauth",
|
||||
"key-mismatch",
|
||||
"beacon-report",
|
||||
"radar-detected"
|
||||
"radar-detected",
|
||||
"ft-finish",
|
||||
"sta-authorized"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,10 @@ namespace OpenWifi {
|
||||
Producer.poll((std::chrono::milliseconds) 0);
|
||||
}
|
||||
}
|
||||
if (Queue_.size() == 0) {
|
||||
// message queue is empty, flush all previously sent messages
|
||||
Producer.flush();
|
||||
}
|
||||
} catch (const cppkafka::HandleException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("Caught a Kafka exception (producer): {}", E.what()));
|
||||
@@ -126,10 +130,6 @@ namespace OpenWifi {
|
||||
} catch (...) {
|
||||
poco_error(Logger_, "std::exception");
|
||||
}
|
||||
if (Queue_.size() == 0) {
|
||||
// message queue is empty, flush all previously sent messages
|
||||
Producer.flush();
|
||||
}
|
||||
Note = Queue_.waitDequeueNotification();
|
||||
}
|
||||
Producer.flush();
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace OpenWifi::KafkaTopics {
|
||||
inline const char * EVENT_LEAVE = "leave";
|
||||
inline const char * EVENT_KEEP_ALIVE = "keep-alive";
|
||||
inline const char * EVENT_REMOVE_TOKEN = "remove-token";
|
||||
inline const char * EVENT_PERMISSIONS_UPDATE = "permissions-update";
|
||||
|
||||
namespace Fields {
|
||||
inline const char * EVENT = "event";
|
||||
@@ -38,7 +37,6 @@ namespace OpenWifi::KafkaTopics {
|
||||
inline const char * KEY = "key";
|
||||
inline const char * VRSN = "version";
|
||||
inline const char * TOKEN = "token";
|
||||
inline const char * ROLE = "role";
|
||||
} // namespace Fields
|
||||
} // namespace ServiceEvents
|
||||
} // namespace OpenWifi::KafkaTopics
|
||||
|
||||
@@ -155,16 +155,6 @@ namespace OpenWifi {
|
||||
BusLogger,
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
|
||||
}
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_PERMISSIONS_UPDATE) {
|
||||
if (Object->has(KafkaTopics::ServiceEvents::Fields::ROLE)) {
|
||||
// Permissions of this role have updated, cached user info is now invalid
|
||||
AuthClient()->EmptyCacheForRole(
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::ROLE).toString());
|
||||
} else {
|
||||
poco_information(
|
||||
logger(),
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing role", Event));
|
||||
}
|
||||
} else {
|
||||
poco_information(BusLogger,
|
||||
fmt::format("Unknown Event: {} Source: {}", Event, ID));
|
||||
@@ -855,4 +845,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
// This must be defined for poco_debug and poco_trace macros to function.
|
||||
|
||||
@@ -40,6 +41,7 @@ namespace OpenWifi {
|
||||
#include "Poco/Util/OptionSet.h"
|
||||
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||
#include "Poco/Util/ServerApplication.h"
|
||||
#include "Poco/ThreadPool.h"
|
||||
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
|
||||
@@ -60,52 +60,9 @@ namespace OpenWifi {
|
||||
AlwaysAuthorize_(AlwaysAuthorize), Server_(Server), MyRates_(Profile),
|
||||
TransactionId_(TransactionId) {}
|
||||
|
||||
inline int nthOccurrence(const std::string& str, const std::string& findMe, int nth) {
|
||||
/*
|
||||
Helper function to get the index of the nth occurence of string findMe in string str.
|
||||
if there are not n occurrences of findMe in str, returns -1.
|
||||
*/
|
||||
size_t pos = 0;
|
||||
int count = 0;
|
||||
|
||||
while(count != nth)
|
||||
{
|
||||
pos+=1;
|
||||
pos = str.find(findMe, pos);
|
||||
if (pos == std::string::npos)
|
||||
return -1;
|
||||
count++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
inline bool RoleIsAuthorized([[maybe_unused]] const std::string &Path,
|
||||
[[maybe_unused]] const std::string &Method,
|
||||
[[maybe_unused]] std::string &Reason) {
|
||||
// If user role is admin or root, authorized is true
|
||||
if (UserInfo_.userinfo.userRole == SecurityObjects::USER_ROLE::ADMIN || UserInfo_.userinfo.userRole == SecurityObjects::USER_ROLE::ROOT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We just want the /api/v1/x part of the path so we need to account for
|
||||
// extra path variables as well as query variables.
|
||||
std::string pathstubtmp = Path.substr(0, nthOccurrence(Path, "/", 3));
|
||||
std::string pathstub = pathstubtmp.substr(0, nthOccurrence(pathstubtmp, "?", 1));
|
||||
|
||||
// Next check the pathstub against the whitelist
|
||||
if (SecurityObjects::API_WHITELIST.find(pathstub) != SecurityObjects::API_WHITELIST.end()) {
|
||||
std::set<std::string> allowed_methods = SecurityObjects::API_WHITELIST.at(pathstub);
|
||||
// The API stub is in the whitelist, but we also need to check that this method is whitelisted for this stub.
|
||||
if (allowed_methods.find(Method) != allowed_methods.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the user is not root/admin and the API + method is not whitelisted, so we disallow any method that is not a GET.
|
||||
if (Method != Poco::Net::HTTPRequest::HTTP_GET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -474,6 +431,11 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
inline void Accepted() {
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTP_ACCEPTED);
|
||||
Response->send();
|
||||
}
|
||||
|
||||
inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
|
||||
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
|
||||
SetCommonHeaders();
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace OpenWifi {
|
||||
P.verificationDepth = 9;
|
||||
P.loadDefaultCAs = root_ca_.empty();
|
||||
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
||||
P.dhUse2048Bits = true;
|
||||
P.caLocation = cas_;
|
||||
// P.securityLevel =
|
||||
|
||||
@@ -68,6 +67,16 @@ namespace OpenWifi {
|
||||
Context->addCertificateAuthority(Issuing);
|
||||
}
|
||||
|
||||
if (!client_cas_.empty()) {
|
||||
// add certificates specified in clientcas
|
||||
std::vector<Poco::Crypto::X509Certificate> Certs =
|
||||
Poco::Net::X509Certificate::readPEM(client_cas_);
|
||||
for (const auto &cert : Certs) {
|
||||
Context->addChainCertificate(cert);
|
||||
Context->addCertificateAuthority(cert);
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
|
||||
Context->usePrivateKey(Key);
|
||||
|
||||
@@ -334,4 +343,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace OpenWifi {
|
||||
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
|
||||
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
|
||||
[[nodiscard]] inline auto RootCA() const { return root_ca_; };
|
||||
[[nodiscard]] inline auto ClientCas() const { return client_cas_; };
|
||||
[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
|
||||
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
|
||||
[[nodiscard]] inline auto Name() const { return name_; };
|
||||
|
||||
@@ -210,10 +210,16 @@ namespace OpenWifi {
|
||||
n = Client->second->WS_->receiveFrame(IncomingFrame, flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (n == -1) {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("UI-EMPTY({}): {} Empty Frame flags {}.",
|
||||
Client->second->Id_, Client->second->UserName_, flags));
|
||||
return;
|
||||
}
|
||||
if (n == 0) {
|
||||
poco_debug(Logger(),
|
||||
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
return EndConnection(Client);
|
||||
}
|
||||
|
||||
@@ -221,7 +227,7 @@ namespace OpenWifi {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
Client->second->WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
@@ -231,6 +237,11 @@ namespace OpenWifi {
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
return EndConnection(Client);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("CONT({}): {} Unexpected CONT Frame - Ignoring.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
constexpr const char *DropMessagesCommand = "drop-notifications";
|
||||
IncomingFrame.append(0);
|
||||
@@ -319,4 +330,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -433,6 +433,10 @@ namespace OpenWifi::RESTAPI::Errors {
|
||||
|
||||
static const struct msg InvalidRRMAction { 1192, "Invalid RRM Action." };
|
||||
|
||||
static const struct msg InvalidPackageURL { 1193, "Invalid URL, must start with http:// or https://." };
|
||||
static const struct msg FailedToDownload { 1194, "Failed to download package." };
|
||||
static const struct msg FailedToDecompress { 1195, "Failed to decompress package data."};
|
||||
|
||||
static const struct msg SimulationDoesNotExist {
|
||||
7000, "Simulation Instance ID does not exist."
|
||||
};
|
||||
@@ -550,6 +554,10 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
static const char *DEBUG = "debug";
|
||||
static const char *SCRIPT = "script";
|
||||
static const char *TIMEOUT = "timeout";
|
||||
static const char *PACKAGE = "package";
|
||||
static const char *PACKAGES = "packages";
|
||||
static const char *PACKAGEINST = "packageInstall";
|
||||
static const char *PACKAGEDEL = "packageDelete";
|
||||
|
||||
static const char *NEWPASSWORD = "newPassword";
|
||||
static const char *USERS = "users";
|
||||
@@ -582,6 +590,8 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
static const char *BANDWIDTH = "bandwidth";
|
||||
|
||||
static const char *FIXEDCONFIG = "fixedconfig";
|
||||
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
|
||||
static const char *REENROLL = "reenroll";
|
||||
} // namespace OpenWifi::RESTAPI::Protocol
|
||||
|
||||
namespace OpenWifi::uCentralProtocol {
|
||||
@@ -610,6 +620,7 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *CFGPENDING = "cfgpending";
|
||||
static const char *RECOVERY = "recovery";
|
||||
static const char *COMPRESS_64 = "compress_64";
|
||||
static const char *COMPRESS_SZ = "compress_sz";
|
||||
static const char *CAPABILITIES = "capabilities";
|
||||
static const char *REQUEST_UUID = "request_uuid";
|
||||
static const char *SANITY = "sanity";
|
||||
@@ -666,6 +677,9 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *SIGNATURE = "signature";
|
||||
static const char *INFO = "info";
|
||||
static const char *DATE = "date";
|
||||
static const char *PACKAGE = "package";
|
||||
static const char *PACKAGES = "packages";
|
||||
static const char *CATEGORY = "category";
|
||||
|
||||
static const char *SERIALNUMBER = "serialNumber";
|
||||
static const char *COMPATIBLE = "compatible";
|
||||
@@ -695,7 +709,10 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *ACTIONS = "actions";
|
||||
|
||||
static const char *FIXEDCONFIG = "fixedconfig";
|
||||
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
|
||||
static const char *REENROLL = "reenroll";
|
||||
|
||||
static const char *OPERATION = "op";
|
||||
} // namespace OpenWifi::uCentralProtocol
|
||||
|
||||
namespace OpenWifi::uCentralProtocol::Events {
|
||||
@@ -730,7 +747,7 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
ET_EVENT,
|
||||
ET_WIFISCAN,
|
||||
ET_ALARM,
|
||||
ET_REBOOTLOG
|
||||
ET_REBOOTLOG,
|
||||
};
|
||||
|
||||
inline EVENT_MSG EventFromString(const std::string &Method) {
|
||||
@@ -793,6 +810,9 @@ namespace OpenWifi::APCommands {
|
||||
transfer,
|
||||
powercycle,
|
||||
fixedconfig,
|
||||
cablediagnostics,
|
||||
reenroll,
|
||||
package,
|
||||
unknown
|
||||
};
|
||||
|
||||
@@ -808,7 +828,8 @@ namespace OpenWifi::APCommands {
|
||||
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
|
||||
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
|
||||
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
|
||||
RESTAPI::Protocol::FIXEDCONFIG
|
||||
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS,
|
||||
RESTAPI::Protocol::REENROLL, RESTAPI::Protocol::PACKAGE
|
||||
};
|
||||
|
||||
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
|
||||
|
||||
@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Compress given data using utility function and encode it in base64 format.
|
||||
//
|
||||
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) {
|
||||
|
||||
unsigned long CompressedDataSize = UnCompressedData.size();
|
||||
std::vector<Bytef> CompressedData(CompressedDataSize);
|
||||
auto status = compress(&CompressedData[0], &CompressedDataSize,
|
||||
(Bytef*) UnCompressedData.c_str(), UnCompressedData.size());
|
||||
if (status == Z_OK) {
|
||||
CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize);
|
||||
}
|
||||
else {
|
||||
// failed to compress data
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsAlphaNumeric(const std::string &s) {
|
||||
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
|
||||
}
|
||||
@@ -868,78 +888,15 @@ namespace OpenWifi::Utils {
|
||||
return password;
|
||||
}
|
||||
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain) {
|
||||
std::vector<NAPTRRecord> naptrRecords;
|
||||
|
||||
unsigned char buf[4096];
|
||||
ns_msg handle;
|
||||
ns_initparse(buf, NS_PACKETSZ, &handle);
|
||||
|
||||
// Query NAPTR records for the given domain
|
||||
int response = res_query(domain.c_str(), ns_c_in, ns_t_naptr, buf, sizeof(buf));
|
||||
if (response < 0) {
|
||||
return naptrRecords;
|
||||
}
|
||||
|
||||
if(ns_initparse(buf, response, &handle) < 0) {
|
||||
return naptrRecords;
|
||||
}
|
||||
|
||||
// Iterate through the DNS response and extract NAPTR records
|
||||
int count = ns_msg_count(handle, ns_s_an);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ns_rr rr;
|
||||
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
|
||||
char rdata[256];
|
||||
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
|
||||
NAPTRRecord record;
|
||||
std::istringstream os(rdata);
|
||||
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.order >> record.preference >> record.flags
|
||||
>> record.service >> record.regexp >> record.replacement;
|
||||
naptrRecords.push_back(record);
|
||||
}
|
||||
}
|
||||
|
||||
return naptrRecords;
|
||||
}
|
||||
/*
|
||||
Note that these 2 functions aren't used. They have been removed due to this deprecation warning:
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
#47 3.825 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::NAPTRRecord> OpenWifi::Utils::getNAPTRRecords(const std::string&)':
|
||||
#47 3.825 /owgw/src/framework/utils.cpp:915:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
|
||||
|
||||
std::vector<SrvRecord> getSRVRecords(const std::string& domain) {
|
||||
std::vector<SrvRecord> srvRecords;
|
||||
|
||||
// Buffer to hold the DNS response
|
||||
unsigned char buf[4096];
|
||||
ns_msg handle;
|
||||
ns_initparse(buf, NS_PACKETSZ, &handle);
|
||||
|
||||
// Query NAPTR records for the given domain
|
||||
int response = res_query(domain.c_str(), ns_c_in, ns_t_srv, buf, sizeof(buf));
|
||||
if (response < 0) {
|
||||
std::cerr << "DNS query failed for " << domain << ": " << hstrerror(h_errno) << std::endl;
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
if(ns_initparse(buf, response, &handle) < 0) {
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
// Iterate through the DNS response and extract NAPTR records
|
||||
int count = ns_msg_count(handle, ns_s_an);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ns_rr rr;
|
||||
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
|
||||
char rdata[256];
|
||||
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
|
||||
SrvRecord record;
|
||||
std::istringstream os(rdata);
|
||||
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.pref >> record.weight >>
|
||||
record.port >> record.srvname ;
|
||||
srvRecords.push_back(record);
|
||||
}
|
||||
}
|
||||
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
#47 3.833 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::SrvRecord> OpenWifi::Utils::getSRVRecords(const std::string&)':
|
||||
#47 3.833 /owgw/src/framework/utils.cpp:952:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
|
||||
*/
|
||||
|
||||
} // namespace OpenWifi::Utils
|
||||
|
||||
@@ -151,6 +151,8 @@ namespace OpenWifi::Utils {
|
||||
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
std::string &UnCompressedData, uint64_t compress_sz);
|
||||
|
||||
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData);
|
||||
|
||||
inline bool match(const char* first, const char* second)
|
||||
{
|
||||
// If we reach at the end of both strings, we are done
|
||||
@@ -296,8 +298,10 @@ namespace OpenWifi::Utils {
|
||||
std::string replacement;
|
||||
};
|
||||
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
|
||||
// removed due to deprecation: see utils.cpp
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
//std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
|
||||
|
||||
struct SrvRecord {
|
||||
std::string name;
|
||||
std::string ttl;
|
||||
@@ -309,7 +313,8 @@ namespace OpenWifi::Utils {
|
||||
std::string srvname;
|
||||
};
|
||||
|
||||
std::vector<SrvRecord> getSRVRecords(const std::string& domain);
|
||||
// removed due to deprecation: see utils.cpp
|
||||
// std::vector<SrvRecord> getSRVRecords(const std::string& domain);
|
||||
|
||||
struct HostNameServerResult{
|
||||
std::string Hostname;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "Poco/NObserver.h"
|
||||
#include <Poco/Net/Context.h>
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/WebSocketImpl.h"
|
||||
@@ -71,6 +72,7 @@ namespace OpenWifi {
|
||||
const auto &RootCas =
|
||||
MicroServiceConfigPath("ucentral.websocket.host.0.rootca", "");
|
||||
const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", "");
|
||||
const auto &ClientCasFile = MicroServiceConfigPath("ucentral.websocket.host.0.clientcas", "");
|
||||
|
||||
Poco::Net::Context::Params P;
|
||||
|
||||
@@ -86,6 +88,7 @@ namespace OpenWifi {
|
||||
Poco::Crypto::X509Certificate Cert(CertFileName);
|
||||
Poco::Crypto::X509Certificate Root(RootCaFileName);
|
||||
Poco::Crypto::X509Certificate Issuing(IssuerFileName);
|
||||
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts;
|
||||
Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword);
|
||||
|
||||
DeviceSecureContext->useCertificate(Cert);
|
||||
@@ -93,7 +96,11 @@ namespace OpenWifi {
|
||||
DeviceSecureContext->addCertificateAuthority(Root);
|
||||
DeviceSecureContext->addChainCertificate(Issuing);
|
||||
DeviceSecureContext->addCertificateAuthority(Issuing);
|
||||
DeviceSecureContext->addCertificateAuthority(Root);
|
||||
ClientCasCerts = Poco::Net::X509Certificate::readPEM(ClientCasFile);
|
||||
for (const auto &cert : ClientCasCerts) {
|
||||
DeviceSecureContext->addChainCertificate(cert);
|
||||
DeviceSecureContext->addCertificateAuthority(cert);
|
||||
}
|
||||
DeviceSecureContext->enableSessionCache(true);
|
||||
DeviceSecureContext->setSessionCacheSize(0);
|
||||
DeviceSecureContext->setSessionTimeout(120);
|
||||
@@ -573,14 +580,16 @@ namespace OpenWifi {
|
||||
try {
|
||||
Client = Clients_.find(pNf->socket().impl()->sockfd());
|
||||
if (Client == end(Clients_)) {
|
||||
poco_warning(Logger(), fmt::format("Cannot find client socket: {}",
|
||||
pNf->socket().impl()->sockfd()));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("Cannot find client socket: {}",
|
||||
pNf->socket().impl()->sockfd()));
|
||||
return;
|
||||
}
|
||||
Connection = Client->second;
|
||||
if(Connection->WSSocket_==nullptr || Connection->WSSocket_->impl()==nullptr) {
|
||||
poco_warning(Logger(), fmt::format("WebSocket is no valid: {}",
|
||||
Connection->SerialNumber_));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("WebSocket is not valid: {}",
|
||||
Connection->SerialNumber_));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -589,15 +598,25 @@ namespace OpenWifi {
|
||||
|
||||
auto ReceivedBytes = Connection->WSSocket_->receiveFrame(FrameBuffer, sizeof(FrameBuffer), flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (ReceivedBytes == -1) {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("WS-EMPTY{}: Non-blocking try-again empty Frame: flags {}",
|
||||
Connection->SerialNumber_, flags));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Op) {
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
Connection->WSSocket_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
if (ReceivedBytes == 0) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
@@ -624,19 +643,29 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
if (ReceivedBytes == 0) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
} else {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("Sending {} key strokes to device.", ReceivedBytes));
|
||||
fmt::format("Sending {} key strokes to device.", ReceivedBytes));
|
||||
if (!RTTYS_server().KeyStrokes(Connection, FrameBuffer, ReceivedBytes)) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
// may have to handle this, but not sure whether it's a continuation for text or
|
||||
// binary, seems to be a hole in the protocol.
|
||||
poco_warning(Logger(),
|
||||
fmt::format("CONT Frame {} received, ignoring for now.",
|
||||
ReceivedBytes));
|
||||
}
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
@@ -682,8 +711,8 @@ namespace OpenWifi {
|
||||
if (Connection->WSSocket_ != nullptr && Connection->WSSocket_->impl()!= nullptr) {
|
||||
try {
|
||||
Connection->WSSocket_->sendFrame(Buf, len,
|
||||
Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
(int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
(int) Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return;
|
||||
} catch (...) {
|
||||
poco_error(Logger(), "SendData shutdown.");
|
||||
@@ -985,8 +1014,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool RTTYS_server::SendToClient(Poco::Net::WebSocket &WebSocket, const u_char *Buf, int len) {
|
||||
WebSocket.sendFrame(
|
||||
Buf, len, Poco::Net::WebSocket::FRAME_FLAG_FIN | Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
WebSocket.sendFrame(Buf, len,
|
||||
(int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
(int) Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1117,4 +1147,4 @@ namespace OpenWifi {
|
||||
RTTYS_EndPoint::~RTTYS_EndPoint() {
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -644,21 +644,7 @@ namespace OpenWifi {
|
||||
uint64_t Size = FileContent.str().size();
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Statement(Sess);
|
||||
|
||||
std::string StatementStr;
|
||||
|
||||
// Get the existing command
|
||||
|
||||
StatementStr =
|
||||
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
|
||||
|
||||
Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
|
||||
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Statement.execute();
|
||||
Sess.commit();
|
||||
if (Size < FileUploader()->MaxSize()) {
|
||||
|
||||
Poco::Data::BLOB TheBlob;
|
||||
@@ -678,9 +664,24 @@ namespace OpenWifi {
|
||||
Insert.execute();
|
||||
Sess.commit();
|
||||
} else {
|
||||
poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("File {} is too large ({} >= {} max bytes).",
|
||||
UUID, Size, FileUploader()->MaxSize()));
|
||||
}
|
||||
|
||||
// update CommandList here to ensure that file us uploaded
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Statement(Sess);
|
||||
std::string StatementStr;
|
||||
StatementStr =
|
||||
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
|
||||
|
||||
Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
|
||||
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Statement.execute();
|
||||
Sess.commit();
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -689,7 +690,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
|
||||
std::string &FileContent, std::string &Type) {
|
||||
std::string &FileContent, std::string &Type, int &WaitingForFile) {
|
||||
try {
|
||||
Poco::Data::BLOB L;
|
||||
/*
|
||||
@@ -702,10 +703,10 @@ namespace OpenWifi {
|
||||
Poco::Data::Statement Select1(Sess);
|
||||
|
||||
std::string TmpSerialNumber;
|
||||
std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
|
||||
std::string st1{"SELECT SerialNumber, Command , WaitingForFile FROM CommandList WHERE UUID=?"};
|
||||
std::string Command;
|
||||
Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
|
||||
Poco::Data::Keywords::into(Command), Poco::Data::Keywords::use(UUID);
|
||||
Poco::Data::Keywords::into(Command), Poco::Data::Keywords::into(WaitingForFile), Poco::Data::Keywords::use(UUID);
|
||||
Select1.execute();
|
||||
|
||||
if (TmpSerialNumber != SerialNumber) {
|
||||
@@ -825,4 +826,4 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -172,27 +172,18 @@ namespace OpenWifi {
|
||||
R.set<30>(D.connectReason);
|
||||
}
|
||||
|
||||
bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform, bool includeProvisioned) {
|
||||
bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
|
||||
if(!platform.empty()) {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
}
|
||||
std::string st{"SELECT COUNT(*) FROM Devices WHERE DeviceType='" + platform + "'"};
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
} else {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||
}
|
||||
std::string st{"SELECT COUNT(*) FROM Devices"};
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
}
|
||||
st = fmt::format("SELECT COUNT(*) FROM Devices {}", whereClause);
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
Select.execute();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -211,15 +202,14 @@ namespace OpenWifi {
|
||||
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
if(!platform.empty()) {
|
||||
if (!platform.empty()) {
|
||||
if (includeProvisioned == false) {
|
||||
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
//whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='{}'", platform);
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
//whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
|
||||
}
|
||||
|
||||
|
||||
//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
|
||||
} else {
|
||||
if (includeProvisioned == false) {
|
||||
@@ -227,7 +217,7 @@ namespace OpenWifi {
|
||||
}
|
||||
//st = "SELECT SerialNumber From Devices ";
|
||||
}
|
||||
|
||||
|
||||
st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
|
||||
|
||||
if (orderBy.empty())
|
||||
@@ -905,9 +895,9 @@ namespace OpenWifi {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
|
||||
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
st =
|
||||
@@ -916,7 +906,7 @@ namespace OpenWifi {
|
||||
ComputeRange(From, HowMany));
|
||||
|
||||
//Logger().information(fmt::format(" GetDevices st is {} ", st));
|
||||
|
||||
|
||||
Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
|
||||
Select.execute();
|
||||
|
||||
|
||||
@@ -49,8 +49,7 @@ namespace OpenWifi {
|
||||
"Data TEXT, "
|
||||
"Recorded BIGINT, "
|
||||
"INDEX StatSerial0 (SerialNumber)), ",
|
||||
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))",
|
||||
Poco::Data::Keywords::now;
|
||||
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))", Poco::Data::Keywords::now;
|
||||
}
|
||||
return 0;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -154,8 +153,7 @@ namespace OpenWifi {
|
||||
"alter table devices add column lastRecordedContact bigint",
|
||||
"alter table devices add column simulated boolean",
|
||||
"alter table devices add column certificateExpiryDate bigint",
|
||||
"alter table devices add column connectReason TEXT"
|
||||
};
|
||||
"alter table devices add column connectReason TEXT"};
|
||||
|
||||
for (const auto &i : Script) {
|
||||
try {
|
||||
@@ -279,9 +277,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::now;
|
||||
}
|
||||
|
||||
std::vector<std::string> Script{
|
||||
"alter table DefaultConfigs add column Platform text"
|
||||
};
|
||||
std::vector<std::string> Script{"alter table DefaultConfigs add column Platform text"};
|
||||
|
||||
for (const auto &i : Script) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user