AWS IAM (Identity & Access Management) service allows AWS services to interact with each other by using roles. Those roles can easily be used to give permissions to your Qovery application, container or job.
It is a secure way to give your application permissions without having to manage credentials. More than that, it rotates the token automatically.
This tutorial will show you how to add AWS IAM roles to your Qovery application, container or job.
Application requiring S3 permissions
In this first step, we will create a simple application that needs AWS permissions to access s3 buckets.
Create an application
We are going to will create a simple container, but you can use an existing one if you want (or an application or job).
Here is a simple Debian container example:
Set only 1 instance and 128MB of memory is enough for this example. Then continue until you have the Create
button, there is nothing more to setup.
Get Kubernetes namespace name
Then in this container (or any application in this environment) Variables
, search for the variable called QOVERY_KUBERNETES_NAMESPACE_NAME
and copy its value somewhere.
It is the Kubernetes namespace name where the container is located.
Configure OIDC provider
Get your Cluster OIDC provider URL
On your AWS console, go to your EKS cluster and Overview
section. Copy the OpenID Connect provider URL
:
Create an Identity provider
On your AWS console, go to IAM
service, then Identity providers
section, and Add provider
button:
- Select the
OpenID Connect
provider type - Paste the
OpenID Connect provider URL
previously copied toProvider URL
- Click on
Get thumbprint
button, once done the button will change toEdit URL
- Add
sts.amazonaws.com
asAudience
- Click on
Add provider
button
Configure AWS IAM roles
Create a role
Now we can create a role. In the IAM
service, go to Roles
section, and click on Create role
button.
You have to select the Trusted entity type. For this tutorial, we are going to use the Web identity
type.
Set the Identity provider
to the one you just created, and the Audience
to sts.amazonaws.com
. Then click on the Next
button.
Role permissions
Select the policy of your choice. For this example, the policy AmazonS3ReadOnlyAccess
will be used to list S3 buckets. Then click on the Next
button.
To finish, set the role name and description of your choice and click on Create role
button.
Configure trusted entities
Once created, select your freshly created role, go to the Trust relationships
tab, and click on Edit trust policy
button.
Update the policy line regarding the OIDC
condition from:
"oidc.eks.eu-west-3.amazonaws.com/id/xxxxxxx:aud": "sts.amazonaws.com"
to:
"oidc.eks.eu-west-3.amazonaws.com/id/xxxxxxx:sub": "system:serviceaccount:kubernetes_namespace:service_account_name"
Replace:
kubernetes_namespace
: with the namespace name (previously copied in step 1)service_account_name
: define a service account name which will be re-use later (ex:my-s3-role
)
Once done, click on the Update policy
button.
Last element to copy and save somewhere: the role ARN
.
Create a service account
This step will help you on deploying a service account on your Kubernetes cluster. In case you want to do it manually on the cluster with kubectl
, you just have to push a service account like:
apiVersion: v1kind: ServiceAccountmetadata:name: $SERVICE_ACCOUNT_NAMEnamespace: $QOVERY_KUBERNETES_NAMESPACE_NAMEannotations:eks.amazonaws.com/role-arn: $AWS_ROLE_ARN
Kubernetes authentication
On AWS, there are several ways to authenticate to Kubernetes. To make it simple, we are going to use a dedicated IAM user, but you can select the best method for your need.
From your AWS Console, create an IAM user account, get Access key ID
and Secret access key
and save them somewhere.
Qovery helps IAM users to get quick access to the Kubernetes cluster. Simply add this user to the Admins
group.
Create a Lifecycle job
In the same environment than your application, create a Lifecycle job
which will be used to deploy a service account on the Kubernetes cluster:
Here a container qoveryrd/create-sa:1.0
available on DockerHub made by Qovery is used, but you can fork this repository and update to your needs if you prefer.
Click on the Continue
button and select the Start
event because we want to deploy the service account at the environment start. Then click on the Continue
button, set the resources (128Mb is enough) and click on the Continue
button.
Then add the following environment variables to the job
scope:
KUBERNETES_VERSION
: the version of your Kubernetes cluster which will be used to download kubectl (ex: 1.23.0)SERVICE_ACCOUNT_NAME
: the name of the service account in Kubernetes (the same name you have declared for the role in theTrusted entities
policy section)AWS_ROLE_ARN
: the AWS ARN role you have just createdAWS_ACCESS_KEY_ID
: the AWS access key ID of the IAM user you have created (if you decided to use this authentication method)AWS_SECRET_ACCESS_KEY
: the AWS secret access key of the IAM user you have created (if you decided to use this authentication method)
Then Create
the Lifecycle job
. Go into the Variables
tab and create a Variable Alias
on QOVERY_CLOUD_PROVIDER_REGION
, name it AWS_DEFAULT_REGION
and scope it to the job
.
You can now run your job by clicking on the Deploy now
button. You should see the following output in your job logs:
-> Ensuring required environment variables are present-> Downloading kubectl version 1.23.0-> Generated service account:apiVersion: v1kind: ServiceAccountmetadata:name: my-s3-rolenamespace: xxxxxxannotations:eks.amazonaws.com/role-arn: arn:aws:iam::xxxxxx:role/my-s3-role-> Getting kubeconfigAdded new context arn:aws:eks:region:id:cluster/cluster-name to /root/.kube/config-> Deploying service accountserviceaccount/aws-permissions created
Set application service account
Set service account
The final step is to set this service account (pointing to the AWS role) to your application. Go into your application Advanced settings
and set the Service account
to the one you have just created:
Deploy your application with the Deploy now
button.
At this stage, the job should have been executed and the service account should be deployed on your Kubernetes cluster, and the Debian container, running.
Validate access
To validate the AWS role has correctly been deployed, we can connect to the pod, and see if we have the AWS token. We will use the Qovery CLI to connect to our pod:
$ qovery shellQovery: Select organizationOrganization:✔ QoveryQovery: Select projectProject:✔ AWS roles tutorialQovery: Select environmentEnvironment:✔ aws-roleQovery: Select serviceServices:✔ debian
Now we are connected to the pod, we can check the AWS token:
$ env | grep AWSAWS_DEFAULT_REGION=us-east-2AWS_REGION=us-east-2AWS_ROLE_ARN=arn:aws:iam::xxxxxx:role/my-s3-roleAWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/tokenAWS_STS_REGIONAL_ENDPOINTS=regional
Token is here! Let's install the AWS CLI and validate the role access. We should be able to list S3 buckets:
$ apt-get update && apt-get -y install awscli$ aws s3 ls2022-09-23 06:56:38 aws-cloudtrail-logs-qovery...
It works! We have access to S3 buckets using the AWS role.
Conclusion
The first setup phase can be time-consuming. However, once done, applying roles to your applications is very easy and fast. You can now use roles to access any AWS service!