<p>Hey im trying to cross account access for a role. <strong>i have 2 accounts: prod and non-prod</strong>.
and <strong>bucket in prod account</strong>, which im trying to write files to there from a non-prod role which is used as a service account in k8s cluster.</p>
<p><strong>in prod account i configured:</strong>
a role with the following policy(read write access to the bucket):</p>
<pre><code>{
&quot;Version&quot;: &quot;2012-10-17&quot;,
&quot;Statement&quot;: [
    {
        &quot;Sid&quot;: &quot;ListObjectsInBucket&quot;,
        &quot;Effect&quot;: &quot;Allow&quot;,
        &quot;Action&quot;: [
            &quot;s3:ListBucket&quot;
        ],
        &quot;Resource&quot;: [
            &quot;arn:aws:s3:::test2&quot;
        ]
    },
    {
        &quot;Sid&quot;: &quot;AllObjectActions&quot;,
        &quot;Effect&quot;: &quot;Allow&quot;,
        &quot;Action&quot;: &quot;s3:*Object&quot;,
        &quot;Resource&quot;: [
            &quot;arn:aws:s3:::test2/*&quot;
        ]
    }
]
</code></pre>
<p>}</p>
<p>and the following trust:</p>
<pre><code>{


&quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Principal&quot;: {
        &quot;AWS&quot;: &quot;arn:aws:iam::non-prod-AccountID:role/name-of-the-non-prod-role&quot;
      },
      &quot;Action&quot;: &quot;sts:AssumeRole&quot;,
      &quot;Condition&quot;: {}
    }
  ]
}
</code></pre>
<p><strong>in non prod i configured:</strong></p>
<p>a role with the following policy:</p>
<pre><code>   {
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Principal&quot;: {
        &quot;AWS&quot;: &quot;arn:aws:iam::prod-Account-ID:role/prod-role-name&quot;
      },
      &quot;Action&quot;: &quot;sts:AssumeRole&quot;,
      &quot;Condition&quot;: {}
    }
  ]
}
</code></pre>
<p>and trust as follows:</p>
<pre><code>{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Principal&quot;: {
        &quot;Federated&quot;: &quot;arn:aws:iam::non-prod-accountID:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111&quot;
      },
      &quot;Action&quot;: &quot;sts:AssumeRoleWithWebIdentity&quot;,
      &quot;Condition&quot;: {
        &quot;StringEquals&quot;: {
          &quot;oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111:sub&quot;: 
            &quot;system:serviceaccount:name-space:name-of-the-service-account&quot;
        }
      }
    }
  ]
}
</code></pre>
<p>serviceAccount annotation is:</p>
<pre><code>annotations: 
eks.amazonaws.com/role-arn: arn:aws:iam::non-prod-AccountID:role/non-prod-role-name
</code></pre>
<p>when running the command from inside the pod with the service account of the role in non-prod:</p>
<pre><code>aws s3 cp hello.txt s3://test2/hello.txt
</code></pre>
<p>im having:</p>
<pre><code>upload failed: ./hello.txt to s3://test2/hello.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
</code></pre>
<p>by the way the cluster is in another account (devops account) if its related, surely added OIDC provider identity to both non-prod and prod accounts as identity provider.</p>

<p>If you're getting the error <code>An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: No OpenIDConnect provider found in your account for $oidc_url</code> when trying to cross-account assume roles, but you can assume roles in your cluster account normally, here's some points:</p>
<p><strong>EKS ACCOUNT</strong></p>
<ol>
<li>Create a ServiceAccount</li>
</ol>
<pre><code>apiVersion: v1
kind: ServiceAccount
metadata:
  name: $sa_name
  namespace: $eks_ns
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::$resource_account_id:role/$role_name
</code></pre>
<ol start="2">
<li>Annotate your deployment</li>
</ol>
<pre><code>spec.template.spec:
  serviceAccountName: $sa_name
</code></pre>
<ol start="3">
<li>Get info about your cluster OIDC Provider</li>
</ol>
<pre><code>aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::$eks_cluster_account_id:oidc-provider/$oidc_provider
</code></pre>
<p>3.1. The output will be like:</p>
<pre><code>{
    &quot;Url&quot;: &quot;...&quot;,
    &quot;ClientIDList&quot;: [&quot;...&quot;],
    &quot;ThumbprintList&quot;: [&quot;...&quot;],
    &quot;CreateDate&quot;: &quot;...&quot;,
    &quot;Tags&quot;: [...]
}
</code></pre>
<p>3.2. Take note of the outputs (<em>Url</em> and <em>ThumbprintList</em> specially)</p>
<p><strong>RESOURCE ACCOUNT</strong></p>
<ol>
<li>Add the provider (if you don`t have it already), using the output from your cluster account</li>
</ol>
<pre><code>aws iam create-open-id-connect-provider --url $oidc_url --client-id-list sts.amazonaws.com --thumbprint-list $oidc_thumbprint
</code></pre>
<p>This should be enought to the mentioned error stop. If you now get <code>An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity</code>, you're problably using the <em>$eks_cluster_account_id</em> on Principal.Federated, instead of <em>$resource_account_id</em> created on the previous step. So, make sure you're using the ARN from the IP that is assigned to the resource account, not the cluster account.</p>
<ol start="2">
<li>Create a role and a policy to access your resources with following trusted entities policy:</li>
</ol>
<pre><code>{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Principal&quot;: {
                &quot;Federated&quot;: &quot;arn:aws:iam::$resource_account_id:oidc-provider/$oidc_provider&quot;
            },
            &quot;Action&quot;: &quot;sts:AssumeRoleWithWebIdentity&quot;
        }
    ]
}
</code></pre>
<p>Also, there's no need to have two roles. One is enough.</p>
