OpenShift can be configured to use temporary credentials for different components with AWS Security Token Service (STS). It enables an authentication flow allowing a component to assume an IAM Role resulting in short-lived credentials. It also automates requesting and refreshing of credentials using an AWS IAM OpenID Connect (OIDC) Identity Provider. OpenShift can sign ServiceAccount tokens trusted by AWS IAM which can be projected into a Pod and used for authentication. The following is a diagram showing how it works.
Previously, if we checked the credentials secret, we'd find the following base64 encoded content in the credentials
key of the data
field.
[default]
aws_access_key_id = <access_key_id>
secret_access_key = <secret_access_key>
With STS we have a full-fledged AWS configuration that defines a role
and web identity token
[default]
sts_regional_endpoints = regional
role_name = arn:...:role/some-role-name
web_identity_token_file = /path/to/token
The token is a projected ServiceAccount into the Pod, and is short lived for an hour after which it is refreshed.
-
Set the variable
$RELEASE_IMAGE
$RELEASE_IMAGE
should be a recent and supported OpenShift release image that you want to deploy in your cluster. Please refer to the support matrix for compatibilities.A sample release image would be
RELEASE_IMAGE=quay.io/openshift-release-dev/ocp-release:${RHOCP_version}-${Arch}
Where
RHOCP_version
is the OpenShift version (e.g4.10.0-fc.4
or4.9.3
) and theArch
is the architecture type (e.gx86_64
) -
Extract the AWS Credentials Request objects from the above release image
With newer version of oc CLI (4.7+):
mkdir credreqs ; oc adm release extract --cloud=aws --credentials-requests $RELEASE_IMAGE --to=./credreqs
-
Extract the
openshift-install
andccoctl
binaries from the release image.oc adm release extract --command=openshift-install $RELEASE_IMAGE CCO_IMAGE=$(oc adm release info --image-for='cloud-credential-operator' ${RELEASE_IMAGE}) && oc image extract ${CCO_IMAGE} --file='/usr/bin/ccoctl' --registry-config=${PULL_SECRET_PATH:-.}/pull-secret
-
Create an install-config.yaml
./openshift-install create install-config
-
Make sure that we install the cluster in Manual mode
echo "credentialsMode: Manual" >> install-config.yaml
-
Create install manifests
./openshift-install create manifests
-
There are two options to expose the public endpoint used by the IAM OIDC identity provider on AWS: A) public S3 Bucket (default); B) AWS CloudFront Distribution serving thumbprints stored on private S3 Bucket:
A. Create AWS resources using the ccoctl tool (you will need aws credentials with sufficient permissions). The command below will generate public/private ServiceAccount signing keys, create the S3 bucket (with public read-only access), upload the OIDC config into the bucket, set up an IAM Identity Provider that trusts that bucket configuration, and create IAM Roles for each AWS CredentialsRequest extracted above. It will also dump the files needed by the installer in the _output
directory
./ccoctl aws create-all \
--name <aws_infra_name> \
--region <aws_region> \
--credentials-requests-dir ./credreqs \
--output-dir _output/
B. To create a CloudFront Distribution with a private S3 bucket to store OIDC config, run the following command. More information on the technical details here
./ccoctl aws create-all \
--name <aws_infra_name> \
--region <aws_region> \
--credentials-requests-dir ./credreqs \
--output-dir _output/
--create-private-s3-bucket
- Copy the manifests created in the step 7 and put them in the same location as install-config.yaml in the
manifests
directorycp _output/manifests/* /path/to/dir/with/install-config.yaml/manifests/
- Copy the private key for the ServiceAccount signer and put it in the same location as install-config.yaml
cp -a _output/tls ./path/to/dir/with/install-config.yaml/
- Run the OpenShift installer
./openshift-install create cluster --log-level=debug
- Connect to the newly installed cluster and verify that the OpenShift cluster does not have
root
credentials. The following command should throw a secret not found error:oc get secrets -n kube-system aws-creds
- Verify that components are assuming the IAM Role specified in the secret manifests, instead of creds minted by the cloud-credential-operator. The following command should show you the
role
andweb identity token
used by the image registry operatorsample output of the above commandoc get secrets -n openshift-image-registry installer-cloud-credentials -o json | jq -r .data.credentials | base64 -d
[default] role_arn = arn:aws:iam::123456789:role/<aws_infra_name>-openshift-image-registry-installer-cloud-credentials web_identity_token_file = /var/run/secrets/openshift/serviceaccount/token
NOTE This is just for developers interested in taking an existing cluster to STS. This is explicitly NOT RECOMMENED OR SUPPORTED.
- Extract the cluster's ServiceAccount public signing key:
$ oc get configmap --namespace openshift-kube-apiserver bound-sa-token-signing-certs --output json | jq --raw-output '.data["service-account-001.pub"]' > serviceaccount-signer.public
- Pretend that
ccoctl
created a key pair by placing the public key where it would have been created:
$ mkdir ./newstscluster ; mv serviceaccount-signer.public ./newstscluster/serviceaccount-signer.public
- Create the AWS IAM Identity provider and the S3 bucket with the OIDC config files:
In
<name-you-choose>
it will be the prefix of the OIDC bucket name and identity provider name that would be created (since under the hood it's an S3 bucket name, it should be globally unique).
$ ./ccoctl aws create-identity-provider --output-dir newstscluster --name <name-you-choose> --region us-east-2
-
Save/note the last line from that output which contains the ARN for the IAM Identity provider.
-
Update the cluster's Authentication CR's spec.serviceAccountIssuer field to put the URL holding the OIDC files:
$ cat newstscluster/manifests/cluster-authentication-02-config.yaml | awk '/serviceAccountIssuer/ { print $2 }'
$ oc edit authentication cluster
- Wait for the kube-apiserver pods to be updated with the new config:
$ oc get pods -n openshift-kube-apiserver | grep kube-apiserver
- Restart all pods (this will take a while) in the cluster (because all ServiceAccounts need to be refreshed after updating the serviceAccountIssuer field):
$ for I in $(oc get ns -o jsonpath='{range .items[*]} {.metadata.name}{"\n"} {end}'); \
do oc delete pods --all -n $I; \
sleep 1; \
done
-
Set the CloudCredentials CR's .spec.credentialsMode to Manual with:
oc edit cloudcredentials cluster
-
Get the current version of the cluster:
$ oc get clusterversion version -o json | jq -r '.status.desired.version'
- Get the release image for that version:
$ oc get clusterversion version -o json | jq -r '.status.history[] | select(.version == "VERSION_FROM_PREVIOUS_COMMAND") | .image'
- Extract CredentialsRequests resources from that release image:
$ oc adm release extract --credentials-requests --cloud=aws RELEASE_IMAGE_FROM_PREVIOUS_COMMAND --to cred-reqs
- Create IAM Roles for each of the CredentialsRequests from the release image:
$ ./ccoctl aws create-iam-roles --output-dir ./newstscluster/ --name newstscluster --identity-provider-arn ARN_CREATED_FROM_CREATE_IDENTITY_PROVIDER_COMMAND --region us-east-2 --credentials-requests-dir ./cred-reqs/
- Apply the Secrets generated by the above command:
$ find ./cred-reqs -iname "*yaml" -print0 | xargs -I {} -0 -t oc replace -f {}
- At this point the cluster is using STS. The previously created IAM Users/credentials can be deleted as they are not being used. The "root" AWS creds Secret can also be removed (
oc delete secret -n kube-system aws-creds
).
Delete the S3 bucket, IAM identity provider, and IAM Roles using the ccoctl tool.