Beanstalk Audit: ================ Overview: --------- I recently ran a configuration and security assessment on my company's AWS beanstalk ecosystem. The process was mostly manual as I worked my way through identifying how to obtain the information I needed for the assessment. If I have to do many more of these, I'll figure out a way to automate at least some of it. The assessment was both command line based and via the AWS portal. I used the portal to see what information was available to me, then tried ot figure out a command to obtain it. While the aws cli commands are easily automated, either through shell scripts or an sdk, the eb commands seem to require intervention. You can't loop through 14 different environments across 3 different applications, for instance. The commands below assume aws sso is configured, logged in, and current. References to ${profile} indicate the AWS profile in which the AWS beanstalk ecosystem exists. Memory map: ----------- As mentioned elsewhere, I recently came across the concept of memory maps and quite like them. They strike me as graphical checklists which fit well with my standard approach to tasks like this. With that, here's the memory map I generated for auditing beanstalk applications. Unfortunately, I haven't figured out how to display them reasonably inline, so :download:`download the image <./bstalk_audit_mindmap.svg>` or right click to open in a new tab. Lessons learned: ---------------- * Two switch beanstalk apps/envs, need to blast .elasticbeanstalk/config.yaml and rerun ``eb init``. Haven't found a way through that yet. AWS cli commands: ----------------- AMIs: ~~~~~ * Give detailed info on a specific ami:: aws ec2 describe-images --image-ids ami-017a87410cd29f14e \ --region $region --profile ${profile} * Filtering describe images by 'Corretto' and the owner id:: aws ec2 describe-images --filters "Name=name, Values=*corretto*" "Name=owner-id, Values=732788773938" \ --profile ${profile} --query 'Images[*].[ImageId,CreationDate,Name]' --output text | \ sort -k 2 Network: ~~~~~~~~ * Get security group rules. Need the security group ID (${sg}):: aws ec2 describe-security-groups --profile ${profile} \ --group-ids ${sg} --region ${region} \ --query 'SecurityGroups[*].IpPermissions' --output yaml: Beanstalk commands: ~~~~~~~~~~~~~~~~~~~ * Creates a table of application info. Descriptions with embedded newline cause issues:: aws elasticbeanstalk describe-applications --region ${region} \ --profile ${profile} --output table \ --query 'Applications[*].[ApplicationName, Description, DateUpdated]' * Obtain a list of applications, descriptions and when they were last updated. sed command removes embedded newlines in the descriptions:: aws elasticbeanstalk describe-applications --region ${region} \ --profile ${profile} \ --query 'Applications[*].[ApplicationName, Description, DateUpdated]' \ --output text | sed 's/\n//g' | column -t -s$'\t' App1 Application one description 2024-03-08T14:52:08.312000+00:00 App2 Application two description 2023-05-08T09:51:43.550000+00:00 App3 Application three description 2023-03-23T17:20:26.009000+00:00 ... AppN Application N description 2022-12-08T15:30:30.127000+00:00: * List applications; can be used as source for other commands:: aws elasticbeanstalk describe-applications --region ${region} \ --profile ${profile} --query 'Applications[*].ApplicationName' \ --output yaml | sed 's/^- //g' App1 App2 App3 ... AppN: * Creates a tabular view of an application's environments:: aws elasticbeanstalk describe-environments --application ${an} \ --region $region --profile ${profile} --query 'Environments[*].{ Appname:ApplicationName, Env: EnvironmentName, Health: Health, Status: HealthStatus, Updated: DateUpdated}' --output table ---------------------------------------------------------------------------------- | DescribeEnvironments | +---------+------------+---------+---------+-------------------------------------+ | Appname | Env | Health | Status | Updated | +---------+------------+---------+---------+-------------------------------------+ | App1 | App1-prod | Green | Ok | 2024-04-24T06:00:47.140000+00:00 | | App1 | App1-uat | Green | Ok | 2024-04-24T06:02:46.480000+00:00 | | App1 | App1-dev | Green | Ok | 2024-04-24T13:50:45.292000+00:00 | +---------+------------+---------+---------+-------------------------------------+ * Another tabular view of an application's environments w/env id:: aws elasticbeanstalk describe-environments \ --application-name "${app}" --profile ${profile} \ --query 'Environments[*].{ App:ApplicationName, Env:EnvironmentName, ID:EnvironmentId}' --output table: --------------------------------------------------- | DescribeEnvironments | +---------------+----------------+----------------+ | App | Env | ID | +---------------+----------------+----------------+ | App2 | app2-test-v5 | e-hcjiaputsk | | App2 | app2-prod-v5 | e-iii8i3admr | | App2 | app2-demo | e-xji2nh2bhv | +---------------+----------------+----------------+ * Inline script to loop through application names then generate the table above for each app:: aws elasticbeanstalk describe-applications --region ${region} --profile ${profile} \ --query 'Applications[*].ApplicationName' --output yaml | sed 's/^- //g' | \ while read an do aws elasticbeanstalk describe-environments --application "${an}" --region $r \ --profile ${profile} --query 'Environments[*].{ Appname:ApplicationName, Env: EnvironmentName, Status: HealthStatus, Updated: DateUpdated, StackName: SolutionStackName}' --output table done * List available stacks. Compare/contrast against what's running:: aws elasticbeanstalk list-available-solution-stacks --profile ${profile} * Displays app/env configuraiton settings. Useful for checking sslpolicy and SSLCertificateArns for environment ssl info:: aws elasticbeanstalk describe-configuration-settings \ --application-name your-app-name --environment-name your-env-name * ID instance IDs associated with specific env:: aws elasticbeanstalk describe-instances-health \ --environment-name App3-prod --profile ${profile} --query 'InstanceHealthList[*].InstanceId' --output yaml * Retrieve all instance ids using a data file as a source. Columns separated by '|' and the first column is enviornment name:: for e in $(awk -F\| '{print $1}' envs) do id=$(aws elasticbeanstalk describe-instances-health --environment-name ${e} \ --profile ${profile} --query 'InstanceHealthList[*].InstanceId' --output yaml | \ sed 's/^- //g') printf "%-25s %s\n" ${e} ${id} done * Reads environment name and instance ID from a '|' separated source file, obtains token requirement and if IMDv2 is enabled:: awk -F\| '{print $1, $3}' envs | while read env id do read token epoint <<< $( aws ec2 describe-instances --instance-ids ${id} \ --profile ${profile} \ --query 'Reservations[*].Instances[*].MetadataOptions.[HttpTokens,HttpEndpoint]' \ --output text) printf "%-25s %s %-10s %s\n" ${env} ${id} ${token} ${epoint} done app1-dev-env-1 i-07b53e9c7f8504aff required enabled app1-prod i-0ae4e5725092961a7 required enabled app1-uat-env-1 i-0f54e229b0efb1a38 required enabled app2-demo-1 i-02c9d48fcc9f885c4 optional enabled app2-prod i-0501d814272e35fdf optional enabled app3-demo i-01afdf58466f50548 required enabled app3-dev i-0dd44322dfd28c90d optional enabled app3-prod i-011477e04f2931cea required enabled eb commands: ------------ eb init:: Selects application and enviornment. Creates .elasticbeanstalk/config.yaml which is then used by other eb commands. eb config:: Prints out a long yaml dump of information about the environment. eb printenv:: Prints out the environment configuration pararameters. These are set as env vars in the instance(s) eb tags: Lists the tags that are defined for the environment