Onboarding
6 min read
Prerequisites
- You must have an AWS account and permissions to configure AWS resources.
- You must have the Admin role in the Footprint dashboard.
- You must have a YubiKey that supports the PIV card interface over USB. A YubiKey 5C should suffice. Amazon often has the YubiKey 5C NFC available for fast delivery.
1. Install Vault Disaster Recovery tools
First install the CLI tool used for enrollment and decryption. On a Mac, run the following:
bash
For other platforms, you can download releases from here.
2. Create an API key and log in with the CLI
Go to the API Keys page on the Footprint dashboard and use the toggle in the top right corner to select Sandbox or Live mode, depending on which data set you would like to enroll.
Create a new API key with an admin scope.
Run footprint-dr login [--sandbox/--live] and paste the API key at the prompt.
Example Output1$ footprint-dr login --live 2Enter Footprint Live API key: <hidden>
3. Create a bucket for encrypted data storage
Footprint needs a dedicated customer-owned Amazon S3 bucket to store encrypted data. Create a new S3 bucket similar to the one in the Terraform example below. Ensure you are creating the bucket using the us-east-1 region for optimal performance.
terraform1resource "aws_s3_bucket" "fp_vault_data" { 2 bucket = "acme-inc-footprint-vault-data" 3 4} 5 6resource "aws_s3_bucket_public_access_block" "fp_vault_data_public_access_block" { 7 bucket = aws_s3_bucket.fp_vault_data.id 8 9 block_public_acls = true 10 block_public_policy = true 11 ignore_public_acls = true 12 restrict_public_buckets = true 13}
We recommend that you create this S3 Bucket in a dedicated AWS account with tight access controls. Keeping access to this bucket to a minimum helps reduce the impact of unintentional leaks of an org private key.
We also recommend that you enable CloudTrail audit logs for data events on this bucket. See the following example Terraform:
terraform1resource "aws_s3_bucket" "fp_vault_data_cloudtrail" { 2 bucket = "acme-inc-footprint-vault-data-cloudtrail" 3} 4 5resource "aws_s3_bucket_public_access_block" "fp_vault_data_cloudtrail_pab" { 6 bucket = aws_s3_bucket.fp_vault_data_cloudtrail.id 7 8 block_public_acls = true 9 block_public_policy = true 10 ignore_public_acls = true 11 restrict_public_buckets = true 12} 13 14locals { 15 fp_vault_data_cloudtrail_name = "footprint-vault-data-cloudtrail" 16} 17 18data "aws_iam_policy_document" "fp_vault_data_cloudtrail" { 19 statement { 20 sid = "AWSCloudTrailAclCheck" 21 effect = "Allow" 22 23 principals { 24 type = "Service" 25 identifiers = ["cloudtrail.amazonaws.com"] 26 } 27 28 actions = ["s3:GetBucketAcl"] 29 resources = [aws_s3_bucket.fp_vault_data_cloudtrail.arn] 30 condition { 31 test = "StringEquals" 32 variable = "aws:SourceArn" 33 values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/${local.fp_vault_data_cloudtrail_name}"] 34 } 35 } 36 37 statement { 38 sid = "AWSCloudTrailWrite" 39 effect = "Allow" 40 41 principals { 42 type = "Service" 43 identifiers = ["cloudtrail.amazonaws.com"] 44 } 45 46 actions = ["s3:PutObject"] 47 resources = ["${aws_s3_bucket.fp_vault_data_cloudtrail.arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"] 48 49 condition { 50 test = "StringEquals" 51 variable = "s3:x-amz-acl" 52 values = ["bucket-owner-full-control"] 53 } 54 condition { 55 test = "StringEquals" 56 variable = "aws:SourceArn" 57 values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/${local.fp_vault_data_cloudtrail_name}"] 58 } 59 } 60} 61 62resource "aws_s3_bucket_policy" "fp_vault_data_cloudtrail" { 63 bucket = aws_s3_bucket.fp_vault_data_cloudtrail.id 64 policy = data.aws_iam_policy_document.fp_vault_data_cloudtrail.json 65} 66 67resource "aws_cloudtrail" "fp_vault_data_cloudtrail" { 68 name = local.fp_vault_data_cloudtrail_name 69 s3_bucket_name = aws_s3_bucket.fp_vault_data_cloudtrail.id 70 71 include_global_service_events = false 72 73 depends_on = [aws_s3_bucket_policy.fp_vault_data_cloudtrail] 74 75 event_selector { 76 read_write_type = "All" 77 include_management_events = true 78 79 data_resource { 80 type = "AWS::S3::Object" 81 82 values = ["${aws_s3_bucket.fp_vault_data.arn}/"] 83 } 84 } 85}
4. Fetch your external ID
Your external ID will help secure the cross-account IAM access. Run footprint-dr get-external-id [--sandbox/--live] to fetch it.
Example Output1$ footprint-dr get-external-id --live 242ee4f928973996f8f855aebaebf70cd
5. Create an IAM role for bucket management
Footprint needs read and write access to the bucket to manage the encrypted data. Create a IAM role to delegate access like the one in the Terraform example below, substituting your external ID.
terraform1locals { 2 external_id = "42ee4f928973996f8f855aebaebf70cd" 3} 4 5resource "aws_iam_role" "fp_vault_data_management" { 6 name = "fp-vault-data-management" 7 8 assume_role_policy = data.aws_iam_policy_document.fp_vault_data_management_assume_role_policy.json 9} 10 11data "aws_iam_policy_document" "fp_vault_data_management_assume_role_policy" { 12 statement { 13 actions = ["sts:AssumeRole"] 14 15 principals { 16 type = "AWS" 17 identifiers = ["725896863556"] 18 } 19 20 condition { 21 test = "StringEquals" 22 variable = "sts:ExternalId" 23 values = [local.external_id] 24 } 25 } 26} 27 28data "aws_iam_policy_document" "fp_vault_data_management_policy" { 29 statement { 30 sid = "AllowPutObject" 31 32 actions = [ 33 "s3:PutObject", 34 ] 35 36 resources = [ 37 "${aws_s3_bucket.fp_vault_data.arn}/*", 38 ] 39 } 40 41 statement { 42 sid = "AllowListBucket" 43 44 actions = [ 45 "s3:ListBucket", 46 ] 47 48 resources = [ 49 aws_s3_bucket.fp_vault_data.arn, 50 ] 51 } 52 53 statement { 54 sid = "AllowGetBucketLocation" 55 56 actions = [ 57 "s3:GetBucketLocation", 58 ] 59 60 resources = [ 61 aws_s3_bucket.fp_vault_data.arn, 62 ] 63 } 64} 65 66resource "aws_iam_policy" "fp_vault_data_management" { 67 name = "fp-vault-data-management" 68 policy = data.aws_iam_policy_document.fp_vault_data_management_policy.json 69} 70 71resource "aws_iam_role_policy_attachment" "fp_vault_data_management_assume_role" { 72 role = aws_iam_role.fp_vault_data_management.name 73 policy_arn = aws_iam_policy.fp_vault_data_management.arn 74}
6. Generate your Disaster Recovery org key pair
Org identities (private keys) are stored on one or more YubiKeys. Using hardware security tokens helps virtually eliminate the risk of accidentally leaking a private key, which is a sensitive component of the recovery flow. Depending on your data durability requirements, you may choose to mitigate the risk of lost or damaged hardware by registering redundant YubiKeys.
The age YubiKey plugin helps makes the enrollment process simple. Install age and age-plugin-yubikey on a workstation with a USB port for the YubiKey.
bash1# On a Mac: 2brew install age age-plugin-yubikey ykman
Plug in the YubiKey. Now, change the management key by running the following command. Press the enter key to use the default management key, and enter the default YubiKey pin of 123456 at the prompt.
bash1ykman piv access change-management-key -a TDES --protect
Then, run a command like the following to generate an age identity for your org. Adjust the name and mode (sandbox/live) for your own reference. You will be prompted to change your PIN/PUK. Choose a PIN and retain it in your password manager of choice. The PIN will be necessary to use your YubiKey to decrypt your Vault Disaster Recovery backups.
bash1age-plugin-yubikey \ 2 --generate \ 3 --name "Footprint Vault DR org age identity: Acme Inc. Live" \ 4 --pin-policy once \ 5 --touch-policy cached \ 6 --slot 1
You may choose a different slot number if slot 1 is already in use, though we advise using dedicated YubiKeys for live-mode Vault Disaster Recovery. We recommend the pin policy of once and the touch policy of cached to improve the experience of the test recovery flow.
You do not need to save any of the output, but make note of the recipient (starting with age1yubikey) which you will paste into the next step. You can retrieve the recipient again by running the following:
bash1age-plugin-yubikey --list
Repeat the key generation step once for each YubiKey you wish to register for Vault Disaster recovery, collecting a list of your org’s age1yubikey age recipients.
7. Complete enrollment
Run footprint-dr enroll [--sandbox/--live] and follow the prompts.
Example Output1$ footprint-dr enroll --live 2Enrolling Acme Inc. (Live) in Vault Disaster Recovery. 3 4Enter org public key (age recipient): age1yubikey1qgceu0h4fzsv46jg32gnfz0hf5lnaaqm8wn8skxf33qm0t4v4rz427fh79x 5Add another org public key? [y/n] y 6Enter org public key (age recipient): age1yubikey1q2eggw2hftplqfr27s9h8nwuez39m45ms6qv78m9m6kfhmsyf6gacj2km7u 7Add another org public key? [y/n] n 8 9Enter AWS Account ID: 123456789012 10Enter AWS role name: acme-inc-footprint-disaster-recovery 11Enter S3 bucket name: acme-inc-footprint-encrypted-data 12 13Verifying configuration... OK 14 15Enrollment complete. 16 17Store the following information to locate your encrypted data: 18 S3 Bucket Name: acme-inc-footprint-disaster-recovery 19 Bucket Namespace: a39evoii5rgqhdz4jansho3tten4z0oz
Unplug the YubiKey, clearly label it, and store it in a physically secure location (e.g. an office safe). You will need to retrieve the YubiKey to decrypt Disaster Recovery data.
Store the printed S3 Bucket Name and Bucket Namespace in your records to ensure you can locate your Disaster Recovery data.