

# Set up IAM roles for service accounts
<a name="set-up-irsa"></a>

With IAM roles for service accounts, you can associate an IAM role with a Kubernetes service account. This service account can then provide AWS permissions to the containers in any pod that uses that service account. For more information, see [IAM roles for service accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html).

IAM roles for service accounts are also known as *service roles*.

In Amazon Managed Service for Prometheus, using service roles can help you get the roles you need to authorize and authenticate between Amazon Managed Service for Prometheus, Prometheus servers, and Grafana servers.

**Prerequisites**

The procedures on this page require that you have the AWS CLI and EKSCTL command line interface installed.

## Set up service roles for the ingestion of metrics from Amazon EKS clusters
<a name="set-up-irsa-ingest"></a>

To set up the service roles to enable Amazon Managed Service for Prometheus to ingest metrics from Prometheus servers in Amazon EKS clusters, you must be logged on to an account with the following permissions:
+ `iam:CreateRole`
+ `iam:CreatePolicy`
+ `iam:GetRole`
+ `iam:AttachRolePolicy`
+ `iam:GetOpenIDConnectProvider`

**To set up the service role for ingestion into Amazon Managed Service for Prometheus**

1. Create a file named `createIRSA-AMPIngest.sh` with the following content. Replace `<my_amazon_eks_clustername>` with the name of your cluster, and replace `<my_prometheus_namespace>` with your Prometheus namespace.

   ```
   #!/bin/bash -e
   CLUSTER_NAME=<my_amazon_eks_clustername>
   SERVICE_ACCOUNT_NAMESPACE=<my_prometheus_namespace>
   AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
   OIDC_PROVIDER=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
   SERVICE_ACCOUNT_AMP_INGEST_NAME=amp-iamproxy-ingest-service-account
   SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE=amp-iamproxy-ingest-role
   SERVICE_ACCOUNT_IAM_AMP_INGEST_POLICY=AMPIngestPolicy
   #
   # Set up a trust policy designed for a specific combination of K8s service account and namespace to sign in from a Kubernetes cluster which hosts the OIDC Idp.
   #
   cat <<EOF > TrustPolicy.json
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
         },
         "Action": "sts:AssumeRoleWithWebIdentity",
         "Condition": {
           "StringEquals": {
             "${OIDC_PROVIDER}:sub": "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_AMP_INGEST_NAME}"
           }
         }
       }
     ]
   }
   EOF
   #
   # Set up the permission policy that grants ingest (remote write) permissions for all AMP workspaces
   #
   cat <<EOF > PermissionPolicyIngest.json
   {
     "Version": "2012-10-17",		 	 	 
      "Statement": [
          {"Effect": "Allow",
           "Action": [
              "aps:RemoteWrite", 
              "aps:GetSeries", 
              "aps:GetLabels",
              "aps:GetMetricMetadata"
           ], 
           "Resource": "*"
         }
      ]
   }
   EOF
   
   function getRoleArn() {
     OUTPUT=$(aws iam get-role --role-name $1 --query 'Role.Arn' --output text 2>&1)
   
     # Check for an expected exception
     if [[ $? -eq 0 ]]; then
       echo $OUTPUT
     elif [[ -n $(grep "NoSuchEntity" <<< $OUTPUT) ]]; then
       echo ""
     else
       >&2 echo $OUTPUT
       return 1
     fi
   }
   
   #
   # Create the IAM Role for ingest with the above trust policy
   #
   SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE_ARN=$(getRoleArn $SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE)
   if [ "$SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE_ARN" = "" ]; 
   then
     #
     # Create the IAM role for service account
     #
     SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE_ARN=$(aws iam create-role \
     --role-name $SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE \
     --assume-role-policy-document file://TrustPolicy.json \
     --query "Role.Arn" --output text)
     #
     # Create an IAM permission policy
     #
     SERVICE_ACCOUNT_IAM_AMP_INGEST_ARN=$(aws iam create-policy --policy-name $SERVICE_ACCOUNT_IAM_AMP_INGEST_POLICY \
     --policy-document file://PermissionPolicyIngest.json \
     --query 'Policy.Arn' --output text)
     #
     # Attach the required IAM policies to the IAM role created above
     #
     aws iam attach-role-policy \
     --role-name $SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE \
     --policy-arn $SERVICE_ACCOUNT_IAM_AMP_INGEST_ARN  
   else
       echo "$SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE_ARN IAM role for ingest already exists"
   fi
   echo $SERVICE_ACCOUNT_IAM_AMP_INGEST_ROLE_ARN
   #
   # EKS cluster hosts an OIDC provider with a public discovery endpoint.
   # Associate this IdP with AWS IAM so that the latter can validate and accept the OIDC tokens issued by Kubernetes to service accounts.
   # Doing this with eksctl is the easier and best approach.
   #
   eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --approve
   ```

