Merge pull request #1183 from dod-ccpo/cdn

Set up a CDN
This commit is contained in:
dandds 2019-11-22 11:26:39 -05:00 committed by GitHub
commit 5cc032b655
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 119 additions and 39 deletions

View File

@ -54,6 +54,22 @@ commands:
name: Apply the default permission sets 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 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: deploy:
parameters: parameters:
namespace: namespace:
@ -124,20 +140,19 @@ commands:
kubectl set image cronjobs.batch/crls crls=<< parameters.tag >> --namespace=<< parameters.namespace >> kubectl set image cronjobs.batch/crls crls=<< parameters.tag >> --namespace=<< parameters.namespace >>
jobs: jobs:
docker-build: docker-build-staging:
docker: docker:
- image: docker:18.06.0-ce-git - image: docker:18.06.0-ce-git
steps: steps:
- checkout - docker-build:
- setup_remote_docker: cdn_url: https://atat-cdn-staging.azureedge.net/static/assets
docker_layer_caching: true
version: 18.06.0-ce docker-build-master:
- run: docker:
name: Build image - image: docker:18.06.0-ce-git
command: | steps:
docker build . --target builder --build-arg CSP=azure -f ./Dockerfile -t atat:builder - docker-build:
docker build . --build-arg CSP=azure -f ./Dockerfile -t atat:latest cdn_url: https://atat-cdn.azureedge.net/static/assets
- cache_docker_image
test: test:
docker: docker:
@ -194,6 +209,19 @@ jobs:
--virtualenv /install/.venv \ --virtualenv /install/.venv \
--http-socket :8000 --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: - run:
name: Execute Ghost Inspector test suite name: Execute Ghost Inspector test suite
command: | command: |
@ -257,29 +285,49 @@ workflows:
version: 2 version: 2
run-tests: run-tests:
jobs: jobs:
- docker-build - docker-build-staging
- test: - test:
requires: requires:
- docker-build - docker-build-staging
- integration-tests: - integration-tests:
requires: requires:
- docker-build - docker-build-staging
- deploy-staging:
requires: build-staging:
- test jobs:
- integration-tests - docker-build-staging:
filters: filters:
branches: branches:
only: only:
- staging - staging
- deploy-master: - test:
requires:
- docker-build-staging
- integration-tests:
requires:
- docker-build-staging
- deploy-staging:
requires: requires:
- test - test
- integration-tests - integration-tests
build-master:
jobs:
- docker-build-master:
filters: filters:
branches: branches:
only: only:
- master - master
- test:
requires:
- docker-build-master
- integration-tests:
requires:
- docker-build-master
- deploy-master:
requires:
- test
- integration-tests
test-crl-parser: test-crl-parser:
triggers: triggers:
@ -288,9 +336,9 @@ workflows:
filters: filters:
branches: branches:
only: only:
- master - staging
jobs: jobs:
- docker-build - docker-build-staging
- test-crl-parser: - test-crl-parser:
requires: requires:
- docker-build - docker-build-staging

View File

@ -98,7 +98,7 @@
"hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3",
"is_secret": false, "is_secret": false,
"is_verified": false, "is_verified": false,
"line_number": 20, "line_number": 21,
"type": "Secret Keyword" "type": "Secret Keyword"
} }
], ],

View File

@ -1,6 +1,7 @@
FROM python:3.7.3-alpine3.9 AS builder FROM python:3.7.3-alpine3.9 AS builder
ARG CSP ARG CSP
ARG CDN_URL=/static/assets/
ENV TZ UTC ENV TZ UTC
RUN mkdir -p /install/.venv RUN mkdir -p /install/.venv
@ -41,7 +42,7 @@ RUN ./script/write_dotenv && \
yarn install && \ yarn install && \
rm -r ./static/fonts/ &> /dev/null || true && \ rm -r ./static/fonts/ &> /dev/null || true && \
cp -rf ./node_modules/uswds/src/fonts ./static/ && \ cp -rf ./node_modules/uswds/src/fonts ./static/ && \
yarn build yarn build-prod
## NEW IMAGE ## NEW IMAGE
FROM python:3.7.3-alpine3.9 FROM python:3.7.3-alpine3.9

