Exfiltrating data from Microsoft® Windows® to AWS EFS

Let’s say you have a Microsoft® Windows® “Server” instance in AWS EC2 and you would like to get a large tree of directories and thousands of files off the local NFTS filesystem and into an AWS EFS Access Point. The easiest approach would be to create a tarball and drop it into S3 for processing by a Linux host that is already connected to EFS.

But what if you’d like to keep the filesystem in sync as little changes are made to the files trapped on Microsoft® Windows®? One option is to mount EFS in Windows® Subsystem for Linux® and periodically run rsync.

Unless you have the “metal” flavor of AWS EC2 instance, you will need to run the old WSL v1; the virutalization features required by WSL v2 are not offered by AWS. See the installation instructions, or blindly follow my procedure by pasting the following into MS-DOS running as a really real Administrator, i.e. not the SSM user:

wsl --install --enable-wsl1 --no-launch
shutdown -r
wsl --set-default-version 1
wsl --install --distribution ubuntu

It doesn’t much matter what the non-root username is; I use ec2-user following the AWS convention. Within the Ubuntu installation in WSL, install unzip, then execute the standard AWS CLI installation instructions:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install unzip nfs-common
cd $(mktemp -d)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o awscliv2.zip
unzip -q awscliv2.zip
sudo ./aws/install

Microsoft® Windows® may crash when installing the AWS CLI. If it does, try to reconnect after a reboot.

Then build and install the efs-utils package:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. "$HOME/.cargo/env"

sudo apt-get install git binutils rustc cargo pkg-config libssl-dev
mkdir -p "$HOME/aws-busy-work/efs-utils"
cd "$HOME/aws-busy-work/efs-utils"
git clone https://github.com/aws/efs-utils.git .
./build-deb.sh
mv ./build/amazon-efs-utils*deb /tmp/
sudo apt-get -y install /tmp/amazon-efs-utils*deb

It’s common for Microsoft® Windows® to crash when cloning the repository from Microsoft® GitHub®, because Microsoft® Windows® has stability issues. Prepare to mount an EFS Access Point

efs_fs_id=fs-1234567890abcdef
efs_ap_id=fsap-1234567890abcdef
mount_point=content

cd $HOME
mkdir -p $mount_point
sudo mount -t efs -o tls,iam,accesspoint=$ $: $mount_point

If Microsoft® Windows® reboots from the crash, try copying files to the mounted EFS Access Point.

ACME Certificate for Internal Server using Route 53

This procedure results in a TLS certificate issued by an ACME CA for an internal server using an AWS Route 53 Hosted Zone that is designated for ACME DNS verification.

Consider a company that has a domain registration of company.com with a legacy DNS provider that does not have an API for dynamic record creation. A private AWS Route 53 Hosted Zone exists for internal.company.com that is inaccessible from the public internet; there is no zone delegation from company.com to this zone. A TLS certificate is desired for app.internal.company.com using DNS verification. A public AWS Route 53 Hosted Zone exists for aws.company.com and an AWS IAM user has permission to add TXT records to that zone.

A static CNAME is created manually in the legacy DNS system for _acme-challenge.app.internal.company.com pointing to _acme-challenge.app.aws.company.com. When acme.sh is executed using the DNS verification method, it will create a record in the AWS Route 53 Hosted Zone for aws.company.com that can be queried by the ACME CA.

First let’s get setup for running acme.sh:

  • Create an acme_home directory at ~/.acme.sh.docker or another location of your choice. The reason a directory named ~/.acme.sh.docker is suggested instead of the default location of ~/.acme.sh is that it the Docker container and a local installation of acme.sh can’t share the same configuration files.

  • Create an AWS IAM user that has permission to update AWS Route 53 only. An example Terraform module shows the resources necessary. The example below shows retrieving the AWS API Access Key from using 1Password CLI when performing an interactive experiment. It’s worth noting that the current version of acme.sh stores the AWS credentials in $acme_home/account.conf for later use. This is suboptimal and I hope an option to disable this is added.

Modify the values in the following script and execute to register and an ACME CA:

Then evaluate and modify the following to create a new TLS certificate:

If the procedure completes successfully, the key, certificate, and chain content will be located in $acme_home/$hostname.