diff --git a/.circleci/config.yml b/.circleci/config.yml
index bc71204..160485a 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -145,7 +145,8 @@ jobs:
build-and-test:
executor: docker-python
steps:
- - checkout
+ - checkout:
+ method: full
- setup_remote_docker
- sonarcloud/scan
- run:
@@ -229,6 +230,31 @@ jobs:
steps:
- deploy-lambda:
stage: "production"
+ assume-role-pre-production:
+ executor: docker-python
+ steps:
+ - assume-role-and-persist-workspace:
+ aws-account: $AWS_ACCOUNT_PRE_PRODUCTION
+ terraform-init-and-plan-pre-production:
+ executor: docker-terraform
+ steps:
+ - terraform-init-then-plan:
+ environment: "pre-production"
+ terraform-compliance-pre-production:
+ executor: docker-terraform
+ steps:
+ - terraform-compliance:
+ environment: "pre-production"
+ terraform-apply-pre-production:
+ executor: docker-terraform
+ steps:
+ - terraform-apply:
+ environment: "pre-production"
+ deploy-to-pre-production:
+ executor: docker-dotnet
+ steps:
+ - deploy-lambda:
+ stage: "pre-production"
workflows:
check-and-deploy-development:
@@ -360,3 +386,69 @@ workflows:
filters:
branches:
only: release
+
+ deploy-terraform-pre-production:
+ jobs:
+ - permit-pre-production-terraform-workflow:
+ type: approval
+ filters:
+ branches:
+ only: release
+ - assume-role-pre-production:
+ context: api-assume-role-housing-pre-production-context
+ requires:
+ - permit-pre-production-terraform-workflow
+ filters:
+ branches:
+ only: release
+ - terraform-init-and-plan-pre-production:
+ requires:
+ - assume-role-pre-production
+ filters:
+ branches:
+ only: release
+ - terraform-compliance-pre-production:
+ requires:
+ - terraform-init-and-plan-pre-production
+ filters:
+ branches:
+ only: release
+ - permit-pre-production-terraform-deployment:
+ type: approval
+ requires:
+ - terraform-compliance-pre-production
+ filters:
+ branches:
+ only: release
+ - terraform-apply-pre-production:
+ requires:
+ - permit-pre-production-terraform-deployment
+ filters:
+ branches:
+ only: release
+
+ deploy-code-pre-production:
+ jobs:
+ - build-and-test:
+ context:
+ - api-nuget-token-context
+ - SonarCloud
+ filters:
+ branches:
+ only: release
+ - assume-role-pre-production:
+ context: api-assume-role-housing-pre-production-context
+ requires:
+ - build-and-test
+ filters:
+ branches:
+ only: release
+ - deploy-to-pre-production:
+ context:
+ - api-nuget-token-context
+ - "Serverless Framework"
+ requires:
+ - assume-role-pre-production
+ filters:
+ branches:
+ only: release
diff --git a/NotesApi/NotesApi.csproj b/NotesApi/NotesApi.csproj
index 9cf4a66..16ea964 100644
--- a/NotesApi/NotesApi.csproj
+++ b/NotesApi/NotesApi.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/NotesApi/serverless.yml b/NotesApi/serverless.yml
index aaf1402..090eced 100644
--- a/NotesApi/serverless.yml
+++ b/NotesApi/serverless.yml
@@ -132,15 +132,6 @@ resources:
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- - Effect: "Allow"
- Action:
- - "s3:PutObject"
- - "s3:GetObject"
- Resource:
- Fn::Join:
- - ""
- - - "arn:aws:s3:::"
- - "Ref": "ServerlessDeploymentBucket"
- PolicyName: lambdaInvocation
PolicyDocument:
Version: '2012-10-17'
@@ -151,9 +142,10 @@ resources:
Resource: "*"
custom:
authorizerArns:
- development: arn:aws:lambda:eu-west-2:859159924354:function:api-auth-verify-token-new-development-apiauthverifytokennew
+ development: arn:aws:lambda:eu-west-2:859159924354:function:api-gateway-lambda-authorizer
staging: arn:aws:lambda:eu-west-2:715003523189:function:api-auth-verify-token-new-staging-apiauthverifytokennew
production: arn:aws:lambda:eu-west-2:153306643385:function:api-auth-verify-token-new-production-apiauthverifytokennew
+ pre-production: arn:aws:lambda:eu-west-2:578479666894:function:api-auth-verify-token-new-pre-production-apiauthverifytokennew
safeguards:
- title: Require authorizer
safeguard: require-authorizer
@@ -165,6 +157,7 @@ custom:
development: vpc-0d15f152935c8716f
staging: vpc-064521a7a4109ba31
production: vpc-0ce853ddb64e8fb3c
+ pre-production: vpc-062a957b99c8b12e6
vpc:
development:
securityGroupIds:
@@ -184,3 +177,9 @@ custom:
subnetIds:
- subnet-06a697d86a9b6ed01
- subnet-0beb266003a56ca82
+ pre-production:
+ securityGroupIds:
+ - Ref: LambdaSecurityGroup
+ subnetIds:
+ - subnet-08aa35159a8706faa
+ - subnet-0b848c5b14f841dfb
diff --git a/terraform/pre-production/aws_ssm_parameter.tf b/terraform/pre-production/aws_ssm_parameter.tf
new file mode 100644
index 0000000..a65dfe8
--- /dev/null
+++ b/terraform/pre-production/aws_ssm_parameter.tf
@@ -0,0 +1,11 @@
+resource "aws_ssm_parameter" "aspnetcore_environment" {
+ name = "/housing-tl/pre-production/aspnetcore-environment"
+ type = "String"
+ value = "to_be_set_manually"
+
+ lifecycle {
+ ignore_changes = [
+ value,
+ ]
+ }
+}
diff --git a/terraform/pre-production/dynamodb.tf b/terraform/pre-production/dynamodb.tf
new file mode 100644
index 0000000..6f3cdaa
--- /dev/null
+++ b/terraform/pre-production/dynamodb.tf
@@ -0,0 +1,38 @@
+resource "aws_dynamodb_table" "notesapi_dynamodb_table" {
+ name = "Notes"
+ billing_mode = "PROVISIONED"
+ read_capacity = 10
+ write_capacity = 10
+ hash_key = "targetId"
+ range_key = "id"
+
+ attribute {
+ name = "id"
+ type = "S"
+ }
+
+ attribute {
+ name = "targetId"
+ type = "S"
+ }
+
+ attribute {
+ name = "createdAt"
+ type = "S"
+ }
+
+ local_secondary_index {
+ name = "NotesByCreated"
+ range_key = "createdAt"
+ projection_type = "ALL"
+ }
+
+ tags = merge(
+ local.default_tags,
+ { BackupPolicy = "Dev", Backup = false, Confidentiality = "Internal" }
+ )
+
+ point_in_time_recovery {
+ enabled = false
+ }
+}
diff --git a/terraform/pre-production/maint.tf b/terraform/pre-production/maint.tf
new file mode 100644
index 0000000..1cf1dd3
--- /dev/null
+++ b/terraform/pre-production/maint.tf
@@ -0,0 +1,46 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 3.0"
+ }
+ }
+}
+
+provider "aws" {
+ region = "eu-west-2"
+}
+
+locals {
+ default_tags = {
+ Name = "notes-api-${var.environment_name}"
+ Environment = var.environment_name
+ terraform-managed = true
+ project_name = var.project_name
+ Application = "MTFH Housing Pre-Production"
+ TeamEmail = "developementteam@hackney.gov.uk"
+ }
+}
+
+terraform {
+ backend "s3" {
+ bucket = "housing-pre-production-terraform-state"
+ encrypt = true
+ region = "eu-west-2"
+ key = "services/notes-api/state"
+ dynamodb_table = "housing-pre-production-terraform-state-lock"
+ }
+}
+
+resource "aws_sns_topic" "notes" {
+ name = "notes.fifo"
+ fifo_topic = true
+ content_based_deduplication = true
+ kms_master_key_id = "alias/aws/sns"
+}
+
+resource "aws_ssm_parameter" "notes_sns_arn" {
+ name = "/sns-topic/pre-production/notes/arn"
+ type = "String"
+ value = aws_sns_topic.notes.arn
+}
diff --git a/terraform/pre-production/terraform-compliance/dynamodb.feature b/terraform/pre-production/terraform-compliance/dynamodb.feature
new file mode 100644
index 0000000..2a1b7ec
--- /dev/null
+++ b/terraform/pre-production/terraform-compliance/dynamodb.feature
@@ -0,0 +1,26 @@
+Feature: DynamoDB is used as our NoSQL database service
+ In order to improve security
+ As engineers
+ We'll use ensure our DynamoDB tables are configured correctly
+
+ Scenario: Ensure BackupPolicy tag is present
+ Given I have aws_dynamodb_table defined
+ Then it must contain tags
+ And it must contain BackupPolicy
+
+ Scenario: Ensure point in time recovery disabled
+ Given I have aws_dynamodb_table defined
+ Then it must contain point_in_time_recovery
+ And its enabled property must be false
+
+ Scenario: Ensure a maximum of 1 LSIs
+ Given I have aws_dynamodb_table defined
+ When it contains local_secondary_index
+ When I count them
+ Then I expect the result is less and equal to 1
+
+ Scenario: Ensure a maximum of 2 GSIs
+ Given I have aws_dynamodb_table defined
+ When it contains global_secondary_index
+ When I count them
+ Then I expect the result is less and equal to 2
\ No newline at end of file
diff --git a/terraform/pre-production/terraform-compliance/sns.feature b/terraform/pre-production/terraform-compliance/sns.feature
new file mode 100644
index 0000000..38278d6
--- /dev/null
+++ b/terraform/pre-production/terraform-compliance/sns.feature
@@ -0,0 +1,8 @@
+Feature: SNS is used as our notification service
+ In order to improve security
+ As engineers
+ We'll use ensure our SNS topics are configured correctly
+
+ Scenario: Ensure encryption is enabled
+ Given I have aws_sns_topic defined
+ Then it must contain kms_master_key_id
diff --git a/terraform/pre-production/variables.tf b/terraform/pre-production/variables.tf
new file mode 100644
index 0000000..c92cb7b
--- /dev/null
+++ b/terraform/pre-production/variables.tf
@@ -0,0 +1,9 @@
+variable "environment_name" {
+ type = string
+ default = "pre-prod"
+}
+
+variable "project_name" {
+ type = string
+ default = "Housing-Pre-Production"
+}