diff --git a/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts b/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts index a116daf48..7b9c5d27a 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts @@ -187,7 +187,7 @@ export class MountableBlockVolume implements IMountableLinuxFilesystem { const uniqueId = 'MountableBlockVolumeAsset' + uuid.replace(/[-]/g, ''); return (stack.node.tryFindChild(uniqueId) as Asset) ?? new Asset(stack, uniqueId, { path: path.join(__dirname, '..', 'scripts', 'bash'), - exclude: [ '**/*', '!mountEbsBlockVolume.sh', '!metadataUtilities.sh' ], + exclude: [ '**/*', '!mountEbsBlockVolume.sh', '!metadataUtilities.sh', '!ec2-certificates.crt' ], }); } } diff --git a/packages/aws-rfdk/lib/core/lib/mountable-efs.ts b/packages/aws-rfdk/lib/core/lib/mountable-efs.ts index e348eee25..f009c673e 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-efs.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-efs.ts @@ -102,7 +102,7 @@ export class MountableEfs implements IMountableLinuxFilesystem { const uniqueId = 'MountableEfsAsset' + uuid.replace(/[-]/g, ''); return (stack.node.tryFindChild(uniqueId) as Asset) ?? new Asset(stack, uniqueId, { path: path.join(__dirname, '..', 'scripts', 'bash'), - exclude: [ '**/*', '!mountEfs.sh', '!metadataUtilities.sh' ], + exclude: [ '**/*', '!mountEfs.sh', '!metadataUtilities.sh', '!ec2-certificates.crt' ], }); } } diff --git a/packages/aws-rfdk/lib/core/scripts/bash/ec2-certificates.crt b/packages/aws-rfdk/lib/core/scripts/bash/ec2-certificates.crt new file mode 100644 index 000000000..ee816a39c --- /dev/null +++ b/packages/aws-rfdk/lib/core/scripts/bash/ec2-certificates.crt @@ -0,0 +1,74 @@ +-----BEGIN CERTIFICATE----- +MIIC7TCCAq0CCQCWukjZ5V4aZzAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw +FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD +VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xMjAxMDUxMjU2MTJaFw0z +ODAxMDUxMjU2MTJaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u +IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl +cnZpY2VzIExMQzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCjkvcS2bb1VQ4yt/5e +ih5OO6kK/n1Lzllr7D8ZwtQP8fOEpp5E2ng+D6Ud1Z1gYipr58Kj3nssSNpI6bX3 +VyIQzK7wLclnd/YozqNNmgIyZecN7EglK9ITHJLP+x8FtUpt3QbyYXJdmVMegN6P +hviYt5JH/nYl4hh3Pa1HJdskgQIVALVJ3ER11+Ko4tP6nwvHwh6+ERYRAoGBAI1j +k+tkqMVHuAFcvAGKocTgsjJem6/5qomzJuKDmbJNu9Qxw3rAotXau8Qe+MBcJl/U +hhy1KHVpCGl9fueQ2s6IL0CaO/buycU1CiYQk40KNHCcHfNiZbdlx1E9rpUp7bnF +lRa2v1ntMX3caRVDdbtPEWmdxSCYsYFDk4mZrOLBA4GEAAKBgEbmeve5f8LIE/Gf +MNmP9CM5eovQOGx5ho8WqD+aTebs+k2tn92BBPqeZqpWRa5P/+jrdKml1qx4llHW +MXrs3IgIb6+hUIB+S8dz8/mmO0bpr76RoZVCXYab2CZedFut7qc3WUH9+EUAH5mw +vSeDCOUMYQR7R9LINYwouHIziqQYMAkGByqGSM44BAMDLwAwLAIUWXBlk40xTwSw +7HX32MxXYruse9ACFBNGmdX2ZBrVNGrN9N2f6ROk0k9K +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC7zCCAq4CCQCO7MJe5Y3VLjAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw +FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD +VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xOTAyMDMwMjIxMjFaFw00 +NTAyMDMwMjIxMjFaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u +IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl +cnZpY2VzIExMQzCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQDvQ9RzVvf4MAwGbqfX +blCvCoVb9957OkLGn/04CowHXJ+vTBR7eyIa6AoXltsQXBOmrJswToFKKxT4gbuw +jK7s9QQX4CmTRWcEgO2RXtZSVjOhsUQMh+yf7Ht4OVL97LWnNfGsX2cwjcRWHYgI +7lvnuBNBzLQHdSEwMNq0Bk76PwIVAMan6XIEEPnwr4e6u/RNnWBGKd9FAoGBAOCG +eSNmxpW4QFu4pIlAykm6EnTZKKHT87gdXkAkfoC5fAfOxxhnE2HezZHp9Ap2tMV5 +8bWNvoPHvoKCQqwfm+OUBlAxC/3vqoVkKL2mG1KgUH9+hrtpMTkwO3RREnKe7I5O +x9qDimJpOihrL4I0dYvy9xUOoz+DzFAW8+ylWVYpA4GFAAKBgQDbnBAKSxWr9QHY +6Dt+EFdGz6lAZLedeBKpaP53Z1DTO34J0C55YbJTwBTFGqPtOLxnUVDlGiD6GbmC +80f3jvogPR1mSmGsydbNbZnbUEVWrRhe+y5zJ3g9qs/DWmDW0deEFvkhWVnLJkFJ +9pdOu/ibRPH1lE2nz6pK7GbOQtLyHTAJBgcqhkjOOAQDAzAAMC0CFQCoJlwGtJQC +cLoM4p/jtVFOj26xbgIUUS4pDKyHaG/eaygLTtFpFJqzWHc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC7jCCAq4CCQCVWIgSmP8RhTAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw +FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD +VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xOTAyMDUxMzA2MjFaFw00 +NTAyMDUxMzA2MjFaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u +IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl +cnZpY2VzIExMQzCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQDcwojQfgWdV1QliO0B +8n6cLZ38VE7ZmrjZ9OQV//Gst6S1h7euhC23YppKXi1zovefSDwFU54zi3/oJ++q +PHlP1WGL8IZ34BUgRTtG4TVolvp0smjkMvyRu5hIdKtzjV93Ccx15gVgyk+o1IEG +fZ2Kbw/Dd8JfoPS7KaSCmJKxXQIVAIZbIaDFRGa2qcMkW2HWASyNDl7bAoGBANtz +IdhfMq+l2I5iofY2oj3HI21Kj3LtZrWEg3W+/4rVhL3lTm0Nne1rl9yGujrjQwy5 +Zp9V4A/w9w2O10Lx4K6hj34Eefy/aQnZwNdNhv/FQP7Az0fju+Yl6L13OOHQrL0z +Q+9cF7zEosekEnBQx3v6psNknKgD3Shgx+GO/LpCA4GFAAKBgQCVS7m77nuNAlZ8 +wvUqcooxXMPkxJFl54NxAsAul9KP9KN4svm0O3Zrb7t2FOtXRM8zU3TqMpryq1o5 +mpMPsZDg6RXo9BF7Hn0DoZ6PJTamkFA6md+NyTJWJKvXC7iJ8fGDBJqTciUHuCKr +12AztQ8bFWsrTgTzPE3p6U5ckcgV1TAJBgcqhkjOOAQDAy8AMCwCFB2NZGWm5EDl +86ayV3c1PEDukgQIAhQow38rQkN/VwHVeSW9DqEshXHjuQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDNjCCAh4CCQD3yZ1w1AVkTzANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJV +UzEZMBcGA1UECBMQV2FzaGluZ3RvbiBTdGF0ZTEQMA4GA1UEBxMHU2VhdHRsZTEg +MB4GA1UEChMXQW1hem9uIFdlYiBTZXJ2aWNlcyBMTEMwIBcNMTUwNTEzMDk1OTE1 +WhgPMjE5NDEwMTYwOTU5MTVaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNo +aW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24g +V2ViIFNlcnZpY2VzIExMQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMWk9vyppSmDU3AxZ2Cy2bvKeK3F1UqNpMuyeriizi+NTsZ8tQqtNloaQcqhto/l +gsw9+QSnEJeYWnmivJWOBdn9CyDpN7cpHVmeGgNJL2fvImWyWe2f2Kq/BL9l7N7C +P2ZT52/sH9orlck1n2zO8xPi7MItgPHQwu3OxsGQsAdWucdxjHGtdchulpo1uJ31 +jsTAPKZ3p1/sxPXBBAgBMatPHhRBqhwHO/Twm4J3GmTLWN7oVDds4W3bPKQfnw3r +vtBj/SM4/IgQ3xJslFcl90TZbQbgxIi88R/gWTbs7GsyT2PzstU30yLdJhKfdZKz +/aIzraHvoDTWFaOdy0+OOaECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdSzN2+0E +V1BfR3DPWJHWRf1b7zl+1X/ZseW2hYE5r6YxrLv+1VPf/L5I6kB7GEtqhZUqteY7 +zAceoLrVu/7OynRyfQetJVGichaaxLNM3lcr6kcxOowb+WQQ84cwrB3keykH4gRX +KHB2rlWSxta+2panSEO1JX2q5jhcFP90rDOtZjlpYv57N/Z9iQ+dvQPJnChdq3BK +5pZlnIDnVVxqRike7BFy8tKyPj7HzoPEF5mh9Kfnn1YoSVu+61lMVv/qRjnyKfS9 +c96nE98sYFj0ZVBzXw8Sq4Gh8FiVmFHbQp1peGC19idOUqxPxWsasWxQXO0azYsP +9RyWLHKxH1dMuA== +-----END CERTIFICATE----- diff --git a/packages/aws-rfdk/lib/core/scripts/bash/metadataUtilities.sh b/packages/aws-rfdk/lib/core/scripts/bash/metadataUtilities.sh index e86571095..704c2cbde 100644 --- a/packages/aws-rfdk/lib/core/scripts/bash/metadataUtilities.sh +++ b/packages/aws-rfdk/lib/core/scripts/bash/metadataUtilities.sh @@ -16,6 +16,35 @@ function get_metadata_token() { curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30" 2> /dev/null } +function authenticate_identity_document() { + # Cryptographically verify that the instance identity document is authentic by + # using the instructions here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-pkcs7.html + + if ! which openssl > /dev/null 2>&1 + then + if ! sudo yum install -y openssl || sudo apt-get install -y openssl + then + echo "ERROR -- Authenticating the instance identity document requires openssl" + return 1 + fi + fi + + SCRIPT_DIRECTORY=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) + TOKEN=$(get_metadata_token) + + CERT_FILE=$(mktemp) + echo "-----BEGIN PKCS7-----" > "${CERT_FILE}" + curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 2> /dev/null >> "${CERT_FILE}" + echo "" >> "${CERT_FILE}" + echo "-----END PKCS7-----" >> "${CERT_FILE}" + + DOCUMENT_FILE=$(mktemp) + curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/dynamic/instance-identity/document 2> /dev/null > "${DOCUMENT_FILE}" + + echo "Verifying identity document authenticity" + openssl smime -verify -in "${CERT_FILE}" -inform PEM -content "${DOCUMENT_FILE}" -certfile ${SCRIPT_DIRECTORY}/ec2-certificates.crt -noverify 1> /dev/null +} + function get_identity_document() { # Usage: $0 TOKEN=$1 diff --git a/packages/aws-rfdk/lib/core/scripts/bash/mountEbsBlockVolume.sh b/packages/aws-rfdk/lib/core/scripts/bash/mountEbsBlockVolume.sh index ee69c1928..b140fcf97 100644 --- a/packages/aws-rfdk/lib/core/scripts/bash/mountEbsBlockVolume.sh +++ b/packages/aws-rfdk/lib/core/scripts/bash/mountEbsBlockVolume.sh @@ -290,6 +290,10 @@ MOUNT_PATH=$3 MOUNT_OPTIONS=$4 GIVEN_TARGET_DEVICE=${5:-} +# Make sure that the EC2 instance identity document is authentic before we use it to fetch +# information about the instance we're running on. +authenticate_identity_document + # If the EBS volume is already attached, then get the device # name it's attached as. TARGET_DEVICE=$(get_attached_device ${VOL_ID}) diff --git a/packages/aws-rfdk/lib/core/scripts/bash/mountEfs.sh b/packages/aws-rfdk/lib/core/scripts/bash/mountEfs.sh index f74060ea8..8c0cb6196 100644 --- a/packages/aws-rfdk/lib/core/scripts/bash/mountEfs.sh +++ b/packages/aws-rfdk/lib/core/scripts/bash/mountEfs.sh @@ -25,6 +25,10 @@ fi SCRIPT_DIR=$(dirname $0) source "${SCRIPT_DIR}/metadataUtilities.sh" +# Make sure that the EC2 instance identity document is authentic before we use it to fetch +# information about the instance we're running on. +authenticate_identity_document + METADATA_TOKEN=$(get_metadata_token) AWS_REGION=$(get_region "${METADATA_TOKEN}") diff --git a/packages/aws-rfdk/lib/core/test/asset-constants.ts b/packages/aws-rfdk/lib/core/test/asset-constants.ts index f56d8205a..97f976116 100644 --- a/packages/aws-rfdk/lib/core/test/asset-constants.ts +++ b/packages/aws-rfdk/lib/core/test/asset-constants.ts @@ -17,9 +17,9 @@ export const CWA_ASSET_WINDOWS = { Key: 'AssetParameters76c2f3fd118bbb1894503f8fe671dcf7c6cca1425afa1e770af547a1f23ebee7S3VersionKey6031009A', }; -// mountEbsBlockVolume.sh + metadataUtilities.sh +// mountEbsBlockVolume.sh + metadataUtilities.sh + ec2-certificates.crt export const MOUNT_EBS_SCRIPT_LINUX = { - Bucket: stringLike('AssetParameters*S3BucketE9BCAE61'), + Bucket: stringLike('AssetParameters*S3BucketEE3D2B6B'), }; export const INSTALL_MONGODB_3_6_SCRIPT_LINUX = {