Amazon Managed Service for Prometheus authentication
This document is a description of different ways users can authenticate metrics queries sent by the Nobl9 agent to the Amazon Managed Service for Prometheus.
Basic conceptsβ
The following is a high-level overview of the basic AWS IAM concepts:
- 
IAM stands for AWS Identity and Access Management. It is a system that ensures fine-grained permissions management in AWS. 
- 
ARN stands for Amazon Resource Name. It is a string with a specified format ( :signs to separate Its different parts) that uniquely identifies a resource in AWS. For example:arn:aws:iam::123123123123:role/amp-query-role
- 
IAM Policy is an object in AWS. When it is associated with an identity or resource, it defines its permissions. You can create your own policy or use AWS managed policies and describe them using JSON. The following is an example of the AWS managed policy that allows users to query Amazon Managed Service for Prometheus. The policy is called AmazonPrometheusQueryAccess:{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Action": [
 "aps:GetLabels",
 "aps:GetMetricMetadata",
 "aps:GetSeries",
 "aps:QueryMetrics"
 ],
 "Effect": "Allow",
 "Resource": "*"
 }
 ]
 }The aps:QueryMetricsallows the agent to query AWS for Metrics (whereapsstands for Amazon Prometheus Service).
You can find a complete list of permissions along with associated actions here.
- 
IAM Identity can either be a user,user group,orrole. You can attachIAM PoliciestoIAM Identitiesto define what a specificidentityis permitted to do.
- 
IAM User is an entity you can create. It represents a person or an application that interacts with AWS through permission policies. IAM Userconsists of a name and static credentials, which can be (most commonly):- 
Passwordis a standard static credential for a user.
- 
Access keysare common for applications and consist ofAccess keyandSecret access key.
 
- 
- 
IAM Role is similar to a userwith several key differences:- 
It is not associated with one person/application. It can be assumed by any user or application that requires it. 
- 
It does not have static credentials. Instead, it provides you with temporary security credentials for your role session when you assume a role. 
 
- 
A role can be assumed by another role. This is called role chaining.
Nobl9 agent signing processβ
Nobl9 agent uses Golang AWS SDK (v1), which provides a Signature V4 signing process for signing requests to Amazon Managed Service for Prometheus.
Authentication pathsβ
The paths listed below do not cover all the authentication paths an application may choose from when accessing Amazon Managed Service for Prometheus. The purpose of this document is to list the most common ways that the Nobl9 agent supports.
The following diagram outlines all possible authentication paths for Amazon Prometheus and their copendencies (click to enlarge):
The primary environment we expect the agent to run in is a k8s cluster.
Dedicated user with static credentialsβ
In the scenario outlined below, we create a dedicated user and generate access keys for this user. You can do this through the Security credentials tab on the user view, where you can Create access key. We will be using the generated access keys to sign our request to query metrics.
Once it is generated, store your secret key in a safe location as you will not be able to access it afterward.
When created, you must expose the Access key to the agent. In the following example, we use the env variables configuration:
export AWS_ACCESS_KEY_ID="ASIA!XAE6VILQ54NYAOV"
export AWS_SECRET_ACCESS_KEY="Q16Vep/WU1JHCLo1oMIYOoGAB6j2MFtjZPqm0ac"
This is a preferred method of exposing the AWS security credentials to the agent. For details on other possible ways, go to this page.
If you are running the agent on k8s cluster, add these env declarations to your agent configuration:
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: agent-container
          env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  key: <KEY_NAME>
                  name: <SECRET_NAME>
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  key: <KEY_NAME>
                  name: <SECRET_NAME>
The standard and secure way to provide secrets to the running container in k8s is through Secret resource. You can also provide these credentials directly in the Deployment, but we do not recommend this method.
If you already have these credentials deployed in a Secret in your cluster, replace the KEY_NAME and SECRET_NAME placeholders accordingly.
If you do not have such Secret, follow the below example that shows how to create it:
apiVersion: v1
kind: Secret
metadata:
  name: nobl9-agent-user-amazon-credentials
  namespace: default
type: Opaque
stringData:
  aws_access_key_id: "ASIA!XAE6VILQ54NYAOV"
  aws_secret_access_key: "Q16Vep/WU1JHCLo1oMIYOoGAB6j2MFtjZPqm0ac"
aws_access_key_id and aws_secret_access_key contain exemplary values.
Now, replace the placeholders from the above YAML:
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: agent-container
          env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  key: aws_access_key_id
                  name: nobl9-agent-user-amazon-credentials
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  key: aws_secret_access_key
                  name: nobl9-agent-user-amazon-credentials
Defining userβs permissionβ
The agent connection to AWS is fully configured once you deploy the agent with the credentials exposed to the running container.
Make sure that the user you have generated the credentials for has the correct permissions to query metrics. To do that, click the Add permissions button in the Permissions section on the user view in the AWS console.
We recommend using a predefined permission policy AmazonPrometheusQueryAccess.
You can also define your own policy. To do that, Amazon Prometheus needs the aps:QueryMetrics permission. The below example shows a JSON configuration of the permission:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "aps:QueryMetrics"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
The configuration is complete once you have assigned the above permission to a user.
Defining permissions for shared rolesβ
If you do not want to grant the permission directly to a user, AWS allows you to create a shared role that this user can assume.
To assign permissions to a shared role, follow all the authentication path steps outlined above. Using a shared role method, you still need to provide the agent with the users' credentials. However, instead of assigning permission directly to a user, you make it assume a shared role with the sts:AssumeRole permission.
To assign permissions to a shared role:
- 
Grant the user with sts:AssumeRolethat points to the role ARN you wish to assume. For example, you can do this through the following JSON configuration:{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Sid": "VisualEditor0",
 "Effect": "Allow",
 "Action": "sts:AssumeRole",
 "Resource": "arn:aws:iam::123123123123:role/amp-query-role"
 }
 ]
 }
