diff --git a/.circleci/config.yml b/.circleci/config.yml index 10ed47a8..1374452f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,6 +54,22 @@ commands: name: Apply the default permission sets command: docker run --network atat -e PGDATABASE=<< parameters.pgdatabase >> << parameters.container_env >> atat:builder .venv/bin/python script/seed_roles.py + docker-build: + parameters: + cdn_url: + type: string + steps: + - checkout + - setup_remote_docker: + docker_layer_caching: true + version: 18.06.0-ce + - run: + name: Build image + command: | + docker build . --build-arg CSP=azure --build-arg CDN_URL=<< parameters.cdn_url >> -f ./Dockerfile -t atat:builder --target builder + docker build . --build-arg CSP=azure --build-arg CDN_URL=<< parameters.cdn_url >> -f ./Dockerfile -t atat:latest + - cache_docker_image + deploy: parameters: namespace: @@ -124,20 +140,19 @@ commands: kubectl set image cronjobs.batch/crls crls=<< parameters.tag >> --namespace=<< parameters.namespace >> jobs: - docker-build: + docker-build-staging: docker: - image: docker:18.06.0-ce-git steps: - - checkout - - setup_remote_docker: - docker_layer_caching: true - version: 18.06.0-ce - - run: - name: Build image - command: | - docker build . --target builder --build-arg CSP=azure -f ./Dockerfile -t atat:builder - docker build . --build-arg CSP=azure -f ./Dockerfile -t atat:latest - - cache_docker_image + - docker-build: + cdn_url: https://atat-cdn-staging.azureedge.net/static/assets + + docker-build-master: + docker: + - image: docker:18.06.0-ce-git + steps: + - docker-build: + cdn_url: https://atat-cdn.azureedge.net/static/assets test: docker: @@ -194,6 +209,19 @@ jobs: --virtualenv /install/.venv \ --http-socket :8000 " + - run: + name: Wait for ATAT container to be available + command: | + docker pull curlimages/curl:latest + docker run --network atat \ + curlimages/curl:latest \ + curl --connect-timeout 3 \ + --max-time 5 \ + --retry 120 \ + --retry-connrefused \ + --retry-delay 1 \ + --retry-max-time 120 \ + test-atat:8000 - run: name: Execute Ghost Inspector test suite command: | @@ -257,29 +285,49 @@ workflows: version: 2 run-tests: jobs: - - docker-build + - docker-build-staging - test: requires: - - docker-build + - docker-build-staging - integration-tests: requires: - - docker-build - - deploy-staging: - requires: - - test - - integration-tests + - docker-build-staging + + build-staging: + jobs: + - docker-build-staging: filters: branches: only: - staging - - deploy-master: + - test: + requires: + - docker-build-staging + - integration-tests: + requires: + - docker-build-staging + - deploy-staging: requires: - test - integration-tests + + build-master: + jobs: + - docker-build-master: filters: branches: only: - master + - test: + requires: + - docker-build-master + - integration-tests: + requires: + - docker-build-master + - deploy-master: + requires: + - test + - integration-tests test-crl-parser: triggers: @@ -288,9 +336,9 @@ workflows: filters: branches: only: - - master + - staging jobs: - - docker-build + - docker-build-staging - test-crl-parser: requires: - - docker-build + - docker-build-staging diff --git a/.secrets.baseline b/.secrets.baseline index 9353d013..dd2428f1 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -98,7 +98,7 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 20, + "line_number": 21, "type": "Secret Keyword" } ], diff --git a/Dockerfile b/Dockerfile index bf9b26be..e11a8723 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.7.3-alpine3.9 AS builder ARG CSP +ARG CDN_URL=/static/assets/ ENV TZ UTC RUN mkdir -p /install/.venv @@ -41,7 +42,7 @@ RUN ./script/write_dotenv && \ yarn install && \ rm -r ./static/fonts/ &> /dev/null || true && \ cp -rf ./node_modules/uswds/src/fonts ./static/ && \ - yarn build + yarn build-prod ## NEW IMAGE FROM python:3.7.3-alpine3.9 diff --git a/atst/app.py b/atst/app.py index 0ba56929..346ffe8b 100644 --- a/atst/app.py +++ b/atst/app.py @@ -2,11 +2,12 @@ import os import re from configparser import ConfigParser from datetime import datetime -from flask import Flask, request, g, session +from flask import Flask, request, g, session, url_for as flask_url_for from flask_session import Session import redis from unipath import Path from flask_wtf.csrf import CSRFProtect +from urllib.parse import urljoin from atst.database import db from atst.assets import environment as assets_environment @@ -63,6 +64,7 @@ def make_app(config): make_flask_callbacks(app) register_filters(app) + register_jinja_globals(app) make_csp_provider(app, config.get("CSP", "mock")) make_crl_validator(app) make_mailer(app) @@ -125,6 +127,8 @@ def make_flask_callbacks(app): def set_default_headers(app): # pragma: no cover + static_url = app.config.get("STATIC_URL") + @app.after_request def _set_security_headers(response): response.headers[ @@ -133,6 +137,7 @@ def set_default_headers(app): # pragma: no cover response.headers["X-Content-Type-Options"] = "nosniff" response.headers["X-Frame-Options"] = "SAMEORIGIN" response.headers["X-XSS-Protection"] = "1; mode=block" + response.headers["Access-Control-Allow-Origin"] = app.config.get("CDN_ORIGIN") if ENV == "dev": response.headers[ @@ -141,7 +146,7 @@ def set_default_headers(app): # pragma: no cover else: response.headers[ "Content-Security-Policy" - ] = "default-src 'self' 'unsafe-eval' 'unsafe-inline'" + ] = f"default-src 'self' 'unsafe-eval' 'unsafe-inline' {static_url}" return response @@ -293,3 +298,16 @@ def apply_json_logger(): "root": {"level": "INFO", "handlers": ["wsgi"]}, } ) + + +def register_jinja_globals(app): + static_url = app.config.get("STATIC_URL", "/static/") + + def _url_for(endpoint, **values): + if endpoint == "static": + filename = values["filename"] + return urljoin(static_url, filename) + else: + return flask_url_for(endpoint, **values) + + app.jinja_env.globals["url_for"] = _url_for diff --git a/config/base.ini b/config/base.ini index b68e526c..76e0f03e 100644 --- a/config/base.ini +++ b/config/base.ini @@ -1,17 +1,19 @@ [default] -USE_AUDIT_LOG = false +ASSETS_URL CAC_URL = http://localhost:8000/login-redirect CA_CHAIN = ssl/server-certs/ca-chain.pem -CLASSIFIED = false -CONTRACT_START_DATE = 2019-09-14 -CONTRACT_END_DATE = 2022-09-14 +CDN_ORIGIN=http://localhost:8000 CELERY_DEFAULT_QUEUE=celery -DISABLE_CRL_CHECK = false +CLASSIFIED = false +CONTRACT_END_DATE = 2022-09-14 +CONTRACT_START_DATE = 2019-09-14 CRL_FAIL_OPEN = false CRL_STORAGE_CONTAINER = crls CSP=mock DEBUG = true +DISABLE_CRL_CHECK = false ENVIRONMENT = dev +LIMIT_CONCURRENT_SESSIONS = false LOG_JSON = false PERMANENT_SESSION_LIFETIME = 1800 PE_NUMBER_CSV_URL = http://c95e1ebb198426ee57b8-174bb05a294821bedbf46b6384fe9b1f.r31.cf5.rackcdn.com/penumbers.csv @@ -32,5 +34,6 @@ SESSION_COOKIE_NAME=atat SESSION_TYPE = redis SESSION_USE_SIGNER = True SQLALCHEMY_ECHO = False +STATIC_URL=/static/ +USE_AUDIT_LOG = false WTF_CSRF_ENABLED = true -LIMIT_CONCURRENT_SESSIONS = false diff --git a/deploy/azure/atst-envvars-configmap.yml b/deploy/azure/atst-envvars-configmap.yml index b521e8d2..4870e6a6 100644 --- a/deploy/azure/atst-envvars-configmap.yml +++ b/deploy/azure/atst-envvars-configmap.yml @@ -5,12 +5,15 @@ metadata: name: atst-envvars namespace: atat data: - CSP: azure + ASSETS_URL: https://atat-cdn.azureedge.net/ CELERY_DEFAULT_QUEUE: celery-master + CDN_ORIGIN: https://azure.atat.code.mil + CSP: azure FLASK_ENV: dev LOG_JSON: "true" OVERRIDE_CONFIG_FULLPATH: /opt/atat/atst/atst-overrides.ini PGSSLMODE: verify-full PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt + STATIC_URL: https://atat-cdn.azureedge.net/static/ TZ: UTC UWSGI_CONFIG_FULLPATH: /opt/atat/atst/uwsgi.ini diff --git a/deploy/overlays/staging/envvars.yml b/deploy/overlays/staging/envvars.yml index 64feb666..99721ec9 100644 --- a/deploy/overlays/staging/envvars.yml +++ b/deploy/overlays/staging/envvars.yml @@ -6,10 +6,15 @@ metadata: data: CELERY_DEFAULT_QUEUE: celery-staging SERVER_NAME: staging.atat.code.mil + FLASK_ENV: staging --- apiVersion: v1 kind: ConfigMap metadata: name: atst-envvars data: + ASSETS_URL: https://atat-cdn-staging.azureedge.net/ + CDN_ORIGIN: https://staging.atat.code.mil CELERY_DEFAULT_QUEUE: celery-staging + FLASK_ENV: staging + STATIC_URL: https://atat-cdn-staging.azureedge.net/static/ diff --git a/package.json b/package.json index 3b7f50c4..8521623c 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "watch": "parcel watch js/index.js -d static/assets --public-url /static/assets -o index.js --no-autoinstall", "build": "parcel build js/index.js -d static/assets --public-url /static/assets -o index.js", + "build-prod": "parcel build js/index.js -d static/assets --public-url $CDN_URL -o index.js", "test": "jest", "test:coverage": "jest --coverage --collectCoverageFrom='js/**/*.js'", "test:watch": "jest --watch --no-cache" diff --git a/templates/about.html b/templates/about.html index b7ebce79..6e24b662 100644 --- a/templates/about.html +++ b/templates/about.html @@ -6,7 +6,8 @@
diff --git a/templates/base.html b/templates/base.html index c06a05fb..fabcb92c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,7 +8,7 @@ {% assets "css" %} {% endassets %} - + diff --git a/templates/base_public.html b/templates/base_public.html index 248c302a..7b872471 100644 --- a/templates/base_public.html +++ b/templates/base_public.html @@ -10,7 +10,7 @@ {% assets "css" %} {% endassets %} - + diff --git a/templates/error_base.html b/templates/error_base.html index 253a62f8..92be8e60 100644 --- a/templates/error_base.html +++ b/templates/error_base.html @@ -7,7 +7,7 @@ {% assets "css" %} {% endassets %} - + diff --git a/templates/help/docs/getting-started.html b/templates/help/docs/getting-started.html index deb9b935..bf32e037 100644 --- a/templates/help/docs/getting-started.html +++ b/templates/help/docs/getting-started.html @@ -132,6 +132,6 @@

Here’s an example:
Application A has a development environment, production environment, and sandbox environment. The cloud resources in the development environment are grouped and accessed separately from the production environment and sandbox environment.

-AT-AT FAQs Content +AT-AT FAQs Content {% endblock %} diff --git a/templates/home.html b/templates/home.html index bcfc5c04..91774138 100644 --- a/templates/home.html +++ b/templates/home.html @@ -94,7 +94,7 @@
- JEDI heirarchy diagram + JEDI heirarchy diagram