Skip to content

Latest commit

 

History

History
274 lines (210 loc) · 8.38 KB

AUTHENTICATION.md

File metadata and controls

274 lines (210 loc) · 8.38 KB

Authenticating to AWS API

provider-aws requires credentials to be provided in order to authenticate to the AWS API. This can be done in one of two ways:

  1. Base64 encoding static credentials in a Kubernetes Secret. This is described in detail here.
  2. Authenticating using IAM Roles for Kubernetes ServiceAccounts. This functionality is only available when running Crossplane on EKS, and the feature has been enabled in the cluster.
  3. Authenticating using kube2iam. This solution allows to avoid using static credentials with non-EKS cluster.

Using IAM Roles for Service Accounts

Using IAM Roles for Service Accounts requires some additional setup for the time-being. The steps for enabling are described below. Many of the steps can also be found in the AWS docs.

Steps

These steps assume you already have a running EKS cluster with a sufficiently large node pool.

  1. Connect to your EKS cluster
aws eks --region "${AWS_REGION}" update-kubeconfig --name "${CLUSTER_NAME}"
  1. Get AWS account information

Get AWS account information and pick an IAM role name. These will be used to setup an OIDC provider and inject credentials into the provider-aws controller pod.

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
export IAM_ROLE_NAME=provider-aws # name for IAM role, can be anything you want
  1. Install Crossplane

Install Crossplane from stable channel:

kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable

helm install crossplane --namespace crossplane-system crossplane-stable/crossplane

provider-aws can be installed with the Crossplane CLI, but we will do so manually so that we can also create and reference a ControllerConfig:

cat > provider-config.yaml <<EOF
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
  name: aws-config
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::$AWS_ACCOUNT_ID:role/$IAM_ROLE_NAME
spec:
  podSecurityContext:
    fsGroup: 2000
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws
spec:
  package: crossplane/provider-aws:alpha
  controllerConfigRef:
    name: aws-config
EOF

kubectl apply -f provider-config.yaml
  1. Identify provider-aws service account

Make sure that the appropriate ServiceAccount exists:

kubectl get serviceaccounts -n crossplane-system

If you used the install command above you should see a ServiceAccount in the output named provider-aws-*. You should also see the provider-aws-* controller Pod running if you execute kubectl get pods -n crossplane-system. Set environment variables to match the name and namespace of this ServiceAccount:

SERVICE_ACCOUNT_NAMESPACE=crossplane-system
SERVICE_ACCOUNT_NAME=provider-aws-<YOUR-SERVICE-ACCOUNT-EXTENSION>
  1. Create OIDC provider for cluster

If you do not have eksctl installed you may use the AWS Console

eksctl utils associate-iam-oidc-provider --cluster "${CLUSTER_NAME}" --region "${AWS_REGION}" --approve
  1. Create IAM Role that provider-aws will use using eksctl

Create IAM role with trust relationship:

eksctl create iamserviceaccount --cluster "${CLUSTER_NAME}" --region "${AWS_REGION}" --name="$SERVICE_ACCOUNT_NAME" --namespace="$SERVICE_ACCOUNT_NAMESPACE" --role-name="$IAM_ROLE_NAME" --role-only --attach-policy-arn="arn:aws:iam::aws:policy/AdministratorAccess" --approve

The variable ${SERVICE_ACCOUNT_NAME} contains default service account name and changes with every provider release.

  1. Create IAM Role that provider-aws will use manually (skip if you created IAM Role using eksctl)

Set environment variables that will be used in subsequent commands:

OIDC_PROVIDER=$(aws eks describe-cluster --name "${CLUSTER_NAME}" --region "${AWS_REGION}" --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")

Create trust relationship for IAM role:

read -r -d '' TRUST_RELATIONSHIP <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "${OIDC_PROVIDER}:sub": "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:provider-aws-*"
        }
      }
    }
  ]
}
EOF
echo "${TRUST_RELATIONSHIP}" > trust.json

The default service account name is the provider-aws revision and changes with every provider release. The conditional above wildcard matches the default service account name in order to keep the role consistent across provider releases. The above policy assumes a service account name of provider-aws-*

Create IAM role:

aws iam create-role --role-name "${IAM_ROLE_NAME}" --assume-role-policy-document file://trust.json --description "IAM role for provider-aws"

Associate a policy with the IAM role. This example uses AdministratorAccess, but you should select a policy with the minimum permissions required to provision your resources.

aws iam attach-role-policy --role-name "${IAM_ROLE_NAME}" --policy-arn=arn:aws:iam::aws:policy/AdministratorAccess
  1. Create ProviderConfig

Ensure that ProviderConfig resource kind was created:

kubectl explain providerconfig --api-version='aws.crossplane.io/v1beta1'

To utilize those credentials to provision new resources, you must create a ProviderConfig with source: InjectedIdentity:

cat > provider-config.yaml <<EOF
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-provider
spec:
  credentials:
    source: InjectedIdentity
EOF

kubectl apply -f provider-config.yaml

You can now reference this ProviderConfig to provision any provider-aws resources.

Using kube2iam

This guide assumes that you already have :

  • created a policy with the minimum permissions required to provision your resources
  • created an IAM role that AWS Provider will assume to interact with AWS
  • associated the policy to the IAM role

Please refer to the previous section for details about these prerequisites.

Let's say the role you created is : infra/k8s/crossplane

Steps

  1. Deploy a ControllerConfig

Crossplane provides a ControllerConfig type that allows you to customize the deployment of a provider’s controller Pod.

A ControllerConfig can be created and referenced by any number of Provider objects that wish to use its configuration.

Note: the kube2iam annotation must be under spec.metadata.annotations that will be added to the AWS provider pod.

cat > controller-config.yaml <<EOF
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
  name: aws-config
spec:
  metadata:
    annotations:
      # kube2iam annotation that will be added to the aws-provider defined in the next section
      iam.amazonaws.com/role: cdsf/k8s/kube2iam-crossplane-integration
  podSecurityContext:
    fsGroup: 2000
EOF

kubectl apply -f controller-config.yaml
  1. Deploy the Provider and a ProviderConfig

The AWS Provider is referencing the ControllerConfig we deployed in the previous step. The ProviderConfig configures how AWS controllers will connect to AWS API.

cat > provider-config.yaml <<EOF
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: aws-provider
spec:
  package: crossplane/provider-aws:master
  controllerConfigRef:
    name: aws-config
---
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
  spec:
  credentials:
    # Set source to 'InjectedIdentity' to be compliant with kube2iam behavior
    source: InjectedIdentity
EOF

kubectl apply -f provider-config.yaml

Note: Because the name of the ProviderConfig is default it will be used by any managed resources that do not explicitly reference a ProviderConfig.