The above example assumes that your role ARN is arn:aws:iam::123123123123:role/amp-query-role and it has the sts:QueryMetrics permission. You can add permission policies following the same steps that you assign them to an individual user.
- Tell the role you want to assume to trust this user
- Use the Trust relationshipstab on theRole viewin your AWS Console.
- Click Edit trust relationships. Below is an example of JSON configuration:
 
- Use the 
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123123123123:user/agent-user"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
This example assumes that your user's ARN is arn:aws:iam::123123123123:user/agent-user.
- Now, set the envvariableN9_PROMETHEUS_AWS_ROLE_ARNfor the agent. Configure it in the agent'sDeployment:
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: agent-container
          env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  key: aws_access_key_id
                  name: nobl9-agent-user-amazon-credentials
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  key: aws_secret_access_key
                  name: nobl9-agent-user-amazon-credentials
            - name: N9_PROMETHEUS_AWS_ROLE_ARN
              value: arn:aws:iam::123123123123:role/amp-query-role
Role-based accessβ
This method differs from a user-based authentication. In the role-based access method, you are not providing any static credentials to the agent. The role credentials used to sign the request are supplied by the ServiceAccount that you attach to the Pod in the Kubernetes cluster.
For more details on IAM roles for service accounts, refer to the AWS guide available here
Before creating the ServiceAccount and configuring the Trust relationship for the role you want the ServiceAccount to provide, make sure an OIDC provider is running in your cluster. For more details, refer to Create an IAM OIDC provider for your cluster.
For the time being, Nobl9 does not support IAM roles for Amazon EC2.
Defining permissions for a roleβ
If you want to bind a role to the ServiceAccount, the role has to have aps:QueryMetrics permission.
- 
Refer to the above section on the Access keys for more details. 
- 
To create a role that can be linked to the ServiceAccount, refer to this guide.
- 
Update the Trust relationshipof the created role. Follow the below JSON declaration:{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": {
 "Federated": "arn:aws:iam::123123123123:oidc-provider/${OIDC_PROVIDER}"
 },
 "Action": "sts:AssumeRoleWithWebIdentity",
 "Condition": {
 "StringEquals": {
 "${OIDC_PROVIDER}:sub": "system:serviceaccount:default:amp-query-role"
 }
 }
 }
 ]
 }
- 
Now, create a ServiceAccountfor this role:apiVersion: v1
 kind: ServiceAccount
 metadata:
 name: amp-query-role
 namespace: default
 annotations:
 eks.amazonaws.com/role-arn: arn:aws:iam::123123123123:role/amp-query-role
- 
To complete the configuration, you need to tell the agent's Deploymentthat you want thisServiceAccountto be attached to the pods that run under it. To do this, modify theDeploymentas follows:apiVersion: apps/v1
 kind: Deployment
 spec:
 template:
 spec:
 serviceAccount: amp-query-role
 serviceAccountName: amp-query-role
Role chainingβ
This case builds on top of the previous one and differs in a similar way in which the user with permission differs from the user with the assumed role.
Our role does not have the permissions defined itself but instead relies on a different role to provide it:
- 
The JSON declarations for both roles will look the same as in the previous case, Trust relationshipforarn:aws:iam::123123123123:role/amp-query-role:{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": {
 "AWS": "arn:aws:iam::123123123123:user/the-role-which-wants-to-assume"
 },
 "Action": "sts:AssumeRole",
 "Condition": {}
 }
 ]
 }
- 
Apply Permissionsfor thearn:aws:iam::123123123123:role/the-role-which-wants-to-assume:{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Sid": "VisualEditor0",
 "Effect": "Allow",
 "Action": "sts:AssumeRole",
 "Resource": "arn:aws:iam::123123123123:role/amp-query-role"
 }
 ]
 }
- 
Create and configure ServiceAccountfor thethe-role-which-wants-to-assumejust as in:apiVersion: v1
 kind: ServiceAccount
 metadata:
 name: the-role-which-wants-to-assume
 namespace: default
 annotations:
 eks.amazonaws.com/role-arn: arn:aws:iam::123123123123:role/the-role-which-wants-to-assume
- 
To finish the configuration, set N9_PROMETHEUS_AWS_ROLE_ARNin the agent's environment:apiVersion: apps/v1
 kind: Deployment
 spec:
 template:
 spec:
 serviceAccount: the-role-which-wants-to-assume
 serviceAccountName: the-role-which-wants-to-assume
 containers:
 - name: agent-container
 env:
 - name: N9_PROMETHEUS_AWS_ROLE_ARN
 value: arn:aws:iam::123123123123:role/amp-query-role