Skip to content

Commit

Permalink
Define HTTPS certificate resolver differently for different environme…
Browse files Browse the repository at this point in the history
…nts (#869)

* use LE dns challenge in development

* upgrade traefik

* configure certificate challenge differently for different environments

* pass all environment variables automatically to deployment script

* add a comment and required variable to verify staging and prod environments are in an internal network

* add VPN host limitation to dev env temporarily

* improve missing variable messaging

* remove VPN restriction from dev environments

* improve formatting
  • Loading branch information
rikukissa authored Jan 26, 2024
1 parent 2789345 commit cbc90a2
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 104 deletions.
73 changes: 42 additions & 31 deletions .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,44 +95,55 @@ jobs:
sleep 10
done
- name: Export all secrets and environment variables
run: |
cd ./${{ github.event.repository.name }}
SECRETS_JSON_WITH_NEWLINES=$(cat<<EOF
${{ toJSON(secrets) }}
EOF)
#
# Secrets & variables with newlines are filtered out automatically
# This includes SSH_KEY and KNOWN_HOSTS
#
while IFS= read -r secret; do
echo "$secret" >> .env.${{ github.event.inputs.environment }}
done < <(
jq -r '
to_entries |
map(
select(.value | test("\n") | not) |
"\(.key)=\"\(.value)\""
) |
.[]' <<< "$SECRETS_JSON_WITH_NEWLINES"
)
VARS_JSON_WITH_NEWLINES=$(cat<<EOF
${{ toJSON(vars) }}
EOF)
while IFS= read -r var; do
echo "$var" >> .env.${{ github.event.inputs.environment }}
done < <(
jq -r '
to_entries |
map(
select(.value | test("\n") | not) |
"\(.key)=\"\(.value)\""
) |
.[]' <<< "$VARS_JSON_WITH_NEWLINES"
)
- name: Deploy to ${{ github.event.inputs.environment }}
env:
DOMAIN: ${{ vars.DOMAIN }}
REPLICAS: ${{ vars.REPLICAS }}
NOTIFICATION_TRANSPORT: ${{ vars.NOTIFICATION_TRANSPORT }}
SMTP_PORT: ${{ secrets.SMTP_PORT }}
SMTP_HOST: ${{ secrets.SMTP_HOST }}
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
SMTP_SECURE: ${{ secrets.SMTP_SECURE }}
ALERT_EMAIL: ${{ secrets.ALERT_EMAIL }}
DOCKERHUB_ACCOUNT: ${{ secrets.DOCKERHUB_ACCOUNT }}
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_REPO }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
KIBANA_USERNAME: ${{ secrets.KIBANA_USERNAME }}
KIBANA_PASSWORD: ${{ secrets.KIBANA_PASSWORD }}
MONGODB_ADMIN_USER: ${{ secrets.MONGODB_ADMIN_USER }}
MONGODB_ADMIN_PASSWORD: ${{ secrets.MONGODB_ADMIN_PASSWORD }}
ELASTICSEARCH_SUPERUSER_PASSWORD: ${{ secrets.ELASTICSEARCH_SUPERUSER_PASSWORD }}
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
INFOBIP_SENDER_ID: ${{ secrets.INFOBIP_SENDER_ID }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
INFOBIP_GATEWAY_ENDPOINT: ${{ secrets.INFOBIP_GATEWAY_ENDPOINT }}
INFOBIP_API_KEY: ${{ secrets.INFOBIP_API_KEY }}
SENDER_EMAIL_ADDRESS: ${{ secrets.SENDER_EMAIL_ADDRESS }}
SUPER_USER_PASSWORD: ${{ secrets.SUPER_USER_PASSWORD }}
CONTENT_SECURITY_POLICY_WILDCARD: ${{ vars.CONTENT_SECURITY_POLICY_WILDCARD }}
SSH_ARGS: ${{ vars.SSH_ARGS }}
run: |
cd ./${{ github.event.repository.name }}
yarn deploy \
--clear_data=no \
--environment=${{ github.event.inputs.environment }} \
--host=${{ env.DOMAIN }} \
--host=${{ vars.DOMAIN }} \
--ssh_host=${{ secrets.SSH_HOST }} \
--ssh_user=${{ secrets.SSH_USER }} \
--version=${{ github.event.inputs.core-image-tag }} \
--country_config_version=${{ github.event.inputs.countryconfig-image-tag }} \
--replicas=${{ env.REPLICAS }}
--replicas=${{ vars.REPLICAS }}
106 changes: 43 additions & 63 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,85 +97,65 @@ jobs:
sleep 10
done
- name: Export all secrets and environment variables
run: |
cd ./${{ github.event.repository.name }}
SECRETS_JSON_WITH_NEWLINES=$(cat<<EOF
${{ toJSON(secrets) }}
EOF)
#
# Secrets & variables with newlines are filtered out automatically
# This includes SSH_KEY and KNOWN_HOSTS
#
while IFS= read -r secret; do
echo "$secret" >> .env.${{ github.event.inputs.environment }}
done < <(
jq -r '
to_entries |
map(
select(.value | test("\n") | not) |
"\(.key)=\"\(.value)\""
) |
.[]' <<< "$SECRETS_JSON_WITH_NEWLINES"
)
VARS_JSON_WITH_NEWLINES=$(cat<<EOF
${{ toJSON(vars) }}
EOF)
while IFS= read -r var; do
echo "$var" >> .env.${{ github.event.inputs.environment }}
done < <(
jq -r '
to_entries |
map(
select(.value | test("\n") | not) |
"\(.key)=\"\(.value)\""
) |
.[]' <<< "$VARS_JSON_WITH_NEWLINES"
)
- name: Deploy to ${{ github.event.inputs.environment }}
id: deploy
continue-on-error: ${{ github.event.inputs.debug == true }}
env:
DOMAIN: ${{ vars.DOMAIN }}
REPLICAS: ${{ vars.REPLICAS }}
NOTIFICATION_TRANSPORT: ${{ vars.NOTIFICATION_TRANSPORT }}
SMTP_PORT: ${{ secrets.SMTP_PORT }}
SMTP_HOST: ${{ secrets.SMTP_HOST }}
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
SMTP_SECURE: ${{ secrets.SMTP_SECURE }}
ALERT_EMAIL: ${{ secrets.ALERT_EMAIL }}
DOCKERHUB_ACCOUNT: ${{ secrets.DOCKERHUB_ACCOUNT }}
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_REPO }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
KIBANA_USERNAME: ${{ secrets.KIBANA_USERNAME }}
KIBANA_PASSWORD: ${{ secrets.KIBANA_PASSWORD }}
MONGODB_ADMIN_USER: ${{ secrets.MONGODB_ADMIN_USER }}
MONGODB_ADMIN_PASSWORD: ${{ secrets.MONGODB_ADMIN_PASSWORD }}
ELASTICSEARCH_SUPERUSER_PASSWORD: ${{ secrets.ELASTICSEARCH_SUPERUSER_PASSWORD }}
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
INFOBIP_SENDER_ID: ${{ secrets.INFOBIP_SENDER_ID }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
INFOBIP_GATEWAY_ENDPOINT: ${{ secrets.INFOBIP_GATEWAY_ENDPOINT }}
INFOBIP_API_KEY: ${{ secrets.INFOBIP_API_KEY }}
WIREGUARD_ADMIN_PASSWORD: ${{ secrets.WIREGUARD_ADMIN_PASSWORD }}
SENDER_EMAIL_ADDRESS: ${{ secrets.SENDER_EMAIL_ADDRESS }}
SUPER_USER_PASSWORD: ${{ secrets.SUPER_USER_PASSWORD }}
SSH_ARGS: ${{ vars.SSH_ARGS }}
CONTENT_SECURITY_POLICY_WILDCARD: ${{ vars.CONTENT_SECURITY_POLICY_WILDCARD }}
run: |
cd ./${{ github.event.repository.name }}
yarn deploy \
--clear_data=no \
--environment=${{ github.event.inputs.environment }} \
--host=${{ env.DOMAIN }} \
--host=${{ vars.DOMAIN }} \
--ssh_host=${{ secrets.SSH_HOST }} \
--ssh_user=${{ secrets.SSH_USER }} \
--version=${{ github.event.inputs.core-image-tag }} \
--country_config_version=${{ github.event.inputs.countryconfig-image-tag }} \
--replicas=${{ env.REPLICAS }}
--replicas=${{ vars.REPLICAS }}
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: ${{ github.event.inputs.debug == true }}
env:
DOMAIN: ${{ vars.DOMAIN }}
REPLICAS: ${{ vars.REPLICAS }}
NOTIFICATION_TRANSPORT: ${{ vars.NOTIFICATION_TRANSPORT }}
SMTP_PORT: ${{ secrets.SMTP_PORT }}
SMTP_HOST: ${{ secrets.SMTP_HOST }}
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
SMTP_SECURE: ${{ secrets.SMTP_SECURE }}
ALERT_EMAIL: ${{ secrets.ALERT_EMAIL }}
DOCKERHUB_ACCOUNT: ${{ secrets.DOCKERHUB_ACCOUNT }}
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_REPO }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
KIBANA_USERNAME: ${{ secrets.KIBANA_USERNAME }}
KIBANA_PASSWORD: ${{ secrets.KIBANA_PASSWORD }}
MONGODB_ADMIN_USER: ${{ secrets.MONGODB_ADMIN_USER }}
MONGODB_ADMIN_PASSWORD: ${{ secrets.MONGODB_ADMIN_PASSWORD }}
ELASTICSEARCH_SUPERUSER_PASSWORD: ${{ secrets.ELASTICSEARCH_SUPERUSER_PASSWORD }}
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
WIREGUARD_ADMIN_PASSWORD: ${{ secrets.WIREGUARD_ADMIN_PASSWORD }}
INFOBIP_SENDER_ID: ${{ secrets.INFOBIP_SENDER_ID }}
INFOBIP_GATEWAY_ENDPOINT: ${{ secrets.INFOBIP_GATEWAY_ENDPOINT }}
INFOBIP_API_KEY: ${{ secrets.INFOBIP_API_KEY }}
SENDER_EMAIL_ADDRESS: ${{ secrets.SENDER_EMAIL_ADDRESS }}
SUPER_USER_PASSWORD: ${{ secrets.SUPER_USER_PASSWORD }}
SSH_KEY: ${{ secrets.SSH_KEY }}
SSH_ARGS: ${{ vars.SSH_ARGS }}
CONTENT_SECURITY_POLICY_WILDCARD: ${{ vars.CONTENT_SECURITY_POLICY_WILDCARD }}

