Skip to content

Commit

Permalink
✨(project) add acl-proxy application
Browse files Browse the repository at this point in the history
We need fine-grained control over dashboard permissions to ensure users
cannot access variable values they are not expected to.

As it appears that we cannot forbid dashboard input variable values
passed via a GET request, we've designed a FastAPI-based application
that proxy dashboards requests and check input values given grafana
logged user.

The acl-proxy application is used as a companion of our grafana instance
along with the Caddy2 web proxy using an x-accel-redirect workflow.
  • Loading branch information
jmaupetit committed Jan 28, 2022
1 parent fcaad31 commit d0987ad
Show file tree
Hide file tree
Showing 25 changed files with 1,593 additions and 12 deletions.
9 changes: 2 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ jobs:
working_directory: ~/fun
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Build development image
command: make build
Expand All @@ -66,7 +64,6 @@ jobs:
compile:
machine:
image: ubuntu-2004:202104-01
docker_layer_caching: true
working_directory: ~/fun
steps:
- checkout
Expand All @@ -85,7 +82,6 @@ jobs:
lint:
machine:
image: ubuntu-2004:202104-01
docker_layer_caching: true
working_directory: ~/fun
steps:
- checkout
Expand All @@ -104,7 +100,6 @@ jobs:
plugins:
machine:
image: ubuntu-2004:202104-01
docker_layer_caching: true
working_directory: ~/fun
steps:
- checkout
Expand Down Expand Up @@ -153,7 +148,7 @@ jobs:
name: Build release archive
command: |
mkdir releases
tar cvzf releases/postie-${RELEASE}.tgz -C ~/fun var/lib/grafana
tar cvzf releases/potsie-${RELEASE}.tgz -C ~/fun var/lib/grafana
- run:
name: Get release changes
command: |
Expand Down Expand Up @@ -196,7 +191,7 @@ workflows:
branches:
ignore: main
tags:
only: /(?!^v).*/
only: /.*/
- lint-changelog:
filters:
branches:
Expand Down
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
# Mac Os
.DS_Store

# Ignore compiled objects
var/

# Ignore node packages
node_modules/
dist/
coverage/

# == Python
# Packaging
build
dist
*.egg-info

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# Unit test / coverage reports
htmlcov/
.coverage
.cache
.pytest_cache
nosetests.xml
coverage.xml
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to

## [Unreleased]

### Added

- ACL proxy application

## [0.3.0] - 2022-01-27

### Added
Expand Down
64 changes: 59 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ DOCKER_GID = $(shell id -g)
DOCKER_USER = $(DOCKER_UID):$(DOCKER_GID)
COMPOSE = DOCKER_USER=$(DOCKER_USER) docker-compose
COMPOSE_RUN = $(COMPOSE) run --rm
COMPOSE_RUN_ACL = $(COMPOSE_RUN) acl

# -- Node
COMPOSE_RUN_NODE = $(COMPOSE_RUN) node
Expand Down Expand Up @@ -53,10 +54,22 @@ bootstrap: \
bootstrap: ## bootstrap the application
.PHONY: bootstrap

build: ## build potsie development image
@$(COMPOSE) build app
build: \
build-app \
build-acl
build: ## build development images
.PHONY: build

build-app: ## build potsie development image
@echo "Building grafana dashboards..."
@$(COMPOSE) build app
.PHONY: build-app

build-acl: ## build acl development image
@echo "Building acl companion app..."
@$(COMPOSE) build acl
.PHONY: build-acl

clean: \
down
clean: ## remove project files and containers (warning: it removes the database container)
Expand Down Expand Up @@ -93,12 +106,47 @@ format: ## format Jsonnet sources and libraries
bin/jsonnetfmt -i $(sources) $(libraries)
.PHONY: format

lint: ## lint Jsonnet sources and libraries
lint-black: ## lint back-end python sources with black
@echo 'lint:black started…'
@$(COMPOSE_RUN_ACL) black acl tests
.PHONY: lint-black

lint-flake8: ## lint back-end python sources with flake8
@echo 'lint:flake8 started…'
@$(COMPOSE_RUN_ACL) flake8
.PHONY: lint-flake8

lint-isort: ## automatically re-arrange python imports in back-end code base
@echo 'lint:isort started…'
@$(COMPOSE_RUN_ACL) isort --atomic .
.PHONY: lint-isort

