A tool for enumerating and downloading EBS snapshots
Install
# with apt package manager
sudo apt install python3-dsnap
# with pipx
pipx install dnsap
Enumerating Snapshots
You need the AWS action ebs:ListSnapshotBlocks
# list all snapshots available in an account you have valid credentials for
dsnap --profile <profileName> --region <awsRegion> list
Id | Owneer ID | Description
snap-11111111111111111 123456789012 mysnapshot
Downloading Snapshots
You need the AWS action ebs:GetSnapshotBlock
With Access to the AWS Account
So long as the snapshot exists in an AWS account you have access to, you can download it
dsnap --profile <profileName> --region <awsRegion> get snap-11111111111111111
Selected snapshot with id snap-11111111111111111
Output Path: /home/parallels/snap-11111111111111111.img
Truncating file to 8.0 GB
Without Access to the AWS Account
If you don't have credentials for an AWS account where the public snapshot is, you can't download it
dsnap --profile <profileName> --region <awsRegion> get snap-22222222222222222
Selected snapshot with id snap-22222222222222222
[snip]
botocore.errorfactory.ValidationException: An error occurred (ValidationException) when calling the ListSnapshotBlocks operation: Public snapshots are not supported
To resolve this, first copy the snapshot from the target account to your account
Alternatively, you can create an ec2 in your account and use this snapshot which may be beneficial depending on the snapshot size / your download speeds
dsnap --profile <profileName> --region <awsRegion> get snap-11111111111111111
Selected snapshot with id snap-11111111111111111
Output Path: /home/parallels/snap-11111111111111111.img
Truncating file to 8.0 GB
Mounting the Snapshot for Local Inspection
If you decide to download the snapshot locally (rather than run it on an EC2) then we need to mount it
Mounting the snapshot is like attaching a USB drive to your computer. You have access to all the files on the drive but it's not running the operating system.
parted snap-11111111111111111.img unit s print
# output
WARNING: You are not superuser. Watch out for permissions.
Model: (file)
Disk /home/parallels/snap-11111111111111111.img: 16777216s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
14 2048s 10239s 8192s bios_grub
15 10240s 227327s 217088s fat32 boot, esp
1 227328s 16777182s 16549855s ext4
We take the start point of the ext4 partition (227328) and multiply it by the sector size (512 bytes), which gives us an offset value of 116391936. This offset tells the operating system where to begin reading the partition within the disk image. Without specifying the correct offset, the operating system might attempt to read from the wrong location—such as the partition table or unallocated space—causing errors or preventing access to the file system.
# make a directory to mount the snapshot
sudo mkdir /mnt/snapshot
# mount the snapshot
sudo mount -o loop,offset=116391936 snap-11111111111111111.img /mnt/snapshot
Now we can access the snapshot
ls -alh /mnt/snapshot
# output
total 88K
drwxr-xr-x 19 root root 4.0K Dec 21 2023 .
drwxr-xr-x 3 root root 4.0K Jan 4 13:06 ..
lrwxrwxrwx 1 root root 7 Dec 6 2023 bin -> usr/bin
drwxr-xr-x 4 root root 4.0K Dec 6 2023 boot
drwxr-xr-x 4 root root 4.0K Dec 6 2023 dev
drwxr-xr-x 93 root root 4.0K Dec 21 2023 etc
drwxr-xr-x 3 root root 4.0K Dec 21 2023 home
lrwxrwxrwx 1 root root 7 Dec 6 2023 lib -> usr/lib
[snip]
You'll notice the files and directories are all owned by root since we had to use sudo to mount this
We have a few options, the easiest being to switch to the root user
ls root/
#output
ls: cannot open directory 'root': Permission denied
sudo su
ls root/
# output
root_file1 root_file2
Or you can change ownership of the mount directory to our current user (parallels for me)
sudo chown -R $USER:$USER /mnt/snapshot
ls -alh /mnt/snapshot
# output
total 88K
drwxr-xr-x 19 parallels parallels 4.0K Dec 21 2023 .
drwxr-xr-x 3 root root 4.0K Jan 4 13:06 ..
lrwxrwxrwx 1 parallels parallels 7 Dec 6 2023 bin -> usr/bin
drwxr-xr-x 4 parallels parallels 4.0K Dec 6 2023 boot
drwxr-xr-x 4 parallels parallels 4.0K Dec 6 2023 dev
[snip]
Change it back to root if you want
sudo chown -R root:root /mnt/snapshot
ls -alh /mnt/snapshot
# output
total 88K
drwxr-xr-x 19 root root 4.0K Dec 21 2023 .
drwxr-xr-x 3 root root 4.0K Jan 4 13:06 ..
lrwxrwxrwx 1 root root 7 Dec 6 2023 bin -> usr/bin
drwxr-xr-x 4 root root 4.0K Dec 6 2023 boot
drwxr-xr-x 4 root root 4.0K Dec 6 2023 dev
Running the Snapshot in a Local Docker Container
Dsnap can spin up a local docker container to run the snapshot from but I haven't had luck getting this to work on an Apple Silicon mac (though I haven't tried for over a year)