Skip to content

Commit

Permalink
Updating all files to match latest internal working versions staged for
Browse files Browse the repository at this point in the history
initial product launch.  Adding missing licensing info to all files.
  • Loading branch information
LordAlfredo committed Jun 26, 2019
1 parent 2c190e4 commit d998839
Show file tree
Hide file tree
Showing 34 changed files with 1,005 additions and 219 deletions.
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
VERSION_FILE=./VERSION
pkgver=$(shell cat $(VERSION_FILE))
version = $(firstword $(subst -, ,$(pkgver)))
release = $(lastword $(subst -, ,$(pkgver)))

default: clean ;

deb:
./bin/make_deb.sh $(version) $(release)

rpm:
./bin/make_rpm.sh $(version) $(release)

clean:
$(shell rm -rf ec2-instance-connect*)
$(shell rm -rf ./rpmbuild/SOURCES)
$(shell rm -rf ./deb-src)
$(shell rm -rf ./srpm_results)
$(shell rm -rf ./rpm_results)
69 changes: 51 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,27 @@

This package contains the EC2 instance configuration and scripts necessary to enable AWS EC2 Instance Connect.

This package does *not* include the build configuration or packaging for EC2's package repositories - such packaging is handled by the Amazon Linux maintainers.

## AuthorizedKeysCommand

The AuthorizedKeysCommand is split into two parts, both under src/opt/aws/bin/
The AuthorizedKeysCommand is split into three parts:

* curl_authorized_keys, which is the entry point for sshd on an ssh call
* parse_authorized_keys, which is the main authorized keys command logic
* eic_run_authorized_keys is the main entry point and wraps the rest in a 5 second timeout
* eic_curl_authorized_keys, which is the entry point for sshd on an ssh call
* eic_parse_authorized_keys, which is the main authorized keys command logic

This split is intentional - as parse takes all necessary pieces as command inputs is can be unit tested independently. curl, however, obviously needs to curl EC2 Instance Metadata Service and so cannot be tested without mocking the actual service.

### curl_authorized_keys
### eic_curl_authorized_keys

The curl script is a dumb entry point and serves only to curl the relevant information from EC2 Instance Metadata Service and send it to parse.
The curl script verifies we are actually running on an EC2 instance and cURLs relevant information from EC2 Instance Metadata Service and send it to parse.

Note that it must make several curl commands to proceed. If it cannot do so it fast-fails to prevent blocking the ssh daemon.

An interesting part to note is that the command also queries several OCSP staples from EC2 Instance Metadata Service.
The command also queries several OCSP staples from EC2 Instance Metadata Service.
These OCSP staples are provided from the AWS EC2 Instance Connect Service to avoid needing to query each CRL or OCSP authority at ssh calltime as that would have major performance implications.
The staples are passed to and used by parse_authorized_keys to check certificate validity without the need for extra external calls.

### parse_authorized_keys
### eic_parse_authorized_keys

In addition to the fields required to complete all the below process, a key fingerprint may be provided. If a key fingerprint is specified then only ssh keys found matching that fingerprint will be returned.

Expand All @@ -37,9 +36,9 @@ The signing certificate goes through a deep verification flow that checks:
* The certificate trust chain can be verified up through the Amazon Trust Services Certificate Authority
* The entire certificate chain is valid - ie, none of them have been revoked

The first and second are done via standard openssl checks. The third, however, does not query the relevant CRLs or OCSP authorities at runtime.
Instead, OCSP staples are expected to be provided by the invoker (such as curl_authorized_keys).
As OCSP staples are cryptographically sound these are considered a sufficient validity check.
The first and second are done via standard openssl checks. The third, however, does not query the relevant CRLs or OCSP authorities at runtime to avoid adding a network call to sshd.
Instead, OCSP staples are expected to be provided by the invoker (i.e., eic_curl_authorized_keys).
As OCSP staples are cryptographically signed and can be verified against a trusted authority these are considered a sufficient validity check.

#### Key Processing

Expand Down Expand Up @@ -73,7 +72,21 @@ If all of these checks pass then the key will be presented to the ssh daemon. O

Any time a key is provided to the ssh daemon it will be logged to the system authpriv log for auditing purposes.

## Testing
## Host Key Harvesting

The fourth script, eic_harvest_hostkeys, has no direct relation to the AuthorizedKeysCommand. Instead, it is used to pass the instance's ssh host keys back to the EC2 Instance Connect Service.
This is necessary to establish trust for the EC2 Console for the console's one-click in-browser ssh terminal feature.

### systemd Module

The systemd module provided for host key harvesting is a basic one-shot to invoke eic_harvest_hostkeys.

### eic_harvest_host_keys

The host key harvesting script has to run similar logic to eic_curl_authorized_keys to get some basic information from Instance Metadata Service about the instance itself.
It then reads the ssh host keys on the machine, then creates and signs an AWS Signature Version 4 Request to

