Skip to content

Commit

Permalink
use vars rather than secrets where appropriate
Browse files Browse the repository at this point in the history
Plaintext variables were only introduced after the initial development
of Marxan’s CI workflows:
https://github.blog/changelog/2023-01-10-github-actions-support-for-configuration-variables-in-workflows/

Keeping only true secret values as GitHub Actions secrets allows better
inspectability of what is configured in terms of CI keys/values.
  • Loading branch information
hotzevzl committed Mar 19, 2024
1 parent 9aa6eae commit f8a5c20
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 84 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/deploy-to-kubernetes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:

- name: Add custom host data
run: |
sudo sh -c 'echo "127.0.0.1 ${{ secrets.AZURE_AKS_HOST }}" >> /etc/hosts'
sudo sh -c 'echo "127.0.0.1 ${{ env.AZURE_AKS_HOST }}" >> /etc/hosts'
- name: Install kubectl
uses: azure/setup-kubectl@v3
Expand All @@ -88,12 +88,12 @@ jobs:
- name: Config kubectl
run: |
mkdir ~/.kube
az aks get-credentials --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} --name ${{ secrets.AZURE_AKS_CLUSTER_NAME }}
az aks get-credentials --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --name ${{ env.AZURE_AKS_CLUSTER_NAME }}
sed -i 's/\([[:alnum:]]\+\?.privatelink.[[:alnum:]]\+\?.azmk8s.io\):443/\1:4433/g' ~/.kube/config
- name: Creating SSH tunnel
run: |
ssh -i ~/.ssh/bastion.key -o StrictHostKeyChecking=no -N -L 4433:${{ secrets.AZURE_AKS_HOST }}:443 ${{ secrets.BASTION_USER }}@${{ secrets.BASTION_HOST }} -T &
ssh -i ~/.ssh/bastion.key -o StrictHostKeyChecking=no -N -L 4433:${{ env.AZURE_AKS_HOST }}:443 ${{ env.BASTION_USER }}@${{ env.BASTION_HOST }} -T &
- name: Redeploy production pods
if: ${{ github.ref == 'refs/heads/main' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
path: playwright-report/
retention-days: 30
env:
NEXT_PUBLIC_MAPBOX_API_TOKEN: ${{ secrets.NEXT_PUBLIC_MAPBOX_API_TOKEN }}
NEXT_PUBLIC_MAPBOX_API_TOKEN: ${{ env.NEXT_PUBLIC_MAPBOX_API_TOKEN }}
# Recommended: pass the GitHub token lets this action correctly
# determine the unique run id necessary to re-run the checks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42 changes: 21 additions & 21 deletions .github/workflows/publish-marxan-docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ jobs:
- name: Build and push image
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
login-server: ${{ env.REGISTRY_LOGIN_SERVER }}
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- run: |
docker build ./api -f api/api.Dockerfile \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-api:${{ github.sha }} \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-api:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-api
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-api:${{ github.sha }} \
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-api:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-api
push_geoprocessing_to_registry:
name: Push Geoprocessing Docker image to Azure Container Registry
Expand All @@ -95,15 +95,15 @@ jobs:
- name: Build and push image
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
login-server: ${{ env.REGISTRY_LOGIN_SERVER }}
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- run: |
docker build ./api -f api/geo.Dockerfile \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing:${{ github.sha }} \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing:${{ github.sha }} \
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-geoprocessing
push_client_to_registry:
name: Push Client Docker image to Azure Container Registry
Expand All @@ -124,19 +124,19 @@ jobs:
- name: Build and push image
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
login-server: ${{ env.REGISTRY_LOGIN_SERVER }}
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- run: |
docker build ./app \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-client:${{ github.sha }} \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-client:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }} \
--build-arg NEXT_PUBLIC_URL=${{ github.ref != 'refs/heads/main' && secrets.NEXT_PUBLIC_URL_STAGING || secrets.NEXT_PUBLIC_URL_PRODUCTION }} \
--build-arg NEXT_PUBLIC_API_URL=${{ github.ref != 'refs/heads/main' && secrets.NEXT_PUBLIC_API_URL_STAGING || secrets.NEXT_PUBLIC_API_URL_PRODUCTION }} \
--build-arg NEXTAUTH_URL=${{ github.ref != 'refs/heads/main' && secrets.NEXTAUTH_URL_STAGING || secrets.NEXTAUTH_URL_PRODUCTION }} \
--build-arg NEXT_PUBLIC_FEATURE_FLAGS=${{ github.ref != 'refs/heads/main' && secrets.NEXT_PUBLIC_FEATURE_FLAGS_STAGING || secrets.NEXT_PUBLIC_FEATURE_FLAGS_PRODUCTION }} \
--build-arg NEXT_PUBLIC_MAPBOX_API_TOKEN=${{ secrets.NEXT_PUBLIC_MAPBOX_API_TOKEN }} \
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-client:${{ github.sha }} \
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-client:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }} \
--build-arg NEXT_PUBLIC_URL=${{ github.ref != 'refs/heads/main' && env.NEXT_PUBLIC_URL_STAGING || env.NEXT_PUBLIC_URL_PRODUCTION }} \
--build-arg NEXT_PUBLIC_API_URL=${{ github.ref != 'refs/heads/main' && env.NEXT_PUBLIC_API_URL_STAGING || env.NEXT_PUBLIC_API_URL_PRODUCTION }} \
--build-arg NEXTAUTH_URL=${{ github.ref != 'refs/heads/main' && env.NEXTAUTH_URL_STAGING || env.NEXTAUTH_URL_PRODUCTION }} \
--build-arg NEXT_PUBLIC_FEATURE_FLAGS=${{ github.ref != 'refs/heads/main' && env.NEXT_PUBLIC_FEATURE_FLAGS_STAGING || env.NEXT_PUBLIC_FEATURE_FLAGS_PRODUCTION }} \
--build-arg NEXT_PUBLIC_MAPBOX_API_TOKEN=${{ env.NEXT_PUBLIC_MAPBOX_API_TOKEN }} \
--build-arg ENABLE_MAINTENANCE_MODE=${{ github.event.inputs.enable_maintenance_mode }} \
--build-arg NEXT_PUBLIC_CONTACT_EMAIL=${{ secrets.NEXT_PUBLIC_CONTACT_EMAIL }}
docker push -a ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-client
--build-arg NEXT_PUBLIC_CONTACT_EMAIL=${{ env.NEXT_PUBLIC_CONTACT_EMAIL }}
docker push -a ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-client
10 changes: 5 additions & 5 deletions .github/workflows/publish-webshot-docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ jobs:
- name: Build and push image
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
login-server: ${{ env.REGISTRY_LOGIN_SERVER }}
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- run: |
docker build ./webshot \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-webshot:${{ github.sha }} \
-t ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-webshot:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ secrets.REGISTRY_LOGIN_SERVER }}/marxan-webshot
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-webshot:${{ github.sha }} \
-t ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-webshot:${{ github.ref != 'refs/heads/main' && 'staging' || 'production' }}
docker push -a ${{ env.REGISTRY_LOGIN_SERVER }}/marxan-webshot
34 changes: 25 additions & 9 deletions infrastructure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,39 @@ the services on kubernetes, which is done by this plan.

