diff --git a/.github/workflows/azure-deploy-dev.yml b/.github/workflows/azure-deploy-dev.yml index 252ca7f1..4eaa95a6 100644 --- a/.github/workflows/azure-deploy-dev.yml +++ b/.github/workflows/azure-deploy-dev.yml @@ -28,6 +28,7 @@ env: ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} DOCKER_IMAGE: ghcr.io/dfe-digital/help-for-early-years-providers + RELEASE_VERSION: ${{ github.sha }} jobs: build-and-deploy: @@ -69,7 +70,7 @@ jobs: build-args: BUILDKIT_INLINE_CACHE=1 cache-from: | ${{ env.DOCKER_IMAGE }}-dev:builder - push: true + push: true tags: ${{ env.DOCKER_IMAGE }}-dev:builder target: builder @@ -81,7 +82,7 @@ jobs: build-args: BUILDKIT_INLINE_CACHE=1 cache-from: | ${{ env.DOCKER_IMAGE }}-dev:gems-node-modules - push: true + push: true tags: ${{ env.DOCKER_IMAGE }}-dev:gems-node-modules target: help-for-early-years-providers-gems-node-modules @@ -93,7 +94,7 @@ jobs: build-args: BUILDKIT_INLINE_CACHE=1 cache-from: | ${{ env.DOCKER_IMAGE }}-dev:assets-precompile - push: true + push: true tags: ${{ env.DOCKER_IMAGE }}-dev:assets-precompile target: assets-precompile @@ -126,4 +127,4 @@ jobs: uses: azure/webapps-deploy@v2 with: app-name: ${{ vars.WEBAPP_NAME }} - images: ${{ env.DOCKER_IMAGE }}:${{ github.sha }} \ No newline at end of file + images: ${{ env.DOCKER_IMAGE }}:${{ github.sha }} diff --git a/.github/workflows/azure-deploy-stage.yml b/.github/workflows/azure-deploy-stage.yml new file mode 100644 index 00000000..df012720 --- /dev/null +++ b/.github/workflows/azure-deploy-stage.yml @@ -0,0 +1,92 @@ +name: 'HfEYP App Deploy [Azure - STAGE]' + +on: + workflow_dispatch: + inputs: + candidate: + description: 'Create release candidate version ("rcx.x.x")' + type: string + required: true + ref: + description: 'Git ref or branch to deploy' + type: string + required: true + default: main + +# Permissions for OIDC authentication +permissions: + id-token: write + contents: write + packages: write + +env: + ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + DOCKER_IMAGE: ghcr.io/dfe-digital/help-for-early-years-providers + RELEASE_VERSION: ${{ inputs.candidate || github.sha }} + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + environment: staging + steps: + # Checkout the repository to the GitHub Actions runner + - name: Checkout Code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref_name }} + + # Tag the branch with the release candidate version + - name: Tag candidate + if: ${{ inputs.candidate }} + run: | + git tag --force ${{ inputs.candidate }} + git push --force origin refs/tags/${{ inputs.candidate }} + echo "HEAD=$(git rev-parse ${{ inputs.candidate }})" >> $GITHUB_ENV + + # Create and boot Docker image builder + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + version: v0.9.1 + + # Login to Github Container Registry + - name: Login to Github Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build and push image + - name: Build and push Docker Image + uses: docker/build-push-action@v5 + with: + target: production + context: . + file: Dockerfile.azure + build-args: | + BUILDKIT_INLINE_CACHE=1 + SHA=${{ github.sha }} + cache-from: | + ${{ env.DOCKER_IMAGE }}:${{ github.sha }} + ${{ env.DOCKER_IMAGE }}:${{ inputs.ref || github.ref_name }} + tags: | + ${{ env.DOCKER_IMAGE }}:${{ github.sha }} + ${{ env.DOCKER_IMAGE }}:${{ inputs.candidate || github.ref_name }} + + # Login to Azure using OIDC + - name: Login to Azure CLI + uses: azure/login@v1 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + # Deploy Web Application + - name: Deploy to Azure App Services + uses: azure/webapps-deploy@v2 + with: + app-name: ${{ vars.WEBAPP_NAME }} + images: ${{ env.DOCKER_IMAGE }}:${{ inputs.candidate || github.ref_name }} \ No newline at end of file diff --git a/config/credentials/production.yml.enc b/config/credentials/production.yml.enc index 2e9408b0..d177aed7 100644 --- a/config/credentials/production.yml.enc +++ b/config/credentials/production.yml.enc @@ -1 +1 @@ -MNHimzHKDFqAUc9oJSgl6ulO+sw2H7QjpmpfcBj0JvHlP9DTGj2ZW0EYRCJrcgvA/+84UUWTK3ueNLQBR9/eJtTDYrL2RDI3STFtZdbMYkCvDJCpx8kGvCoTjpKRKt+3S4tKmDQfCrDmjywQw+gRbjL6fUCy5w5mh3qDbpuvUXFYfeu1Ck0Zx9IZJ9Q6WsbL3D0TuHQftpfCnZHjmkCbJkXLgk3hOttbtYMXtvyzpSgc8S2XVHsqCPhEtk7oQueyPSpNE40wBEXzGLMaj7Yy9hLHKUI2ZJd0SK0WmnQexP6hguvAT5upHeKLF5VXzDmkybdi3qDzn4zy5Q7VYum5K3OcrMlOoiY2meuYy8uSkIrtUJ9xTdiqel0Fk+QoPSE954FQRe9RFWBRhD3DNeCkbCimaKF2lCbiE7X6Kd+Gr/c33MGH8/Q+Nv72vUHVB2QqT0xyKmkFKqNgaeSVqTaH//Ii6fYmP3CaORNi/rOeiB2edX16bQn/gL8qQWuHg38J0ojR9cFRtmm76Jv6Ped9CYQSRsrGwz3wFn2WKMq+QR5+zTIXXnyItPEmbMwCzwhkagW60HyeONG78QLmKz34uYVvCGPPgLeDCOXMNy8hyVkNcThEZWBH6nlRXfPrj4HgVzZkg9snl8bkds0izLPNppJJNCjAy+m6Lbr7QJDf8g0UtNjkscaOP3e5ahw/Ihk8maMq20L5oq6xuTm4dcrm6R/oTnYPn5TIAGEa/RYg+MErLLLBgRRfdOwKSmeQNdbSNbYh6bRzp72QkwNqK9AkIs8gt9p9qloeDnDir+09Y8QN7NUAHMcTpUCY5B/tf+/6NYwZf0P7n0can0AWyv0PKMCBnAyxeZH3PoP5Kt0NM/3RZZhfWde/o/izE5+fMrYhk08sltHw1kcj9h8z4BrXBPu0I1KWAvFGTAF7FENJtnvnnuLZ15jdsaWgCjznv/ysbRU6orm/Tp5CSXbrGGGb/GYdCekFpVnqUKW3ZozORYWnT4e8DgGhastGOp48KRvsfpd1WUy9v8M=--E5LhUUa8YnK1vAHX--Ra7YwT8uHdwB/qzEzSpLfw== \ No newline at end of file +3bh88bS4CI7nS/DOCV9D9DHKoxieWMxD5Xsxh8HF2azlEUtMVGIHZT9fI3UkCZB5mwezDX1qjc8XqeBEmK/Le/rMNgNHffbMcBjMe31tVz7b4DOi74Uv69XobhvSTCp4syZ15OuHiG5CRiwQCeT0keXO9Bb3tBx0MbdjLQCsnG6JGGAm6Emkmqo8rD2cgwyxQ90XoBfz9szhFyr7Nnv7aA8PTbx58CrhoF19OtUFeFRWpS9kJ4FTNN9tiGAzEm4Sq2faAJf4Nr8hx+M2MGkoOPKZnBVZT/1N4CJCkDYTySLa+jLb2iD9fLrqD4TCJOZkY/4xIRC+2xb7j0+9Vq4cR4wG3Ber5eAhVi1jaXGJhcjC/jedQ+mEvYoBc+6Rl0QS23Tyc+o21lw93oE9UK2bRE2yRwU+/DB/mELPIg4ZD9wLKdm8Lhcsj7ckVp1j3Z8VP+qsLnhU1U/wxuW7FvHyo+Bm4LpP3/lJhOk5bkqxII26n3IdhWcjneir27Nb/q6SgtUfvvaklWrx2yCbCB5tQbzWCrwWfG5adR/x3Aa5Q7RIz7kBuxkQQLH4xPXUPJaSZB4ByKjJtuIxGBw6Y7SenYfl/JVKknZw7JiiyRmY9pvEFgf3reWmwJZaJBMt6igZJX14z1K4XJ+PJyQv8GbCnxlf5HtiMJmqhaHBIXArFaBKpUVC2TGa2ovbVISdl2KapIb+/el7z9+4Xa4FEfKluvhVWsWEunUZjUqsy4xWTPBrnOgHBEW4v3Hsz8aEYq51PwyT6FQCCFwovcNcTWHm+UzYBLPyTwH4EFm0gErdgp5QKvT1vVu1WfHajLh/8sLVJYNmYc8uY8fUvSaYpNNvFJbv0KxR0FMo60LBt4hihRBYivfdADm5OSMZn/FBHgDec0A5wwxSWQHe3EgSAxwuoAqQNDjRg6p5xsO6pBgo+RxZKRbLnwt8ZJRvwKnnh3enQFQXrecYMG4BMnVup1qQVJDwufK8lFvp7n/AzCzguyHjJiY2HWYfcVK8cXRMhIirW/CRlJOqS2+6YZlEVr8t/nTkMFIWm6VaYJL+XT/q4IBypNfR1NyUPrIi--q/wx5B6nVwp4CgHK--rScnJ5MUq8ZWzfxsLa0Z2A== \ No newline at end of file diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index a95d9f27..8894a3e5 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -41,6 +41,7 @@ policy.font_src :self, :https, *GOVUK_DOMAINS, *GOOGLE_STATIC_DOMAINS, :data policy.frame_src :self, *GOOGLE_ANALYTICS_DOMAINS, *OPTIMIZE_DOMAINS policy.img_src :self, + "images.ctfassets.net", *GOVUK_DOMAINS, *S3_DOMAINS, *GOOGLE_ANALYTICS_DOMAINS, # Tracking pixels diff --git a/config/routes.rb b/config/routes.rb index 16c50039..b2cae70a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ Rails.application.routes.draw do get "/check" => "application#check" + get "/health" => "application#check" # Note These have to be above the wildcard route get "/404", to: "errors#not_found", via: :all diff --git a/entrypoints/docker-entrypoint.sh b/entrypoints/docker-entrypoint.sh index 558502f9..c2dda137 100755 --- a/entrypoints/docker-entrypoint.sh +++ b/entrypoints/docker-entrypoint.sh @@ -9,6 +9,8 @@ fi /usr/sbin/sshd +eval $(printenv | sed -n "s/^\([^=]\+\)=\(.*\)$/export \1=\2/p" | sed 's/"/\\\"/g' | sed '/=/s//="/' | sed 's/$/"/' >> /etc/profile) + bundle exec rake db:prepare db:seed # Start the application diff --git a/terraform-azure/terraform-azure-database/main.tf b/terraform-azure/terraform-azure-database/main.tf index 65f34c31..5d84a1bc 100644 --- a/terraform-azure/terraform-azure-database/main.tf +++ b/terraform-azure/terraform-azure-database/main.tf @@ -56,4 +56,4 @@ resource "azurerm_postgresql_flexible_server_database" "psqldb_slot" { server_id = azurerm_postgresql_flexible_server.psqlfs.id collation = "en_US.utf8" charset = "utf8" -} \ No newline at end of file +} diff --git a/terraform-azure/terraform-azure-remote-state/main.tf b/terraform-azure/terraform-azure-remote-state/main.tf index 5ed7e406..516bf099 100644 --- a/terraform-azure/terraform-azure-remote-state/main.tf +++ b/terraform-azure/terraform-azure-remote-state/main.tf @@ -86,6 +86,8 @@ resource "azurerm_storage_account" "tfstate" { #checkov:skip=CKV2_AZURE_1:Microsoft Managed keys are sufficient #checkov:skip=CKV2_AZURE_38:Soft-delete not required #checkov:skip=CKV2_AZURE_33:VNet not configured + #checkov:skip=CKV2_AZURE_41:Ensure storage account is configured with SAS expiration policy + #checkov:skip=CKV2_AZURE_40:Ensure storage account is not configured with Shared Key authorization } resource "azurerm_storage_container" "tfstate" { diff --git a/terraform-azure/terraform-azure-web/webapp.tf b/terraform-azure/terraform-azure-web/webapp.tf index 379b9859..9d0d97e6 100644 --- a/terraform-azure/terraform-azure-web/webapp.tf +++ b/terraform-azure/terraform-azure-web/webapp.tf @@ -12,6 +12,7 @@ resource "azurerm_service_plan" "asp" { } #checkov:skip=CKV_AZURE_212:Argument not available + #checkov:skip=CKV_AZURE_225:Ensure the App Service Plan is zone redundant } # Create Web Application @@ -354,4 +355,4 @@ resource "azurerm_app_service_certificate_binding" "webapp_custom_domain_cert_bi hostname_binding_id = azurerm_app_service_custom_hostname_binding.webapp_custom_domain[0].id certificate_id = azurerm_app_service_certificate.webapp_custom_domain_cert[0].id ssl_state = "SniEnabled" -} \ No newline at end of file +} diff --git a/terraform-azure/variables.tf b/terraform-azure/variables.tf index d7279847..1a3eee99 100644 --- a/terraform-azure/variables.tf +++ b/terraform-azure/variables.tf @@ -5,13 +5,13 @@ variable "azure_region" { } variable "environment" { - default = "development" + default = "staging" description = "Environment to deploy resources" type = string } variable "resource_name_prefix" { - default = "s195d01-hfeyp" + default = "s195t01-hfeyp" description = "Prefix for resource names" type = string }