lint-pylint: ## lint back-end python sources with pylint
@echo 'lint:pylint started…'
@$(COMPOSE_RUN_ACL) pylint acl tests
.PHONY: lint-pylint

lint-bandit: ## lint back-end python sources with bandit
@echo 'lint:bandit started…'
@$(COMPOSE_RUN_ACL) bandit -qr acl
.PHONY: lint-bandit

lint-jsonnet: ## lint Jsonnet sources and libraries
bin/jsonnet-lint $(sources) $(libraries)
.PHONY: lint-jsonnet

lint: \
lint-isort \
lint-black \
lint-flake8 \
lint-pylint \
lint-bandit \
lint-jsonnet
lint: ## lint all sources
.PHONY: lint

logs: ## display grafana logs (follow mode)
@$(COMPOSE) logs -f grafana
@$(COMPOSE) logs -f caddy acl grafana
.PHONY: logs

plugins: ## download, build and install plugins
Expand All @@ -121,7 +169,7 @@ run: ## start the development server
@$(COMPOSE) up -d postgresql
@echo "Wait for database to be up..."
@$(WAIT_DB)
@$(COMPOSE) up -d grafana
@$(COMPOSE) up -d caddy
@echo "Wait for grafana to be up..."
@$(WAIT_GRAFANA)
.PHONY: run
Expand All @@ -134,6 +182,12 @@ stop: ## stop the development server
@$(COMPOSE) stop
.PHONY: stop

test: \
run
test: ## run acl tests
bin/pytest
.PHONY: test

update: ## update jsonnet bundles
@$(COMPOSE_RUN) jb update
$(MAKE) build
Expand Down
6 changes: 6 additions & 0 deletions bin/pytest
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

declare DOCKER_USER
DOCKER_USER="$(id -u):$(id -g)"

DOCKER_USER=${DOCKER_USER} docker-compose run --rm acl pytest "$@"
28 changes: 28 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,34 @@ services:
- elasticsearch
- postgresql

caddy:
image: caddy:2.4.6
restart: unless-stopped
ports:
- "8090:8090"
volumes:
- ./docker/files/etc/caddy/Caddyfile:/etc/caddy/Caddyfile
depends_on:
- grafana
- acl

acl:
build:
context: src/acl
target: development
image: potsie-acl-proxy:development
ports:
- 8000:8000
volumes:
- ./src/acl:/app
- ./docker/files/etc/acl/logging.json:/etc/acl/logging.json
env_file:
- env.d/acl
logging:
options:
max-size: "200k"
user: "${DOCKER_USER:-1000}"

app:
build:
context: .
Expand Down
37 changes: 37 additions & 0 deletions docker/files/etc/acl/logging.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(levelprefix)s %(name)s:%(funcName)s >> %(message)s",
"use_colors": true
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(levelprefix)s %(client_addr)s - \"%(request_line)s\" %(status_code)s"
}
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"uvicorn": { "handlers": ["default"], "level": "INFO" },
"uvicorn.error": { "level": "INFO" },
"uvicorn.access": {
"handlers": ["access"],
"level": "INFO",
"propagate": false
},
"acl": {"handlers": ["default"], "level": "DEBUG"}
}
}
12 changes: 12 additions & 0 deletions docker/files/etc/caddy/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
localhost:8090

reverse_proxy * grafana:3000

reverse_proxy /d/* acl:8000 {

@accel header X-Accel-Redirect *
handle_response @accel {
rewrite {http.reverse_proxy.header.X-Accel-Redirect}
reverse_proxy grafana:3000
}
}
15 changes: 15 additions & 0 deletions env.d/acl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
EDX_DATABASE_HOST=edx_mysql
EDX_DATABASE_NAME=edxapp
EDX_DATABASE_PORT=3306
EDX_DATABASE_USER_NAME=edxapp_user
EDX_DATABASE_USER_PASSWORD=funfunfun
EDX_DATASOURCE_NAME=edx_app
GRAFANA_ROOT_URL=http://grafana:3000
# Required for aiomysql
USERNAME=acl
# Grafana
GRAFANA_DATABASE_HOST=postgresql
GRAFANA_DATABASE_NAME=potsie
GRAFANA_DATABASE_PORT=5432
GRAFANA_DATABASE_USER_NAME=fun
GRAFANA_DATABASE_USER_PASSWORD=pass
Loading

0 comments on commit d0987ad

Please sign in to comment.