1. Enter the following command to give the script the necessary privileges.

   ```
   chmod +x createIRSA-AMPIngest.sh
   ```

1. Run the script.

## Set up IAM roles for service accounts for the querying of metrics
<a name="set-up-irsa-query"></a>

To set up the IAM role for service account (service role) to enable the querying of metrics from Amazon Managed Service for Prometheus workspaces, you must be logged on to an account with the following permissions:
+ `iam:CreateRole`
+ `iam:CreatePolicy`
+ `iam:GetRole`
+ `iam:AttachRolePolicy`
+ `iam:GetOpenIDConnectProvider`

**To set up service roles for the querying of Amazon Managed Service for Prometheus metrics;**

1. Create a file named `createIRSA-AMPQuery.sh` with the following content. Replace `<my_amazon_eks_clustername>` with the name of your cluster, and replace <my\$1prometheus\$1namespace> with your Prometheus namespace.

   ```
   #!/bin/bash -e
   CLUSTER_NAME=<my_amazon_eks_clustername>
   SERVICE_ACCOUNT_NAMESPACE=<my_prometheus_namespace>
   AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
   OIDC_PROVIDER=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
   SERVICE_ACCOUNT_AMP_QUERY_NAME=amp-iamproxy-query-service-account
   SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE=amp-iamproxy-query-role
   SERVICE_ACCOUNT_IAM_AMP_QUERY_POLICY=AMPQueryPolicy
   #
   # Setup a trust policy designed for a specific combination of K8s service account and namespace to sign in from a Kubernetes cluster which hosts the OIDC Idp.
   #
   cat <<EOF > TrustPolicy.json
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
         },
         "Action": "sts:AssumeRoleWithWebIdentity",
         "Condition": {
           "StringEquals": {
             "${OIDC_PROVIDER}:sub": "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_AMP_QUERY_NAME}"
           }
         }
       }
     ]
   }
   EOF
   #
   # Set up the permission policy that grants query permissions for all AMP workspaces
   #
   cat <<EOF > PermissionPolicyQuery.json
   {
     "Version": "2012-10-17",		 	 	 
      "Statement": [
          {"Effect": "Allow",
           "Action": [
              "aps:QueryMetrics",
              "aps:GetSeries", 
              "aps:GetLabels",
              "aps:GetMetricMetadata"
           ], 
           "Resource": "*"
         }
      ]
   }
   EOF
   
   function getRoleArn() {
     OUTPUT=$(aws iam get-role --role-name $1 --query 'Role.Arn' --output text 2>&1)
   
     # Check for an expected exception
     if [[ $? -eq 0 ]]; then
       echo $OUTPUT
     elif [[ -n $(grep "NoSuchEntity" <<< $OUTPUT) ]]; then
       echo ""
     else
       >&2 echo $OUTPUT
       return 1
     fi
   }
   
   #
   # Create the IAM Role for query with the above trust policy
   #
   SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE_ARN=$(getRoleArn $SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE)
   if [ "$SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE_ARN" = "" ]; 
   then
     #
     # Create the IAM role for service account
     #
     SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE_ARN=$(aws iam create-role \
     --role-name $SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE \
     --assume-role-policy-document file://TrustPolicy.json \
     --query "Role.Arn" --output text)
     #
     # Create an IAM permission policy
     #
     SERVICE_ACCOUNT_IAM_AMP_QUERY_ARN=$(aws iam create-policy --policy-name $SERVICE_ACCOUNT_IAM_AMP_QUERY_POLICY \
     --policy-document file://PermissionPolicyQuery.json \
     --query 'Policy.Arn' --output text)
     #
     # Attach the required IAM policies to the IAM role create above
     #
     aws iam attach-role-policy \
     --role-name $SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE \
     --policy-arn $SERVICE_ACCOUNT_IAM_AMP_QUERY_ARN  
   else
       echo "$SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE_ARN IAM role for query already exists"
   fi
   echo $SERVICE_ACCOUNT_IAM_AMP_QUERY_ROLE_ARN
   #
   # EKS cluster hosts an OIDC provider with a public discovery endpoint.
   # Associate this IdP with AWS IAM so that the latter can validate and accept the OIDC tokens issued by Kubernetes to service accounts.
   # Doing this with eksctl is the easier and best approach.
   #
   eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --approve
   ```

1. Enter the following command to give the script the necessary privileges.

   ```
   chmod +x createIRSA-AMPQuery.sh
   ```

1. Run the script.