Skip to content

Module for creating Linux bastion servers in member AWS accounts • This repository is defined and managed in Terraform

License

Notifications You must be signed in to change notification settings

ministryofjustice/modernisation-platform-terraform-bastion-linux

Repository files navigation

Bastion Linux Server Creation

Standards Icon Format Code Icon Scorecards Icon SCA Icon Terraform SCA Icon

Terraform module for creating Linux bastion servers in member AWS accounts

Usage

create file named 'bastion_linux.json' and populate with below format. Add user names and public ssh keys as required.

{
    "keys": {
        "development": {
            "username1": "public key data ~~~~~~~~~~~~~~~",
            "username2": "public key data ~~~~~~~~~~~~~~~"
        },
        "test": {
            "username1": "public key data ~~~~~~~~~~~~~~~",
            "username2": "public key data ~~~~~~~~~~~~~~~"
        },
        "preproduction": {
            "username1": "public key data ~~~~~~~~~~~~~~~",
            "username2": "public key data ~~~~~~~~~~~~~~~"
        },
        "production": {
            "username1": "public key data ~~~~~~~~~~~~~~~",
            "username2": "public key data ~~~~~~~~~~~~~~~"
        }
    }
}

create a bastion_linux.tf file as below, change options as required

locals {
  public_key_data = jsondecode(file("./bastion_linux.json"))
}

module "bastion_linux" {
  source = "github.com/ministryofjustice/modernisation-platform-terraform-bastion-linux?ref=v3.0.4"

  providers = {
    aws.share-host   = aws.core-vpc            # core-vpc-(environment) holds the networking for all accounts
    aws.share-tenant = aws                     # The default provider (unaliased, `aws`) is the tenant
  }

  # s3 - used for logs and user public keys
  bucket_name           = "bastion"
  # public keys
  public_key_data       = local.public_key_data.keys[local.environment]
  # logs
  log_auto_clean        = "Enabled"
  log_standard_ia_days  = 30    # days before moving to IA storage
  log_glacier_days      = 60    # days before moving to Glacier
  log_expiry_days       = 180   # days before log expiration
  # bastion
  allow_ssh_commands    = false

  app_name              = var.networking[0].application
  business_unit         = local.vpc_name
  subnet_set            = local.subnet_set
  environment           = local.environment
  region                = "eu-west-2"

  # Tags
  tags_common = local.tags
  tags_prefix = terraform.workspace
}

Note:

Passing in a custom KMS key? You'll need to make sure the bastion iam role has permissions to use it. See aws_kms_key_policy.bastion_s3 in main.tf for an example. This module ouputs the bastion iam role object (see outputs.tf), so you can use it in your own policy.

Looking for issues?

If you're looking to raise an issue with this module, please create a new issue in the Modernisation Platform repository.

Linting exclusions

  • checkov_exclude: CKV_AWS_144 (Ensure S3 bucket has cross-region replication enabled): Enabling cross-region replication for the bastion module might be an overkill. Looking at the use cases provided by Amazon https://aws.amazon.com/s3/features/replication/ none of them seems relevant to our bastion logs. Besides, the checkov_exclude: CKV_AWS_144 needs to be in place anyway because checkov will require replication for the replication bucket as it cannot separate it from the regular non-replication bucket. If in the future we do decide to enable cross-region replication we should use the following terraform module, which supports cross-region replication as an optional configuration: https://github.com/ministryofjustice/modernisation-platform-terraform-s3-bucket
  • checkov_exclude: CKV_AWS_18 (Ensure the S3 bucket has access logging enabled), tfsec_exclude: AWS002 (Resource 'aws_s3_bucket.default' does not have logging enabled): After a discussion with the team we decided not to enable server access logging for the S3 bucket. The S3 bucket is only used by the bastion server and will not be accessed directly. Therefore, access logs are not important. If in the future we do decide to enable server access logging, we should use the following terraform module, setting the log_bucket configuration option: https://github.com/ministryofjustice/modernisation-platform-terraform-s3-bucket

S3 bucket versioning notes (for developers)

We have S3 versioning enabled in bastion not as much for versioning but more so to allow recovering logs that are accidentally deleted.

We record every SSH session into a separate file named using the current time rounded to the minute. Then, every 10 minutes we copy log files to S3 and delete log files that are older than a day. Deleting log files older than a day is simply a way to clear the local ephemeral storage (also cleared upon restart). Since older logs are already stored in S3 and we don't provide the -delete option into the aws s3 sync command, they will be retrievable from S3.