reset:
needs: deploy
if: ${{ github.event.inputs.reset == 'true' && needs.deploy.outputs.outcome == 'success' }}
Expand Down
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# Changelog

## [1.4.0](https://github.com/opencrvs/opencrvs-core/compare/v1.3.3...v1.4.0) (TBD)
## [1.4.0](https://github.com/opencrvs/opencrvs-farajaland/compare/v1.3.3...v1.4.0) (TBD)

- Adds examples of configuring HTTP-01, DNS-01 and manual HTTPS certificates By default development & QA uses HTTP-01 and others DNS-01.
- All secrets & variables defined in Github Secrets are now passed automatically to the deployment script
- Make VPN_HOST_ADDRESS variable required for staging and production installations. This is to verify deployments are not publicly accessible on public internet.

### Bug fixes

See [Releases](https://github.com/opencrvs/opencrvs-core/releases) for release notes of older releases.
See [Releases](https://github.com/opencrvs/opencrvs-farajaland/releases) for release notes of older releases.

## [1.3.3](https://github.com/opencrvs/opencrvs-farajaland/compare/v1.3.2...v1.3.3) (TBD)

Expand Down
3 changes: 1 addition & 2 deletions infrastructure/deployment/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ COMPOSE_FILES_USED="$COMPOSE_FILES_DOWNLOADED_FROM_CORE $INFRASTRUCTURE_DIRECTOR

echo $COMPOSE_FILES_USED


# Read environment variable file for the environment
# .env.qa
# .env.development
Expand Down Expand Up @@ -164,7 +163,7 @@ configured_rsync() {
get_environment_variables() {
local env_vars=""
# Define an array of variables to exclude
local exclude_vars=("PATH" "SSH_ARGS" "HOME" "LANG" "USER" "SHELL" "PWD" "KNOWN_HOSTS")
local exclude_vars=("PATH" "SSH_ARGS" "HOME" "LANG" "USER" "SHELL" "PWD")

while IFS='=' read -r name value; do
# Check if the variable is in the exclude list
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from 'fs'
import { basename } from 'path'

function extractEnvVars(content: string): string[] {
const regex = /(?<!\$)\$\{(.*?)\}/g
Expand Down Expand Up @@ -27,7 +28,7 @@ function main(): void {
// Taking file paths from command line arguments
const filePaths = process.argv.slice(2)
if (filePaths.length === 0) {
console.log('Please provide YAML file paths as arguments.')
console.error('Please provide YAML file paths as arguments.')
process.exit(1)
}

Expand All @@ -38,8 +39,16 @@ function main(): void {
const missingValues = requiredValues.filter((name) => !process.env[name])

if (missingValues.length > 0) {
console.log('Missing values for the following variables:')
console.log(missingValues)
console.log('\n\n')
console.error(
'Missing secrets or variables for values found in docker compose files:'
)
console.error(missingValues)
console.error(
'\nCheck the following files for more details:\n',
filePaths.map((path) => `- ${basename(path)}`).join('\n')
)
console.log('\n')
process.exit(1)
}
}
Expand Down
4 changes: 2 additions & 2 deletions infrastructure/docker-compose.deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ services:
# Note: these published port will override UFW rules as Docker manages it's own iptables
# Only publish the exact ports that are required for OpenCRVS to work
traefik:
image: 'traefik:v2.9'
image: 'traefik:v2.10'
ports:
- target: 80
published: 80
Expand All @@ -32,7 +32,7 @@ services:
- --api.dashboard=true
- --api.insecure=true
- --log.level=WARNING
- --certificatesresolvers.certResolver.acme.email=ryan@jembi.org
- --certificatesresolvers.certResolver.acme.email=riku@opencrvs.org
- --certificatesresolvers.certResolver.acme.storage=acme.json
- --certificatesresolvers.certResolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.certResolver.acme.httpchallenge.entrypoint=web
Expand Down
26 changes: 26 additions & 0 deletions infrastructure/docker-compose.development-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,29 @@ services:
environment:
- QA_ENV=true
- NODE_ENV=production

traefik:
command:
# Use HTTP-01 challenge as the web server is publicly available
# https://doc.traefik.io/traefik/https/acme/#httpchallenge
# For DNS-01 challenge and manual certificates, check staging and production configurations
- --certificatesresolvers.certResolver.acme.email=riku@opencrvs.org
- --certificatesresolvers.certResolver.acme.storage=acme.json
- --certificatesresolvers.certResolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.certResolver.acme.httpchallenge.entrypoint=web

- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.docker
- --providers.docker.swarmMode=true
- --api.dashboard=true
- --api.insecure=true
- --log.level=WARNING
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --serverstransport.insecureskipverify=true
- --entrypoints.websecure.address=:443
- --accesslog=true
- --accesslog.format=json
- --ping=true
Loading

0 comments on commit cbc90a2

Please sign in to comment.