From c75f1dadef0b837debf42db15639326cd5a2c949 Mon Sep 17 00:00:00 2001 From: Leif Madsen Date: Tue, 18 Oct 2022 15:22:15 -0400 Subject: [PATCH] rebase upstream (#10) * Fix issue when passing common args to the Docker image. Signed-off-by: Volker Theile * Allow users to customize the command via ARGS and RUN_ARGS environment variables. Signed-off-by: Volker Theile * Update RPM spec and Debian changelog. Signed-off-by: Volker Theile * Fix issue in MIB. 'prometheusAlertNotificationRawData' needs to be a 'DisplayString'. Signed-off-by: Volker Theile * Add 'Docker' section to README. Signed-off-by: Volker Theile * Update README. Signed-off-by: Volker Theile * Bump pyyaml from 5.1 to 5.4 Bumps [pyyaml](https://github.com/yaml/pyyaml) from 5.1 to 5.4. - [Release notes](https://github.com/yaml/pyyaml/releases) - [Changelog](https://github.com/yaml/pyyaml/blob/master/CHANGES) - [Commits](https://github.com/yaml/pyyaml/compare/5.1...5.4) Signed-off-by: dependabot[bot] * - Improve tox.ini - Fix code * Add option to enable HTTPS Add option to enable HTTPS * Update changelog. Signed-off-by: Volker Theile * Add a Dockerfile * Run dnf clean all after install That should save some size * Fix the path and add python3-prometheus_client * Fedora on Dockerhub still on f31 * Change order of arguments * Add debugging tools * Quay has not fedora 32 * Add debug level * Remove snmp timeout and retries for now * Update spec file for Fedora * Fix systemd_pre in spec file systemd_pre was missing its % * Address issues from the review - %pre scripts (missing %) - License - silence %setup * Adjust Dockerfile to use packages also change package build to also build on Centos8 * Use quay.io as the base image repository (#5) Use quay.io to avoid issues building from docker.io and quota overuse. Drop deprecated MAINTAINER option. Remove unused commented line. Also remove telnet package which is not necessary to the operation of this container image. * migrate ci (#6) * Add initial CI * Only lint Dockerfile * Address linting issues * Add .hadolint.yaml Add .hadolint.yaml so that DL3041 can be ignored. We implicitly want the latest versions (unpinned) in the top branch. * Enable pip installs and Cachito compatibility (#9) * Add setup.py for pip compatibility This allows prometheus_webhook_snmp to be installed using pip install. * Add requirements and build requirements, all with locked versions Cachito requires locking all versions to work. It is also generally a good thing to do. * Dockerfile: install with pip instead of RPMs * Rebase prometheus_webhook_snmp.py against upstream Apply changes from https://github.com/SUSE/prometheus-webhook-snmp/commit/4c58245a56953d4f49dc42b71452394aefea6e57 against our prometheus_webhook_snmp/ directory where we moved the main binary into from the root directory. * Update linting tool Signed-off-by: Volker Theile Signed-off-by: dependabot[bot] Co-authored-by: Volker Theile Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nam Xuan Nguyen Co-authored-by: Matthias Runge Co-authored-by: Chris Sibbitt Co-authored-by: Miguel Garcia --- .github/workflows/main.yml | 15 ++++-- .pylintrc | 3 +- CHANGELOG.md | 2 + README.md | 5 ++ .../prometheus_webhook_snmp.py | 9 +++- prometheus_webhook_snmp/utils.py | 19 ++++++-- requirements-test.txt | 2 + requirements.txt | 1 + tests/test_misc.py | 9 ++-- tests/test_server.py | 3 +- tox.ini | 48 +++++++++++++++++-- 11 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 requirements-test.txt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d300ce2..77ba967 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,19 +1,26 @@ name: CI -on: push +on: + push: + branches-ignore: [master, main] + pull_request: + branches: [master, main] jobs: super-linting: name: Super Linting - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Run Super-Linter - uses: github/super-linter@v3 + uses: github/super-linter/slim@v4 env: DEFAULT_BRANCH: master GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_ALL_CODEBASE: false VALIDATE_DOCKERFILE: true VALIDATE_DOCKERFILE_HADOLINT: true diff --git a/.pylintrc b/.pylintrc index 023799d..37b4887 100644 --- a/.pylintrc +++ b/.pylintrc @@ -143,7 +143,8 @@ disable=print-statement, invalid-name, missing-docstring, too-few-public-methods, - too-many-arguments + too-many-arguments, + consider-using-f-string # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/CHANGELOG.md b/CHANGELOG.md index d4eb9f0..882596f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ v1.5 * Issue #26: Fix 'TypeError' when using '--port' argument. + * Add HTTPS support. Use the arguments '--cert' and '--key' to configure + the SSL certificate (in PEM format). v1.4 * Issue #22: Prevent Python type errors when sending an SNMP trap. diff --git a/README.md b/README.md index 4bccddc..4f59ed9 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ To start the receiver execute the command: $ ./prometheus-webhook-snmp run +To start with HTTPS, pass the certificate and key parameters: + + $ ./prometheus-webhook-snmp --cert "certificate.pem" --key "key.pem" run + +Note: Both '--cert' and '--key' are needed to enable HTTPS. # Send a test SNMP trap If you want to send a test SNMP trap, then simply execute the following command. This can be used to test your command line parameters. diff --git a/prometheus_webhook_snmp/prometheus_webhook_snmp.py b/prometheus_webhook_snmp/prometheus_webhook_snmp.py index 2f15918..d00aff9 100755 --- a/prometheus_webhook_snmp/prometheus_webhook_snmp.py +++ b/prometheus_webhook_snmp/prometheus_webhook_snmp.py @@ -72,11 +72,18 @@ def cli(ctx, debug, snmp_host, snmp_port, snmp_community, snmp_retries, @click.option('--metrics', is_flag=True, help='Provide Prometheus metrics from this receiver.') +@click.option('--cert', + help='The CA certificate for setting up HTTPS. ' + 'Need to be used with --key. Without this option, HTTP is used.') +@click.option('--key', + help='The CA private key for setting up HTTPS. Need to be used with --cert.') @pass_context -def run(ctx, host, port, metrics): +def run(ctx, host, port, metrics, cert, key): ctx.config['host'] = host ctx.config['port'] = port ctx.config['metrics'] = True if metrics else None + ctx.config['cert'] = cert + ctx.config['key'] = key ctx.config.dump() utils.run_http_server(ctx) sys.exit(0) diff --git a/prometheus_webhook_snmp/utils.py b/prometheus_webhook_snmp/utils.py index 7bbc7bb..ad1d1ad 100755 --- a/prometheus_webhook_snmp/utils.py +++ b/prometheus_webhook_snmp/utils.py @@ -9,7 +9,6 @@ import dateutil.parser import prometheus_client import yaml - from pysnmp import hlapi logger = logging.getLogger(__name__) @@ -76,7 +75,8 @@ def parse_notification(config, notification): alertname = labels.pop('alertname', None) summary = annotations.pop('summary', None) description = annotations.pop('description', None) - timestamp = int(time.replace(tzinfo=datetime.timezone.utc).timestamp()) + timestamp = int(time.replace( + tzinfo=datetime.timezone.utc).timestamp()) result.append({ 'oid': labels.pop(config['alert_oid_label'], @@ -184,6 +184,15 @@ def run_http_server(ctx): :param ctx: The application context. :type ctx: dict """ + if ctx.config['cert'] and ctx.config['key']: + cherrypy.config.update({ + 'server.ssl_module': 'builtin', + 'server.ssl_certificate': ctx.config['cert'], + 'server.ssl_private_key': ctx.config['key'] + }) + elif ctx.config['cert'] or ctx.config['key']: + raise Exception("Both '--cert' and '--key' are needed") + cherrypy.config.update({ 'environment': 'production', 'server.socket_host': ctx.config['host'], @@ -217,7 +226,9 @@ def defaults(): 'trap_default_severity': '', 'host': '0.0.0.0', 'port': 9099, - 'metrics': False + 'metrics': False, + 'cert': '', + 'key': '' } def dump(self): @@ -249,7 +260,7 @@ def load(self, prog_name): ] for path_name in path_names: try: - with open(path_name, 'r') as stream: + with open(path_name, 'r', encoding='UTF-8') as stream: config = yaml.safe_load(stream) # Automatically convert hyphens to underscores. for key in list(config.keys()): diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..906fe14 --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,2 @@ +pyfakefs==3.5.8 +pytest==4.4.0 diff --git a/requirements.txt b/requirements.txt index 494a12e..9f8ef62 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,6 +43,7 @@ ply==3.11 portend==2.7.1 # via cherrypy prometheus_client==0.6.0 +pysnmp>=4.4.1 # via -r requirements.in py==1.10.0 # via pytest diff --git a/tests/test_misc.py b/tests/test_misc.py index 861fba9..0680b98 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,10 +1,10 @@ import unittest -import mock +import mock from pyfakefs import fake_filesystem -from prometheus_webhook_snmp.utils import parse_notification, Config, \ - send_snmp_trap +from prometheus_webhook_snmp.utils import (Config, parse_notification, + send_snmp_trap) NOTIFICATION_FIRING = { 'receiver': 'test-01', @@ -145,7 +145,8 @@ def test_reset(self): config = Config() config['snmp_community'] = 'private' config.reset('snmp_community') - self.assertEqual(config['snmp_community'], Config.defaults()['snmp_community']) + self.assertEqual(config['snmp_community'], + Config.defaults()['snmp_community']) def test_reset_all(self): config = Config() diff --git a/tests/test_server.py b/tests/test_server.py index b846e1e..bab09d6 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -1,7 +1,8 @@ import json -import cherrypy +import cherrypy from cherrypy.test import helper + from prometheus_webhook_snmp.utils import Context, Root, get_http_server_config diff --git a/tox.ini b/tox.ini index 6697af8..24feb78 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,48 @@ [tox] -envlist = py3-{lint,test} +envlist = + fix, + lint, + test skipsdist = true -sitepackages = true + +[base] +deps = + -rrequirements.txt + +[base-test] +deps = + -rrequirements-test.txt [testenv] +setenv = + PYTHONPATH=$PYTHONPATH:./ + +[testenv:lint] +basepython = python3 +deps = + {[base]deps} + {[base-test]deps} + pylint + isort +commands = + pylint --jobs=0 --rcfile=.pylintrc . prometheus-webhook-snmp prometheus_webhook_snmp tests + isort --check-only --diff . + +[testenv:fix] +basepython = python3 +deps = + autopep8 + isort +modules = + prometheus-webhook-snmp +commands = + autopep8 --in-place --recursive --max-line-length 100 . + isort . + +[testenv:test] +basepython = python3 +deps = + {[base]deps} + {[base-test]deps} commands = - pip install -r {toxinidir}/requirements.txt - lint: pylint --jobs=0 --rcfile=.pylintrc . prometheus-webhook-snmp prometheus_webhook_snmp tests - test: pytest + pytest {posargs}