diff --git a/.github/workflows/tf-azure-deploy-stage.yml b/.github/workflows/tf-azure-deploy-stage.yml
new file mode 100644
index 000000000..e716310c0
--- /dev/null
+++ b/.github/workflows/tf-azure-deploy-stage.yml
@@ -0,0 +1,164 @@
+name: 'Terraform Deploy [Azure - STAGE]'
+
+on:
+ workflow_dispatch:
+
+defaults:
+ run:
+ working-directory: ./terraform-azure
+
+# Permissions for OIDC authentication
+permissions:
+ id-token: write
+ contents: write
+
+env:
+ ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
+ ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
+ ARM_USE_OIDC: true
+ ARM_SKIP_PROVIDER_REGISTRATION: true
+
+jobs:
+ terraform-plan:
+ name: 'Terraform Plan'
+ runs-on: ubuntu-latest
+ environment: staging
+ outputs:
+ tfplanExitCode: ${{ steps.tf-plan.outputs.exitcode }}
+
+ steps:
+ # Checkout the repository to the GitHub Actions runner
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ # Install the latest version of the Terraform CLI
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v2
+ with:
+ terraform_version: 1.5.6
+ terraform_wrapper: false
+
+ # Initialise a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
+ - name: Terraform Init
+ run: >
+ terraform init
+ -backend-config="resource_group_name=${{ secrets.TERRAFORM_STATE_RESOURCE_GROUP }}"
+ -backend-config="storage_account_name=${{ secrets.TERRAFORM_STATE_STORAGE_ACCOUNT_NAME }}"
+ -backend-config="container_name=${{ secrets.TERRAFORM_STATE_STORAGE_CONTAINER_NAME }}"
+ -backend-config="key=${{ secrets.TERRAFORM_STATE_KEY }}"
+
+ # Checks that all Terraform configuration files adhere to a canonical format
+ # Will fail the build if not
+ - name: Terraform Format
+ run: terraform fmt -check
+
+ # Generates Terraform input variables
+ - name: Generate Terraform Variables
+ shell: bash
+ env:
+ WEB_SECRETS: ${{ toJSON(secrets) }}
+ WEB_VARS: ${{ toJSON(vars) }}
+ run: |
+ printf '%s\n' "$WEB_SECRETS" > tmp-secrets.json
+ printf '%s\n' "$WEB_VARS" > tmp-vars.json
+ jq 'with_entries(.key |= ascii_downcase)' tmp-secrets.json > web-secrets.auto.tfvars.json
+ jq 'with_entries(.key |= ascii_downcase)' tmp-vars.json > web-vars.auto.tfvars.json
+
+ # Generates an execution plan for Terraform
+ # An exit code of 0 indicated no changes, 1 a terraform failure, 2 there are pending changes.
+ - name: Terraform Plan
+ id: tf-plan
+ run: |
+ export exitcode=0
+ terraform plan -detailed-exitcode -no-color -out tfplan || export exitcode=$?
+
+ echo "exitcode=$exitcode" >> $GITHUB_OUTPUT
+
+ if [ $exitcode -eq 1 ]; then
+ echo Terraform Plan Failed!
+ exit 1
+ else
+ exit 0
+ fi
+
+ # Save Terraform Plan
+ - name: Publish Terraform Plan
+ uses: actions/upload-artifact@v3
+ with:
+ name: tfplan
+ path: terraform-azure/tfplan
+
+ # Create string output of Terraform Plan
+ - name: Create String Output
+ id: tf-plan-string
+ run: |
+ TERRAFORM_PLAN=$(terraform show -no-color tfplan)
+
+ delimiter="$(openssl rand -hex 8)"
+ echo "summary<<${delimiter}" >> $GITHUB_OUTPUT
+ echo "## Terraform Plan Output" >> $GITHUB_OUTPUT
+ echo "Click to expand
" >> $GITHUB_OUTPUT
+ echo "" >> $GITHUB_OUTPUT
+ echo '```terraform' >> $GITHUB_OUTPUT
+ echo "$TERRAFORM_PLAN" >> $GITHUB_OUTPUT
+ echo '```' >> $GITHUB_OUTPUT
+ echo " " >> $GITHUB_OUTPUT
+ echo "${delimiter}" >> $GITHUB_OUTPUT
+
+ # Publish Terraform Plan as task summary
+ - name: Publish Terraform Plan to Task Summary
+ env:
+ SUMMARY: ${{ steps.tf-plan-string.outputs.summary }}
+ run: |
+ echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY
+
+# terraform-apply:
+# name: 'Terraform Apply'
+# if: needs.terraform-plan.outputs.tfplanExitCode == 2
+# runs-on: ubuntu-latest
+# environment: staging
+# needs: [terraform-plan]
+#
+# steps:
+# # Checkout the repository to the GitHub Actions runner
+# - name: Checkout
+# uses: actions/checkout@v4
+#
+# # Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token
+# - name: Setup Terraform
+# uses: hashicorp/setup-terraform@v2
+# with:
+# terraform_version: 1.5.6
+#
+# # Initialise a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
+# - name: Terraform Init
+# run: >
+# terraform init
+# -backend-config="resource_group_name=${{ secrets.TERRAFORM_STATE_RESOURCE_GROUP }}"
+# -backend-config="storage_account_name=${{ secrets.TERRAFORM_STATE_STORAGE_ACCOUNT_NAME }}"
+# -backend-config="container_name=${{ secrets.TERRAFORM_STATE_STORAGE_CONTAINER_NAME }}"
+# -backend-config="key=${{ secrets.TERRAFORM_STATE_KEY }}"
+#
+# # Generates Terraform input variables
+# - name: Generate Terraform Variables
+# shell: bash
+# env:
+# WEB_SECRETS: ${{ toJSON(secrets) }}
+# WEB_VARS: ${{ toJSON(vars) }}
+# run: |
+# printf '%s\n' "$WEB_SECRETS" > tmp-secrets.json
+# printf '%s\n' "$WEB_VARS" > tmp-vars.json
+# jq 'with_entries(.key |= ascii_downcase)' tmp-secrets.json > web-secrets.auto.tfvars.json
+# jq 'with_entries(.key |= ascii_downcase)' tmp-vars.json > web-vars.auto.tfvars.json
+#
+# # Download saved plan from artifacts
+# - name: Download Terraform Plan
+# uses: actions/download-artifact@v3
+# with:
+# name: tfplan
+# path: terraform-azure/tfplan
+#
+# # Terraform Apply
+# - name: Terraform Apply
+# run: terraform apply -auto-approve tfplan/tfplan
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index aa8bf9d0c..93c312bb8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -217,6 +217,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
+ google-protobuf (3.24.0)
google-protobuf (3.24.0-aarch64-linux)
google-protobuf (3.24.0-arm64-darwin)
google-protobuf (3.24.0-x86_64-darwin)
@@ -330,6 +331,7 @@ GEM
memoist (0.16.2)
method_source (1.0.0)
mini_mime (1.1.5)
+ mini_portile2 (2.8.4)
minitest (5.20.0)
msgpack (1.6.0)
multi_json (1.15.0)
@@ -343,6 +345,9 @@ GEM
net-smtp (0.3.3)
net-protocol
nio4r (2.5.9)
+ nokogiri (1.15.4)
+ mini_portile2 (~> 2.8.2)
+ racc (~> 1.4)
nokogiri (1.15.4-aarch64-linux)
racc (~> 1.4)
nokogiri (1.15.4-arm64-darwin)
@@ -795,6 +800,7 @@ PLATFORMS
arm64-darwin-20
arm64-darwin-21
arm64-darwin-22
+ ruby
x86_64-darwin-19
x86_64-darwin-20
x86_64-darwin-21
diff --git a/app/controllers/training/responses_controller.rb b/app/controllers/training/responses_controller.rb
index c1953ba8e..7f31adb21 100644
--- a/app/controllers/training/responses_controller.rb
+++ b/app/controllers/training/responses_controller.rb
@@ -39,7 +39,7 @@ def save_response!
correct_answers = content.confidence_question? ? true : content.correct_answers.eql?(user_answers)
if ENV['DISABLE_USER_ANSWER'].present?
- current_user_response.update(answers: user_answers, correct: correct_answers)
+ current_user_response.update(answers: user_answers, correct: correct_answers, schema: content.schema)
else
current_user_response.update(answer: user_answers, correct: correct_answers)
end
@@ -62,12 +62,21 @@ def redirect
# @return [Ahoy::Event] Update action
def track_question_answer
- track('questionnaire_answer',
- uid: content.id,
- mod_uid: mod.id,
- type: content.assessments_type, # TODO: will be replaced with content.page_type
- success: current_user_response.correct?,
- answers: current_user_response.answers)
+ if ENV['DISABLE_USER_ANSWER'].present?
+ track('questionnaire_answer',
+ uid: content.id,
+ mod_uid: mod.id,
+ type: content.question_type,
+ success: current_user_response.correct?,
+ answers: current_user_response.answers)
+ else
+ track('questionnaire_answer',
+ uid: content.id,
+ mod_uid: mod.id,
+ type: content.assessments_type, # TODO: will be replaced with content.page_type
+ success: current_user_response.correct?,
+ answers: current_user_response.answers)
+ end
end
end
end
diff --git a/app/models/data/confidence_check_scores.rb b/app/models/data/confidence_check_scores.rb
new file mode 100644
index 000000000..201742f2d
--- /dev/null
+++ b/app/models/data/confidence_check_scores.rb
@@ -0,0 +1,36 @@
+module Data
+ class ConfidenceCheckScores
+ include ToCsv
+
+ class << self
+ # @return [Array]
+ def column_names
+ %w[
+ Module
+ Question
+ Answers
+ Count
+ ]
+ end
+
+ # @return [Array Mixed}>]
+ def dashboard
+ confidence_check_scores.map do |(module_name, question_name, answers), count|
+ {
+ module_name: module_name,
+ question_name: question_name,
+ answers: answers,
+ count: count,
+ }
+ end
+ end
+
+ private
+
+ # @return [Hash{Array => Integer}]
+ def confidence_check_scores
+ Response.confidence.group(:training_module, :question_name, :answers).count
+ end
+ end
+ end
+end
diff --git a/app/models/data/high_fail_questions.rb b/app/models/data/high_fail_questions.rb
index 795dc3c2e..2357cc97c 100644
--- a/app/models/data/high_fail_questions.rb
+++ b/app/models/data/high_fail_questions.rb
@@ -25,14 +25,22 @@ def dashboard
private
- # @return [Hash{Array => Integer}]
+ # @return [Hash{Array => Integer}]
def question_attempts
- UserAnswer.summative.group(:module, :name).count
+ if ENV['DISABLE_USER_ANSWER'].present?
+ Response.summative.group(:training_module, :question_name).count
+ else
+ UserAnswer.summative.group(:module, :name).count
+ end
end
- # @return [Hash{Array => Integer}]
+ # @return [Hash{Array => Integer}]
def question_failures
- UserAnswer.summative.where(correct: false).group(:module, :name).count
+ if ENV['DISABLE_USER_ANSWER'].present?
+ Response.summative.where(correct: false).group(:training_module, :question_name).count
+ else
+ UserAnswer.summative.where(correct: false).group(:module, :name).count
+ end
end
# @return [Integer]
diff --git a/app/models/response.rb b/app/models/response.rb
index 47bb005a1..18c84ebfe 100644
--- a/app/models/response.rb
+++ b/app/models/response.rb
@@ -9,6 +9,9 @@ class Response < ApplicationRecord
validates :answers, presence: true
scope :unarchived, -> { where(archived: false) }
+ scope :formative, -> { where('schema->>4 = ?', 'formative') }
+ scope :summative, -> { where('schema->>4 = ?', 'summative') }
+ scope :confidence, -> { where('schema->>4 = ?', 'confidence') }
delegate :to_partial_path, :legend, to: :question
diff --git a/app/models/training/answer.rb b/app/models/training/answer.rb
index 5c3b617d1..5b70ff72f 100644
--- a/app/models/training/answer.rb
+++ b/app/models/training/answer.rb
@@ -42,9 +42,9 @@ def incorrect_answers
incorrect_options.map(&:id)
end
- # @return [Hash{Symbol => Array}]
+ # @return [Hash{Symbol => Array}]
def schema
- { correct: correct_answers, incorrect: incorrect_answers }
+ { options: options.map(&:schema), correct: correct_answers, incorrect: incorrect_answers }
end
# @param disabled [Boolean]
@@ -91,6 +91,11 @@ class Option < Dry::Struct
alias_method :correct?, :correct
alias_method :checked?, :checked
alias_method :disabled?, :disabled
+
+ # @return [Hash{Symbol => nil, String}]
+ def schema
+ { id: id, label: label }
+ end
end
end
end
diff --git a/app/models/training/question.rb b/app/models/training/question.rb
index 079afc1ea..0d133f14a 100644
--- a/app/models/training/question.rb
+++ b/app/models/training/question.rb
@@ -57,6 +57,7 @@ def true_false?
answer.options.map(&:label).sort.eql? %w[False True]
end
+ # TODO: remove once user_answers is removed
# @return [String]
def assessments_type
{
@@ -66,9 +67,17 @@ def assessments_type
}.fetch(page_type.to_sym)
end
+ def question_type
+ {
+ formative_questionnaire: 'formative',
+ summative_questionnaire: 'summative',
+ confidence_questionnaire: 'confidence',
+ }.fetch(page_type.to_sym)
+ end
+
# @return [Array]
def schema
- [name, page_type, body, answer.schema]
+ [name, page_type, body, answer.schema, question_type]
end
# @return [String]
diff --git a/app/services/dashboard.rb b/app/services/dashboard.rb
index 41d6ac01f..f72e0cfc4 100644
--- a/app/services/dashboard.rb
+++ b/app/services/dashboard.rb
@@ -17,6 +17,7 @@ class Dashboard
{ model: 'User', folder: 'userdata', file: 'users' },
{ model: 'UserAnswer', folder: 'useranswers', file: 'user_answers' },
{ model: 'Response', folder: 'useranswers', file: 'responses' },
+ { model: 'Data::ConfidenceCheckScores', folder: 'useranswers', file: 'confidence_check_scores' },
{ model: 'UserAssessment', folder: 'userassessments', file: 'user_assessments' },
{ model: 'Data::LocalAuthorityUser', folder: 'localauthorities', file: 'local_authority_users' },
{ model: 'Data::AveragePassScores', folder: 'summativequiz', file: 'average_pass_scores' },
diff --git a/db/migrate/20230724160222_add_schema_to_responses.rb b/db/migrate/20230724160222_add_schema_to_responses.rb
new file mode 100644
index 000000000..3fd4e53c0
--- /dev/null
+++ b/db/migrate/20230724160222_add_schema_to_responses.rb
@@ -0,0 +1,7 @@
+class AddSchemaToResponses < ActiveRecord::Migration[7.0]
+ def change
+ change_table :responses, bulk: true do |t|
+ t.jsonb :schema
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 787825696..bc371754d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -157,6 +157,7 @@
t.bigint "user_assessment_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.jsonb "schema"
t.index ["user_assessment_id"], name: "index_responses_on_user_assessment_id"
t.index ["user_id", "training_module", "question_name"], name: "user_question"
t.index ["user_id"], name: "index_responses_on_user_id"
diff --git a/lib/tasks/data.rake b/lib/tasks/data.rake
new file mode 100644
index 000000000..d9bc5fee8
--- /dev/null
+++ b/lib/tasks/data.rake
@@ -0,0 +1,33 @@
+namespace :data do
+ desc 'Run all migrations'
+ task migrations: :environment do
+ Rake.application.in_namespace(:data) do |namespace|
+ namespace.tasks.each do |task|
+ next if task.name == 'data:migrations'
+
+ puts "Invoking #{task.name}"
+ task.invoke
+ end
+ end
+ end
+
+ desc 'Migrate user answers to responses'
+ task migrate_user_answers_to_responses: :environment do
+ puts 'Truncate responses'
+ ActiveRecord::Base.connection.execute('TRUNCATE responses RESTART IDENTITY CASCADE')
+ puts 'Migrating user answers to responses'
+ UserAnswer.all.each do |user_answer|
+ response = Response.create!(
+ user_id: user_answer.user_id,
+ training_module: user_answer.module,
+ question_name: user_answer.name,
+ answers: user_answer.answer,
+ correct: user_answer.correct,
+ schema: user_answer.question.schema,
+ user_assessment_id: user_answer.user_assessment_id,
+ )
+ response.save!(validate: false)
+ end
+ puts 'Migrated user answers to responses'
+ end
+end
diff --git a/spec/factories/response.rb b/spec/factories/response.rb
index af84c4aee..41a23addb 100644
--- a/spec/factories/response.rb
+++ b/spec/factories/response.rb
@@ -4,5 +4,56 @@
training_module { 'alpha' }
question_name { '1-1-4-1' }
answers { [(1..5).to_a.sample] }
+
+ trait :correct do
+ correct { true }
+ end
+
+ trait :incorrect do
+ correct { false }
+ end
+
+ trait :confidence_check do
+ schema do
+ [
+ '9-9-9',
+ 'confidence_check',
+ 'How confident are you? - Select from following',
+ {
+ "correct": [1, 2, 3, 4, 5],
+ "options": [
+ { "id": 1, "label": 'Strongly agree' },
+ { "id": 2, "label": 'Agree' },
+ { "id": 3, "label": 'Neither agree nor disagree' },
+ { "id": 4, "label": 'Disagree' },
+ { "id": 5, "label": 'Strongly Disagree' },
+ ],
+ "incorrect": [],
+ },
+ 'confidence',
+ ]
+ end
+ end
+
+ trait :summative do
+ schema do
+ [
+ '1-1-4',
+ 'summative_questionnaire',
+ 'Question - Select from following',
+ {
+ "correct": [2, 3],
+ "options": [
+ { "id": 1, "label": 'Wrong answer 1' },
+ { "id": 2, "label": 'Correct answer 1' },
+ { "id": 3, "label": 'Correct answer 2' },
+ { "id": 4, "label": 'Wrong answer 2' },
+ ],
+ "incorrect": [1, 4],
+ },
+ 'summative',
+ ]
+ end
+ end
end
end
diff --git a/spec/models/data/confidence_check_scores_spec.rb b/spec/models/data/confidence_check_scores_spec.rb
new file mode 100644
index 000000000..6461006f8
--- /dev/null
+++ b/spec/models/data/confidence_check_scores_spec.rb
@@ -0,0 +1,38 @@
+require 'rails_helper'
+
+RSpec.describe Data::ConfidenceCheckScores do
+ before do
+ skip if ENV['DISABLE_USER_ANSWER'].blank?
+ create(:response, :confidence_check, training_module: 'module_1', question_name: 'q1', answers: [1])
+ create(:response, :confidence_check, training_module: 'module_1', question_name: 'q2', answers: [2])
+ create(:response, :confidence_check, training_module: 'module_1', question_name: 'q2', answers: [2])
+ end
+
+ let(:headers) do
+ %w[
+ Module
+ Question
+ Answers
+ Count
+ ]
+ end
+
+ let(:rows) do
+ [
+ {
+ module_name: 'module_1',
+ question_name: 'q1',
+ answers: [1],
+ count: 1,
+ },
+ {
+ module_name: 'module_1',
+ question_name: 'q2',
+ answers: [2],
+ count: 2,
+ },
+ ]
+ end
+
+ it_behaves_like 'a data export model'
+end
diff --git a/spec/models/data/high_fail_questions_spec.rb b/spec/models/data/high_fail_questions_spec.rb
index 0bdce5fb5..625df3fed 100644
--- a/spec/models/data/high_fail_questions_spec.rb
+++ b/spec/models/data/high_fail_questions_spec.rb
@@ -25,10 +25,17 @@
end
before do
- create(:user_answer, :correct, :questionnaire, :summative, module: 'module_1', name: 'q1')
- create(:user_answer, :correct, :questionnaire, :summative, module: 'module_2', name: 'q1')
- create(:user_answer, :incorrect, :questionnaire, :summative, module: 'module_1', name: 'q2')
- create(:user_answer, :incorrect, :questionnaire, :summative, module: 'module_1', name: 'q2')
+ if ENV['DISABLE_USER_ANSWER'].present?
+ create(:response, :correct, :summative, training_module: 'module_1', question_name: 'q1', answers: [1])
+ create(:response, :correct, :summative, training_module: 'module_2', question_name: 'q1', answers: [1])
+ create(:response, :incorrect, :summative, training_module: 'module_1', question_name: 'q2', answers: [2])
+ create(:response, :incorrect, :summative, training_module: 'module_1', question_name: 'q2', answers: [2])
+ else
+ create(:user_answer, :correct, :questionnaire, :summative, module: 'module_1', name: 'q1')
+ create(:user_answer, :correct, :questionnaire, :summative, module: 'module_2', name: 'q1')
+ create(:user_answer, :incorrect, :questionnaire, :summative, module: 'module_1', name: 'q2')
+ create(:user_answer, :incorrect, :questionnaire, :summative, module: 'module_1', name: 'q2')
+ end
end
it_behaves_like 'a data export model'
diff --git a/spec/models/response_spec.rb b/spec/models/response_spec.rb
index 9a6121ad6..ccb495ec6 100644
--- a/spec/models/response_spec.rb
+++ b/spec/models/response_spec.rb
@@ -1,22 +1,28 @@
require 'rails_helper'
RSpec.describe Response, type: :model do
+ before do
+ skip if ENV['DISABLE_USER_ANSWER'].blank?
+ end
+
describe 'dashboard' do
- let(:response) { create(:response, answers: [1]) }
+ let(:user) { create :user }
+ let(:question) do
+ # uncached
+ # described_class.find_by(name: , training_module: { name: 'alpha' }).load.first
+
+ # cached
+ Training::Module.by_name('alpha').page_by_name('1-1-4')
+ end
+
+ let(:response) do
+ user.response_for(question).tap do |response|
+ response.update(answers: [1], correct: true, schema: question.schema)
+ end
+ end
let(:headers) do
- %w[
- id
- user_id
- training_module
- question_name
- answers
- archived
- correct
- user_assessment_id
- created_at
- updated_at
- ]
+ %w[id user_id training_module question_name answers archived correct user_assessment_id created_at updated_at schema]
end
let(:rows) do
diff --git a/spec/models/training/question_spec.rb b/spec/models/training/question_spec.rb
index 5f0a08445..62a7c6c3f 100644
--- a/spec/models/training/question_spec.rb
+++ b/spec/models/training/question_spec.rb
@@ -24,6 +24,10 @@
['Wrong answer 1'],
]
end
+
+ it '#question_type' do
+ expect(question.question_type).to eq 'formative'
+ end
end
describe '#options' do
diff --git a/spec/services/dashboard_spec.rb b/spec/services/dashboard_spec.rb
index c50cb2ed6..5e8d33893 100644
--- a/spec/services/dashboard_spec.rb
+++ b/spec/services/dashboard_spec.rb
@@ -18,7 +18,7 @@
let(:data_files) { Dir.glob path.join('*/*/*.csv') }
it 'exports 7 database tables' do
- expect(data_files.count).to be 20
+ expect(data_files.count).to be 21
end
it 'exports data in CSV format' do
diff --git a/terraform-azure/terraform-azure-database/variables.tf b/terraform-azure/terraform-azure-database/variables.tf
index 8dc365252..8ead0c389 100644
--- a/terraform-azure/terraform-azure-database/variables.tf
+++ b/terraform-azure/terraform-azure-database/variables.tf
@@ -13,13 +13,13 @@ variable "resource_name_prefix" {
type = string
}
-variable "psqlfs_subnet_id" {
- description = "ID of the delegated Subnet for the Database Server"
+variable "environment" {
+ description = "Environment to deploy resources"
type = string
}
-variable "environment" {
- description = "Environment to deploy resources"
+variable "psqlfs_subnet_id" {
+ description = "ID of the delegated Subnet for the Database Server"
type = string
}
diff --git a/terraform-azure/terraform-azure-network/cert.tf b/terraform-azure/terraform-azure-network/cert.tf
index 1feaa2450..0c07079f4 100644
--- a/terraform-azure/terraform-azure-network/cert.tf
+++ b/terraform-azure/terraform-azure-network/cert.tf
@@ -56,6 +56,37 @@ resource "azurerm_key_vault_access_policy" "kv_ap" {
"SetIssuers",
"Update"
]
+
+ lifecycle {
+ ignore_changes = [object_id]
+ }
+}
+
+# Access Policy for GitHub Actions
+resource "azurerm_key_vault_access_policy" "kv_gh_ap" {
+ # Key Vault only deployed to the Test and Production subscription
+ count = var.environment != "development" ? 1 : 0
+
+ key_vault_id = azurerm_key_vault.kv[0].id
+ tenant_id = data.azurerm_client_config.az_config.tenant_id
+ object_id = data.azurerm_client_config.az_config.object_id
+
+ secret_permissions = [
+ "Get"
+ ]
+
+ certificate_permissions = [
+ "Create",
+ "Get",
+ "GetIssuers",
+ "Import",
+ "List",
+ "ListIssuers",
+ "ManageContacts",
+ "ManageIssuers",
+ "SetIssuers",
+ "Update"
+ ]
}
resource "azurerm_key_vault_access_policy" "kv_mi_ap" {
diff --git a/terraform-azure/terraform-azure-web/appgateway.tf b/terraform-azure/terraform-azure-web/appgateway.tf
index d12ac59c2..ba9e2e7a0 100644
--- a/terraform-azure/terraform-azure-web/appgateway.tf
+++ b/terraform-azure/terraform-azure-web/appgateway.tf
@@ -11,6 +11,14 @@ resource "azurerm_web_application_firewall_policy" "agw_wafp" {
managed_rule_set {
type = "OWASP"
version = "3.2"
+
+ rule_group_override {
+ rule_group_name = "REQUEST-920-PROTOCOL-ENFORCEMENT"
+ rule {
+ id = "920420"
+ enabled = false
+ }
+ }
}
managed_rule_set {
@@ -178,4 +186,4 @@ resource "azurerm_monitor_diagnostic_setting" "agw_logs_monitor" {
lifecycle {
ignore_changes = [metric]
}
-}
\ No newline at end of file
+}
diff --git a/terraform-azure/terraform-azure-web/webapp.tf b/terraform-azure/terraform-azure-web/webapp.tf
index e736ecfd3..73fcac766 100644
--- a/terraform-azure/terraform-azure-web/webapp.tf
+++ b/terraform-azure/terraform-azure-web/webapp.tf
@@ -47,17 +47,6 @@ resource "azurerm_linux_web_app" "webapp" {
}
}
- dynamic "ip_restriction" {
- # Deploy App Gateway rules only to the Test and Production subscription
- for_each = var.environment != "development" ? [1] : []
- content {
- name = "Allow health check"
- action = "Allow"
- priority = 400
- ip_address = "127.0.0.1/0"
- }
- }
-
dynamic "ip_restriction" {
# Deploy App Gateway rules only to the Test and Production subscription
for_each = var.environment != "development" ? [1] : []
diff --git a/terraform-azure/variables.tf b/terraform-azure/variables.tf
index 03c6fc494..87a698d7b 100644
--- a/terraform-azure/variables.tf
+++ b/terraform-azure/variables.tf
@@ -11,7 +11,6 @@ variable "environment" {
}
variable "resource_name_prefix" {
- default = "s187d01-eyrecovery"
description = "Prefix for resource names"
type = string
}