Home

Awesome

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

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.

<!-- BEGIN_TF_DOCS -->

Requirements

NameVersion
<a name="requirement_terraform"></a> terraform>= 1.0.1
<a name="requirement_aws"></a> aws~> 5.0
<a name="requirement_random"></a> random~> 3.4

Providers

NameVersion
<a name="provider_aws"></a> aws~> 5.0
<a name="provider_aws.share-host"></a> aws.share-host~> 5.0
<a name="provider_random"></a> random~> 3.4

Modules

NameSourceVersion
<a name="module_s3-bucket"></a> s3-bucketgithub.com/ministryofjustice/modernisation-platform-terraform-s3-bucket7b2b75c178f855d8c48d3bda4ac53df782288c02

Resources

NameType
aws_autoscaling_group.bastion_linux_dailyresource
aws_autoscaling_schedule.bastion_linux_scale_downresource
aws_autoscaling_schedule.bastion_linux_scale_upresource
aws_iam_instance_profile.bastion_profileresource
aws_iam_policy.bastion_policyresource
aws_iam_policy.bastion_ssm_s3_policyresource
aws_iam_role.bastion_roleresource
aws_iam_role_policy_attachment.bastion_host_ssm_s3resource
aws_iam_role_policy_attachment.bastion_managedresource
aws_iam_role_policy_attachment.bastion_s3resource
aws_kms_alias.bastion_s3resource
aws_kms_key.bastion_s3resource
aws_kms_key_policy.bastion_s3resource
aws_launch_template.bastion_linux_templateresource
aws_s3_object.bucket_public_keys_readmeresource
aws_s3_object.user_public_keysresource
aws_security_group.bastion_linuxresource
aws_security_group_rule.bastion_linux_egress_1resource
aws_security_group_rule.bastion_linux_egress_2resource
aws_security_group_rule.bastion_linux_egress_3resource
random_string.random6resource
aws_caller_identity.currentdata source
aws_iam_policy_document.bastion_assume_policy_documentdata source
aws_iam_policy_document.bastion_policy_documentdata source
aws_iam_policy_document.bastion_ssm_s3_policy_documentdata source
aws_security_group.core_vpc_protecteddata source
aws_subnet.local_accountdata source
aws_subnet.private_az_adata source
aws_subnets.local_accountdata source
aws_vpc.shared_vpcdata source
aws_vpc_endpoint.s3data source

Inputs

NameDescriptionTypeDefaultRequired
<a name="input_allow_ssh_commands"></a> allow_ssh_commandsAllow SSH commands to be specifiedbooln/ayes
<a name="input_app_name"></a> app_nameName of applicationstringn/ayes
<a name="input_autoscaling_cron"></a> autoscaling_cronCron expressions for scale up and scale downmap(string)<pre>{<br/> "down": "0 20 * * *",<br/> "up": "0 5 * * *"<br/>}</pre>no
<a name="input_bucket_name"></a> bucket_nameBucket used for bucket log storage and user public keysstringn/ayes
<a name="input_business_unit"></a> business_unitFixed variable to specify business-unit for RAM shared subnetsstringn/ayes
<a name="input_custom_s3_kms_arn"></a> custom_s3_kms_arnKMS ARN for S3 bucket encryptionstring""no
<a name="input_environment"></a> environmentapplication environmentstringn/ayes
<a name="input_extra_user_data_content"></a> extra_user_data_contentExtra user data content for Bastion ec2string""no
<a name="input_instance_name"></a> instance_nameName of instancestring"bastion_linux"no
<a name="input_log_auto_clean"></a> log_auto_cleanEnable or not the lifecyclestringn/ayes
<a name="input_log_expiry_days"></a> log_expiry_daysNumber of days before logs expirationnumbern/ayes
<a name="input_log_glacier_days"></a> log_glacier_daysNumber of days before moving logs to Glaciernumbern/ayes
<a name="input_log_standard_ia_days"></a> log_standard_ia_daysNumber of days before moving logs to IA Storagenumbern/ayes
<a name="input_public_key_data"></a> public_key_dataUser public keys for specific environmentmap(any)n/ayes
<a name="input_region"></a> region#Mainstringn/ayes
<a name="input_subnet_set"></a> subnet_setFixed variable to specify subnet-set for RAM shared subnetsstringn/ayes
<a name="input_tags_common"></a> tags_commonMOJ required tagsmap(string)n/ayes
<a name="input_tags_prefix"></a> tags_prefixprefix for name tagsstringn/ayes
<a name="input_volume_size"></a> volume_sizeSize of the volume in gibibytes (GiB)number8no

Outputs

NameDescription
<a name="output_bastion_iam_role"></a> bastion_iam_roleIAM role of bastion
<a name="output_bastion_kms_key"></a> bastion_kms_keyn/a
<a name="output_bastion_kms_key_alias"></a> bastion_kms_key_aliasn/a
<a name="output_bastion_launch_template"></a> bastion_launch_templateLaunch template of bastion
<a name="output_bastion_s3_bucket"></a> bastion_s3_bucketS3 bucket of bastion
<a name="output_bastion_security_group"></a> bastion_security_groupSecurity group of bastion
<a name="output_bastion_security_group_map"></a> bastion_security_group_mapSecurity group details of bastion
<!-- END_TF_DOCS -->