#### Github Actions

As part of this infrastructure, Github Actions are used to automatically build and push Docker images to Azure ACR, and
to redeploy Kubernetes pods once that happens. Said Github Actions depend on specific Github Secrets, that are listed below
for reference. Said secrets are automatically created by the `base` Terraform project, and do not need to be created manually.
As part of this infrastructure, Github Actions are used to automatically build
and push Docker images to Azure ACR, and to redeploy Kubernetes pods once that
happens. Said Github Actions depend on specific Github Secrets and Variables,
that are listed below for reference.

Secrets and variables listed below are automatically created by the `base`
Terraform project, and do not need to be created manually. Their value often
depends on the outputs of other Terraform modules, so configuring all these via
Terraform (and avoiding to change them manually within the settings of the
relevant GitHub repository) guarantees that values available to GitHub actions
are always coherent with the state of the terraformed infrastructure.

For example, AKS-related variables depend on settings for the cluster name as
well as the hostname of the AKS API server, which is assigned by Azure upon
creation of an AKS cluster.

##### Secrets

- `AZURE_AKS_CLUSTER_NAME`: The name of the AKS cluster. Get from `Base`'s `k8s_cluster_name`
- `AZURE_AKS_HOST`: The AKS cluster hostname (without port or protocol). Get from `Base`'s `k8s_cluster_private_fqdn`
- `AZURE_CLIENT_ID`: The hostname for the Azure ACT. Get from `Base`'s `container_registry_client_id`
- `AZURE_RESOURCE_GROUP`: The AKS Resource Group name. Specified by you when setting up the infrastructure.
- `AZURE_SUBSCRIPTION_ID`: The Azure Subscription Id. Get from `Base`'s `azure_subscription_id`
- `AZURE_TENANT_ID`: The Azure Tenant Id. Get from `Base`'s `azure_tenant_id`
- `BASTION_SSH_PRIVATE_KEY`: The ssh private key to access the bastion host. Get it by connection to the bastion host using SSH, and generating a new public/private SSH key pair.
- `REGISTRY_PASSWORD`: The password to access the Azure. Get from `Base`'s `container_registry_password`

