I have bash script to run as user data script when launching EC2 instance. For that I need to pass external API access key id and secret key. I don't want to store these keys in my user data scripts as it is visible in plaintext. Is there any way that I can store this keys in somewhere such as AWS Secret Manager and use that in user data scripts?
I would suggest either storing it in Secrets Manager or SSM Parameter Store.
You would need to use the CLI in your userdata script to retrieve the value.
For SSM you would retrieve the secret by using the get-parameter function.
secret=$(aws ssm get-parameter --name "MyStringParameter")
For Secrets Manager you would retrieve the secret using the get-secret-value function.
secret=$(aws secretsmanager get-secret-value --secret-id MyTestDatabaseSecret)
Then in your bash script when you want to reference it you would just need to use the variable $secret
to actually replace with your secret.
If you decide to use either of these you will need to ensure EC2 instance has an IAM role attached to the instance with the correct policy to apply the permissions you require.
Alternatively if this is a process that happens frequently (autoscaled instance for example) then you should take a look at configuring the base server image (AMI) ahead of time and then referencing this as the source AMI.
With tools such as Ansible, Chef and Puppet you could provision the base image with your secret which would replace any need to do anything in the UserData
as it would be available ahead of time.