View File

@ -2,11 +2,12 @@ import os
import re import re
from configparser import ConfigParser from configparser import ConfigParser
from datetime import datetime 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 from flask_session import Session
import redis import redis
from unipath import Path from unipath import Path
from flask_wtf.csrf import CSRFProtect from flask_wtf.csrf import CSRFProtect
from urllib.parse import urljoin
from atst.database import db from atst.database import db
from atst.assets import environment as assets_environment from atst.assets import environment as assets_environment
@ -63,6 +64,7 @@ def make_app(config):
make_flask_callbacks(app) make_flask_callbacks(app)
register_filters(app) register_filters(app)
register_jinja_globals(app)
make_csp_provider(app, config.get("CSP", "mock")) make_csp_provider(app, config.get("CSP", "mock"))
make_crl_validator(app) make_crl_validator(app)
make_mailer(app) make_mailer(app)
@ -125,6 +127,8 @@ def make_flask_callbacks(app):
def set_default_headers(app): # pragma: no cover def set_default_headers(app): # pragma: no cover
static_url = app.config.get("STATIC_URL")
@app.after_request @app.after_request
def _set_security_headers(response): def _set_security_headers(response):
response.headers[ response.headers[
@ -133,6 +137,7 @@ def set_default_headers(app): # pragma: no cover
response.headers["X-Content-Type-Options"] = "nosniff" response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "SAMEORIGIN" response.headers["X-Frame-Options"] = "SAMEORIGIN"
response.headers["X-XSS-Protection"] = "1; mode=block" response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Access-Control-Allow-Origin"] = app.config.get("CDN_ORIGIN")
if ENV == "dev": if ENV == "dev":
response.headers[ response.headers[
@ -141,7 +146,7 @@ def set_default_headers(app): # pragma: no cover
else: else:
response.headers[ response.headers[
"Content-Security-Policy" "Content-Security-Policy"
] = "default-src 'self' 'unsafe-eval' 'unsafe-inline'" ] = f"default-src 'self' 'unsafe-eval' 'unsafe-inline' {static_url}"
return response return response
@ -293,3 +298,16 @@ def apply_json_logger():
"root": {"level": "INFO", "handlers": ["wsgi"]}, "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

View File

@ -1,17 +1,19 @@
[default] [default]
USE_AUDIT_LOG = false ASSETS_URL
CAC_URL = http://localhost:8000/login-redirect CAC_URL = http://localhost:8000/login-redirect
CA_CHAIN = ssl/server-certs/ca-chain.pem CA_CHAIN = ssl/server-certs/ca-chain.pem
CLASSIFIED = false CDN_ORIGIN=http://localhost:8000
CONTRACT_START_DATE = 2019-09-14
CONTRACT_END_DATE = 2022-09-14
CELERY_DEFAULT_QUEUE=celery 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_FAIL_OPEN = false
CRL_STORAGE_CONTAINER = crls CRL_STORAGE_CONTAINER = crls
CSP=mock CSP=mock
DEBUG = true DEBUG = true
DISABLE_CRL_CHECK = false
ENVIRONMENT = dev ENVIRONMENT = dev
LIMIT_CONCURRENT_SESSIONS = false
LOG_JSON = false LOG_JSON = false
PERMANENT_SESSION_LIFETIME = 1800 PERMANENT_SESSION_LIFETIME = 1800
PE_NUMBER_CSV_URL = http://c95e1ebb198426ee57b8-174bb05a294821bedbf46b6384fe9b1f.r31.cf5.rackcdn.com/penumbers.csv 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_TYPE = redis
SESSION_USE_SIGNER = True SESSION_USE_SIGNER = True
SQLALCHEMY_ECHO = False SQLALCHEMY_ECHO = False
STATIC_URL=/static/
USE_AUDIT_LOG = false
WTF_CSRF_ENABLED = true WTF_CSRF_ENABLED = true
LIMIT_CONCURRENT_SESSIONS = false

View File

@ -5,12 +5,15 @@ metadata:
name: atst-envvars name: atst-envvars
namespace: atat namespace: atat
data: data:
CSP: azure ASSETS_URL: https://atat-cdn.azureedge.net/
CELERY_DEFAULT_QUEUE: celery-master CELERY_DEFAULT_QUEUE: celery-master
CDN_ORIGIN: https://azure.atat.code.mil
CSP: azure
FLASK_ENV: dev FLASK_ENV: dev
LOG_JSON: "true" LOG_JSON: "true"
OVERRIDE_CONFIG_FULLPATH: /opt/atat/atst/atst-overrides.ini OVERRIDE_CONFIG_FULLPATH: /opt/atat/atst/atst-overrides.ini
PGSSLMODE: verify-full PGSSLMODE: verify-full
PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt
STATIC_URL: https://atat-cdn.azureedge.net/static/
TZ: UTC TZ: UTC
UWSGI_CONFIG_FULLPATH: /opt/atat/atst/uwsgi.ini UWSGI_CONFIG_FULLPATH: /opt/atat/atst/uwsgi.ini

View File

@ -6,10 +6,15 @@ metadata:
data: data:
CELERY_DEFAULT_QUEUE: celery-staging CELERY_DEFAULT_QUEUE: celery-staging
SERVER_NAME: staging.atat.code.mil SERVER_NAME: staging.atat.code.mil
FLASK_ENV: staging
--- ---
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: atst-envvars name: atst-envvars
data: data:
ASSETS_URL: https://atat-cdn-staging.azureedge.net/
CDN_ORIGIN: https://staging.atat.code.mil
CELERY_DEFAULT_QUEUE: celery-staging CELERY_DEFAULT_QUEUE: celery-staging
FLASK_ENV: staging
STATIC_URL: https://atat-cdn-staging.azureedge.net/static/

View File

@ -6,6 +6,7 @@
"scripts": { "scripts": {
"watch": "parcel watch js/index.js -d static/assets --public-url /static/assets -o index.js --no-autoinstall", "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": "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": "jest",
"test:coverage": "jest --coverage --collectCoverageFrom='js/**/*.js'", "test:coverage": "jest --coverage --collectCoverageFrom='js/**/*.js'",
"test:watch": "jest --watch --no-cache" "test:watch": "jest --watch --no-cache"

View File

@ -6,7 +6,8 @@
<div class="home-container"> <div class="home-container">
<div class="home-container__logo"> <div class="home-container__logo">
<img src="/static/img/ccpo-logo.svg" alt="Cloud Computing Program Office Logo"> <img src="{{ url_for("static", filename="img/ccpo-logo.svg") }}"
alt="Cloud Computing Program Office Logo">
</div> </div>
<div class="home-container__body"> <div class="home-container__body">

View File

@ -8,7 +8,7 @@
{% assets "css" %} {% assets "css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css"> <link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css">
{% endassets %} {% endassets %}
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"> <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='img/favicon.ico') }} " />
</head> </head>
<body> <body>

View File

@ -10,7 +10,7 @@
{% assets "css" %} {% assets "css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css"> <link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css">
{% endassets %} {% endassets %}
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"> <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='img/favicon.ico') }} " />
</head> </head>
<body> <body>

View File

@ -7,7 +7,7 @@
{% assets "css" %} {% assets "css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css"> <link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css">
{% endassets %} {% endassets %}
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"> <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='img/favicon.ico') }} " />
</head> </head>
<body class="{% if g.modalOpen %} modalOpen{% endif %}"> <body class="{% if g.modalOpen %} modalOpen{% endif %}">

View File

@ -132,6 +132,6 @@
<p>Heres an example:<br> <p>Heres an example:<br>
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.</p> 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.</p>
<img src='/static/img/at-at_faqs_content.svg' alt='AT-AT FAQs Content'> <img src='{{ url_for("static", filename="img/at-at_faqs_content.svg") }}' alt='AT-AT FAQs Content'>
{% endblock %} {% endblock %}

View File

@ -94,7 +94,7 @@
</toggler> </toggler>
</div> </div>
<img id='jedi-heirarchy' src="/static/img/JEDIhierarchyDiagram.png" alt="JEDI heirarchy diagram"> <img id='jedi-heirarchy' src="{{ url_for("static", filename="img/JEDIhierarchyDiagram.png")}}" alt="JEDI heirarchy diagram">
</div> </div>
</main> </main>