From a3817066a5da25a6fc3609e3193c1c5874b72291 Mon Sep 17 00:00:00 2001 From: Yurii Kovalchuk Date: Wed, 28 Feb 2024 10:29:57 +0200 Subject: [PATCH] ATOR-173 - Bandwidth authority setup, docker support and CI --- .github/actions/build-and-push/action.yml | 34 ++++ .github/actions/deploy/action.yml | 24 +++ .github/workflows/dev-deploy.yml | 28 ++++ .github/workflows/stage-deploy.yml | 28 ++++ .gitignore | 1 + docker/destination/Dockerfile | 9 ++ docker/destination/default.conf | 16 ++ docker/destination/docker-entrypoint.sh | 5 + docker/docker-compose.yml | 16 ++ docker/scanner/.sbws.ini | 58 +++++++ docker/scanner/Dockerfile | 18 +++ docker/scanner/docker-entrypoint.sh | 6 + operations/admin-ui-ca.crt | 31 ++++ operations/deploy-dev.hcl | 183 ++++++++++++++++++++++ operations/deploy-stage.hcl | 183 ++++++++++++++++++++++ sbws/globals.py | 2 + sbws/util/config.py | 5 +- 17 files changed, 645 insertions(+), 2 deletions(-) create mode 100644 .github/actions/build-and-push/action.yml create mode 100644 .github/actions/deploy/action.yml create mode 100644 .github/workflows/dev-deploy.yml create mode 100644 .github/workflows/stage-deploy.yml create mode 100755 docker/destination/Dockerfile create mode 100644 docker/destination/default.conf create mode 100755 docker/destination/docker-entrypoint.sh create mode 100755 docker/docker-compose.yml create mode 100755 docker/scanner/.sbws.ini create mode 100755 docker/scanner/Dockerfile create mode 100755 docker/scanner/docker-entrypoint.sh create mode 100644 operations/admin-ui-ca.crt create mode 100644 operations/deploy-dev.hcl create mode 100644 operations/deploy-stage.hcl diff --git a/.github/actions/build-and-push/action.yml b/.github/actions/build-and-push/action.yml new file mode 100644 index 00000000..45c7a83f --- /dev/null +++ b/.github/actions/build-and-push/action.yml @@ -0,0 +1,34 @@ +name: Build and Push Docker Image +inputs: + docker-username: + required: true + docker-password: + required: true + docker-tag: + required: true + +runs: + using: "composite" + steps: + - name: Log in to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ inputs.docker-username }} + password: ${{ inputs.docker-password }} + + - name: Build and push Docker image of scanner + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ${{ inputs.docker-username }}/sbws-scanner:${{ github.sha }},${{ inputs.docker-username }}/sbws-scanner:${{ inputs.docker-tag }} + + - name: Build and push Docker image of destination + uses: docker/build-push-action@v2 + with: + context: ./docker/destination + file: ./docker/destination/Dockerfile + push: true + tags: ${{ inputs.docker-username }}/sbws-destination:${{ github.sha }},${{ inputs.docker-username }}/sbws-destination:${{ inputs.docker-tag }} + diff --git a/.github/actions/deploy/action.yml b/.github/actions/deploy/action.yml new file mode 100644 index 00000000..42728d8b --- /dev/null +++ b/.github/actions/deploy/action.yml @@ -0,0 +1,24 @@ +name: 'Deploy new version' +inputs: + environment: + required: true + nomad-cacert: + required: true + nomad-token: + required: true + nomad-addr: + required: true + +runs: + using: "composite" + steps: + - name: Deploy new version + shell: bash + env: + NOMAD_CACERT: ${{ inputs.nomad-cacert }} + NOMAD_TOKEN: ${{ inputs.nomad-token }} + NOMAD_ADDR: ${{ inputs.nomad-addr }} + run: | + curl -L https://releases.hashicorp.com/nomad/1.6.3/nomad_1.6.3_linux_amd64.zip -o nomad.zip + unzip nomad.zip + ./nomad job run operations/deploy-${{ inputs.environment }}.hcl diff --git a/.github/workflows/dev-deploy.yml b/.github/workflows/dev-deploy.yml new file mode 100644 index 00000000..f32a0ac3 --- /dev/null +++ b/.github/workflows/dev-deploy.yml @@ -0,0 +1,28 @@ +name: Build and Push Docker Image + +on: + pull_request: + branches: + - development + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + - name: Build and push + uses: ./.github/actions/build-and-push + with: + docker-username: ${{ secrets.DOCKER_HUB_USERNAME }} + docker-password: ${{ secrets.DOCKER_HUB_PASSWORD }} + docker-tag: latest-dev +# - name: Deploy +# uses: ./.github/actions/deploy +# with: +# environment: dev +# nomad-cacert: operations/admin-ui-ca.crt +# nomad-token: ${{ secrets.NOMAD_TOKEN_SBWS_DEPLOY }} +# nomad-addr: ${{ secrets.NOMAD_DEPLOY_ADDR }} diff --git a/.github/workflows/stage-deploy.yml b/.github/workflows/stage-deploy.yml new file mode 100644 index 00000000..8d55ade6 --- /dev/null +++ b/.github/workflows/stage-deploy.yml @@ -0,0 +1,28 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + - name: Build and push + uses: ./.github/actions/build-and-push + with: + docker-username: ${{ secrets.DOCKER_HUB_USERNAME }} + docker-password: ${{ secrets.DOCKER_HUB_PASSWORD }} + docker-tag: latest + - name: Deploy + uses: ./.github/actions/deploy + with: + environment: stage + nomad-cacert: operations/admin-ui-ca.crt + nomad-token: ${{ secrets.NOMAD_TOKEN_SBWS_DEPLOY }} + nomad-addr: ${{ secrets.NOMAD_DEPLOY_ADDR }} diff --git a/.gitignore b/.gitignore index 744436b7..ea66127a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ dist build *.lockfile chutney +.idea diff --git a/docker/destination/Dockerfile b/docker/destination/Dockerfile new file mode 100755 index 00000000..421ad176 --- /dev/null +++ b/docker/destination/Dockerfile @@ -0,0 +1,9 @@ +FROM nginx + +WORKDIR /app/destination + +COPY docker-entrypoint.sh /app/destination + +#COPY default.conf /etc/nginx/conf.d/default.conf + +ENTRYPOINT [ "sh", "docker-entrypoint.sh" ] diff --git a/docker/destination/default.conf b/docker/destination/default.conf new file mode 100644 index 00000000..cb9e54f3 --- /dev/null +++ b/docker/destination/default.conf @@ -0,0 +1,16 @@ +server { + + root /app/destination/data; + + autoindex on; + + listen 0.0.0.0:80; + + location / { + try_files $uri $uri/ =404; + } + + location ~/\.ht { + deny all; + } +} diff --git a/docker/destination/docker-entrypoint.sh b/docker/destination/docker-entrypoint.sh new file mode 100755 index 00000000..28d5660b --- /dev/null +++ b/docker/destination/docker-entrypoint.sh @@ -0,0 +1,5 @@ +mkdir -p data && cd data + +head -c $((1024*1024*1024)) /dev/urandom > 1GiB + +nginx -g 'daemon off;' diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100755 index 00000000..0f06dbd3 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,16 @@ +version: '2.2' +services: + sbws-scanner: + image: sbws-scanner + restart: always + volumes: + - ./scanner/.sbws.ini:/root/.sbws.ini + - ./scanner/data/:/app/scanner/data + sbws-destination: + image: sbws-destination + restart: always + ports: + - "8888:80" + volumes: + - ./destination/default.conf:/etc/nginx/conf.d/default.conf + - ./destination/data/:/app/destination/data diff --git a/docker/scanner/.sbws.ini b/docker/scanner/.sbws.ini new file mode 100755 index 00000000..d6225776 --- /dev/null +++ b/docker/scanner/.sbws.ini @@ -0,0 +1,58 @@ +# Minimum configuration that needs to be customized +[scanner] +# ISO 3166-1 alpha-2 country code where the scanner is located. +# Default AA, to detect it was not edited. +country = DE +# A human-readable string with chars in a-zA-Z0-9 to identify the dirauth +# nickname that will publish the BandwidthFiles generated from this scanner. +# Default to a non existing dirauth_nickname to detect it was not edited. +dirauth_nickname = Anon + +[destinations] +# With several destinations, the scanner can continue even if some of them +# fail, which can be caused by a network problem on their side. +# If all of them fail, the scanner will stop, which +# will happen if there is network problem on the scanner side. + +# A destination can be disabled changing `on` by `off` +foo = on + +[destinations.foo] +# the domain and path to the 1GB file or POST URL. +url = http://host.docker.internal:8888/1GiB +# Whether to verify or not the TLS certificate. Default True +verify = False +# ISO 3166-1 alpha-2 country code where the Web server destination is located. +# Default AA, to detect it was not edited. +# Use ZZ if the location is unknown (for instance, a CDN). +country = ZZ + +## The following logging options are set by default. +## There is no need to change them unless other options are preferred. +; [logging] +; # Whether or not to log to a rotating file the directory paths.log_dname +; to_file = yes +; # Whether or not to log to stdout +; to_stdout = yes +; # Whether or not to log to syslog +; # NOTE that when sbws is launched by systemd, stdout goes to journal and +; # syslog. +; to_syslog = no + +; # Level to log at. Debug, info, warning, error, critical. +; # `level` must be set to the lower of all the handler levels. +; level = debug +; to_file_level = debug +; to_stdout_level = info +; to_syslog_level = info +; # Format string to use when logging +; format = %(module)s[%(process)s]: <%(levelname)s> %(message)s +; # verbose formatter useful for debugging +; to_file_format = %(asctime)s %(levelname)s %(threadName)s %(filename)s:%(lineno)s - %(funcName)s - %(message)s +; # Not adding %(asctime)s to to stdout since it'll go to syslog when using +; # systemd, and it'll have already the date. +; to_stdout_format = ${format} +; to_syslog_format = ${format} + +# To disable certificate validation, uncomment the following +# verify = False diff --git a/docker/scanner/Dockerfile b/docker/scanner/Dockerfile new file mode 100755 index 00000000..f0452cc5 --- /dev/null +++ b/docker/scanner/Dockerfile @@ -0,0 +1,18 @@ +FROM debian:bookworm + +RUN apt update && \ + DEBIAN_FRONTEND=noninteractive apt install -y \ + python3-dateutil python3-stem pip cron +# pip install requests + +WORKDIR /app/scanner + +ADD ../.. /app/scanner/temp + +RUN cd temp && ls -la && \ + pip install . --break-system-packages && \ + cp docker/scanner/docker-entrypoint.sh .. && \ + cd .. && \ + rm -rf temp + +ENTRYPOINT [ "sh", "docker-entrypoint.sh" ] diff --git a/docker/scanner/docker-entrypoint.sh b/docker/scanner/docker-entrypoint.sh new file mode 100755 index 00000000..35fc4751 --- /dev/null +++ b/docker/scanner/docker-entrypoint.sh @@ -0,0 +1,6 @@ +mkdir -p /app/scanner/data/logs + +crontab -l | { cat; echo "*/5 * * * * sbws generate >> /app/scanner/data/logs/generate.log 2>&1"; } | crontab - +crontab -l | { cat; echo "30 0 * * * sbws cleanup >> /app/scanner/data/logs/cleanup.log 2>&1"; } | crontab - + +cron -f diff --git a/operations/admin-ui-ca.crt b/operations/admin-ui-ca.crt new file mode 100644 index 00000000..939344fb --- /dev/null +++ b/operations/admin-ui-ca.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgIUdUo5LO+M2vEiSyfvDSOhKxVBko0wDQYJKoZIhvcNAQEL +BQAwOzELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEF0b3IgTExDMRkwFwYDVQQDDBBB +dG9yIEFkbWluIFVJIENBMB4XDTIzMDUxMDE0NTk0M1oXDTQzMDIyNDE0NTk0M1ow +OzELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEF0b3IgTExDMRkwFwYDVQQDDBBBdG9y +IEFkbWluIFVJIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1gcK +cqC81T4YHcu3DfoSA2ghART6ImQSStXhuJfWqJPjJG0PtT58t3OJ6jS84zxTWPoZ +e2gfcA4VunW5+gTTQVra8gBdNthT4jOZJ9TYS54kSRJ9st7ZPctOYzD97NXeMeWp +TCgtkoGhaVLBeFE2z8xI2V+coIs00WG+GyC1St4DlmbezKUrpODWdfiRZfYa3lNy +uamPLY3nsDq8APVq4BKrauAxfnVmeItIdjC82KhCykeWyVVOrj7PeXbfWus79YON +KuXsLbFnSR1xO5QEtaYk3A3XXN81Xe0i5qNoWJAczYIrPLAsjIo+fDw/8ENoC9+j +SfS6gNdgd0A2Le31J5Bd76QZipDBa9+5EhZNGK/19qfypTzayRT4JpErAa8zKGIy +V9csdacobuQ+0UuU+li8EavWl8vFUSb1Uh1cnhudhr2NbAiuqjwwffOmgcTnOESg +cbAXPUhGWSQU2DyrFiDebo/HbiFZGzKxL7FcoK1j08gqcMzc+3gIF4uCKkMM+rk0 +5GWNsp3VoQv9E5ytYYbN8Lk1yxRY3KWhISiDmK/cS3FW4LRrcS2H+Se+hWLNyHDN +P0yQXQh068DdCjZAQYOeXcQWKBAI1kcwu6KyidOpZKwhCZKbMGHsoURhKsfL9NEh +HDjQXrPXJ7d++Akmek2Eu9tXz7sVFJE7mB3SE0cCAwEAAaNTMFEwHQYDVR0OBBYE +FJAGJ5Vj7nX/cRLIKorIuudZoHcbMB8GA1UdIwQYMBaAFJAGJ5Vj7nX/cRLIKorI +uudZoHcbMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAFk8SYO0 +w0RHpCfrytF/rFTZUtIPNnol3/PRMq6WYT/fmTLhpt8S8+Yuz6YykRzVf4JI4LT8 +Y5nbZV/5fynbCfOP3pBWl/C7npdQtVsGVGVX7Hh1M+8Q9RKl+NA8gyHxKYfXJtEr +c6sSewBJ62eARP4dztbO8T/ydvfI6VJyKbJhGeO7vU+p13qbYAVMYeQ3sUjpazKZ +haqtTRp2lNDKK4SJ2mxW+pnac8S8E88+LP1O8U0hZphddfRgmwjuzeu+remwjkF8 +obreQRk2BR58v+tGTxfxHT0XJSK9b+G7QRmEKy+V4hXZPcynF5Xbdqu8fT7cVF6s +TfL9dCDMQoBsiWElFllSmBruWvp5gv086fwObFeQfw94Y3qvFawLMPUdI76uYPlR +3VuAs5MFncohOL12+/2o4nST2v4WKDLoWxcze49r6iCFMe2UEhhuydEXnQHp7el9 +w1NMfXxH6PzOAvMG1WtlkyT45agAIETW76/SSJH8e9j21m6cXcaaK6kJvhPga1X7 +Cd3XaiTg1r39S7Nxm/g8xDmVV738lguuj3TN5RwbNfR/rNcVUG5VUNDGea/bzQLl +eyjkXk1rFn5mYTf8tCcFfvu7pcH0Ds902zZvdysvaMGCxQu3bVpdkSn+3/6dUNCA +FFWzsbx0wrWxCyFPedz8OWgtdYu1TMtvXrWE +-----END CERTIFICATE----- diff --git a/operations/deploy-dev.hcl b/operations/deploy-dev.hcl new file mode 100644 index 00000000..5808851f --- /dev/null +++ b/operations/deploy-dev.hcl @@ -0,0 +1,183 @@ +job "sbws-dev" { + datacenters = ["ator-fin"] + type = "service" + namespace = "ator-network" + + group "sbws-dev-group" { + count = 1 + +# volume "sbws-data" { +# type = "host" +# read_only = false +# source = "sbws-dev" +# } + + network { +# mode = "bridge" + port "http-port" { + static = 9000 + to = 80 +# host_network = "wireguard" + } + } + + ephemeral_disk { + migrate = true + sticky = true + } + + task "sbws-scanner-dev-task" { + driver = "docker" + +# env { +# LOGBASE = "data/logs" +# } + +# volume_mount { +# volume = "sbws-data" +# destination = "/srv/sbws/data" +# read_only = false +# } + + config { + image = "svforte/sbws-scanner:latest-dev" + volumes = [ + "local/.sbws.ini:/root/.sbws.ini:ro", + "local/data:/app/scanner/data" + ] + } + + resources { + cpu = 256 + memory = 1024 + } + + template { + change_mode = "noop" + data = < %(message)s +; # verbose formatter useful for debugging +; to_file_format = %(asctime)s %(levelname)s %(threadName)s %(filename)s:%(lineno)s - %(funcName)s - %(message)s +; # Not adding %(asctime)s to to stdout since it'll go to syslog when using +; # systemd, and it'll have already the date. +; to_stdout_format = ${format} +; to_syslog_format = ${format} + +# To disable certificate validation, uncomment the following +# verify = False + EOH + destination = "local/.sbws.ini" + } + } + + task "sbws-destination-dev-task" { + driver = "docker" + +# volume_mount { +# volume = "sbws-data" +# destination = "/var/www/sbws-destination/data" +# read_only = true +# } + + config { + image = "svforte/sbws-destination:latest-dev" + volumes = [ + "local/nginx-sbws:/etc/nginx/conf.d/default.conf:ro" + ] + ports = ["http-port"] + } + + resources { + cpu = 256 + memory = 256 + } + + service { + name = "sbws-destination-dev" + provider = "nomad" + tags = ["sbws"] + port = "http-port" + check { + name = "sbws destination nginx http server alive" + type = "tcp" + interval = "10s" + timeout = "10s" + check_restart { + limit = 10 + grace = "30s" + } + } + } + + template { + change_mode = "noop" + data = < %(message)s +; # verbose formatter useful for debugging +; to_file_format = %(asctime)s %(levelname)s %(threadName)s %(filename)s:%(lineno)s - %(funcName)s - %(message)s +; # Not adding %(asctime)s to to stdout since it'll go to syslog when using +; # systemd, and it'll have already the date. +; to_stdout_format = ${format} +; to_syslog_format = ${format} + +# To disable certificate validation, uncomment the following +# verify = False + EOH + destination = "local/.sbws.ini" + } + } + + task "sbws-destination-stage-task" { + driver = "docker" + + # volume_mount { + # volume = "sbws-data" + # destination = "/var/www/sbws-destination/data" + # read_only = true + # } + + config { + image = "svforte/sbws-destination:latest" + volumes = [ + "local/nginx-sbws:/etc/nginx/conf.d/default.conf:ro" + ] + ports = ["http-port"] + } + + resources { + cpu = 256 + memory = 256 + } + + service { + name = "sbws-destination-stage" + provider = "nomad" + tags = ["sbws"] + port = "http-port" + check { + name = "sbws destination nginx http server alive" + type = "tcp" + interval = "10s" + timeout = "10s" + check_restart { + limit = 10 + grace = "30s" + } + } + } + + template { + change_mode = "noop" + data = <