Possible AWS credential exposure in EC2 user data

Keep real AWS secret keys out of EC2 user data and use instance roles with temporary credentials.

Description

Real AWS secrets in EC2 user_data can be exposed to people who can access the playbook or user data. Use an instance role with only the required permissions and temporary credentials instead of long-term access keys.

An access key ID alone cannot authenticate an AWS request. The secret access key is also required, and temporary credentials additionally require a session token. Check whether a suspicious value is a documentation example or a real credential. If a real secret was exposed, removing it from the current file is not sufficient.

Potential impact

  • An exposed, valid credential set can be used for unwanted AWS requests within its permission scope.
  • Copies can remain in repository history, user data or deployment records. Rotating a shared key may also require changes to dependent workloads.

Remediation

  • Remove real secrets from user_data and attach a least-privilege IAM role through an instance profile. Configure the application to use temporary credentials through a supported SDK's default credential provider.
  • Promptly deactivate or revoke and replace a valid exposed key while accounting for dependent workloads. Check repository history and existing user-data copies as well as current files.
  • Investigate relevant access records and verify that required workloads continue to function with the new authentication method.

Examples

The key strings are public documentation examples, not real credentials. Choose an AMI, instance type and subnet for your environment. For the after-example, prepare an instance profile containing the required role and give the deployment identity permission to attach it.

Before

yaml
- name: start an instance
  community.aws.ec2_instance:
    name: credential-example
    image_id: "{{ ami_id }}"
    instance_type: "{{ instance_type }}"
    vpc_subnet_id: "{{ subnet_id }}"
    user_data: |
      #!/bin/bash
      export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
      export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

The startup script embeds a key pair. Using real keys this way leaves secrets in the user data and playbook.

After

yaml
- name: start an instance
  community.aws.ec2_instance:
    name: credential-example
    image_id: "{{ ami_id }}"
    instance_type: "{{ instance_type }}"
    vpc_subnet_id: "{{ subnet_id }}"
    iam_instance_profile: "{{ instance_profile_name }}"

An instance profile replaces the embedded keys. Verify that the application uses temporary credentials and has only the required permissions. This change does not revoke keys that were already exposed.

References