Skip to content

Commit

Permalink
Fixing license year
Browse files Browse the repository at this point in the history
Improving SSL certificate bundle handling to support different /etc/ssl/cert structures
  • Loading branch information
LordAlfredo committed Oct 23, 2018
1 parent 506303a commit 2c190e4
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 28 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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/
Expand Down
2 changes: 1 addition & 1 deletion bin/configure_sshd.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/make_tarball.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
18 changes: 18 additions & 0 deletions bin/modify_amazon_linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# Copyright 2018 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.

# Amazon Linux has its installed CAs in a single file called "ca-bundle.crt". We point to that directly instead of just the ssl certs dir.

/bin/sed -ir "/^ca_path=\/etc\/ssl\/certs$/cca_path=\/etc\/ssl\/certs\/ca-bundle.crt" /opt/aws/bin/curl_authorized_keys
2 changes: 1 addition & 1 deletion bin/reset_sshd.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/test/generate_ocsp.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/test/run_authorized_keys_tests.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/test/setup_certificates.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/test/sign_data.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
2 changes: 1 addition & 1 deletion bin/test/test_authorized_keys.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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 Down
15 changes: 10 additions & 5 deletions src/opt/aws/bin/curl_authorized_keys
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
# Reads and echoes EC2 Metadata to get the authorized keys blob for the user $1

if [ -z "${1}" ] ; then
# No user provided, not really anything to query for. Fail out.
/usr/bin/logger -i -p authpriv.info "EC2 Instance Connect was invoked without a user to authorize and will do nothing."
exit 1
fi

/usr/bin/id -u "${1}" > /dev/null 2>&1
if [ $? -ne 0 ] ; then
exit 1
# User doesn't actually exist. Let sshd deal with it.
exit 0
fi

userpath=$(/bin/mktemp -d /dev/shm/tmp-XXXXXXXX)
Expand All @@ -35,10 +38,11 @@ keysfile=allowed-keys
OPENSSL=/usr/bin/openssl
curl_cmd="/usr/bin/curl -s -f -m 1"

# Verify that we have active keys. Fast-fail if we do not.
# Verify that we have active keys. Fast-exit if we do not.
if [ $(eval "${curl_cmd} -o /dev/null -I -w %{http_code} http://169.254.169.254/latest/meta-data/managed-ssh-keys/active-keys/${1}/") -eq 404 ]
then
exit 255
# No keys for this user. Nothing to do.
exit 0
fi

