diff --git a/docs/technical-standards/How-to guides/_category_.json b/docs/technical-standards/How-to guides/_category_.json new file mode 100644 index 0000000..d997d2a --- /dev/null +++ b/docs/technical-standards/How-to guides/_category_.json @@ -0,0 +1,4 @@ +{ + "collapsible": false, + "collapsed": false, +} diff --git a/docs/technical-standards/How-to guides/tagging.md b/docs/technical-standards/How-to guides/tagging.md new file mode 100644 index 0000000..ac1163f --- /dev/null +++ b/docs/technical-standards/How-to guides/tagging.md @@ -0,0 +1,84 @@ +# How to tag your infrastructure + +This guide shows you how to configure tagging to meet the [tagging standard](../Reference/hosting-standards/tagging.md) using infrastructure as code. + +## Terraform + +To add consistent tags to every resource created by a particular provider within a repo, use [the `default_tags` block in your terraform provider block](https://www.hashicorp.com/blog/default-tags-in-the-terraform-aws-provider). This will cascade any tags you specify to all resources created by terraform. For example: + +```hcl +provider "aws" { + region = "eu-west-2" + default_tags { + tags = { + Application = "Developer Playbook" + TeamEmail = "developers@hackney.gov.uk" + Environment = "production" + } + } +} +``` + +See how we use this in [LBHackney-IT/ce-dns](https://github.com/LBHackney-IT/ce-dns/blob/main/providers.tf) for a real-world example, including passing variables into the tag block. + +### Dynamic tags in Terraform + +Tags such as `AutomationBuildUrl` change every time we run the build in CI. Terraform doesn't support reading environment variables directly in the provider, so we need to pass these in as Terraform variables. + +Here's an example for how to add `AutomationBuildUrl`: + +1. Create a variable to hold the value in `variables.tf`: + > ℹ️ We use snake_case for variable names to match the Terraform convention + ```hcl + variable "automation_build_url" { + description = "The URL of the CI build that deployed or modified this infrastructure" + type = string + nullable = false + } + ``` + +2. Use the environment variable in `providers.tf` where you're defining your tags: + ```hcl + provider "aws" { + default_tags { + # ... + AutomationBuildUrl = var.automation_build_url + } + ``` + +3. Then reference the environment variables in `tfvars/production.tfvars`, `tfvars/staging.tfvars`, and any other environments you have. + - For CircleCI this will look like: + ```hcl + automation_build_url = $CIRCLE_BUILD_URL + ``` + - For GitHub Actions this will look like: + + ```hcl + automation_build_url = ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID} + ``` + +## Serverless Framework + +In order to add tagging to AWS resources managed by Serverless Framework: + +1. Install the `serverless-plugin-resource-tagging` Node module, e.g. `npm install serverless-plugin-resource-tagging` or `yarn add serverless-plugin-resource-tagging`. +2. Add the plugin to the `plugins` list in `serverless.yml` in your project and add the tags under `stackTags`, e.g.: + ```yaml + provider: + # ... + stackTags: + Application: "Developer Playbook" + TeamEmail: "developers@hackney.gov.uk" + Environment: "production" + + # For CircleCI + AutomationBuildUrl: ${env:CIRCLE_BUILD_URL} + + # For GitHub Actions + AutomationBuildUrl: ${env:GITHUB_SERVER_URL}/${env:GITHUB_REPOSITORY}/actions/runs/${env:GITHUB_RUN_ID} + + plugins: + - serverless-plugin-resource-tagging + ``` + +Refer to the [tagging standard](../Reference/hosting-standards/tagging.md) for a full list of mandatory and optional tags. diff --git a/docs/technical-standards/Readme.md b/docs/technical-standards/Readme.md new file mode 100644 index 0000000..af48cdf --- /dev/null +++ b/docs/technical-standards/Readme.md @@ -0,0 +1,6 @@ +--- +sidebar_position: 0 +--- +# Technical standards + +These technical standards are the baseline operating requirements for systems and services in Hackney. diff --git a/docs/technical-standards/Reference/_category_.json b/docs/technical-standards/Reference/_category_.json new file mode 100644 index 0000000..d997d2a --- /dev/null +++ b/docs/technical-standards/Reference/_category_.json @@ -0,0 +1,4 @@ +{ + "collapsible": false, + "collapsed": false, +} diff --git a/docs/technical-standards/Reference/hosting-standards/Readme.md b/docs/technical-standards/Reference/hosting-standards/Readme.md new file mode 100644 index 0000000..ab91917 --- /dev/null +++ b/docs/technical-standards/Reference/hosting-standards/Readme.md @@ -0,0 +1,6 @@ +--- +sidebar_position: 1 +--- +# Hosting standards + +Hosting standards apply to everything we host at Hackney, whether it's built in-house, developed externally, or an off-the-shelf product. If we're hosting it in one of our cloud platforms, e.g. AWS, these standards apply diff --git a/docs/technical-standards/Reference/hosting-standards/_category_.json b/docs/technical-standards/Reference/hosting-standards/_category_.json new file mode 100644 index 0000000..d997d2a --- /dev/null +++ b/docs/technical-standards/Reference/hosting-standards/_category_.json @@ -0,0 +1,4 @@ +{ + "collapsible": false, + "collapsed": false, +} diff --git a/docs/technical-standards/Reference/hosting-standards/tagging.md b/docs/technical-standards/Reference/hosting-standards/tagging.md new file mode 100644 index 0000000..4e26bde --- /dev/null +++ b/docs/technical-standards/Reference/hosting-standards/tagging.md @@ -0,0 +1,41 @@ +# Tagging + +We will tag all AWS objects, so we know they have a purpose and have a defined owner to manage cost, maintenance and support. + +## What must be in place + +1. All objects in our cloud hosting providers (primarily AWS) *must* be tagged in line with the requirements set out below. + +To ensure we can consistently search for, and report on, the tags we use, you should use the following tags. In all cases, only use acronyms if you’re confident that someone from another part of the council would understand them. If in doubt, avoid acronyms and use the full term. + +### Mandatory tags + +- `Application`: The full name of the application or service. This should match the name used in the Service Catalogue, e.g. `Repairs Hub`, `Common Fate`. +- `TeamEmail`: The email address of the team responsible for the operation of the service. Must be a valid email group, not an individual. +- `Environment`: The name of the environment, must be one of `dev`, `stg`, `prod` or `mgmt`[^environment-tags-source]. + +### Optional tags + +- `AutomationBuildUrl`: URL of the automation build, must be a valid URL. +- `BackupPolicy`: The backup policy to apply to the resource. If present must be one of `Dev`, `Stg`, `Preprod`, `Prod`, `Mgmt`. +- `Confidentiality`: Data confidentiality of the infrastructure. Only applicable to infrastructure which holds data, e.g. EC2, RDS, EBS, DynamoDB, Glue, and S3. Must be one of `Internal`, `Restricted`, or `Public`[^confidentiality-tags-source]. +- `Department`: The service area this system serves. +- `WeekendShutdown`: If present, regardless of the value provided the resource will be shut down over the weekend. +- `OutOfHoursShutdown`: If present, regardless of the value provided the resource will be shut down out of working hours. + +## Monitoring + +The user creating the object will be notified when an object is untagged with increasing urgency. + +## Resolution/Escalation if the baseline isn't met + +1. Creation of untagged objects will be prevented by technical controls where possible. +2. Newly created untagged objects will be forcefully and automatically shutdown/disabled if they remain untagged for 7 calendar days. +3. Existing untagged objects will not be editable until the mandatory tags have been added. + +## More information + +See the [How to tag your infrastructure](../../How-to%20guides/tagging.md) guide. + +[^confidentiality-tags-source]: https://github.com/LBHackney-IT/aws-tags-lbh/blob/main/variables.tf#L83 +[^environment-tags-source]: https://github.com/LBHackney-IT/aws-tags-lbh/blob/main/variables.tf#L150 diff --git a/docusaurus.config.js b/docusaurus.config.js index 5bf3ce0..257b032 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -86,6 +86,12 @@ const config = { position: 'left', label: 'Ways of working', }, + { + type: 'docSidebar', + sidebarId: 'technicalStandards', + position: 'left', + label: 'Technical standards', + }, { type: 'docSidebar', sidebarId: 'architecturePillars', @@ -162,6 +168,7 @@ const config = { copyright: `Copyright © ${new Date().getFullYear()} London Borough of Hackney Council. The data published here is free to re-use under the Open Government Licence.`, }, prism: { + additionalLanguages: ['hcl'], theme: prismThemes.github, darkTheme: prismThemes.dracula, }, diff --git a/sidebars.js b/sidebars.js index bf6b0e1..5fb6972 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,6 +19,7 @@ const sidebars = { frontendDevelopment: [{type: 'autogenerated', dirName: 'frontend-development'}], apiSpecifications: [{type: 'autogenerated', dirName: 'api-specifications'}], productPlaybook: [{type: 'autogenerated', dirName: 'Product-Playbook'}], + technicalStandards: [{type: 'autogenerated', dirName: 'technical-standards'}], }; export default sidebars;