Compare commits

...

10 Commits

11 changed files with 142 additions and 44 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.7.6-beta current_version = 0.7.8-beta
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)

View File

@ -9,7 +9,7 @@ env:
jobs: jobs:
# Linting # Linting
pylint: pylint:
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
@ -26,7 +26,7 @@ jobs:
- name: Lint with pylint - name: Lint with pylint
run: pipenv run pylint passbook run: pipenv run pylint passbook
black: black:
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
@ -43,7 +43,7 @@ jobs:
- name: Lint with black - name: Lint with black
run: pipenv run black --check passbook run: pipenv run black --check passbook
prospector: prospector:
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
@ -59,6 +59,23 @@ jobs:
run: pip install -U pip pipenv && pipenv install --dev run: pip install -U pip pipenv && pipenv install --dev
- name: Lint with prospector - name: Lint with prospector
run: pipenv run prospector run: pipenv run prospector
bandit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.7'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev
- name: Lint with bandit
run: pipenv run bandit -r passbook
# Actual CI tests # Actual CI tests
migrations: migrations:
needs: needs:
@ -78,7 +95,7 @@ jobs:
image: redis:latest image: redis:latest
ports: ports:
- 6379:6379 - 6379:6379
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
@ -112,7 +129,7 @@ jobs:
image: redis:latest image: redis:latest
ports: ports:
- 6379:6379 - 6379:6379
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1

View File

@ -1,13 +1,13 @@
name: passbook-release name: passbook-release
on: on:
release: release:
types: # This configuration does not affect the page_build event above types:
- created - created
jobs: jobs:
# Build # Build
build-server: build-server:
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Docker Login Registry - name: Docker Login Registry
@ -16,11 +16,17 @@ jobs:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
- name: Building Docker Image - name: Building Docker Image
run: docker build --no-cache -t beryju/passbook:0.7.6-beta -f Dockerfile . run: docker build
- name: Push Docker Container to Registry --no-cache
run: docker push beryju/passbook:0.7.6-beta -t beryju/passbook:0.7.8-beta
-t beryju/passbook:latest
-f Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/passbook:0.7.8-beta
- name: Push Docker Container to Registry (latest)
run: docker push beryju/passbook:latest
build-static: build-static:
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
services: services:
postgres: postgres:
image: postgres:latest image: postgres:latest
@ -41,24 +47,24 @@ jobs:
run: docker build run: docker build
--no-cache --no-cache
--network=$(docker network ls | grep github | awk '{print $1}') --network=$(docker network ls | grep github | awk '{print $1}')
-t beryju/passbook-static:0.7.6-beta -t beryju/passbook-static:0.7.8-beta
-t beryju/passbook-static:latest
-f static.Dockerfile . -f static.Dockerfile .
- name: Push Docker Container to Registry - name: Push Docker Container to Registry (versioned)
run: docker push beryju/passbook-static:0.7.6-beta run: docker push beryju/passbook-static:0.7.8-beta
package-helm: - name: Push Docker Container to Registry (latest)
run: docker push beryju/passbook-static:latest
test-release:
needs: needs:
- build-server - build-server
- build-static - build-static
runs-on: [ubuntu-latest] runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Install Helm - name: Run test suite in final docker images
run: | run: |
apt update && apt install -y curl export PASSBOOK_DOMAIN=localhost
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash docker-compose pull
helm init docker-compose up --no-start
- name: Helm package docker-compose start postgresql redis
run: | docker-compose run -u root server bash -c "pip install --no-cache -r requirements-dev.txt && ./manage.py test"
helm dependency update helm/passbook
helm package helm/passbook

53
.github/workflows/tag.yml vendored Normal file
View File

@ -0,0 +1,53 @@
on:
push:
tags:
- 'version/*'
name: Create Release from Tag
jobs:
build:
name: Create Release from Tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Pre-release test
run: |
export PASSBOOK_DOMAIN=localhost
docker-compose pull
docker build
--no-cache
-t beryju/passbook:latest
-f Dockerfile .
docker-compose up --no-start
docker-compose start postgresql redis
docker-compose run -u root server bash -c "pip install --no-cache -r requirements-dev.txt && ./manage.py test"
- name: Install Helm
run: |
apt update && apt install -y curl
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
- name: Helm package
run: |
helm dependency update helm/
helm package helm/
mv passbook-*.tgz passbook-chart.tgz
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Create Release from Tag
id: upload-release-asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./passbook-chart.tgz
asset_name: passbook-chart.tgz
asset_content_type: application/gzip

View File

@ -1,6 +1,6 @@
apiVersion: v1 apiVersion: v1
appVersion: "0.7.6-beta" appVersion: "0.7.8-beta"
description: A Helm chart for passbook. description: A Helm chart for passbook.
name: passbook name: passbook
version: "0.7.6-beta" version: "0.7.8-beta"
icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png