##### Variables

- `AZURE_AKS_CLUSTER_NAME`: The name of the AKS cluster. Get from `Base`'s `k8s_cluster_name`
- `AZURE_AKS_HOST`: The AKS cluster hostname (without port or protocol). Get from `Base`'s `k8s_cluster_private_fqdn`
- `AZURE_RESOURCE_GROUP`: The AKS Resource Group name. Specified by you when setting up the infrastructure.
- `BASTION_HOST`: The hostname for the bastion machine. Get from `Base`'s `bastion_hostname`
- `BASTION_USER`: By default this will be `ubuntu` if using the initial user created on bastion host instantiation. It is configurable in case infrastructure admins wish to configure a different user on the bastion host or the default distro user is renamed.
- `BASTION_SSH_PRIVATE_KEY`: The ssh private key to access the bastion host. Get it by connection to the bastion host using SSH, and generating a new public/private SSH key pair.
- `REGISTRY_LOGIN_SERVER`: The hostname for the Azure ACR. Get from `Base`'s `container_registry_hostname`
- `REGISTRY_USERNAME`: The username for the Azure ACR. Get from `Base`'s `container_registry_client_id`
- `REGISTRY_PASSWORD`: The password to access the Azure. Get from `Base`'s `container_registry_password`
- `BASTION_SSH_PRIVATE_KEY`: The ssh private key to access the bastion host. Get it by connection to the bastion host using SSH, and generating a new public/private SSH key pair.

