Skip to content

MTO Validation Guide#

In this guide, we will set up two tenantsLogistics and Retail—for an imaginary e-commerce company, each with one user.

  • Falcon will be the user assigned to the Logistics tenant.
  • Bear will be the user assigned to the Retail tenant.

1. Create & Configure AWS IAM Users & Groups#

1.1. Create a user#

Create a user with username falcon@nordmart.com

$ aws iam create-user --user-name falcon@nordmart.com

Output:
{
    "User": {
        "Path": "/",
        "UserName": "falcon@nordmart.com",
        "UserId": "AIDAZFWZTAEJ7ILHDKLLD",
        "Arn": "arn:aws:iam::630742778131:user/falcon@nordmart.com",
        "CreateDate": "2025-02-03T13:09:51Z"
    }
}

1.2. Attach cluster access policy to user#

Create a AWS JSON policy file. This policy will allow the user to access the cluster.

{
    "Statement": [
        {
            "Action": "eks:DescribeCluster",
            "Effect": "Allow",
            "Resource": "*"
        }
    ],
    "Version": "2012-10-17"
}

Attach a policy to user by running the following command

aws iam put-user-policy --user-name falcon@nordmart.com --policy-document file://policy.json --policy-name ClusterAccess

1.3. Generate access key for the user#

Executing the following command will provide the Access Key Id and Access Secret Key Id that can be used to log in later

aws iam create-access-key --user-name "falcon@nordmart.com"

1.4. Grant user access to Kubernetes via ConfigMap#

Use the following command to map this user in aws-auth configmap in kube-system namespace.

eksctl create iamidentitymapping --cluster "<CLUSTER_NAME>" \
                                 --region "<AWS_REGION>" \
                                 --arn "<USER_ARN>" \
                                 --username "falcon@nordmart.com" \
                                 --no-duplicate-arns

Repeat the same steps to create another user bear@nordmart.com for retail tenant.

2. Create Keycloak user for MTO Console#

2.1. Create Keycloak User#

A Keycloak user with same username as IAM user needs to be created for MTO Console. In this section we will create a Keycloak user for Logistics tenant

Ensure that MTO Console is enabled by executing the following command

$ kubectl get integrationconfig tenant-operator-config -o=jsonpath='{.spec.components}' -n multi-tenant-operator
{"console":true,"showback":true}

List the ingresses to access the URL of MTO Console

kubectl get ingress -n multi-tenant-operator

NAME                       CLASS   HOSTS                                  ADDRESS                                                                          PORTS     AGE
tenant-operator-console    nginx   console.iinhdnh6.demo.kubeapp.cloud    ae51c179026a94c90952fc50d5d91b52-a4446376b6415dcb.elb.eu-north-1.amazonaws.com   80, 443   23m
tenant-operator-gateway    nginx   gateway.iinhdnh6.demo.kubeapp.cloud    ae51c179026a94c90952fc50d5d91b52-a4446376b6415dcb.elb.eu-north-1.amazonaws.com   80, 443   23m
tenant-operator-keycloak   nginx   keycloak.iinhdnh6.demo.kubeapp.cloud   ae51c179026a94c90952fc50d5d91b52-a4446376b6415dcb.elb.eu-north-1.amazonaws.com   80, 443   24m
  1. Navigate to Keycloak and Login using default credentials admin/admin

  2. Change the Realm from master to mto

  3. Navigate to Users and Click Add User

  4. Provide a username, this username must be same as IAM username falcon@nordmart.com in our case

    Create Falcon User

  5. Navigate to Credentials tab and set a password

    keycloak password

Repeat the same steps to create another user bear@nordmart.com

3. Create MTO Quota#

As cluster admin create a Quota CR with some resource limits:

kubectl apply -f - <<EOF
apiVersion: tenantoperator.stakater.com/v1beta1
kind: Quota
metadata:
  name: small
