Add SSM:GetParameter to AWS EC2 Instance - amazon-web-services

First time deploying an app to AWS and it's been an adventure. My current error:
Dec 21 03:49:33 ip-172-31-31-185 web: botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetParameter operation: User: arn:aws:sts::[my account number]:assumed-role/aws-elasticbeanstalk-ec2-role/[the instance number] is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-2:[my account number]:parameter/Dev/WebServer/[thing I want to get] because no identity-based policy allows the ssm:GetParameter action
The docs are very good at telling me what I need to do-- it appears I need to add an IAM policy to the instance using AWS systems manager. I even have the policy-- but less good in telling me how to do it. Where can you add instance policies in AWS Console?

Based on the error message - it comes from Beanstalk, the documentation is https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts-roles-instance.html
So likely you already have an instance profile based on an existing role. So that is the role you need to change. The policy is managed in IAM (not Systems Manager), just add ssm:GetParameter rule there either with a star (which may be good enough to debug in the dev environment) and if it works then limit it to your arn, if you for arn:aws:ssm:us-east-2:[my account number]:parameter/Dev/WebServer/[thing I want to get] make [thing I want to get] something like myapp-prefix-[thing I want to get] then you can easily limit the access only to parameters which belongs to this given app. Or you can use tags.

Related

Adding AWS GameLift policies for uploading new builds

I am trying to upload a new AWS GameLift Linux server using the AWS CLI but I get the following error:
An error occurred (AccessDeniedException) when calling the CreateBuild operation: User: arn:aws:iam::------:user/----- is not authorized to perform: gamelift:CreateBuild because no identity-based policy allows the gamelift:CreateBuild action
I added the arn:aws:iam::aws:policy/GameLiftGameServerGroupPolicy to my group permissions. I can see in the policy json that there isn't a CreateBuild action. It either needs to be added or you can't do it this way.
The AWS documentation is useless and on this page: https://docs.aws.amazon.com/gamelift/latest/developerguide/security_iam_troubleshoot.html#security_iam_troubleshoot-no-permissions
it helpfully advises: ... asks his administrator to update his policies
My user is the main root user for my AWS account but I have no idea how to resolve this. Any ideas?
I worked out how to create a new Policy and add the service permissions. You click on 'create policy' and then choose the 'GameLift' service. I added all the available actions. Seemed to do the trick.
Why did AWS miss this out of the documentation?

EC2 instance using the wrong user when executing PHP code