Additional Github Actions Secrets are needed, as required by the [frontend application](../app/README.md#env-variables)
and used by the corresponding [Github workflow](../.github/workflows/publish-marxan-docker-images.yml) that builds
Expand Down
90 changes: 45 additions & 45 deletions infrastructure/base/modules/github_secrets/main.tf
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
resource "github_actions_secret" "azure_aks_cluster_name" {
resource "github_actions_variable" "azure_aks_cluster_name" {
repository = var.repo_name
secret_name = "AZURE_AKS_CLUSTER_NAME"
plaintext_value = var.aks_cluster_name
variable_name = "AZURE_AKS_CLUSTER_NAME"
value = var.aks_cluster_name
}

resource "github_actions_secret" "azure_aks_host" {
resource "github_actions_variable" "azure_aks_host" {
repository = var.repo_name
secret_name = "AZURE_AKS_HOST"
plaintext_value = var.aks_host
variable_name = "AZURE_AKS_HOST"
value = var.aks_host
}

resource "github_actions_secret" "azure_client_id" {
Expand All @@ -16,10 +16,10 @@ resource "github_actions_secret" "azure_client_id" {
plaintext_value = var.client_id
}

resource "github_actions_secret" "azure_resource_group" {
resource "github_actions_variable" "azure_resource_group" {
repository = var.repo_name
secret_name = "AZURE_RESOURCE_GROUP"
plaintext_value = var.resource_group_name
variable_name = "AZURE_RESOURCE_GROUP"
value = var.resource_group_name
}

resource "github_actions_secret" "azure_subscription_id" {
Expand All @@ -34,10 +34,10 @@ resource "github_actions_secret" "azure_tenant_id" {
plaintext_value = var.tenant_id
}

resource "github_actions_secret" "bastion_host" {
resource "github_actions_variable" "bastion_host" {
repository = var.repo_name
secret_name = "BASTION_HOST"
plaintext_value = var.bastion_host
variable_name = "BASTION_HOST"
value = var.bastion_host
}

resource "github_actions_secret" "bastion_ssh_private_key" {
Expand All @@ -46,16 +46,16 @@ resource "github_actions_secret" "bastion_ssh_private_key" {
plaintext_value = var.bastion_ssh_private_key
}

resource "github_actions_secret" "bastion_user" {
resource "github_actions_variable" "bastion_user" {
repository = var.repo_name
secret_name = "BASTION_USER"
plaintext_value = var.bastion_user
variable_name = "BASTION_USER"
value = var.bastion_user
}

resource "github_actions_secret" "registry_login_server" {
resource "github_actions_variable" "registry_login_server" {
repository = var.repo_name
secret_name = "REGISTRY_LOGIN_SERVER"
plaintext_value = var.registry_login_server
variable_name = "REGISTRY_LOGIN_SERVER"
value = var.registry_login_server
}

resource "github_actions_secret" "registry_password" {
Expand All @@ -64,56 +64,56 @@ resource "github_actions_secret" "registry_password" {
plaintext_value = var.registry_password
}

resource "github_actions_secret" "registry_username" {
resource "github_actions_variable" "registry_username" {
repository = var.repo_name
secret_name = "REGISTRY_USERNAME"
plaintext_value = var.registry_username
variable_name = "REGISTRY_USERNAME"
value = var.registry_username
}

resource "github_actions_secret" "mapbox_api_token" {
resource "github_actions_variable" "mapbox_api_token" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_MAPBOX_API_TOKEN"
plaintext_value = var.mapbox_api_token
variable_name = "NEXT_PUBLIC_MAPBOX_API_TOKEN"
value = var.mapbox_api_token
}

resource "github_actions_secret" "contact_email" {
resource "github_actions_variable" "contact_email" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_CONTACT_EMAIL"
plaintext_value = var.support_email
variable_name = "NEXT_PUBLIC_CONTACT_EMAIL"
value = var.support_email
}

resource "github_actions_secret" "next_public_api_url_production" {
resource "github_actions_variable" "next_public_api_url_production" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_API_URL_PRODUCTION"
plaintext_value = "https://api.${var.domain}"
variable_name = "NEXT_PUBLIC_API_URL_PRODUCTION"
value = "https://api.${var.domain}"
}

resource "github_actions_secret" "next_public_url_production" {
resource "github_actions_variable" "next_public_url_production" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_URL_PRODUCTION"
plaintext_value = "https://${var.domain}"
variable_name = "NEXT_PUBLIC_URL_PRODUCTION"
value = "https://${var.domain}"
}

resource "github_actions_secret" "nextauth_url_production" {
resource "github_actions_variable" "nextauth_url_production" {
repository = var.repo_name
secret_name = "NEXTAUTH_URL_PRODUCTION"
plaintext_value = "https://client.${var.domain}"
variable_name = "NEXTAUTH_URL_PRODUCTION"
value = "https://client.${var.domain}"
}

resource "github_actions_secret" "next_public_api_url_staging" {
resource "github_actions_variable" "next_public_api_url_staging" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_API_URL_STAGING"
plaintext_value = "https://api.staging.${var.domain}"
variable_name = "NEXT_PUBLIC_API_URL_STAGING"
value = "https://api.staging.${var.domain}"
}

resource "github_actions_secret" "next_public_url_staging" {
resource "github_actions_variable" "next_public_url_staging" {
repository = var.repo_name
secret_name = "NEXT_PUBLIC_URL_STAGING"
plaintext_value = "https://staging.${var.domain}"
variable_name = "NEXT_PUBLIC_URL_STAGING"
value = "https://staging.${var.domain}"
}

resource "github_actions_secret" "nextauth_url_staging" {
resource "github_actions_variable" "nextauth_url_staging" {
repository = var.repo_name
secret_name = "NEXTAUTH_URL_STAGING"
plaintext_value = "https://client.staging.${var.domain}"
variable_name = "NEXTAUTH_URL_STAGING"
value = "https://client.staging.${var.domain}"
}

0 comments on commit f8a5c20

Please sign in to comment.