Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 2023.04.2 #1375

Merged
merged 74 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
4c84c71
chore(pre-commit): autoupdate hooks
pre-commit-ci[bot] Apr 3, 2023
3083b24
chore(deps): bump django from 4.1.7 to 4.2 in /appcontainer
dependabot[bot] Apr 3, 2023
693eec7
chore: replace deprecated `length_is` in favor of `length` filter
angela-tran Apr 4, 2023
080b18a
chore: update code for configuring static file storage
angela-tran Apr 4, 2023
dd39c12
chore(deps): bump sentry-sdk from 1.18.0 to 1.19.1 in /appcontainer
dependabot[bot] Apr 5, 2023
211ece4
chore(pre-commit): autoupdate hooks (#1344)
thekaveman Apr 6, 2023
e1ac23b
chore(deps): bump sentry-sdk from 1.18.0 to 1.19.1 in /appcontainer (…
thekaveman Apr 6, 2023
5d813d8
chore(deps): bump django from 4.1.7 to 4.2 in /appcontainer (#1345)
angela-tran Apr 6, 2023
0a11b5b
fix(url): fix broken link in docs
machikoyasuda Apr 6, 2023
7616aca
fix(url): fix broken link in docs (#1352)
machikoyasuda Apr 6, 2023
4ef33da
fix(Docker): set platform
machikoyasuda Apr 7, 2023
55ea843
docs(test): testing git
machikoyasuda Apr 7, 2023
4852c7a
test: Test git again
machikoyasuda Apr 7, 2023
200184b
fix: try platform in compose file
thekaveman Apr 7, 2023
6a469f3
chore(pre-commit): autoupdate hooks
pre-commit-ci[bot] Apr 10, 2023
62f3417
chore(pre-commit): autoupdate hooks (#1355)
thekaveman Apr 10, 2023
6cc41f0
refactor: move dependencies to pyproject.toml
thekaveman Apr 10, 2023
9bd4343
ci: update dependabot, tests
thekaveman Apr 10, 2023
0d97c01
fix: tell setuptools which package to install
thekaveman Apr 10, 2023
b981af8
chore(devcontainer): install TOML extension
thekaveman Apr 10, 2023
5b5b02f
refactor: split dev/test extra dependencies
thekaveman Apr 10, 2023
dd3d8a0
Fix: Docker platform issue (#1354)
machikoyasuda Apr 13, 2023
e2af9c7
Refactor: move dependencies and metadata to pyproject.toml (#1356)
thekaveman Apr 13, 2023
6c65db8
feat(settings): enforce strict Content Security Policy
thekaveman Apr 13, 2023
9b20fa7
chore: implement nonce on <script> tags
thekaveman Apr 13, 2023
ad9730d
chore(analytics): add nonce to inject <script> tag
thekaveman Apr 13, 2023
24d954f
chore(enrollment): add nonce to payment processor script
thekaveman Apr 13, 2023
2faabec
feat(sentry): support CSP report-uri directive
thekaveman Apr 13, 2023
02b5ef9
docs: strict CSP, Sentry report-uri config
thekaveman Apr 13, 2023
1f7c9e9
docs: reword to more generic Agency Cards
thekaveman Apr 14, 2023
0b2b230
docs: update interconnections graph
thekaveman Apr 14, 2023
bceb52a
docs: fix cc_data --> ac_data
thekaveman Apr 14, 2023
9d0c22a
chore(pre-commit): autoupdate hooks
pre-commit-ci[bot] Apr 17, 2023
c5227b9
chore(deps-dev): bump cypress from 12.9.0 to 12.10.0 in /tests/cypress
dependabot[bot] Apr 17, 2023
3a1c7da
refactor: MST-specific payment processor
thekaveman Apr 18, 2023
804bbdd
feat: configure a payment processor for SacRT
thekaveman Apr 18, 2023
a7f6081
Feat: Configure a payment processor for SacRT (#1365)
thekaveman Apr 18, 2023
8eb97d7
Separate payment processors (test) (#1366)
thekaveman Apr 18, 2023
9ecf172
chore(nginx): add conf file from base image
thekaveman Apr 14, 2023
4f02d5d
feat(nginx): 404 known scraping targets
thekaveman Apr 14, 2023
c3b60ba
refactor: move rate limit from Django to nginx
thekaveman Apr 14, 2023
8737676
fix(nginx): selective rate-limit for POST
thekaveman Apr 14, 2023
e70b0c5
refactor(nginx): include common directives
thekaveman Apr 14, 2023
ca0731c
docs(rate-limit): update with nginx config
thekaveman Apr 14, 2023
53fd701
fix(tests): mock settings on middleware module
thekaveman Apr 14, 2023
78a77c7
chore(terraform): remove unused rate limit env vars
thekaveman Apr 14, 2023
6fb30ac
refactor(tests): use helper for CC setup
thekaveman Apr 14, 2023
2ddaaf3
refactor(tests): rate limit wait helper
thekaveman Apr 14, 2023
8c0a3b5
test(nginx): assert 404 on known scraping targets
thekaveman Apr 14, 2023
3ba8cc5
fix(nginx): filename optional
thekaveman Apr 14, 2023
1f33670
fix(tests): simplify, ensure nginx throws 404
thekaveman Apr 14, 2023
5b081bc
fix(tests): export rate limit consts
thekaveman Apr 18, 2023
120a962
refactor(tests): move helpers out of specs
thekaveman Apr 18, 2023
a1a3c43
test(rate-limit): ensure nginx returns the failure
thekaveman Apr 18, 2023
48fa60b
Docs: make Agency Cards use-case more generic (#1361)
thekaveman Apr 20, 2023
f2e1ff8
chore(pre-commit): autoupdate hooks (#1362)
thekaveman Apr 20, 2023
639b786
chore(deps-dev): bump cypress from 12.9.0 to 12.10.0 in /tests/cypres…
thekaveman Apr 20, 2023
a997078
Feat: Implement strict Content Security Policy (#1358)
thekaveman Apr 20, 2023
9bdef24
fix(settings): allow unsafe-inline for style-src
thekaveman Apr 20, 2023
b0c31c6
Fix: allow unsafe-inline for style-src (#1369)
thekaveman Apr 20, 2023
eafbe09
feat(sentry): make traces sample rate configurable
thekaveman Apr 14, 2023
afca263
chore(terraform): read traces sample rate from secrets
thekaveman Apr 14, 2023
164a909
docs(sentry): describe traces sample rate setting
thekaveman Apr 14, 2023
2a2cfcf
test(sentry): sample rate should be float
thekaveman Apr 14, 2023
75e3054
fix(sentry): default to 0 for bad env var
thekaveman Apr 20, 2023
2ae770f
chore(sentry): add configuration logging
thekaveman Apr 20, 2023
cdec5fb
Fix: Configurable traces sampling rate for Sentry (#1360)
thekaveman Apr 20, 2023
cfeda54
Feat: improve traffic filtering at nginx (#1359)
thekaveman Apr 20, 2023
eb6651a
chore(release): bump version to 2023.04.2
thekaveman Apr 20, 2023
81d223f
Chore: prep release 2023.04.2 (#1370)
thekaveman Apr 20, 2023
235b046
Deploy 2023.04.2 to test (#1371)
thekaveman Apr 20, 2023
e3b8e91
fix(nginx): relax 404 filter
thekaveman Apr 20, 2023
dcbb425
Fix: relax the 404 filter (#1372)
thekaveman Apr 20, 2023
ee42f91
Deploy to test (#1373)
thekaveman Apr 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 2 additions & 5 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
FROM benefits_client:latest

# install devcontainer requirements
COPY .devcontainer/requirements.txt .devcontainer/requirements.txt
RUN pip install -r .devcontainer/requirements.txt
RUN pip install -e .[dev,test]

# docs requirements are in a separate file for the GitHub Action
COPY docs/requirements.txt docs/requirements.txt
RUN pip install -r docs/requirements.txt

COPY tests/pytest/requirements.txt tests/pytest/requirements.txt
RUN pip install -r tests/pytest/requirements.txt

# install pre-commit environments in throwaway Git repository
# https://stackoverflow.com/a/68758943
COPY .pre-commit-config.yaml .
Expand Down
1 change: 1 addition & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"bungcip.better-toml",
"batisteo.vscode-django",
"bpruitt-goddard.mermaid-markdown-syntax-highlighting",
"eamodio.gitlens",
Expand Down
4 changes: 0 additions & 4 deletions .devcontainer/requirements.txt

This file was deleted.

1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
.flake8
.*ignore
*.db
*.egg-info
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/appcontainer" # main requirements.txt
directory: "/" # pyproject.toml
schedule:
interval: "daily"
commit-message:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/labeler-deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ on:
branches: [dev]
types: [opened]
paths:
- '.github/workflows/deploy-*.yml'
- 'benefits/**'
- 'bin/**'
- ".github/workflows/deploy-*.yml"
- "benefits/**"
- "bin/**"
- Dockerfile
- requirements.txt
- pyproject.toml

jobs:
label-deployment-dev:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests-pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:
with:
python-version-file: .github/workflows/.python-version
cache: pip
cache-dependency-path: "**/requirements.txt"
cache-dependency-path: "**/pyproject.toml"

- name: Install Python dependencies
run: pip install -r appcontainer/requirements.txt -r tests/pytest/requirements.txt
run: pip install -e .[test]

- name: Run setup
run: ./bin/init.sh
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ repos:
args: ["--maxkb=1500"]

- repo: https://github.com/psf/black
rev: 23.1.0
rev: 23.3.0
hooks:
- id: black
types:
Expand All @@ -61,6 +61,6 @@ repos:
types_or: [javascript, css]

- repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.19.16
rev: v1.23.0
hooks:
- id: djlint-django
18 changes: 11 additions & 7 deletions appcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
FROM ghcr.io/cal-itp/docker-python-web:main

# install python dependencies
COPY appcontainer/requirements.txt requirements.txt
RUN pip install -r requirements.txt
# upgrade pip
RUN python -m pip install --upgrade pip

# copy Django utility script
COPY manage.py manage.py
# overwrite default nginx.conf
COPY appcontainer/nginx.conf /etc/nginx/nginx.conf
COPY appcontainer/proxy.conf /home/calitp/run/proxy.conf

# copy source files
COPY bin/ bin/
COPY benefits/ benefits/
COPY manage.py manage.py
COPY bin bin
COPY benefits benefits
COPY pyproject.toml pyproject.toml

RUN pip install -e .

# ensure $USER can compile messages in the locale directories
USER root
Expand Down
92 changes: 92 additions & 0 deletions appcontainer/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
worker_processes auto;
error_log stderr warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
accept_mutex on;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
gzip on;
keepalive_timeout 5;

log_format main '[$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout main;

upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response
server unix:/home/calitp/run/gunicorn.sock fail_timeout=0;
}

# maps $binary_ip_address to $limit variable if request is of type POST
map $request_method $limit {
default "";
POST $binary_remote_addr;
}

# define a zone with 10mb memory, rate limit to 12 requests/min (~= 1 request/5 seconds) on applied locations
# $limit will eval to $binary_remote_addr for POST requests using the above map
# requests with an empty key value (e.g. GET) are not affected
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
limit_req_zone $limit zone=rate_limit:10m rate=12r/m;

server {
listen 8000;

keepalive_timeout 65;

# 404 known scraping path targets
# case-insensitive regex matches the given path fragment anywhere in the request path
location ~* /(\.?git|api|app|assets|ats|bootstrap|bower|cgi|content|credentials|docker|doc|env|example|swagger|web) {
access_log off;
log_not_found off;
return 404;
}

# 404 known scraping file targets
# case-insensitive regex matches the given file extension anywhere in the request path
location ~* /.*\.(asp|axd|cgi|com|env|json|php|xml|ya?ml) {
access_log off;
log_not_found off;
return 404;
}

location /favicon.ico {
access_log off;
log_not_found off;
expires 1y;
add_header Cache-Control public;
}

# path for static files
location /static/ {
alias /home/calitp/app/static/;
expires 1y;
add_header Cache-Control public;
}

location / {
# checks for static file, if not found proxy to app
try_files $uri @proxy_to_app;
}

# apply rate limit to these paths
# case-insensitive regex matches path
location ~* ^/(eligibility/confirm)$ {
limit_req zone=rate_limit;
include /home/calitp/run/proxy.conf;
}

# app path
location @proxy_to_app {
include /home/calitp/run/proxy.conf;
}
}
}
8 changes: 8 additions & 0 deletions appcontainer/proxy.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# the core app proxy directives
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_pass http://app_server;
7 changes: 0 additions & 7 deletions appcontainer/requirements.txt

This file was deleted.

2 changes: 1 addition & 1 deletion benefits/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = "2023.04.1"
__version__ = "2023.04.2"

VERSION = __version__
41 changes: 1 addition & 40 deletions benefits/core/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
The core application: middleware definitions for request/response cycle.
"""
import logging
import time

from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest
from django.http import HttpResponse
from django.shortcuts import redirect
from django.template import loader
from django.template.response import TemplateResponse
from django.utils.decorators import decorator_from_middleware
from django.utils.deprecation import MiddlewareMixin
Expand Down Expand Up @@ -40,43 +38,6 @@ def process_request(self, request):
return user_error(request)


class RateLimit(MiddlewareMixin):
"""Middleware checks settings and session to ensure rate limit is respected."""

def process_request(self, request):
if not settings.RATE_LIMIT_ENABLED:
logger.debug("Rate Limiting is not configured")
return None

if request.method in settings.RATE_LIMIT_METHODS:
session.increment_rate_limit_counter(request)
else:
# bail early if the request method doesn't match
return None

counter = session.rate_limit_counter(request)
reset_time = session.rate_limit_time(request)
now = int(time.time())

if counter > settings.RATE_LIMIT:
if reset_time > now:
logger.warning("Rate limit exceeded")
home = viewmodels.Button.home(request)
page = viewmodels.ErrorPage.server_error(
title="Rate limit error",
headline="Rate limit error",
paragraphs=["You have reached the rate limit. Please try again."],
button=home,
)
t = loader.get_template("400.html")
return HttpResponseBadRequest(t.render(page.context_dict()))
else:
# enough time has passed, reset the rate limit
session.reset_rate_limit(request)

return None


class EligibleSessionRequired(MiddlewareMixin):
"""Middleware raises an exception for sessions lacking confirmed eligibility."""

Expand Down