We also have S3 lifecycle management configured to gradually transition logs to cheaper storage. Therefore, logs remain in S3 for 30 days before moving to IA (Infrequent Access) storage. After 60 days they move to Glacier and after 180 days they expire and are permanently deleted.

In order to prevent older versions from being retained forever, in addition to the lifecycle policy for the current version we also configure a separate lifecycle policy for noncurrent versions. Otherwise, older versions would never be moved to cheaper storage and would never be expired/deleted. We use the S3 bucket module for this which allows both current and noncurrent version lifecycle management.

Requirements

Name Version
terraform >= 1.0.1
aws ~> 5.0
random ~> 3.4

Providers

Name Version
aws ~> 5.0
aws.share-host ~> 5.0
random ~> 3.4

Modules

Name Source Version
s3-bucket github.com/ministryofjustice/modernisation-platform-terraform-s3-bucket 7b2b75c178f855d8c48d3bda4ac53df782288c02

Resources

Name Type
aws_autoscaling_group.bastion_linux_daily resource
aws_autoscaling_schedule.bastion_linux_scale_down resource
aws_autoscaling_schedule.bastion_linux_scale_up resource
aws_iam_instance_profile.bastion_profile resource
aws_iam_policy.bastion_policy resource
aws_iam_policy.bastion_ssm_s3_policy resource
aws_iam_role.bastion_role resource
aws_iam_role_policy_attachment.bastion_host_ssm_s3 resource
aws_iam_role_policy_attachment.bastion_managed resource
aws_iam_role_policy_attachment.bastion_s3 resource
aws_kms_alias.bastion_s3 resource
aws_kms_key.bastion_s3 resource
aws_kms_key_policy.bastion_s3 resource
aws_launch_template.bastion_linux_template resource
aws_s3_object.bucket_public_keys_readme resource
aws_s3_object.user_public_keys resource
aws_security_group.bastion_linux resource
aws_security_group_rule.bastion_linux_egress_1 resource
aws_security_group_rule.bastion_linux_egress_2 resource
aws_security_group_rule.bastion_linux_egress_3 resource
random_string.random6 resource
aws_caller_identity.current data source
aws_iam_policy_document.bastion_assume_policy_document data source
aws_iam_policy_document.bastion_policy_document data source
aws_iam_policy_document.bastion_ssm_s3_policy_document data source
aws_security_group.core_vpc_protected data source
aws_subnet.local_account data source
aws_subnet.private_az_a data source
aws_subnets.local_account data source
aws_vpc.shared_vpc data source
aws_vpc_endpoint.s3 data source

Inputs

Name Description Type Default Required
allow_ssh_commands Allow SSH commands to be specified bool n/a yes
app_name Name of application string n/a yes
autoscaling_cron Cron expressions for scale up and scale down map(string)
{
"down": "0 20 * * *",
"up": "0 5 * * *"
}
no
bucket_name Bucket used for bucket log storage and user public keys string n/a yes
business_unit Fixed variable to specify business-unit for RAM shared subnets string n/a yes
custom_s3_kms_arn KMS ARN for S3 bucket encryption string "" no
environment application environment string n/a yes
extra_user_data_content Extra user data content for Bastion ec2 string "" no
instance_name Name of instance string "bastion_linux" no
log_auto_clean Enable or not the lifecycle string n/a yes
log_expiry_days Number of days before logs expiration number n/a yes
log_glacier_days Number of days before moving logs to Glacier number n/a yes
log_standard_ia_days Number of days before moving logs to IA Storage number n/a yes
public_key_data User public keys for specific environment map(any) n/a yes
region #Main string n/a yes
subnet_set Fixed variable to specify subnet-set for RAM shared subnets string n/a yes
tags_common MOJ required tags map(string) n/a yes
tags_prefix prefix for name tags string n/a yes
volume_size Size of the volume in gibibytes (GiB) number 8 no

Outputs

Name Description
bastion_iam_role IAM role of bastion
bastion_kms_key n/a
bastion_kms_key_alias n/a
bastion_launch_template Launch template of bastion
bastion_s3_bucket S3 bucket of bastion
bastion_security_group Security group of bastion
bastion_security_group_map Security group details of bastion

About

Module for creating Linux bastion servers in member AWS accounts • This repository is defined and managed in Terraform

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published