AT-AT needs to maintain a key-value CRL cache where each key is the DER byte-string of the issuer and the value is a dictionary of the CRL file path and expiration. This way when it checks a client certificate, it can load the correct CRL by comparing the issuers. This is preferable to loading all of the CRLs in-memory. However, it still requires that AT-AT load and parse each CRL when the application boots. Because of the size of the CRLs and their parsed, in-memory size, this leads to the application spiking to use nearly 900MB of memory (resting usage is around 50MB). This change introduces a small function to ad-hoc parse the CRL and obtain the information in the CRL we need: the issuer and the expiration. It does this by reading the CRL byte-by-byte until it reaches the ASN1 sequence that corresponds to the issuer, and then looks ahead to find the nextUpdate field (i.e., the expiration date). The CRLCache class uses this function to build its cache and JSON-serializes the cache to disk. If another AT-AT application process finds the serialized version, it will load that copy instead of rebuilding it. It also entails a change to the function signature for the init method of CRLCache: now it expects the CRL directory as its second argument, instead of a list of locations. The Python script invoked by `script/sync-crls` will rebuild the location cache each time it's run. This means that when the Kubernetes CronJob for CRLs runs, it will refresh the cache each time. When a new application container boots, it will get the refreshed cache. This also adds a nightly CircleCI job to sync the CRLs and test that the ad-hoc parsing function returns the same result as a proper parsing using the Python cryptography library. This provides extra insurance that the function is returning correct results on real data.
265 lines
8.6 KiB
YAML
265 lines
8.6 KiB
YAML
version: 2.1
|
|
|
|
commands:
|
|
cache_docker_image:
|
|
steps:
|
|
- run:
|
|
name: Save the docker images to a cache
|
|
command: |
|
|
mkdir -p docker-cache
|
|
docker save -o docker-cache/atat.tar atat:latest
|
|
docker save -o docker-cache/builder.tar atat:builder
|
|
- save_cache:
|
|
key: docker-cache-{{ .Branch }}-{{ .Revision }}
|
|
paths:
|
|
- docker-cache
|
|
restore_docker_image:
|
|
steps:
|
|
- restore_cache:
|
|
keys:
|
|
- docker-cache-{{ .Branch }}-{{ .Revision }}
|
|
- run:
|
|
name: Restore Docker image from cache
|
|
command: |
|
|
docker load < docker-cache/atat.tar
|
|
docker load < docker-cache/builder.tar
|
|
setup_datastores:
|
|
parameters:
|
|
pgdatabase:
|
|
type: string
|
|
default: atat_test
|
|
container_env:
|
|
type: string
|
|
default: -e PGHOST=postgres -e REDIS_URI=redis://redis:6379
|
|
steps:
|
|
- run:
|
|
name: Set up temporary docker network
|
|
command: docker network create atat
|
|
- run:
|
|
name: Start redis
|
|
command: docker run -d --network atat --link redis:redis -p 6379:6379 --name redis circleci/redis:4-alpine3.8
|
|
- run:
|
|
name: Start postgres
|
|
command: docker run -d --network atat --link postgres:postgres -p 5432:5432 --name postgres circleci/postgres:10-alpine-ram
|
|
- run:
|
|
name: Wait for containers
|
|
command: sleep 3
|
|
- run:
|
|
name: Create database
|
|
command: "docker exec postgres createdb -U postgres << parameters.pgdatabase >>"
|
|
- run:
|
|
name: Apply migrations
|
|
command: docker run --network atat -e PGDATABASE=<< parameters.pgdatabase >> << parameters.container_env >> atat:builder .venv/bin/python .venv/bin/alembic upgrade head
|
|
- run:
|
|
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
|
|
|
|
jobs:
|
|
docker-build:
|
|
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
|
|
|
|
test:
|
|
docker:
|
|
- image: docker:18.06.0-ce-git
|
|
- image: circleci/postgres:10-alpine-ram
|
|
- image: circleci/redis:4-alpine3.8
|
|
steps:
|
|
- setup_remote_docker:
|
|
docker_layer_caching: true
|
|
version: 18.06.0-ce
|
|
- restore_docker_image
|
|
- setup_datastores:
|
|
pgdatabase: atat_test
|
|
- run:
|
|
name: Run CI tests
|
|
command: |
|
|
docker run \
|
|
-e PGHOST=postgres \
|
|
-e REDIS_URI=redis://redis:6379 \
|
|
--network atat \
|
|
atat:builder \
|
|
/bin/sh -c "pipenv install --dev && /bin/sh script/cibuild"
|
|
|
|
integration-tests:
|
|
docker:
|
|
- image: docker:18.06.0-ce-git
|
|
- image: circleci/postgres:10-alpine-ram
|
|
- image: circleci/redis:4-alpine3.8
|
|
steps:
|
|
- setup_remote_docker:
|
|
docker_layer_caching: true
|
|
version: 18.06.0-ce
|
|
- restore_docker_image
|
|
- setup_datastores:
|
|
pgdatabase: atat
|
|
- run:
|
|
name: Start application container
|
|
command: |
|
|
docker run -d \
|
|
-e DISABLE_CRL_CHECK=true \
|
|
-e PGHOST=postgres \
|
|
-e REDIS_URI=redis://redis:6379 \
|
|
-p 8000:8000 \
|
|
--network atat \
|
|
--name test-atat \
|
|
atat:builder \
|
|
/bin/sh -c "
|
|
echo CLOUD_PROVIDER=mock > .env &&\
|
|
yarn build &&\
|
|
uwsgi \
|
|
--callable app \
|
|
--module app \
|
|
--plugin python3 \
|
|
--virtualenv /install/.venv \
|
|
--http-socket :8000
|
|
"
|
|
- run:
|
|
name: Execute Ghost Inspector test suite
|
|
command: |
|
|
docker pull ghostinspector/test-runner-standalone:latest
|
|
docker run \
|
|
-e NGROK_TOKEN=$NGROK_TOKEN \
|
|
-e GI_API_KEY=$GI_API_KEY \
|
|
-e GI_SUITE=$GI_SUITE \
|
|
-e GI_PARAMS_JSON='{}' \
|
|
-e APP_PORT="test-atat:8000" \
|
|
--network atat \
|
|
ghostinspector/test-runner-standalone:latest
|
|
|
|
test-crl-parser:
|
|
docker:
|
|
- image: docker:18.06.0-ce-git
|
|
- image: circleci/postgres:10-alpine-ram
|
|
- image: circleci/redis:4-alpine3.8
|
|
steps:
|
|
- setup_remote_docker:
|
|
docker_layer_caching: true
|
|
version: 18.06.0-ce
|
|
- restore_docker_image
|
|
- setup_datastores:
|
|
pgdatabase: atat_test
|
|
- run:
|
|
name: Sync CRLs and run CRL test
|
|
command: |
|
|
docker run \
|
|
-e PGHOST=postgres \
|
|
-e REDIS_URI=redis://redis:6379 \
|
|
--network atat \
|
|
atat:builder \
|
|
/bin/sh -c "pipenv install --dev && /bin/sh script/sync-crls && pipenv run pytest --no-cov tests/check_crl_parse.py"
|
|
|
|
deploy:
|
|
docker:
|
|
- image: docker:18.06.0-ce-git
|
|
environment:
|
|
AZURE_REGISTRY: pwatat
|
|
RESOURCE_GROUP: atat
|
|
CLUSTER_NAME: atat-cluster
|
|
steps:
|
|
- checkout
|
|
- setup_remote_docker:
|
|
docker_layer_caching: true
|
|
version: 18.06.0-ce
|
|
- restore_docker_image
|
|
- run:
|
|
name: Install Azure CLI
|
|
command: |
|
|
apk update
|
|
apk add bash py-pip
|
|
apk add --virtual=build \
|
|
linux-headers gcc libffi-dev musl-dev openssl-dev python-dev make
|
|
pip --no-cache-dir install -U pip
|
|
pip --no-cache-dir install azure-cli
|
|
apk del --purge build
|
|
- run:
|
|
name: Login to Azure CLI
|
|
command: |
|
|
az login \
|
|
--service-principal \
|
|
--tenant $AZURE_SP_TENANT \
|
|
--password $AZURE_SP_PASSWORD \
|
|
--username $AZURE_SP
|
|
echo "Successfully logged in to Azure CLI."
|
|
az acr login --name $AZURE_REGISTRY
|
|
- run:
|
|
name: Install kubectl
|
|
command: |
|
|
apk add curl
|
|
export KUBECTL_VERSION=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)
|
|
curl -LO https://storage.googleapis.com/kubernetes-release/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl
|
|
chmod +x ./kubectl
|
|
mv ./kubectl /usr/local/bin
|
|
- run:
|
|
name: Configure kubectl
|
|
command: |
|
|
apk add libssl1.0
|
|
az aks get-credentials --name ${CLUSTER_NAME} --resource-group ${RESOURCE_GROUP}
|
|
- run:
|
|
name: Tag images
|
|
command: |
|
|
docker tag atat:latest ${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1}
|
|
docker tag atat:latest ${AZURE_SERVER_NAME}/atat:latest
|
|
- run:
|
|
name: Push image
|
|
command: |
|
|
docker push ${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1}
|
|
docker push ${AZURE_SERVER_NAME}/atat:latest
|
|
- run:
|
|
name: Add gettext package
|
|
command: apk add gettext
|
|
- run:
|
|
command: CONTAINER_IMAGE=${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1} /bin/sh ./script/cluster_migration
|
|
name: Apply Migrations and Seed Roles
|
|
- run:
|
|
name: Update Kubernetes cluster
|
|
command: |
|
|
kubectl set image deployment.apps/atst atst=${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1} --namespace=atat
|
|
kubectl set image deployment.apps/atst-worker atst-worker=${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1} --namespace=atat
|
|
kubectl set image deployment.apps/atst-beat atst-beat=${AZURE_SERVER_NAME}/atat:atat-${CIRCLE_SHA1} --namespace=atat
|
|
|
|
workflows:
|
|
version: 2
|
|
run-tests:
|
|
jobs:
|
|
- docker-build
|
|
- test:
|
|
requires:
|
|
- docker-build
|
|
- integration-tests:
|
|
requires:
|
|
- docker-build
|
|
- deploy:
|
|
requires:
|
|
- test
|
|
- integration-tests
|
|
filters:
|
|
branches:
|
|
only:
|
|
- master
|
|
|
|
test-crl-parser:
|
|
triggers:
|
|
- schedule:
|
|
cron: "0 4 * * *"
|
|
filters:
|
|
branches:
|
|
only:
|
|
- master
|
|
jobs:
|
|
- docker-build
|
|
- test-crl-parser:
|
|
requires:
|
|
- docker-build
|