Skip to content

Latest commit

 

History

History
224 lines (163 loc) · 10.3 KB

File metadata and controls

224 lines (163 loc) · 10.3 KB

Cloudfront Software Installers

This module allows for Fleet software installers to be served via AWS Cloudfront instead of directly from Fleet.

This should improve the performance of software installer delivery. For general information about Fleet and Cloudfront see the following:

https://fleetdm.com/guides/cdn-signed-urls https://victoronsoftware.com/posts/cloudfront-signed-urls/

The second link includes a script that can be used to test and see if signed URLs are working outside of Fleet for troubleshooting purposes.

AWS GovCloud Scope

This addon is intentionally out of scope for AWS GovCloud compatibility. CloudFront is not available inside the AWS GovCloud (US) partition, so using it with GovCloud-hosted resources is a cross-partition architecture that should be designed and reviewed separately.

Other module requirements

These are the minimum versions of modules required if used:

  • tf-mod-root-v1.13.0
  • tf-mod-byo-vpc-v1.14.0
  • tf-mod-byo-db-v1.10.0
  • tf-mod-byo-ecs-v1.9.0
  • tf-mod-addon-logging-alb-v1.3.0

Previous versions do not allow for proper interaction with both the software installers and logging s3 buckets.

Configuration considerations for other modules

tf-mod-root/tf-mod-byo-vpc/tf-mod-byo-db/tf-mod-byo-ecs

For any of these modules, software installers requires a customer-managed KMS key whenever KMS encryption is used at all. CloudFront access requires a key policy statement on that key, and the AWS-managed default key cannot be modified to accept that policy.

Breaking change: this addon no longer manages the software installers KMS key policy. That policy now lives in tf-mod-byo-ecs, which means CloudFront access to the CMK must be configured there by setting software_installers.cloudfront_distribution_arn to the static distribution ARN.

This is the relevant configuration starting at the software installers configuration block:

    software_installers = {
      bucket_prefix               = "fleet-software-installers-"
      create_kms_key              = true
      kms_alias                   = "fleet-software-installers"
      cloudfront_distribution_arn = "arn:aws:cloudfront::<account-id>:distribution/<distribution-id>"
    }

The required configuration items here are create_kms_key, kms_alias, and cloudfront_distribution_arn when CloudFront must read from an SSE-KMS bucket.

tf-mod-addon-logging-alb

No changes required if using at least version tf-mod-addon-logging-alb-v1.3.0. Bucket ACLs are changed to allow for the alb logging bucket to accept Cloudfront logs via ACLs.

Configuration Example

This example assumes that you used the following commands to create your public and private key for consumption by the module:

openssl genrsa -out cloudfront.key 2048
openssl rsa -pubout -in cloudfront.key -out cloudfront.pem

To be able to store these in source control in a sane manner, the objects will be KMS encrypted for storage at rest. This can happen by having a KMS key as follows:


resource "aws_kms_key" "customer_data_key" {
  description = "key used to encrypt sensitive data stored in terraform"
}       
        
resource "aws_kms_alias" "alias" {
  name          = "alias/fleet-terraform-encrypted"
  target_key_id = aws_kms_key.customer_data_key.id
}       
      
output "kms_key_id" {
  value = aws_kms_key.customer_data_key.id
}  

Then with the key, the following encrypt.sh script encrypt the objects:

#!/bin/bash

set -e

function usage() {
	cat <<-EOUSAGE
	
	Usage: $(basename ${0}) <KMS_KEY_ID> <SOURCE> <DESTINATION> [AWS_PROFILE]
	
		This script encrypts an plaintext file from SOURCE into an
		AWS KMS encrypted DESTINATION file.  Optionally you
		may provide the AWS_PROFILE you wish to use to run the aws kms
		commands.

	EOUSAGE
	exit 1
}

