Cross-cloud identity framework with SPIFFE/Spire on OpenShift

Address cross-cloud identity challenges with SPIFFE/SPIRE on OpenShift by deploying and working with applications in a no-cost OpenShift cluster.

Access the Developer Sandbox

Now we have a running instance of Red Hat Developer Hub. Out of the box, this instance has all of its plug-ins installed. However, we need to be able to configure it specifically for our end-user developers. Every organization is different, and Developer Hub allows you to completely configure it to match your organizational and developmental needs. That will be the focus of this lesson.

In order to get full benefit from taking this lesson, you need:

  • Have an AWS account with required permissions and the AWS CLI tool installed.

In this lesson, you will:

  • Create an S3 bucket with a sample file.
  • Create an identity provider of type oidc pointing to the OIDC Discovery service managed by SPIRE.
  • Create and configure an IAM role and policy for access to the S3 bucket.

The following steps use the AWS CLI. If you prefer to use the AWS console, follow the steps documented here

Ensure that the AWS CLI is authenticated, making use of the steps described here.


Create an S3 bucket

Create an AWS S3 bucket and place a sample message within a test file in the newly created bucket. Because the names of S3 buckets must be unique per region, enter a unique name and export the bucket name and AWS region. 

The following will generate a unique bucket name and obtain the currently configured AWS region:   

export S3_BUCKET=spire-blog-$(shuf -i 2000-65000 -n 1)
export S3_REGION=$(aws configure get region)

# list current buckets:
aws s3api list-buckets --output text

# create a new bucket:
aws s3api create-bucket --bucket $S3_BUCKET --region $S3_REGION --create-bucket-configuration LocationConstraint=$S3_REGION

# Upload a file to the bucket
echo "my secret message" | aws s3 cp - s3://${S3_BUCKET}/test

You can test the bucket using your AWS credentials:

aws s3 cp s3://${S3_BUCKET}/test -

Configure an OIDC Identity Provider

These steps configure AWS IAM to point at an OIDC service managed by SPIRE.

  1. First, test the access to our OIDC service installed previously. Use the OIDC route and verify it is returning a valid response by appending the /keys suffix. 

    export OIDC_SERVER=oidc-discovery.$appdomain
    curl https://$OIDC_SERVER/keys
  2. This should trigger a response similar to the following that shows one or many public keys for your OIDC service:

    {
      "keys": [
        {
          "kty": "RSA",
          "kid": "FhpDhZHWzx1md6vQedtGDxFCM16lGJT7",
          "alg": "RS256",
          "n": "yZAKdBaI-RVkHZg5NhPsPm70JUM3mMl7PfgbFapZQLEheSOM7aQTRKzoYCN0cTzQ70GijzjttLV91-073DW4r2PD7Cu3GAm9TrMTJ_B3YrPPKADdsQXJgVW-PYXAwtVuhmYrFMgJqjIDiapaAcMvAMxh0wyUD3n6rQnr8DIhOtOgHHb_6ZsbAbtYKXupvcj498BdngmpgtKl4mob90Ga9kJvJMnNyJPnV-pdF_gefduSWhjGZN3eJXj4EYgQwZyTA-8Hr89GgyiNTcyFCqvz_msapeKV-8t9tURl8GxWZYtyzemiXShyxkQfc1obMML15QO2kFDmquKTY3mc6387Sw",
          "e": "AQAB"
        }
      ]
    }
  3. Use this OIDC URL while setting up the identity provider for IAM. Capture and parse the certificate into a file called certificate.pem:

    # get the OIDC certificate 
    openssl s_client -servername ${OIDC_SERVER} -showcerts -connect ${OIDC_SERVER}:443 | awk '/BEGIN CERTIFICATE/{data=""; capture=1} capture {data=data $0 ORS} /END CERTIFICATE/{block=data; capture=0} END {print block}' > certificate.pem
  4. Now create a thumbprint for this certificate, then create the identity provider.

    # Obtain Certificate Thumbprint
    export OIDC_THUMBPRINT=$(openssl x509 -in certificate.pem -fingerprint -sha1 -noout | awk -F= '{print $2}' | sed 's/://g');echo $OIDC_THUMBPRINT
    
    # create Identity Provider type Open Id
    aws iam create-open-id-connect-provider --url https://${OIDC_SERVER} --thumbprint-list $OIDC_THUMBPRINT --client-id-list mys3
    
    export OIDC_ARN=`aws iam list-open-id-connect-providers | jq '.OpenIDConnectProviderList[].Arn' | grep $OIDC_SERVER | tr -d '"'`
    
    # Remove the certificate file
    rm -f certificate.pem

Create an IAM role in AWS

Note: This section requires the following environment variables, as defined above:

  • OIDC_ARN
  • TRUST_DOMAIN
  • S3_BUCKET

IAM policies define the type of access and actions that can be done on that S3 bucket.

IAM roles define what workload identities can access this bucket. Instead of using a static value, you can construct more complex conditions using wildcards and ForAllValues:StringLike, as provided in this example

Create a role and policy from these templates: 

cat <<EOF >assume-role.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "${OIDC_ARN}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "${OIDC_SERVER}:aud": "mys3",
          "${OIDC_SERVER}:sub": "${TRUST_DOMAIN}/ns/demo/sa/demo"
        }
      }
    }
  ]
}
EOF

cat <<EOF >iam-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "s3:PutAccountPublicAccessBlock",
        "s3:GetAccountPublicAccessBlock",
        "s3:ListAllMyBuckets",
        "s3:ListJobs",
        "s3:CreateJob",
        "s3:ListBucket"
      ],
      "Resource": "*"
    },
    {
      "Sid": "VisualEditor1",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::${S3_BUCKET}",
        "arn:aws:s3:::${S3_BUCKET}/*",
        "arn:aws:s3:*:*:job/*"
      ]
    }
  ]
}
EOF

Then use these files to create actual your role and policy: 

# create AWS IAM role
aws iam create-role --role-name role-${S3_BUCKET} --assume-role-policy-document file://assume-role.json

# create AWS IAM policy
aws iam put-role-policy --role-name role-$S3_BUCKET --policy-name policy-$S3_BUCKET --policy-document file://iam-policy.json

export ROLE_ARN=$(aws iam get-role --role-name role-$S3_BUCKET | jq .Role.Arn | tr -d '"')
echo "ROLE_ARN=`aws iam get-role --role-name role-$S3_BUCKET | jq .Role.Arn | tr -d '"'` *** Use this in the Test step ***"

In this lesson, you successfully configured and deployed AWS services that your application, running within the OpenShift environment, will access. That will be the focus of the next lesson.

Previous resource
Install SPIRE on standard OpenShift or IBM Cloud OpenShift clusters
Next resource
Access AWS S3 from a sample application