I have a ec2 instance with a role attached to it. The role is called webserver and has all the relevant policies attached to it.
I am trying to invoke my lambda function from my PHP code, but I get the following error:
Failed attempt at deleting data/ account: exception 'Aws\Lambda\Exception\LambdaException' with message 'Error executing "Invoke" on "https://lambda.eu-west-2.amazonaws.com/2015-03-31/functions/blahFunction/invocations"; AWS HTTP error: Client error: `POST https://lambda.eu-west-2.amazonaws.com/2015-03-31/functions/blahFunction/invocations` resulted in a `403 Forbidden` response:
{"Message":"User: arn:aws:iam::34234324324342:user/SecretGuy is not authorized to perform: lambda:InvokeFunction on resour (truncated...)
AccessDeniedException (client): User: arn:aws:iam::34234324324342:user/SecretGuy is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:eu-west-2:34234324324342:function:blahFunction because no identity-based policy allows the lambda:InvokeFunction action - {"Message":"User: arn:aws:iam::34234324324342:user/SecretGuy is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:eu-west-2:34234324324342:function:blahFunction because no identity-based policy allows the lambda:InvokeFunction action"}'
Now SecretGuy is a user I created a long time ago, and somehow my ec2 is trying to use that.
I am wondering if anyone can help with this?
Thanks
From my understanding, you are running PHP code on an EC2 instance, and your code invokes the Lambda function.
And this EC2 instance has attached IAM Role with proper permissions to invoke the Lambda function. Then you tried to run your code and faced that the EC2 instance is using an unexpected IAM identity(IAM User named SecretGuy here), not the role you attached.
There's a chance that you might have IAM credentials set by environment variables for that Linux user or static credentials set on your EC2 instance.
AWS SDK client has an order to retrieve credentials on the machine. The official docs of PHP AWS SDK say,
When you initialize a new service client without providing any credential arguments, the SDK uses the default credential provider chain to find AWS credentials. The SDK uses the first provider in the chain that returns credentials without an error.
The default provider chain looks for and uses credentials as follows, in this order:
Use credentials from environment variables.
Setting environment variables is useful if you're doing development work on a machine other than an Amazon EC2 instance.
Use the AWS shared credentials file and profiles.
This credentials file is the same one used by other SDKs and the AWS CLI. If you're already using a shared credentials file, you can use that file for this purpose.
We use this method in most of our PHP code examples.
Assume an IAM role.
IAM roles provide applications on the instance with temporary security credentials to make AWS calls. For example, IAM roles offer an easy way to distribute and manage credentials on multiple Amazon EC2 instances.
To retrieve IAM credentials from the role attached,
You can check which IAM Identity you are using to call AWS API with the below command on the EC2 instance. (as that Linux user, you are running PHP code)
aws sts get-caller-identity
Then it will show result as below,
{
"UserId": "ABCDEFGHIJKLMNOPQRSTU",
"Account": "34234324324342",
"Arn": "arn:aws:iam:: 34234324324342:user/SecretGuy"
}
Then you need to look for environment variables set or static credentials files on that EC2 instance.
My guess is maybe someone used aws CLI on that EC2 before, with SecretGuy credentials, So there would be a file $HOME/.aws/credentials.
If the file exists and is confirmed as a SecretGuy access key, you have to delete that file. (If EC2 runs some critical application, you might want to copy all permissions of SecretGuy to the IAM Role you attached before deleting it to avoid unexpected service outage)
Or, you can look for environment variables.
echo $AWS_ACCESS_KEY_ID
If the above commands return the access key id value, you might have to unset environment variables.
After that, your code will retrieve credentials from IAM Role.

external-secrets operator not using IRSA role

I have external-secrets operator v0.5.1 installed and working with a SecretStore for retrieve AWS parameter store. Also tried updating to V0.5.8
This is working fine with IRSA but if I try to create a external-secret for AWS secrets, with a new SecretStore, the SecretStore' status is Valid but the ExternalSecret that references this SecretStore got the following error: SecretSyncedError
AccessDeniedException: User: arn:aws:sts::12345678:assumed-role/eks-backend-role-pre/external-secrets-provider-aws is not authorized to perform: secretsmanager:GetSecretValue on resource: /backend/pre/PRE_PRIVPGPKEY because no identity-based policy allows the secretsmanager:GetSecretValue action status code: 400,
Please, note the STS is trying to use eks-backend-role-pre/external-secrets-provider-aws which it doesn't exist. The role which exist is eks-backend-role-pre I'm not sure who is adding the suffix external-secrets-provider-aws which invalidate the role name.
Both SecretStore, the one dedicated to AWS Parameter Store and the other that is dedicated to gather from AWS Secrets has the same service account associated.
Why is working one External Secret and the other using the same service account don't?
There was a typo in the policy.
As documentation shows, this is the correct way to declare a principal:
arn:${Partition}:secretsmanager:${Region}:${Account}:secret:${SecretId}
I have incorrect declared the principal:
"arn:aws:secretsmanager:eu-west-1:1234567890:secret/backend/pre/*"
Correct:
"arn:aws:secretsmanager:eu-west-1:1234567890:secret:/backend/pre/*"
In contrast to SSM Parameter store that you declare your principal "arn:aws:ssm:eu-west-1:1234567890:parameter/backend/pre/*"
, with SecretsManager you need to add a colon after the service :secret:

Why is iam:PassRole required in this project?

I cloned this solution azure-devops-on-aws and used dotnet lambda deploy-serverless ... to deploy the MyLizardApp to my personal AWS account.
During the learning curve, I created an S3 bucket my-lizard-test, IAM user group MyLizardGroup with user lizard-user and group policy MyLizardApp-Policy. Included in the policy are these services:
API Gateway (full access, all resources)
CloudFormation (full access, all resources)
Lambda (full access, all resources)
S3 (full access, all resources)
(Eventually) the deployment succeeded and I had a Lambda application serving the simple razor page showing the time.
I then copied the LambdaEntryPoint.cs, aws-lambda-tools-defaults.json and serverless.template files to my own dotnet core webapp (also a razor project) and attempted to deploy it to the same AWS account with the same command. The only changes made were the namespace of the LambdaEntryPoint class (reflected in the serverless.template file) and the .csproj file to include:
<AWSProjectType>Lambda</AWSProjectType>
and:
<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="5.0.0" />
The dotnet lambda deploy-serverless ... command failed with the message:
User: arn:aws:iam::123456789120:user/lizard-user is not authorized to perform: iam:PassRole on resource: arn:aws:iam::123456789120:role/MyLizardAppServiceRole (Service: AWSLambdaInternal; Status Code: 403; Error Code: AccessDeniedException; Request ID: 12345678-1234-1234-1234-123456789012; Proxy: null)
I got the command to succeed by adding the IAM service to the MyLizardApp-Policy with the PassRole (all resources).
Why was this necessary for my personal app and not the demo solution from github? If the answer is not clear, what should I be looking for as differences? My personal app is not significantly different from the demo solution and I don't think the functional differences (in C#) would matter.
Whenever an AWS Service assumes (uses) an IAM Role, the service must have iam:PassRole permission to grant permission to use the Role. This required to prevent users from gaining too much permission.
For example, imagine a normal (non-Admin) user who launches an Amazon EC2 instance. When launching the instance, they can nominate an IAM Role to be assigned to the instance. If this user was permitted to select any IAM Role, they could select an Admin role and assign it to the EC2 instance. They could then login to the instance and use the credentials to make API calls as an Admin. This is an unwanted "privilege escalation".
Similarly, when an AWS Lambda function executes, it uses an IAM Role to obtain permissions. The iam:PassRole permission is used to control which roles a user can assign to the Lambda function.
So, there is something in that project that is trying to use an IAM Role and needs appropriate permissions.
First of all, we need to know what PassRole is:
iam:PassRole is the permission that controls which users can delegate an IAM role to an AWS resource.
As I can see in the repo, there is a file for CodeDeploy which already have credentials so maybe you are using CodeDeploy.
But btw, you are using an instances to deploy a Lambda function, and you need to pass the role to that Lambda so that is what PassRole do
AWS Services cannot directly assume service-linked roles. The role must be passed to the service by a user with the iam::PassRole permission.
The role-passing needs to be done only once, when a resource (e.g. EC2 instance) is created. After that the resource can assume the role repeatedly.
EC2 Instance profile is implemented this way. When a user launches an instance, it passes a role to the instance to act as an instance profile (it in addition needs iam:AddRoleToInstanceProfile for this case).
Other service-linked roles are also passed in this way.
Do not confuse it with the iam::CreateRole permission. A user may freely create service-linked roles, but is unable to pass the role to a service when needed.
In the management console, and to some extent in the CLI commands, role-passing is implicit, so you may encounter it without clear error messages when using non-root accounts.
As for why sometimes you need this permission, ands sometimes you don't, that is because when you use the root user, it will have AdministratorAccess which basically allows all actions on all resources.
If you create a new IAM user or account with blank permissions then you will need to add this permission manually.

CodeDeploy onpremise registration failing with AccessDeniedException on Amazon Lightsail

aws deploy register-on-premises-instance --instance-name XXXXX --iam-user-arn arn:aws:iam::XXXXXXXXXXXX:user/LightSailCodeDeployUser --region ap-south-1
An error occurred (AccessDeniedException) when calling the RegisterOnPremisesInstance operation: User: arn:aws:sts::XXXXXXXXXXX:assumed-role/AmazonLightsailInstanceRole/i-XXXXXXXXXXXXXX is not authorized to perform: codedeploy:RegisterOnPremisesInstance on resource: arn:aws:codedeploy:ap-south-1:XXXXXXXXXX:instance:XXXXXXXXXXXX
I didn't even create the role AmazonLightsailInstanceRole, then how did it come in the picture. My user have all permissions on codedeploy though. I am following this link to set up. https://aws.amazon.com/blogs/compute/using-aws-codedeploy-and-aws-codepipeline-to-deploy-applications-to-amazon-lightsail/
I made the same mistake and then realized that command is meant to be run on your local machine and not the instance!
AmazonLightsailInstanceRole is a service-linked role automatically created by aws:
Service-linked roles are predefined by the service and include all the permissions that the service requires to call other AWS services on your behalf.
The error you are getting is not about you not having the codedeploy:RegisterOnPremisesInstance permission.
The error is about the AmazonLightsailInstanceRole not having it. It does not matter if you (i.e. your IAM user) has all CodeDeploy permissions.
Normally you would add the missing permissions to the role. How to work with the AmazonLightsailInstanceRole is described in the following AWS documentaiton:
Using Service-Linked Roles for Amazon Lightsail
Editing a Service-Linked Role
However, I'm not sure if you can modify the AmazonLightsailInstanceRole and add the missing permissions. Some service-linked roles can be modified, some not.
The documentation is a bit confusing. Create a new user in IAM with admin role (full privileges) and use the credentials of that user to run the command in your local machine.