[ $# -lt 3 ] && usage

if [ -n "${4}" ]; then
	export AWS_PROFILE=${4}
fi

aws kms encrypt --key-id "${1:?}" --plaintext fileb://<(cat "${2:?}") --output text --query CiphertextBlob > "${3:?}"

We can do the following with that script to encrypt the objects:

./encrypt.sh <KMS_KEY_ID> cloudfront.key cloudfront.key.encrypted
./encrypt.sh <KMS_KEY_ID> cloudfront.pem cloudfront.pem.encrypted

Now with those encrypted we could setup the module with something like the following to populate the module (assuming we add the files to a /resources folder):

module "cloudfront-software-installers" {
  source            = "github.com/fleetdm/fleet-terraform/addons/cloudfront-software-installers?ref=tf-mod-addon-cloudfront-software-installers-v1.2.0"
  customer          = "fleet"
  s3_bucket         = module.main.byo-vpc.byo-db.byo-ecs.fleet_s3_software_installers_config.bucket_name
  # OPTIONAL
  # If you'd like to use an existing key_group_id for your new Cloudfront distribution, uncomment key_group_id and supply the value for the key_group_id
  # If you're using an existing key_group_id, public_key_id is required. The public_key_id is the value of a public_key that is also part of the key group that you define.
  # key_group_id      = ""
  # public_key_id     = ""
  public_key        = data.aws_kms_secrets.cloudfront.plaintext["public_key"]
  private_key       = data.aws_kms_secrets.cloudfront.plaintext["private_key"]
  enable_logging    = true
  logging_s3_bucket = module.logging_alb.log_s3_bucket_id
}

data "aws_kms_secrets" "cloudfront" {
  secret {
    name    = "public_key"
    key_id  = aws_kms_key.customer_data_key.id
    payload = file("${path.module}/resources/cloudfront.pem.encrypted")
  }
  secret {
    name    = "private_key"
    key_id  = aws_kms_key.customer_data_key.id
    payload = file("${path.module}/resources/cloudfront.key.encrypted")
  }
}

Then we need to include outputs from this module once applied back into the main fleet-config under the extra_secrets and extra_execution_roles:

This addon also outputs cloudfront_distribution_arn. Do not feed that output back into tf-mod-byo-ecs, because that creates a Terraform cycle. Instead, set the same static ARN directly in software_installers.cloudfront_distribution_arn.

Under the fleet_config section. If not using the mdm module, that could be omitted but was included to show how to include multiple extra items:

  fleet_config = {
  ...
    extra_execution_iam_policies = concat(
      module.mdm.extra_execution_iam_policies,
      module.cloudfront-software-installers.extra_execution_iam_policies,
    )
    extra_secrets = merge(
      module.mdm.extra_secrets,
      module.cloudfront-software-installers.extra_secrets
    )
 }

Requirements

No requirements.

Providers

Name Version
aws 6.36.0

Modules

Name Source Version
cloudfront_software_installers terraform-aws-modules/cloudfront/aws 5.2.0

Resources

Name Type
aws_cloudfront_key_group.software_installers resource
aws_cloudfront_public_key.software_installers resource
aws_iam_policy.software_installers_secret resource
aws_s3_bucket_policy.software_installers resource
aws_secretsmanager_secret.software_installers resource
aws_secretsmanager_secret_version.software_installers resource
aws_iam_policy_document.software_installers_bucket data source
aws_iam_policy_document.software_installers_secret data source
aws_s3_bucket.logging data source
aws_s3_bucket.software_installers data source

Inputs

Name Description Type Default Required
customer Customer name for the cloudfront instance string "fleet" no
enable_logging Enable optional logging to s3 bool false no
key_group_id Cloudfront key group id string null no
logging_s3_bucket s3 bucket to log to string null no
logging_s3_prefix logging s3 bucket prefix string "cloudfront" no
private_key Private key used for signed URLs string n/a yes
public_key Public key used for signed URLs string n/a yes
public_key_id Cloudfront public key id. Required when passing in a key_group_id string null no
s3_bucket Name of the S3 bucket that Cloudfront will point to string n/a yes

Outputs

Name Description
cloudfront_arn n/a
cloudfront_distribution_arn n/a
extra_execution_iam_policies n/a
extra_secrets n/a