## Unit Testing

As parse_authorized_keys requires a valid certificate, CA, and OCSP staples, unit testing is a somewhat involved process.

Expand All @@ -91,14 +104,34 @@ The structure of test/input/unsigned, rather than files, is directories to test.
Each file should have *one* test key blob to sign.
The actual test input will be the result of generating signatures for each file and constructing an imitation of the service's key bundle.

## Manual Setup
## End-to-End Testing

It is strongly recommended you build a sample package for end-to-end testing. If you do you may skip steps 1-4 in favor of installing your test build.

1. Copy the contents of src/bin to a directory on an EC2 instance (such as /opt/aws/bin, see debian/postinst or rpmsrc/SPECS/generic.spec)
2. Create a system user for sshd to use as the AuthorizedKeysCommandUser, such as ec2-instance-connect (see debian/postinst or rpmsrc/SPECS/generic.spec for configuration)
3. Modify /etc/ssh/sshd_config so that you have
* `AuthorizedKeysCommand /path/from/step/1/eic_run_authorized_keys`
* `AuthorizedKeysCommandUser user-from-step-2`
4. Restart sshd (ie, sudo systemctl restart sshd (or ssh on Ubuntu))
5. Attempt to connect to your instance with EC2 Instance Connect

## Building RPM/Debian Packaging

If desired, this scripting can be added to an EC2 instance for further testing. A convenience pair of scripts - bin/make_rpm.sh and bin/make_deb.sh - have been provided to quickly build test packages.
Each may be invoked via `make rpm` and `make deb` respectively. Be sure to update VERSION!

**Debian packaging tools are intended for testing purposes only. Please follow standard Debian process to submit patches.**

### Why is it generic.rpm?

If desired, this scripting can be added to an EC2 instance for further testing. A convenience pair of scripts - bin/make_tarball.sh and bin/configure_sshd.sh - can be used to do so.
"generic.rpm" is used internally to differentiate the specfile for Fedora/RHEL/CentOS from Amazon Linux.
There is a separate Amazon-proprietary rpmspec and build process optimized for Amazon Linux.

* make_tarball will compress the contents of src for easy installation.
* configure_sshd will add an ec2-instance-connect system user and modify /etc/ssh/sshd_config to enable the relevant AuthorizedKeysCommand
## Why UNIX shell?

Note: if you are running an instance with OpenSSH 6.9 or new installed, it is strongly encouraged that in addition to the changes configure_sshd makes you also add `%f` to the AuthorizedKeysCommand line. This flag is not supported on older versions of OpenSSH!
This package is intended as a simple reference implementation of the instance-side pieces of the EC2 Instance Connect feature, though as time has gone on it has become much more complex than originally intended.
Amazon is considering reimplementation in another language for the future but for the time being we will continue to iterate on the shell implementation.

## License

Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.1-10
55 changes: 0 additions & 55 deletions bin/configure_sshd.sh

This file was deleted.

73 changes: 73 additions & 0 deletions bin/make_deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

# Reads authorized keys blob $3 and prints verified, unexpired keys
# Openssl to use provided as $1
# Signer public key file path provided as $2

# XXX: This script builds a local 3.0 (native) package for testing purposes.
# Any actual patches should be developed and submitted using apt-source and Quilt.

# Note: this will only work on a system with dpkg build tools installed (ie, Debian & its derivatives)
# It is also strongly recommended you install devtools (dch, etc) to assist with package building
# You are *REQUIRED* to have debhelper and devscripts installed!