View File

@ -2,7 +2,7 @@
# This is a YAML-formatted file. # This is a YAML-formatted file.
# Declare variables to be passed into your templates. # Declare variables to be passed into your templates.
image: image:
tag: 0.7.6-beta tag: 0.7.8-beta
nameOverride: "" nameOverride: ""

View File

@ -1,2 +1,2 @@
"""passbook""" """passbook"""
__version__ = "0.7.6-beta" __version__ = "0.7.8-beta"

View File

@ -1,5 +1,6 @@
"""passbook audit models""" """passbook audit models"""
from enum import Enum from enum import Enum
from uuid import UUID
from inspect import getmodule, stack from inspect import getmodule, stack
from typing import Optional, Dict, Any from typing import Optional, Dict, Any
@ -32,11 +33,15 @@ def sanitize_dict(source: Dict[Any, Any]) -> Dict[Any, Any]:
source[key] = sanitize_dict(value) source[key] = sanitize_dict(value)
elif isinstance(value, models.Model): elif isinstance(value, models.Model):
model_content_type = ContentType.objects.get_for_model(value) model_content_type = ContentType.objects.get_for_model(value)
source[key] = { source[key] = sanitize_dict(
{
"app": model_content_type.app_label, "app": model_content_type.app_label,
"name": model_content_type.model, "name": model_content_type.model,
"pk": value.pk, "pk": value.pk,
} }
)
elif isinstance(value, UUID):
source[key] = value.hex
return source return source

View File

@ -1,9 +1,11 @@
"""audit event tests""" """audit event tests"""
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from passbook.audit.models import Event, EventAction from passbook.audit.models import Event, EventAction
from passbook.core.models import Policy
class TestAuditEvent(TestCase): class TestAuditEvent(TestCase):
@ -11,6 +13,21 @@ class TestAuditEvent(TestCase):
def test_new_with_model(self): def test_new_with_model(self):
"""Create a new Event passing a model as kwarg""" """Create a new Event passing a model as kwarg"""
event = Event.new(EventAction.CUSTOM, model=get_anonymous_user()) event = Event.new(EventAction.CUSTOM, test={"model": get_anonymous_user()})
event.save() event.save() # We save to ensure nothing is un-saveable
self.assertIsNotNone(event.pk) model_content_type = ContentType.objects.get_for_model(get_anonymous_user())
self.assertEqual(
event.context.get("test").get("model").get("app"),
model_content_type.app_label,
)
def test_new_with_uuid_model(self):
"""Create a new Event passing a model (with UUID PK) as kwarg"""
temp_model = Policy.objects.create()
event = Event.new(EventAction.CUSTOM, model=temp_model)
event.save() # We save to ensure nothing is un-saveable
model_content_type = ContentType.objects.get_for_model(temp_model)
self.assertEqual(
event.context.get("model").get("app"), model_content_type.app_label
)
self.assertEqual(event.context.get("model").get("pk"), temp_model.pk.hex)

View File

@ -100,8 +100,8 @@ def gravatar(email, size=None, rating=None):
# gravatar uses md5 for their URLs, so md5 can't be avoided # gravatar uses md5 for their URLs, so md5 can't be avoided
gravatar_url = "%savatar/%s" % ( gravatar_url = "%savatar/%s" % (
"https://secure.gravatar.com/", "https://secure.gravatar.com/",
md5(email.encode("utf-8")).hexdigest(), md5(email.encode("utf-8")).hexdigest(), # nosec
) # nosec )
parameters = [p for p in (("s", size or "158"), ("r", rating or "g"),) if p[1]] parameters = [p for p in (("s", size or "158"), ("r", rating or "g"),) if p[1]]

View File

@ -13,11 +13,11 @@ class MetricsView(View):
def get(self, request: HttpRequest) -> HttpResponse: def get(self, request: HttpRequest) -> HttpResponse:
"""Check for HTTP-Basic auth""" """Check for HTTP-Basic auth"""
auth_header = request.META.get("HTTP_AUTHORIZATION", "") auth_header = request.META.get("HTTP_AUTHORIZATION", "")
token_type, _, credentials = auth_header.partition(" ") auth_type, _, credentials = auth_header.partition(" ")
creds = f"monitor:{settings.SECRET_KEY}" credentials = f"monitor:{settings.SECRET_KEY}"
expected = b64encode(str.encode(creds)).decode() expected = b64encode(str.encode(credentials)).decode()
if token_type != "Basic" or credentials != expected: if auth_type != "Basic" or credentials != expected:
raise Http404 raise Http404
return ExportToDjangoView(request) return ExportToDjangoView(request)