# Read the current signer cert
Expand Down Expand Up @@ -91,11 +95,12 @@ expected_signer=$(/usr/bin/printf 'managed-ssh-signer.%s.%s' "${region}" "${doma
# Invoke key parser (will automagically echo the results)
curl_command="${curl_cmd} http://169.254.169.254/latest/meta-data/managed-ssh-keys/active-keys/${1}/"
DIR="$( cd "$( dirname "${0}" )" && pwd )"
ca_path=/etc/ssl/certs
if [ -z "${2}" ] ; then
output=$($DIR/parse_authorized_keys -x false -r "${curl_command}" -o "${OPENSSL}" -d "${userpath}" -s "${certificate}" -i "${instance}" -c "${expected_signer}" -a "/etc/ssl/certs/ca-bundle.crt" -v "${ocsp_path}")
output=$($DIR/parse_authorized_keys -x false -r "${curl_command}" -o "${OPENSSL}" -d "${userpath}" -s "${certificate}" -i "${instance}" -c "${expected_signer}" -a "${ca_path}" -v "${ocsp_path}")
exitcode=$? # not quote-escaped since this must be numeric 0-255
else
output=$($DIR/parse_authorized_keys -x false -r "${curl_command}" -o "${OPENSSL}" -d "${userpath}" -s "${certificate}" -i "${instance}" -c "${expected_signer}" -a "/etc/ssl/certs/ca-bundle.crt" -v "${ocsp_path}" -f "${2}")
output=$($DIR/parse_authorized_keys -x false -r "${curl_command}" -o "${OPENSSL}" -d "${userpath}" -s "${certificate}" -i "${instance}" -c "${expected_signer}" -a "${ca_path}" -v "${ocsp_path}" -f "${2}")
exitcode=$? # not quote-escaped since this must be numeric 0-255
fi

Expand Down
57 changes: 42 additions & 15 deletions src/opt/aws/bin/parse_authorized_keys
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Copyright 2018 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,7 +13,7 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

# EC2 Instance Connect AuthorizedKeysCommand v 1.0.0
# EC2 Instance Connect AuthorizedKeysCommand v 1.0.1

# Reads authorized keys blob $3 and prints verified, unexpired keys
# Openssl to use provided as $1
Expand Down Expand Up @@ -47,7 +47,7 @@ removeprefix () {
verifyocsp() {
# First check if this cert is already trusted
cname=$($2 x509 -noout -subject -in $3 2>/dev/null | /bin/sed -n -e 's/^.*CN=//p')
fingerprint=$($2 x509 -noout -fingerprint -sha1 -inform pem -in $3 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint=\(.*\)/\1/p' | tr -d ':')
fingerprint=$($2 x509 -noout -fingerprint -sha1 -inform pem -in $3 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint[[:space:]]*=[[:space:]]*\(.*\)/\1/p' | tr -d ':')
ocsp_out=$($2 ocsp -no_nonce -issuer $4 -cert $3 -VAfile $4 -respin $5/$fingerprint 2>/dev/null)
if [ $? -ne 0 ] || ! startswith "${ocsp_out}" "${3}: good" ; then
fail $1 "EC2 Instance Connect could not verify certificate ${cname} has not been revoked. No keys have been trusted."
Expand Down Expand Up @@ -109,34 +109,61 @@ fi
echo "${signer}" | /usr/bin/awk -v dir="${tmpdir}" 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > dir "/cert" n ".pem"}'

# We want visibility into the CA bundle so we can skip verifying entries in the chain that are already trusted
if [ -d "${ca_path}" ] ; then
ca_path_dir=$ca_path
else
ca_path_dir=$(dirname "${ca_path}")
fi
ca_bundles_dir=$(/bin/mktemp -d $tmpdir/tmp-XXXXXXXX)
/bin/chmod 700 $ca_bundles_dir
end=$(/usr/bin/find $tmpdir -maxdepth 1 -type f -name "cert*.pem" -regextype sed -regex ".*/cert[0-9]\+\.pem" | wc -l)
if [ $(/usr/bin/expr $end) -gt 0 ] ; then
# First see if we already have them
exist=true
for i in `/usr/bin/seq 1 $end` ; do
subject=$($OPENSSL x509 -noout -subject -in "${tmpdir}/cert$i.pem" | /bin/sed -n -e 's/^.*CN=//p')
# Try to pull this CN from the CA bundle
/bin/sed -n -e '/#[[:space:]]'"$subject"'$/,$p' "${ca_path}" | /bin/sed '/-----END[[:space:]]CERTIFICATE-----.*/,$d' | /bin/sed -n '1!p' > "${ca_bundles_dir}/${subject}"
if [ -s "${ca_bundles_dir}/${subject}" ] ; then
/bin/echo "-----END CERTIFICATE-----" >> "${ca_bundles_dir}/${subject}"
subject=$($OPENSSL x509 -noout -subject -in "${tmpdir}/cert$i.pem" | /bin/sed -n -e 's/^.*CN[[:space:]]*=[[:space:]]*//p')
underscored=$(/bin/echo "${subject// /_}") 2>/dev/null
if [ -f "${ca_path_dir}/${underscored}.pem" ] ; then
# We already have it
/bin/cp "${ca_path_dir}/${subject}.pem" "${ca_bundles_dir}/${subject}"
else
/bin/rm -f "${ca_bundles_dir}/${subject}"
if [ ! -d "${ca_path}" ] ; then
# Try to pull this CN from the CA bundle
/bin/sed -n -e '/#[[:space:]]'"$subject"'$/,$p' "${ca_path}" 2>/dev/null | /bin/sed '/-----END[[:space:]]CERTIFICATE-----.*/,$d' | /bin/sed -n '1!p' > "${ca_bundles_dir}/${subject}"
if [ -s "${ca_bundles_dir}/${subject}" ] ; then
/bin/echo "-----END CERTIFICATE-----" >> "${ca_bundles_dir}/${subject}"
else
/bin/rm -f "${ca_bundles_dir}/${subject}"
fi
fi
fi
done
fi

# Build the intermediate trust chain
cat $(/usr/bin/find $tmpdir -maxdepth 1 -type f -name "cert*.pem" -regextype sed -regex ".*/cert[0-9]\+\.pem$") "${ca_path}" > $tmpdir/ca-trust.pem
cat $(/usr/bin/find $tmpdir -maxdepth 1 -type f -name "cert*.pem" -regextype sed -regex ".*/cert[0-9]\+\.pem$") > $tmpdir/ca-trust.pem
if [ -d "${ca_path}" ] ; then
subject=$($OPENSSL x509 -noout -subject -in "${tmpdir}/cert$end.pem" | /bin/sed -n -e 's/^.*CN[[:space:]]*=[[:space:]]*//p')
underscored=$(/bin/echo "${subject// /_}")
cat "${ca_bundles_dir}/${underscored}" >> $tmpdir/ca-trust.pem
else
cat "${ca_path}" >> $tmpdir/ca-trust.pem
fi
/bin/chmod 400 "${tmpdir}/ca-trust.pem"

# Verify the CN
signer_cn=$($OPENSSL x509 -noout -subject -in $tmpdir/cert.pem | /bin/sed -n -e 's/^.*CN=//p')
signer_cn=$($OPENSSL x509 -noout -subject -in $tmpdir/cert.pem | /bin/sed -n -e 's/^.*CN[[:space:]]*=[[:space:]]*//p')
if [ "${signer_cn}" != "${expected_cn}" ] ; then
fail $is_debug "EC2 Instance Connect encountered an unrecognized signer certificate. No keys have been trusted."
fi

# Verify the trust chain
verify_out=$($OPENSSL verify -x509_strict -CApath /dev/null -CAfile $tmpdir/ca-trust.pem $tmpdir/cert.pem)
if [ -d "${ca_path}" ] ; then
ca_path_option="${ca_path}"
else
ca_path_option="/dev/null"
fi
verify_out=$($OPENSSL verify -x509_strict -CApath ${ca_path_option} -CAfile $tmpdir/ca-trust.pem $tmpdir/cert.pem)
if [ $? -ne 0 ] || [ "${verify_out}" != "${tmpdir}/cert.pem: OK" ] ; then
fail $is_debug "EC2 Instance Connect could not verify the signer trust chain. No keys have been trusted."
fi
Expand All @@ -145,13 +172,13 @@ fi
# Iterate from first to second-to-last cert & validate OCSP staples
/bin/mv $tmpdir/cert.pem $tmpdir/cert0.pem # Better naming consistency for loop
for i in `/usr/bin/seq 0 $(( $end - 1 ))` ; do
subject=$($OPENSSL x509 -noout -subject -in "${tmpdir}/cert${i}.pem" | /bin/sed -n -e 's/^.*CN=//p')
subject=$($OPENSSL x509 -noout -subject -in "${tmpdir}/cert${i}.pem" | /bin/sed -n -e 's/^.*CN[[:space:]]*=[[:space:]]*//p')
if [ -f "${ca_bundles_dir}/${subject}" ] ; then
# If we encounter a certificate that's in the CA bundle we can skip the rest as implicitly trusted
hash=$($OPENSSL x509 -hash -noout -in "${tmpdir}/cert${i}.pem" 2>/dev/null)
trusted_hash=$($OPENSSL x509 -hash -noout -in "${ca_bundles_dir}/${subject}" 2>/dev/null)
fingerprint=$($OPENSSL x509 -noout -fingerprint -sha1 -in "${tmpdir}/cert${i}.pem" 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint=\(.*\)/\1/p' | tr -d ':')
trusted_fingerprint=$($OPENSSL x509 -noout -fingerprint -sha1 -in "${ca_bundles_dir}/${subject}" 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint=\(.*\)/\1/p' | tr -d ':')
fingerprint=$($OPENSSL x509 -noout -fingerprint -sha1 -in "${tmpdir}/cert${i}.pem" 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint[[:space:]]*=[[:space:]]*\(.*\)/\1/p' | tr -d ':')
trusted_fingerprint=$($OPENSSL x509 -noout -fingerprint -sha1 -in "${ca_bundles_dir}/${subject}" 2>/dev/null | /bin/sed -n 's/SHA1 Fingerprint[[:space:]]*=[[:space:]]*\(.*\)/\1/p' | tr -d ':')
pkey=$($OPENSSL x509 -pubkey -noout -in "${tmpdir}/cert${i}.pem")
trusted_pkey=$($OPENSSL x509 -pubkey -noout -in "${ca_bundles_dir}/${subject}" )
if [ "${hash}" = "${trusted_hash}" ] && [ "${fingerprint}" = "${trusted_fingerprint}" ] && [ "${pkey}" = "${trusted_pkey}" ] ; then
Expand Down

0 comments on commit 2c190e4

Please sign in to comment.