spec:
  limitrange:
    limits:
    - max:
        cpu: 800m
      min:
        cpu: 200m
      type: Container
  resourcequota:
    hard:
      configmaps: "10"
      memory: "8Gi"
EOF

4. Create MTO Tenants#

As cluster admin create 2 tenants logistics and retail with one user each:

kubectl apply -f - <<EOF
apiVersion: tenantoperator.stakater.com/v1beta3
kind: Tenant
metadata:
  name: logistics
spec:
  namespaces:
    withTenantPrefix:
    - dev
    - build
  accessControl:
    owners:
      users:
      - falcon@nordmart.com
  quota: small
EOF
kubectl apply -f - <<EOF
apiVersion: tenantoperator.stakater.com/v1beta3
kind: Tenant
metadata:
  name: retail
spec:
  namespaces:
    withTenantPrefix:
    - dev
    - build
  accessControl:
    owners:
      users:
      - bear@nordmart.com
  quota: small
EOF

Notice that the only difference in both tenant specs are the users.

5. List namespaces as cluster admin#

Listing the namespaces as cluster admin will show following namespaces:

$ kubectl get namespaces

NAME                    STATUS   AGE
cert-manager            Active   8d
default                 Active   9d
kube-node-lease         Active   9d
kube-public             Active   9d
kube-system             Active   9d
multi-tenant-operator   Active   8d
random                  Active   8d
logistics-dev           Active   5s
logistics-build         Active   5s
retail-dev              Active   5s
retail-build            Active   5s

6. Validate Falcon permissions#

6.1. Switch to falcon#

Set the following environment variables from the access keys generated in previous steps

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION (optional)

Execute the following command to update the kube context

aws configure set region $AWS_REGION
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY

aws eks update-kubeconfig --name <EKS_CLUSTER_NAME> --region $AWS_REGION

6.2. Check CLI permissions#

We will now try to deploy a pod from user falcon@nordmart.com in its tenant namespace logistics-dev

$ kubectl run nginx --image nginx -n logistics-dev

pod/nginx created

And if we try the same operation in the other tenant with the same user, it will fail

$ kubectl run nginx --image nginx -n retail-dev

Error from server (Forbidden): pods is forbidden: User "falcon@nordmart.com" cannot create resource "pods" in API group "" in the namespace "retail-dev"

To be noted, falcon@nordmart.com can not list namespaces

$ kubectl get namespaces

Error from server (Forbidden): namespaces is forbidden: User "falcon@nordmart.com" cannot list resource "namespaces" in API group "" at the cluster scope

6.3. Validate Console permissions#

Navigate to MTO Console URL and Log In with the Keycloak user credentials.

MTO Console Login Page

Dashboard will open after the successful login. Now you can navigate different tenants and namespaces using MTO Console

MTO Console Dashboard

7. Validate Bear permissions#

7.1. Switch to bear#

Set the following environment variables from the access keys generated in previous steps

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION (optional)

Execute the following command to update the kube context

aws configure set region $AWS_REGION
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY

aws eks update-kubeconfig --name <EKS_CLUSTER_NAME> --region $AWS_REGION

7.2. Check CLI permissions#

We will repeat the above operations for our retail user bear@nordmart.com as well

$ kubectl run nginx --image nginx -n retail-dev

pod/nginx created

Trying to do operations outside the scope of its own tenant will result in errors

$ kubectl run nginx --image nginx -n retail-dev

Error from server (Forbidden): pods is forbidden: User "bear@nordmart.com" cannot create resource "pods" in API group "" in the namespace "retail-dev"

To be noted, bear@nordmart.com can not list namespaces

$ kubectl get namespaces

Error from server (Forbidden): namespaces is forbidden: User "bear@nordmart.com" cannot list resource "namespaces" in API group "" at the cluster scope

7.3. Validate Console permissions#

Navigate to MTO Console URL and Log In with the Keycloak user credentials.

MTO Console Login Page

Dashboard will open after the successful login. Now you can navigate different tenants and namespaces using MTO Console

MTO Console Dashboard