Skip to content

Commit

Permalink
Restrict access to metrics from the public network
Browse files Browse the repository at this point in the history
Due to security reasons, access to the `/metrics` endpoint is restricted
by basic HTTP Bearer Token authentication. If you make a request without
the correct token, the server will respond with "Unauthorized Access".

Close #43
  • Loading branch information
Oleg Chaplashkin authored and ochaplashkin committed Apr 4, 2024
1 parent b16fd7a commit 9db0cd3
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 3 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ docker build -t docbot .
Then run it like this:

```sh
docker run -d -p5000:5000 -e GITHUB_TOKEN=<token> -e GITHUB_SIGN_KEY=<sign_key> --name docbot docbot
docker run \
-d -p5000:5000 \
-e GITHUB_TOKEN=<token> \
-e GITHUB_SIGN_KEY=<sign_key> \
-e PROMETHEUS_TOKEN=<token> \
--name docbot docbot
```

To check that it works try to get `localhost:5000` - it will print the
Expand Down
11 changes: 9 additions & 2 deletions docbot/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from elasticapm.contrib.flask import ElasticAPM
from prometheus_flask_exporter import PrometheusMetrics
from flask import Flask, Response, request
from flask_httpauth import HTTPTokenAuth

from .handlers import webhook_handler, list_events_handler
from .logging_config import LOGGING_CONFIG
from .utils import is_verified_signature
from .utils import is_verified_signature, is_verified_prometheus_token


logging.config.dictConfig(LOGGING_CONFIG)
Expand All @@ -15,13 +16,19 @@


app = Flask(__name__)
auth = HTTPTokenAuth()

app.config['ELASTIC_APM'] = {
'SERVICE_NAME': 'docbot',
}
apm = ElasticAPM(app, logging=True)

metrics = PrometheusMetrics(app, group_by='endpoint')
metrics = PrometheusMetrics(app, group_by='endpoint', metrics_decorator=auth.login_required)


@auth.verify_token
def verify_token(token):
return is_verified_prometheus_token(token)

@app.route("/", methods=['GET'])
@metrics.do_not_track()
Expand Down
2 changes: 2 additions & 0 deletions docbot/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

token = os.environ.get('GITHUB_TOKEN')
github_signature = os.environ.get('GITHUB_SIGN_KEY')
prometheus_token = os.environ.get('PROMETHEUS_TOKEN')
assert token is not None
assert github_signature is not None
assert prometheus_token is not None
doc_requests = [' document\r\n', ' document\n']
bot_name = '@TarantoolBot'
title_header = 'Title:'
Expand Down
12 changes: 12 additions & 0 deletions docbot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,15 @@ def is_verified_signature(body, signature):
if not hmac.compare_digest(expected_signature, signature):
return False
return True

def is_verified_prometheus_token(token):
"""Verify that the payload was sent from Prometheus via Bearer token.
Returns True if the request is authorized, otherwise False.
Args:
token: original request token to verify
"""
if token == settings.prometheus_token:
return True
return False
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ click==8.1.3
ecs-logging==2.0.0
elastic-apm==6.9.1
Flask==2.2.5
Flask-HTTPAuth==4.8.0
gunicorn==20.1.0
idna==3.3
itsdangerous==2.1.2
Expand Down

0 comments on commit 9db0cd3

Please sign in to comment.