The allure of AssumeRole lies in its ability to enhance security without sacrificing operational efficiency. To illustrate this point, here is a comprehensive tutorial on setting up the JFrog Registry Operator to leverage AssumeRole’s capabilities in AWS. This configuration ensures seamless integration between Amazon EKS and the JFrog Platform.
Our objective is to create an EKS environment with Kubernetes deployed in a step-by-step fashion, featuring Nginx pulled from the JFrog Platform.
The initial step is selecting the namespace where the operator will be deployed
Next, configure the service account name, which, in our case, is "jf-oper-sa"
The following step involves obtaining the OIDC Provider and Account ID:
Example:
To verify our command, execute the following:
Similarly, with the account ID:
The next step is creating the trust-relationship.json file. This file limits trust to a designated namespace and service account, ensuring that access to the relevant resources are given only as required.
Now the role can be applied:
Example:
Upon submission, the expected outcome should resemble the following:

The next step is creating an IAM Policy for Data Access first using the my-policy.json file.
This policy, with the specified details, grants permission to retrieve the caller's identity using the sts:GetCallerIdentity action on the resource identified by the IAM role's ARN. Additionally, under "Statement1," it allows the specified IAM role's details to be retrieved using the iam:GetRole action on the corresponding IAM role's ARN
my-policy.json
In cases where the ARN of the role is unknown, run the following:
Example:
Thel output includes the role details and ARN:
Now create the policy by running the following command:
Example:
Then attach the policy and the role using the provided command:
Example:
Optional step: By this point, it is important to validate that the updated roles and policies are reflected in the AWS console.


Now that the policy and role are attached to one another, it is necessary to Create OpenID Connect (OIDC) identity providers in AWS.
Therefore in the IAM Console under Access Management --> Identity providers
Click on “Add provider”
Select the “OpenID Connect” option at the top
Enter the value of $oidc_provider as the Provider URL and click on “Get thumbprint” in the type sts.amazonaws.com as in the following example:

Now, navigate to the JFrog platform to complete the circle of trust by assigning a user tothe IAM role. This ensures that all related operations are done on behalf of that user
Here are the steps:
Once that is complete, run the following curl:
Example:
Now validate the operation by running this GET request :
The final step involves installing the operator, enabling retrieval of Docker images directly from the JFrog platform without the need for managing secrets
Prior to executing the installer, it is essential to verify the presence of the following exported variables:
Example:
Export the annotation, a mandatory step for the installation, using the following format:
Example:
Ensure location of the JFrog Helm repository by executing the command:
And then run:
Upon successful completion, the following message should be displayed:

The creation in our namespace is clear, per below:

At this stage, the secret has not been created yet. A final action must still be taken to configure the secret rotator for its creation.
To accomplish this, create a secretrotator.yaml file with the pertinent information, such as the namespace and platform URL:
Apply the configuration using the following command:
Upon completion, the secretrotator pod should display the following logs, indicating a successful operation:

Execute the following command will confirm the creation of a secret:
Our objective is to create an EKS environment with Kubernetes deployed in a step-by-step fashion, featuring Nginx pulled from the JFrog Platform.
The initial step is selecting the namespace where the operator will be deployed
export NAMESPACE=jfrog-operator
Next, configure the service account name, which, in our case, is "jf-oper-sa"
export SERVICE_ACCOUNT_NAME=jf-oper-sa
The following step involves obtaining the OIDC Provider and Account ID:
oidc_provider=$(aws eks describe-cluster --name <Your EKS cluster name> --region <Your EKS region> --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
Example:
oidc_provider=$(aws eks describe-cluster --name devrel-cluster --region eu-central-1 --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
To verify our command, execute the following:
echo ${oidc_provider} Output: oidc.eks.eu-central-1.amazonaws.com/id/0C2D779F09A5788BXXXXXXXXX
Similarly, with the account ID:
account_id=$(aws sts get-caller-identity --query "Account" --output text) Validate: echo ${account_id} Output: 710936890000
The next step is creating the trust-relationship.json file. This file limits trust to a designated namespace and service account, ensuring that access to the relevant resources are given only as required.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<account id>:oidc-provider/<OIDC provider>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "<OIDC provider>:aud": "sts.amazonaws.com", "<OIDC provider>:sub": "system:serviceaccount:<namespace>:<service account>" } } } ] }
Now the role can be applied:
aws iam create-role --role-name <ROLE_NAME> --assume-role-policy-document file://trust-relationship.json --description "my-role-description" --max-session-duration <TOKEN_EXPIRATION_SECONDS>
Example:
aws iam create-role --role-name jfrole --assume-role-policy-document file://trust-relationship.json --description "my-role-description" --max-session-duration 14400
Upon submission, the expected outcome should resemble the following:
The next step is creating an IAM Policy for Data Access first using the my-policy.json file.
This policy, with the specified details, grants permission to retrieve the caller's identity using the sts:GetCallerIdentity action on the resource identified by the IAM role's ARN. Additionally, under "Statement1," it allows the specified IAM role's details to be retrieved using the iam:GetRole action on the corresponding IAM role's ARN
my-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:GetCallerIdentity", "Resource": "<ARN of the IAM role>" }, { "Sid": "Statement1", "Effect": "Allow", "Action": ["iam:GetRole"], "Resource": ["<ARN of the IAM role>"] } ] }
In cases where the ARN of the role is unknown, run the following:
aws iam get-role --role-name <ROLE_NAME>
Example:
aws iam get-role --role-name jfrole
Thel output includes the role details and ARN:
arn:aws:iam::<account_id>:role/<role_name>
Now create the policy by running the following command:
aws iam create-policy --policy-name <Desired-Policy-Name> --policy-document file://my-policy.json
Example:
aws iam create-policy --policy-name jf-policy --policy-document file://my-policy.json
Then attach the policy and the role using the provided command:
aws iam attach-role-policy --role-name <IAM role name> --policy- arn=arn:aws:iam::$account_id:policy/<policy name>
Example:
aws iam attach-role-policy --role-name jfrole --policy-arn=arn:aws:iam::$account_id:policy/jf-policy
Optional step: By this point, it is important to validate that the updated roles and policies are reflected in the AWS console.
Now that the policy and role are attached to one another, it is necessary to Create OpenID Connect (OIDC) identity providers in AWS.
Therefore in the IAM Console under Access Management --> Identity providers
Click on “Add provider”
Select the “OpenID Connect” option at the top
Enter the value of $oidc_provider as the Provider URL and click on “Get thumbprint” in the type sts.amazonaws.com as in the following example:
Now, navigate to the JFrog platform to complete the circle of trust by assigning a user tothe IAM role. This ensures that all related operations are done on behalf of that user
Here are the steps:
- Create a user with the desired permissions you intend to assign or select an existing user
- Generate an admin token based on the existing or newly created user.
Once that is complete, run the following curl:
curl -XPUT -H "Content-type: application/json" -H "Authorization: Bearer <Token>" https://<Platform-URL>/access/api/v1/aws/iam_role -d '{"username":"<Username>", "iam_role": "arn:aws:iam::<Account-ID>:role/<Role-Name>"}' -vv
Example:
curl -XPUT -H "Content-type: application/json" -H "Authorization: Bearer cmVmdGtuOjAxOjAwMDAwMDAwMDA6cGZlZklCZER3RFFDYVIzcktCVURoNmdwZFhR" https://myexampleplatform.jfrog.io/access/api/v1/aws/iam_role -d '{"username":"aws-user", "iam_role": "arn:aws:iam::710936890000:role/jfrole"}' -vv
Now validate the operation by running this GET request :
curl -H "Content-type: application/json" -H "Authorization: Bearer cmVmdGtuOjAxOjAwMDAwMDAwMDA6cGZlZklCZER3RFFDYVIzcktCVURoNmdwZFhR" https://myexampleplatform.jfrog.io/access/api/v1/aws/iam_role/aws-user -vv Response should include something like: { "username" : "aws-user", "iam_role" : "arn:aws:iam::710936890000:role/jfrole" }
The final step involves installing the operator, enabling retrieval of Docker images directly from the JFrog platform without the need for managing secrets
Prior to executing the installer, it is essential to verify the presence of the following exported variables:
echo $SERVICE_ACCOUNT_NAME (if empty, recreate it with the same name you did at the beginning of the process)
Example:
export SERVICE_ACCOUNT_NAME=jf-oper-sa
Export the annotation, a mandatory step for the installation, using the following format:
export ANNOTATIONS="eks.amazonaws.com/role-arn: arn:aws:iam::<account_number>:role/<role_name>"
Example:
export ANNOTATIONS="eks.amazonaws.com/role-arn: arn:aws:iam::710936890000:role/jfrole"
Ensure location of the JFrog Helm repository by executing the command:
helm repo add jfrog https://charts.jfrog.io
And then run:
helm upgrade --install secretrotator jfrog/jfrog-registry-operator --set "serviceAccount.name=${SERVICE_ACCOUNT_NAME}" --set "serviceAccount.annotations=${ANNOTATIONS}" --create-namespace -n ${NAMESPACE}
Upon successful completion, the following message should be displayed:
The creation in our namespace is clear, per below:
At this stage, the secret has not been created yet. A final action must still be taken to configure the secret rotator for its creation.
To accomplish this, create a secretrotator.yaml file with the pertinent information, such as the namespace and platform URL:
apiVersion: apps.jfrog.com/v1alpha1 kind: SecretRotator metadata: labels: app.kubernetes.io/name: secretrotators.apps.jfrog.com app.kubernetes.io/instance: secretrotator app.kubernetes.io/created-by: artifactory-secrets-rotator name: secretrotator spec: namespaceSelector: matchLabels: kubernetes.io/metadata.name: <target namespace> secretName: token-secret artifactoryUrl: <PLATFORM_URL> refreshTime: 30m secretMetadata: annotations: annotationKey: annotationValue labels: labelName: labelValueSpec:
secretName | required | The name of the kubernetes secret object that will be created by the Registry Operator |
namespaceSelector.matchLabels | required | If you wish to apply this to all namespaces, utilize {} for the namespaceSelector, otherwise set the targeted namespaces, or any other label, through common selector setup |
artifactoryUrl | required | The base URL of the host from which Docker images will be retrieved, and where token exchange will take place. if downloads are done from edges, then access federation should be used, or manual setup of the user and certificate on all the relevant edges |
refreshTime | optional | an optional attribute, which overrides the default calculation of refresh time (default is 75% of role max session duration, 'roleMaxSession') You can directly adjust the role max session duration refresh time through the AWS console by navigating to IAM > Roles > [Created Role]. |
secretMetadata.labels | optional | intended to be used to specify identifying attributes of objects that are meaningful and relevant to users |
secretMetadata.anottations | optional | for adding arbitrary metadata to objects (such as pods, services, nodes, and more) that are not used for identification or selection purposes |
Apply the configuration using the following command:
kubectl apply -f secretrotator.yaml -n ${NAMESPACE}
Upon completion, the secretrotator pod should display the following logs, indicating a successful operation:
Execute the following command will confirm the creation of a secret:
k get secrets -n <NAMESPACE> Output: NAME TYPE DATA AGE sh.helm.release.v1.secretrotator.v1 helm.sh/release.v1 1 4m56s token-secret kubernetes.io/dockerconfigjson 1 3m13sHaving completed these steps, you can now effortlessly retrieve images from your private Docker registry without the need to manage secrets. The integration of the JFrog Registry Operator and the secret rotation configuration streamlines the process and elevates the security of your containerized workflows on Amazon EKS.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: <target namesapce> spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: <artifactory_URL>/<DockerRepo-Name>/nginx:latest ports: - containerPort: 80 imagePullSecrets: - name: token-secret