if [ $# -ne 2 ] ; then
echo "Usage: make_deb.sh [version] [release]"
echo " ie, make_deb.sh [1.1] [1]"
exit 1
fi

md5 () {
/bin/echo -n "${val}" | /usr/bin/md5sum | /bin/sed 's/\s.*$//'
}

sha1 () {
/bin/echo -n "${val}" | /usr/bin/sha1sum | /bin/sed 's/\s.*$//'
}

sha256 () {
/bin/echo -n "${val}" | /usr/bin/sha256sum | /bin/sed 's/\s.*$//'
}

TOPDIR=$(dirname "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )")

version=$1
release=$2
pkgdir="${TOPDIR}/ec2-instance-connect-${version}-${release}"

# Copy source files
mkdir $pkgdir
mkdir -p $pkgdir/ec2-instance-connect
cp $TOPDIR/src/bin/* $pkgdir/ec2-instance-connect/
# Dump /bin, /usr/bin, etc from binary paths names since we want to use $PATH on Ubuntu/etc
sed -i "s%/usr/bin/%%g" $pkgdir/ec2-instance-connect/*
sed -i "s%^/bin/%%g" $pkgdir/ec2-instance-connect/*
sed -i "s%\([^\#][^\!]\)/bin/%\1%g" $pkgdir/ec2-instance-connect/*
# Copy ec2-instance-connect service file
cp -r $TOPDIR/src/deb_systemd/ec2-instance-connect.service $pkgdir/

mkdir $pkgdir/debian
cp -r $TOPDIR/debian/* $pkgdir/debian/
sed -i "s/\!VERSION\!/${version}-${release}/" $pkgdir/debian/control

# Do the actual packaging
return_dir=$(pwd)
cd $pkgdir
debuild

# Clean up
cd $return_dir
rm -rf $pkgdir
70 changes: 70 additions & 0 deletions bin/make_rpm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/bash

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

# Reads authorized keys blob $3 and prints verified, unexpired keys
# Openssl to use provided as $1
# Signer public key file path provided as $2

# Note: this will only work on a system with rpm build tools installed (ie, RHEL & its derivatives)

if [ $# -ne 2 ] ; then
echo "Usage: make_rpm.sh [version] [release]"
echo " ie, make_rpm.sh [1.1] [1]"
exit 1
fi

TOPDIR=$(dirname "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )")
BUILDDIR=$TOPDIR/rpmbuild
mkdir -p $BUILDDIR

version=$1
release=$2

mkdir -p $BUILDDIR/{BUILD,RPMS,SOURCES,SPECS,SRPMS,ec2-instance-connect-${version},tmp}
mkdir -p $BUILDDIR/ec2-instance-connect-$version/opt/aws/bin
cp $TOPDIR/rpmsrc/SPECS/generic.spec $BUILDDIR/SPECS/ec2-instance-connect.spec
cp $TOPDIR/src/bin/* $BUILDDIR/ec2-instance-connect-$version/opt/aws/bin/
cp $TOPDIR/rpmsrc/.rpmmacros $BUILDDIR/

/bin/sed -i "s%^ca_path=/etc/ssl/certs$%ca_path=/etc/ssl/certs/ca-bundle.crt%" $BUILDDIR/ec2-instance-connect-$version/opt/aws/bin/eic_curl_authorized_keys

# Trick rpmbuild into thinking this is homedir to read .rpmmacros
REALHOME=$HOME
export HOME=$BUILDDIR

function cleanup {
export HOME=$REALHOME
rm -rf $BUILDDIR/${BUILD,SOURCES,tmp}
rm -rf $BUILDDIR/BUILDROOT # In case we got far enough for this to exist
rm -rf $BUILDDIR/ec2-instance-connect-$version
}
trap cleanup EXIT

cp $TOPDIR/src/rpm_systemd/ec2-instance-connect.service $BUILDDIR/SOURCES/
ls $BUILDDIR/SOURCES

cd $BUILDDIR # Will ensure some paths are set correctly in rpmbuild

# Compress the scripts
tar -czf $BUILDDIR/SOURCES/ec2-instance-connect-$version.tar.gz ec2-instance-connect-$version/

# Fill in the placeholders
sed -i "s/\!VERSION\!/${version}/" $BUILDDIR/SPECS/ec2-instance-connect.spec
sed -i "s/\!RELEASE\!/${release}/" $BUILDDIR/SPECS/ec2-instance-connect.spec

# Build the package
rpmbuild -ba -bs $BUILDDIR/SPECS/ec2-instance-connect.spec

cp $BUILDDIR/RPMS/noarch/ec2-instance-connect-$version-$release.noarch.rpm $TOPDIR/
24 changes: 18 additions & 6 deletions bin/make_tarball.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
Expand All @@ -13,9 +13,21 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

# Reads authorized keys blob $3 and prints verified, unexpired keys
# Openssl to use provided as $1
# Signer public key file path provided as $2

TOPDIR=$(dirname "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )")
mkdir $TOPDIR/ec2-instance-connect-1.0
cp -r $TOPDIR/src/opt $TOPDIR//ec2-instance-connect-1.0
tar -czf $TOPDIR/ec2-instance-connect-1.0.tar.gz -C $TOPDIR ec2-instance-connect-1.0/
rm -rf $TOPDIR/ec2-instance-connect-1.0/*
rmdir $TOPDIR/ec2-instance-connect-1.0

verrel=$(cat $TOPDIR/VERSION)
version=${verrel%-*}
pkgver="ec2-instance-connect-${version}"

mkdir -p $TOPDIR/$pkgver/opt/aws/bin
cp $TOPDIR/src/bin/* $TOPDIR/$pkgver/opt/aws/bin/
if [ $# -eq 1 ] ; then # TODO: better check. Low-priority.
/bin/sed -i "s%^ca_path=/etc/ssl/certs$%ca_path=/etc/ssl/certs/ca-bundle.crt%" $TOPDIR/$pkgver/opt/aws/bin/eic_curl_authorized_keys
fi
tar -czf $TOPDIR/$pkgver.tar.gz -C $TOPDIR $pkgver/
rm -rf $TOPDIR/$pkgver/*
rmdir $TOPDIR/$pkgver
Loading

0 comments on commit d998839

Please sign in to comment.