Elastic Beanstalk hides the EC2 instances, load balancers and Auto Scaling groups behind an application, so teams often inherit broad default roles, plaintext secrets in environment properties and platform versions nobody updates. The service is easy to start with, and the defaults favour getting an application running over least privilege: AWS's own documentation says the managed policies grant every permission an environment might need. This guide covers the three IAM identities every environment depends on, how to move secrets out of environment properties, managed platform updates, IMDSv2, the service S3 bucket, logging and detection. It is written for cloud engineers and application teams running Beanstalk in production. Account-wide controls are in the AWS Security Guide; this page stays on Beanstalk.
This is an independent guide from NHI Mgmt Group, based on AWS's public documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.
Key takeaways
- Three identities, three different blast radii. The instance profile is what your code runs as, the service role is what Beanstalk uses to manage resources, and user policies decide who can deploy; each ships with broad managed policies.
- Environment properties are not a vault. Use the
aws:elasticbeanstalk:application:environmentsecretsnamespace or fetch from Secrets Manager in code, and remember values are read only when an instance boots. - Managed platform updates are the patching mechanism. Turn them on with a weekly two-hour window; they require enhanced health reporting and cannot apply major version changes.
- Enforce IMDSv2 with
DisableIMDSv1. An SSRF flaw in the application otherwise exposes the instance profile credentials. - Watch the control plane. CloudTrail events such as
UpdateEnvironmentand configuration changes to environment properties tell you when someone changes code, roles or secrets.
How identity and access work in Elastic Beanstalk
Beanstalk orchestrates CloudFormation, EC2, Auto Scaling, Elastic Load Balancing and S3 on your behalf. Every one of those actions is taken by an IAM identity, and confusing them is the most common design error.
| Identity | Default name or policy | Who uses it | What to change |
|---|---|---|---|
| Instance profile (EC2 role) | aws-elasticbeanstalk-ec2-role with AWSElasticBeanstalkWebTier, AWSElasticBeanstalkWorkerTier, AWSElasticBeanstalkMulticontainerDocker | Your application code and the Beanstalk agents on each instance | Custom role per application; drop Worker and Docker policies if unused; add only the application's own resource permissions |
| Service role | aws-elasticbeanstalk-service-role with AWSElasticBeanstalkEnhancedHealth and AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy | Beanstalk itself, for health monitoring and managed updates | Keep the trust policy's sts:ExternalId condition; migrate off the deprecated AWSElasticBeanstalkService |
| Service-linked roles | Monitoring role, AWSServiceRoleForElasticBeanstalkManagedUpdates | Beanstalk, when no service role is given or for managed updates | Pre-create them so users do not need iam:CreateServiceLinkedRole |
| Human and pipeline users | AdministratorAccess-AWSElasticBeanstalk, AWSElasticBeanstalkReadOnly | Developers, operators, CI/CD deploy roles | Scope by application with elasticbeanstalk:InApplication; replace deprecated AWSElasticBeanstalkFullAccess |
AWS notes two facts that shape the design. First, Beanstalk no longer creates aws-elasticbeanstalk-ec2-role automatically, because AWS guidelines no longer allow a service to create roles that trust other services, so older accounts may share one old role across many environments. Second, the documentation states that IAM policies on Beanstalk are not a complete security boundary: a user who can create the underlying EC2 or CloudFormation resources can create other resources too. See the AWS IAM Policies and Roles Guide.
Admin roles and privileged access
- Separate deploy from administer: a CI/CD role needs to create application versions and update one environment, not create or delete applications. AWS documents a pattern that denies
CreateApplicationandDeleteApplicationand denies environment actions whereelasticbeanstalk:InApplicationdoes not match the application ARN. - Control which versions may launch: condition
CreateEnvironmentonelasticbeanstalk:FromApplicationVersionso only approved bundles reach production. - Treat
iam:PassRoleas privileged: anyone who can pass any role to Beanstalk can give an environment an administrator instance profile and run code as it. Restrict PassRole to the specific instance profile and service role ARNs for that application. - Read-only is not log access:
AWSElasticBeanstalkReadOnlycannot download logs because logs are staged in S3; grant log retrieval with S3 permissions scoped toresources/environments/logs/*in the Beanstalk bucket rather than allelasticbeanstalk-*buckets. - SSH and Session Manager: avoid EC2 key pairs on production environments; where shell access is required, prefer Systems Manager Session Manager with logging, and restrict who holds any key pair that is attached.
- Custom service roles must include launch template permissions, or updates fail once the environment moves to launch templates.
Integrations, API tokens and service accounts
Most Beanstalk applications talk to RDS, SQS, DynamoDB, S3 and third-party APIs. The credentials for those calls are the non-human identities that matter most here.
Use the instance profile, never access keys
The SDKs in every Beanstalk platform pick up temporary credentials from the instance profile through IMDS. There is no reason to put an IAM user access key in an environment property or in the source bundle. See the AWS Access Keys Security Guide.
Secrets: three options compared
| Option | How it works | Rotation behaviour | When to use |
|---|---|---|---|
Plain environment properties (aws:elasticbeanstalk:application:environment) | Value stored in environment configuration; 4,096 byte total limit | Manual update and redeploy | Non-secret configuration only: endpoints, feature flags |
Secret references (aws:elasticbeanstalk:application:environmentsecrets) | ARN of a Secrets Manager secret or Parameter Store parameter; value fetched at instance bootstrap (platform versions from 26 March 2025) | Running instances keep the old value until UpdateEnvironment or RestartAppServer; the app must accept two valid values during the change | Legacy apps that read environment variables and cannot change code quickly |
| SDK call from application code | App reads Secrets Manager or Parameter Store at runtime using the instance profile | Picks up rotated values on next read or cache expiry | Preferred: AWS calls this the most secure option |
- Grant read on named secrets only: the instance profile needs read access to the specific secret and parameter ARNs, plus decrypt on the KMS key if it is customer managed. The console only validates ARN format, so a wrong permission shows up as a failed deployment.
- JSON key extraction: platform versions from 13 January 2026 can extract one top-level key from a JSON secret with an
:keysuffix on the ARN, which avoids exposing a whole credential document to the process. - Do not log secrets: AWS warns that values printed by the application end up in log files and error messages, which Beanstalk then streams to CloudWatch or bundles into S3.
- Tomcat note: secrets are available only through
System.getenv, notSystem.getProperty.
See the Environment Variables and .env Files guide and the AWS Secrets Manager Guide.
Hardening baseline
| Area | Setting | Recommended value |
|---|---|---|
| Managed updates | aws:elasticbeanstalk:managedactions ManagedActionsEnabled | true |
| Maintenance window | PreferredStartTime (format day:hour:minute, UTC) | A low-traffic weekly slot |
| Update level | aws:elasticbeanstalk:managedactions:platformupdate UpdateLevel | minor for most; patch where minor changes need testing |
| Instance replacement | InstanceRefreshEnabled | true to run a weekly immutable replacement even without a new platform version |
| Health | Enhanced health reporting | Enabled (managed updates require it) |
| Instance metadata | aws:autoscaling:launchconfiguration DisableIMDSv1 | true |
| Secrets | aws:elasticbeanstalk:application:environmentsecrets or SDK | No credentials in plain properties |
| Logs | aws:elasticbeanstalk:cloudwatch:logs StreamLogs | true, with retention set and logs kept after termination |
| Service bucket | elasticbeanstalk-<region>-<account-id> | Keep the bucket policy; delete old source bundles and rotated logs |
Network settings sit outside Beanstalk's own options but matter as much: place instances in private subnets with only the load balancer public, terminate HTTPS at the load balancer with an ACM certificate, and restrict instance security groups to traffic from the load balancer's security group. See the AWS WAF and Shield Guide for edge protection.
Rolling out the baseline
- Inventory: list every environment, its platform branch, instance profile, service role and whether managed updates are on. Record which environments use plain-text properties that look like credentials.
- Clone and test: apply changes first to a cloned environment or a staging environment with the same configuration files in
.ebextensions. - Turn on enhanced health, then managed updates at
patchlevel, and widen tominoronce a few cycles pass cleanly. - Enforce IMDSv2 after confirming every SDK and agent in the bundle supports it; expect a possible migration to launch templates and check the service role allows it.
- Move secrets to references or SDK reads, rotate the old values (they were stored in plain configuration), then delete the plain properties.
- Replace shared roles with a custom instance profile per application and test with IAM Access Analyzer policy generation from CloudTrail activity.
- Rollback: keep the previous application version and saved configuration; managed updates use immutable updates, so a failed health check leaves the old instances in service, and you can redeploy a previous platform version manually if a passed update misbehaves.
Choosing settings for your estate
- Small teams with a handful of environments: start with the managed policies but split the instance profile per application, turn on managed updates at
minorlevel with instance replacement, and use secret references so the application code does not change. The aim is patching and secret hygiene with little operational effort. - Large estates and regulated workloads: replace managed policies with custom policies generated from observed activity, define all option settings in version-controlled
.ebextensionsor infrastructure as code, usepatchlevel with a staged promotion of minor versions through test environments, and read secrets in code with caching so rotation needs no restart. - Worker environments: the worker tier policy adds SQS, DynamoDB leader election and metric permissions; keep worker instance profiles separate from web tier profiles so a compromised web front end cannot drain or poison queues.
- Docker platforms: the ECS managed Docker platform uses native ECS secret syntax instead of the Beanstalk secrets namespace, so check which form your platform branch expects before migrating.
- When to leave Beanstalk: if you need per-service identities, fine-grained network policy or sidecars, a container platform may fit better; the identity principles in this guide carry over.
Logging and detection
| Source | What it records | What to alert on |
|---|---|---|
| CloudTrail (Beanstalk API) | CreateEnvironment, UpdateEnvironment, TerminateEnvironment, CreateApplicationVersion, RestartAppServer | Updates outside pipeline roles; option setting changes to roles, secrets or IMDS; terminations |
| CloudTrail (IAM and STS) | Role and policy changes, PassRole | Policies attached to the instance profile; new roles created from instance credentials |
| CloudTrail (instance profile usage) | API calls made with the role's session | Calls from IP addresses outside your VPC or NAT gateways, a classic sign of stolen IMDS credentials |
| CloudWatch Logs | Web server, deployment (eb-engine.log, eb-hooks.log) and application logs under /aws/elasticbeanstalk/<environment>/ | Deployment failures, unexpected hook execution, application errors containing credentials |
| AWS Config | Configuration history of Beanstalk resources | Drift from rules for managed updates, IMDS and log streaming |
Credential theft from an instance maps to ATT&CK T1552.005 Cloud Instance Metadata API, and later use of the stolen session to T1078.004 Cloud Accounts. Privilege escalation through role and policy changes maps to T1098 Account Manipulation. See the AWS CloudTrail Guide and the EC2 Instance Metadata Service Hardening Guide.
Metrics that show it is working:
- Percentage of environments with managed updates enabled and on a current platform version.
- Percentage of environments with
DisableIMDSv1set to true. - Number of environment properties matching credential patterns (target zero).
- Number of applications sharing an instance profile with another application.
- Days since the last successful managed update, per environment.
Common misconfigurations
- One old instance profile for everything: environments created years apart share
aws-elasticbeanstalk-ec2-rolewith every permission ever added to it, so compromise of the least important app exposes the most important data. - Database passwords in plain environment properties, visible to anyone with read access to the environment configuration and copied into saved configurations.
- Rotating a secret and forgetting the restart: referenced secrets are fetched at bootstrap, so running instances keep the old value until a restart or update, and the application breaks if it cannot handle two valid values.
- Managed updates off because enhanced health was disabled, leaving environments on old platform versions with unpatched operating system and runtime components.
- IMDSv1 left on, turning any server-side request forgery bug in the application into instance profile credential theft.
- Old source bundles and rotated logs never deleted from the Beanstalk S3 bucket; AWS recommends removing them so private information is not retained.
Framework mapping
| Control | NIST SP 800-53 Rev 5 | NIST CSF 2.0 | ATT&CK |
|---|---|---|---|
| Least-privilege roles and PassRole limits | AC-6, AC-2 | PR.AA-05 | T1098 |
| Secrets out of configuration | IA-5, SC-28 | PR.AA-05 | T1552.001 |
| Managed platform updates | SI-2 | PR.PS-02 | T1190 |
| IMDSv2 and configuration baseline | CM-6 | PR.PS-01 | T1552.005 |
| Log streaming and CloudTrail review | AU-6 | PR.PS-04, DE.CM-09 | T1078.004 |
Practitioner checklist
- Create a custom instance profile per application and remove unused Worker and Docker managed policies.
- Confirm the service role uses
AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy, not the deprecatedAWSElasticBeanstalkService. - Restrict
iam:PassRoleand scope deploy roles withelasticbeanstalk:InApplication. - Remove all IAM user access keys from bundles and environment properties; rely on the instance profile.
- Move secrets to
environmentsecretsreferences or SDK reads, rotate the old values and plan restarts for rotation. - Enable enhanced health and managed platform updates with a weekly window and instance replacement.
- Set
DisableIMDSv1to true after testing. - Enable
StreamLogswith retention, and alert on CloudTrail changes to environment configuration. - Clean old source bundles, saved configurations and rotated logs from the Beanstalk bucket.
- Use AWS Config rules to detect drift from this baseline.
Standards and references
- AWS: Elastic Beanstalk security best practices
- AWS: Managing Elastic Beanstalk instance profiles
- AWS: Managing Elastic Beanstalk service roles
- AWS: Fetching secrets to environment variables
- AWS: Managed platform updates
- AWS: Configuring the instance metadata service on Elastic Beanstalk instances
- AWS: Elastic Beanstalk managed user policies
- MITRE ATT&CK: Cloud Instance Metadata API
Related NHI Mgmt Group resources: AWS Security Guide · AWS Secrets Manager Guide · EC2 Instance Metadata Service Hardening Guide · Top 10 AWS IAM Mistakes