1. Home
  2. Documentation
  3. Cloud Platform User Guide
  4. Sharing AWS resources across namespaces using SSM and IRSA

Sharing AWS resources across namespaces using SSM and IRSA

This article explains how to access a resource in one Kubernetes namespace from another using IAM, IRSA and SSM:

For example, namespace-one needs to read from an S3 bucket in namespace-two

This can be done by hard-coding the resource. This guide explains how to avoid hard-coding the resource by using SSM to share the resource name and ARN.

For more information on AWS "IAM roles for Service Accounts" (IRSA), please see IAM roles for Kubernetes Service Accounts:

The Cloud Platform utilises the cloud-platform-terraform-irsa module. Please make sure you are using the latest release in the following config:

Required Configuration:

1.Add the resource name and ARN to AWS SSM in namespace-two

Here is an example of how to add an S3 bucket ARN and name as SSM parameters:

2.Create the IAM role for service accounts config

Create a file (cross-namespace-role-sa.tf) inside the namespace-one folder in the cloud-platform-environments repo, update the template below with the correct values and raise a PR.

    tags = {
    business-unit          = "<Which part of the MoJ is responsible for this service? (e.g HMPPS, Legal Aid Agency)>"
    application            = "<Application name>"
    is-production          = "<true/false>"
    environment-name       = "<dev/test/staging/prod>"
    owner                  = "<team responsible for this application>"
    infrastructure-support = "<Email address for contact/support>"
    }
}
resource "kubernetes_secret" "irsa" {
    metadata {
    name      = "irsa-output"
    namespace = "<namespace>"
    }
    data = {
    role = module.irsa.aws_iam_role_name
    serviceaccount = module.irsa.service_account_name.name
    }
}
    ]
    resources = [
        # refer to the ssm parameter containing the arn of the resource you want to access
        "${data.aws_ssm_parameter.namespace-two-s3-bucket-arn.value}/*",
    ]
    }
}
resource "aws_iam_policy" "<namespace>_<policy_name>" {
    name   = "<namespace>-<policy-name>"
    policy = data.aws_iam_policy_document.<namespace>_<policy_name>.json

    tags = {
    business-unit          = "<Which part of the MoJ is responsible for this service? (e.g HMPPS, Legal Aid Agency)>"
    application            = "<Application name>"
    is-production          = "<true/false>"
    environment-name       = "<dev/test/staging/prod>"
    owner                  = "<team responsible for this application>"
    infrastructure-support = "<Email address for contact/support>"
    }
}
resource "kubernetes_secret" "irsa" {
    metadata {
    name      = "irsa-output"
    namespace = "<namespace>"
    }
    data = {
    role = module.irsa.aws_iam_role_name
    serviceaccount = module.irsa.service_account_name.name
    }
}

# this is the ssm parameter used to supply the application with the S3 bucket name in a k8s secret
data "aws_ssm_parameter" "s3-bucket-name" {
    name = "/namespace-two/s3-bucket-name"
}

# this is the ssm parameter which the aws_iam_policy_document refers to
data "aws_ssm_parameter" "s3-bucket-arn" {
    name = "/namespace-two/s3-bucket-arn"
}

# this is for the application to read from the S3 bucket
resource "kubernetes_secret" "s3-bucket-secret" {
    
    metadata {
        name = "s3-bucket-secret"
        namespace = var.namespace
    }

    data = {
        # reads the S3 bucket name from an SSM parameter
        bucket_name = data.aws_ssm_parameter.s3-bucket-name.value
    }
}

}

  • The service account and the service account IAM role will be created with a random string in the format cloud-platform-jhsdflisuhdfih and can be changed by passing the service_account variable. Make sure there is no existing service_account in the same name. Please see the module README for optional inputs.

  • Once the PR is merged, the IAM role and serviceaccount will be stored as a kubernetes_secret called irsa-output in your namespace.

3.Use the Serviceaccount to deploy your app

Decode the secret irsa-output to get the serviceaccount name and add it to your depolyment manifest as shown in example below:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-rubyapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld-rubyapp
  template:
    metadata:
      labels:
        app: helloworld-rubyapp
    spec:
      serviceAccountName: <serviceaccount>
      containers:
      - name: rubyapp
        image: ministryofjustice/cloud-platform-helloworld-ruby:1.1
        ports:
        - containerPort: 4567
Last reviewed: 5 August 2025Review status: ✗ Review overdueOwner: #cloud-platformSource: View source on GitHub

Was this page useful?