<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Flux – Integrations</title><link>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/</link><description>Recent content in Integrations on Flux</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/index.xml" rel="self" type="application/rss+xml"/><item><title>Flux: Amazon Web Services</title><link>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/aws/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/aws/</guid><description>
&lt;p>The Flux APIs integrate with the following Amazon Web Services (AWS) services:&lt;/p>
&lt;ul>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/ocirepositories/">OCIRepository&lt;/a> API with
&lt;a href="https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html" target="_blank">Amazon Elastic Container Registry (ECR)&lt;/a>
for pulling OCI artifacts into the cluster.&lt;/li>
&lt;li>The source-controller integrates the OCIRepository API with
&lt;a href="https://docs.aws.amazon.com/AmazonECR/latest/public/what-is-ecr.html" target="_blank">Amazon Public Elastic Container Registry (Public ECR)&lt;/a>
for pulling OCI artifacts into the cluster.&lt;/li>
&lt;li>The image-reflector-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagerepositories/">ImageRepository&lt;/a> and
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagepolicies/">ImagePolicy&lt;/a> APIs with ECR and public ECR for scanning tags and digests
of OCI artifacts and reflecting them into the cluster.&lt;/li>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/buckets/">Bucket&lt;/a> API with
&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html" target="_blank">Amazon Simple Storage Service (S3)&lt;/a>
for pulling manifests from buckets and packaging them as artifacts inside the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/kustomize/kustomizations/">Kustomization&lt;/a> API with
&lt;a href="https://docs.aws.amazon.com/kms/latest/developerguide/overview.html" target="_blank">Amazon Key Management Service (KMS)&lt;/a>
for decrypting SOPS-encrypted secrets when applying manifests in the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the Kustomization API with
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html" target="_blank">Amazon Elastic Kubernetes Service (EKS)&lt;/a>
for applying manifests in remote EKS clusters.&lt;/li>
&lt;li>The helm-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/helm/helmreleases/">HelmRelease&lt;/a> API with
EKS for applying Helm charts in remote EKS clusters.&lt;/li>
&lt;/ul>
&lt;p>The next sections briefly describe
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html" target="_blank">AWS IAM&lt;/a>, AWS&amp;rsquo;s identity and access management system, and how it can be used to grant Flux access
to resources offered by the services above. Bear in mind that AWS IAM has more features
than the ones described here. We describe only the features that are relevant for the
Flux integrations.&lt;/p>
&lt;h2 id="identity">Identity&lt;/h2>
&lt;p>For all the integrations with AWS, AWS will authenticate two types of identities for Flux:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html" target="_blank">IAM Roles&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html" target="_blank">IAM Users&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Each has its own methods of authentication. In particular, IAM Roles support
secret-less authentication, while IAM Users support secret-based authentication.
The former is more secure.&lt;/p>
&lt;p>For further understanding how to configure authentication for both types of
identities, refer to the
&lt;a href="#authentication">Authentication&lt;/a> section.&lt;/p>
&lt;h2 id="access-management">Access Management&lt;/h2>
&lt;p>Identities in AWS need &lt;em>permissions&lt;/em> to access resources from AWS services.
Those can be granted using
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html" target="_blank">permission policies&lt;/a>.
Policies group statements that allow specific actions to be performed on specific
resources of specific services. Each policy has a name and a globally unique
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html" target="_blank">Amazon Resource Name (ARN)&lt;/a>.
For example, the policy &lt;code>AmazonS3ReadOnlyAccess&lt;/code>, whose ARN is &lt;code>arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess&lt;/code>,
groups the following statements:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:Get*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:List*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:Describe*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3-object-lambda:Get*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3-object-lambda:List*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The structure of actions is usually &lt;code>&amp;lt;service&amp;gt;:&amp;lt;action&amp;gt;&lt;/code>.&lt;/p>
&lt;p>AWS has a large number of
&lt;a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/policy-list.html" target="_blank">AWS-managed policies&lt;/a>,
but users can also create
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies" target="_blank">customer-managed policies&lt;/a>
inside their AWS accounts.&lt;/p>
&lt;p>AWS supports also
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies" target="_blank">inline policies&lt;/a>.&lt;/p>
&lt;p>Managed and inline policies can be
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_id-based" target="_blank">attached to identities&lt;/a>,
which is a good strategy for when the identity and the resource are in the same AWS account.&lt;/p>
&lt;p>Only inline policies can be
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_resource-based" target="_blank">attached to resources&lt;/a>. This is required when the target resource is in a different
AWS account than the identity.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: As an exception, KMS does not support identity-based policies by default. To enable it, follow these
&lt;a href="https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-root-enable-iam" target="_blank">docs&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="granting-permissions">Granting permissions&lt;/h3>
&lt;p>When attaching permission policies to identities, a statement must enumerate the resources
it applies to. This can be done using ARNs, but it can also be done using
wildcards. For example, the &lt;code>AmazonS3ReadOnlyAccess&lt;/code> policy above uses the wildcard &lt;code>*&lt;/code>
to allow access to all S3 resources. This is not recommended, as it violates the
&lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">Least Privilege Principle&lt;/a>.
The recommended way of granting permissions to Flux is to use specific ARNs, for example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Sid&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;AllowReadObjects&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:GetObject&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:ListBucket&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:s3:::flux-bucket&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:s3:::flux-bucket/*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>When attaching (inline) permission policies to resources, a statement must enumerate also the identities
it applies to, through identity ARNs. For example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Sid&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;AllowReadObjects&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;AWS&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:user/some-user&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:role/some-role&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:GetObject&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:ListBucket&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:s3:::flux-bucket&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;arn:aws:s3:::flux-bucket/*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="via-aws-controllers-for-kubernetes-iam-custom-resources">Via AWS Controllers for Kubernetes IAM custom resources&lt;/h4>
&lt;p>To use
&lt;a href="https://aws-controllers-k8s.github.io/community/docs/community/overview/" target="_blank">AWS Controllers for Kubernetes (ACK)&lt;/a>
for creating permission policies, you can use the following custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/iam/v1alpha1/policy/" target="_blank">&lt;code>Policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Then to create IAM Roles and Users and attach the policies to them, you can use the following:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/iam/v1alpha1/role/" target="_blank">&lt;code>Role&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/iam/v1alpha1/user/" target="_blank">&lt;code>User&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For resource-based policies, see the
&lt;a href="#authorization">Authorization&lt;/a> section below for each
individual resource type that Flux integrates with.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: ACK is the most GitOps-friendly way of managing AWS
resources. With it you can even use Flux itself to deploy and continuously reconcile
your AWS custom resources (the Kubernetes ones), and ACK itself will
&lt;a href="https://aws-controllers-k8s.github.io/community/docs/user-docs/drift-recovery/" target="_blank">continuously reconcile&lt;/a>
the actual AWS resources.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-terraformopentofu-iam-resources">Via Terraform/OpenTofu IAM resources&lt;/h4>
&lt;p>To use Terraform/OpenTofu for creating permission policies, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy" target="_blank">&lt;code>aws_iam_policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Then to create IAM Roles and Users and attach the policies to them, you can use the following:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role" target="_blank">&lt;code>aws_iam_role&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user" target="_blank">&lt;code>aws_iam_user&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For resource-based policies, see the
&lt;a href="#authorization">Authorization&lt;/a> section below for each
individual resource type that Flux integrates with.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Terraform/OpenTofu is a great declarative way of managing AWS resources,
but it&amp;rsquo;s not as GitOps-friendly as ACK, as these tools do not prescribe
continuous reconciliation of the resources. There are alternatives to achieve that,
but they are not a core part of the tools.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-the-aws-cli">Via the &lt;code>aws&lt;/code> CLI&lt;/h4>
&lt;p>To use the &lt;code>aws&lt;/code> CLI for creating permission policies you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-policy.html" target="_blank">&lt;code>aws iam create-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Then to create IAM Roles and Users and attach the policies to them, you can use the following:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-role.html" target="_blank">&lt;code>aws iam create-role&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-user.html" target="_blank">&lt;code>aws iam create-user&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For resource-based policies, see the
&lt;a href="#authorization">Authorization&lt;/a> section below for each
individual resource type that Flux integrates with.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>aws&lt;/code> CLI is a great tool for experimenting with AWS resources and
their integrations with Flux, but it&amp;rsquo;s not a GitOps-friendly way of managing AWS
resources. If you need continuous reconciliation of the resources, prefer using
ACK or Terraform/OpenTofu.&lt;/p>
&lt;/blockquote>
&lt;h3 id="allowing-kubernetes-service-accounts-to-assume-iam-roles-trust-policies">Allowing Kubernetes Service Accounts to assume IAM Roles (Trust Policies)&lt;/h3>
&lt;p>For
&lt;a href="#with-eks-pod-identity">EKS Pod Identity&lt;/a> and
&lt;a href="#with-oidc-federation">OIDC Federation&lt;/a>,
the only supported identity type is IAM Roles. In both cases, an IAM Role must be configured
to allow a Kubernetes Service Account to assume it. This is done by adding a
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#term_trust-policy" target="_blank">Trust Policy&lt;/a>
to the IAM Role.&lt;/p>
&lt;p>Trust policies are similar in syntax to permission policies, but for each
of these two features the trust policy JSON document has particular requirements.
For EKS Pod Identity, see
&lt;a href="#for-eks-pod-identity">here&lt;/a>. For OIDC Federation, see
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>To create an IAM Role with a trust policy using ACK, you can use the following custom resource
(look for the &lt;code>spec.assumeRolePolicyDocument&lt;/code> field):&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/iam/v1alpha1/role/" target="_blank">&lt;code>Role&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create an IAM Role with a trust policy using Terraform/OpenTofu, you can use the following
resource (look for the &lt;code>assume_role_policy&lt;/code> argument):&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role" target="_blank">&lt;code>aws_iam_role&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To configure a trust policy for an IAM Role using the &lt;code>aws&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/update-assume-role-policy.html" target="_blank">&lt;code>aws iam update-assume-role-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="authorization">Authorization&lt;/h2>
&lt;p>In this section we describe the recommended IAM policy bindings for
enabling the Flux integrations with AWS services.&lt;/p>
&lt;h3 id="for-amazon-elastic-container-registry">For Amazon Elastic Container Registry&lt;/h3>
&lt;p>The &lt;code>OCIRepository&lt;/code>, &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> Flux APIs are integrated with
ECR. The &lt;code>OCIRepository&lt;/code> API can be used to pull OCI artifacts from ECR repositories
into the cluster, while the &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs
can be used to reflect tags and digests of such artifacts also inside the cluster.&lt;/p>
&lt;p>For single-tenant setups, the recommended AWS-managed policy containing the required
permissions for the &lt;code>OCIRepository&lt;/code>, &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEC2ContainerRegistryReadOnly.html" target="_blank">AmazonEC2ContainerRegistryReadOnly (&lt;code>arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>It can be attached to IAM Roles or Users.&lt;/p>
&lt;p>This policy grants read-only access to all resources (&lt;code>&amp;quot;Resource&amp;quot;: &amp;quot;*&amp;quot;&lt;/code>). Hence, for
multi-tenant setups, a better approach is attaching an inline policy to the ECR
repositories belonging to the tenant granting access to an IAM Role or User
with the following permissions:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;AWS&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:role/some-tenant-role&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:GetAuthorizationToken&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:BatchCheckLayerAvailability&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:GetDownloadUrlForLayer&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:GetRepositoryPolicy&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:DescribeRepositories&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:ListImages&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:DescribeImages&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:BatchGetImage&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:GetLifecyclePolicy&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:GetLifecyclePolicyPreview&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:ListTagsForResource&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;ecr:DescribeImageScanFindings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The ACK resource kind for creating an ECR repository and attaching an inline permission policy is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/ecr/v1alpha1/repository/" target="_blank">&lt;code>Repository&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu resource for attaching an inline permission policy to an ECR repository is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy" target="_blank">&lt;code>aws_ecr_repository_policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>aws&lt;/code> CLI command for attaching an inline permission policy to an ECR repository is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ecr/set-repository-policy.html" target="_blank">&lt;code>aws ecr set-repository-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-amazon-public-elastic-container-registry">For Amazon Public Elastic Container Registry&lt;/h3>
&lt;p>The &lt;code>OCIRepository&lt;/code>, &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> Flux APIs are integrated with
public ECR. The &lt;code>OCIRepository&lt;/code> API can be used to pull OCI artifacts from public ECR
repositories into the cluster, while the &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs
can be used to reflect tags and digests of such artifacts also inside the cluster.&lt;/p>
&lt;p>For public ECR, attaching the read-only AWS-managed policy suffices for any of the
Flux APIs:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonElasticContainerRegistryPublicReadOnly.html" target="_blank">AmazonElasticContainerRegistryPublicReadOnly (&lt;code>arn:aws:iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>It can be attached to IAM Roles or Users.&lt;/p>
&lt;h3 id="for-amazon-simple-storage-service">For Amazon Simple Storage Service&lt;/h3>
&lt;p>The &lt;code>Bucket&lt;/code> Flux API is integrated with S3. The &lt;code>Bucket&lt;/code> API
can be used to pull manifests from S3 buckets and package them as artifacts inside the cluster.&lt;/p>
&lt;p>For single-tenant setups, the recommended AWS-managed policy containing the required
permissions for the &lt;code>Bucket&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonS3ReadOnlyAccess.html" target="_blank">AmazonS3ReadOnlyAccess (&lt;code>arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>It can be attached to IAM Roles or Users.&lt;/p>
&lt;p>This policy grants read-only access to all resources (&lt;code>&amp;quot;Resource&amp;quot;: &amp;quot;*&amp;quot;&lt;/code>). Hence, for
multi-tenant setups, a better approach is attaching an inline policy to the S3
buckets belonging to the tenant granting access to an IAM Role or User
with the following permissions:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;AWS&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:role/some-tenant-role&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:Get*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:List*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3:Describe*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3-object-lambda:Get*&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;s3-object-lambda:List*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The ACK resource kind for creating an S3 bucket and attaching an inline permission policy is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/s3/v1alpha1/bucket/" target="_blank">&lt;code>Bucket&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu resource for attaching an inline permission policy to an S3 bucket is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy" target="_blank">&lt;code>aws_s3_bucket_policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>aws&lt;/code> CLI command for attaching an inline permission policy to an S3 bucket is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-policy.html" target="_blank">&lt;code>aws s3api put-bucket-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-amazon-key-management-service">For Amazon Key Management Service&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> Flux API is integrated with KMS.
The &lt;code>Kustomization&lt;/code> API is used to apply manifests in the cluster, and it can use KMS to
decrypt SOPS-encrypted secrets before applying them.&lt;/p>
&lt;p>As mentioned in the
&lt;a href="#access-management">Access Management&lt;/a> section, KMS does not support
identity-based policies by default, and it&amp;rsquo;s also part of this security strategy not to
offer AWS-managed policies for KMS.&lt;/p>
&lt;p>The recommended approach for granting an IAM Role or User access to a KMS key is to
attach an inline policy to the KMS key itself, granting access to the IAM Role or User
with the following permissions:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;AWS&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:role/some-tenant-role&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;kms:Decrypt&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;kms:DescribeKey&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A similar policy can be used to grant access to specific KMS keys to IAM Roles or Users
with a customer-managed policy.&lt;/p>
&lt;p>The ACK resource kind for creating a KMS key and attaching an inline permission policy is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/kms/v1alpha1/key/" target="_blank">&lt;code>Key&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu resource for attaching an inline permission policy to a KMS key is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key_policy" target="_blank">&lt;code>aws_kms_key_policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>aws&lt;/code> CLI command for attaching an inline permission policy to a KMS key is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/kms/put-key-policy.html" target="_blank">&lt;code>aws kms put-key-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-amazon-elastic-kubernetes-service">For Amazon Elastic Kubernetes Service&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> Flux APIs can use IAM Roles or Users for applying
and managing resources in remote EKS clusters. Two kinds of access must be configured
for this:&lt;/p>
&lt;ul>
&lt;li>The IAM Role or User must have permission to call the &lt;code>DescribeCluster&lt;/code> EKS API for
the target remote cluster. The Flux controllers need to call this API for retrieving
details required for connecting to the remote cluster, like the cluster&amp;rsquo;s API server
endpoint and certificate authority data. This is done by attaching a permission policy
to the IAM Role or User that allows the &lt;code>eks:DescribeCluster&lt;/code> action on the target
remote cluster.&lt;/li>
&lt;li>The IAM Role or User must have permissions inside the remote cluster to apply and manage
the target resources. For this, there must exist an
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/creating-access-entries.html" target="_blank">Access Entry&lt;/a>
that maps the IAM Role or User to a Kubernetes username and set of groups that will be used
for Kubernetes RBAC inside the remote cluster. Optionally, the Access Entry can also have
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html" target="_blank">Access Policies&lt;/a>,
which are predefined sets of Kubernetes permissions defined by EKS. The resulting set of
permissions granted to the IAM Role or User will be the union of: 1) the permissions granted by
the Access Policies; with 2) the permissions granted via Kubernetes RBAC through the username and
groups configured in the Access Entry, by referencing them in &lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code>
objects inside the cluster.&lt;/li>
&lt;/ul>
&lt;h4 id="permissions-for-the-eks-api">Permissions for the EKS API&lt;/h4>
&lt;p>The following permission policy can be used for granting access to the &lt;code>DescribeCluster&lt;/code>
EKS API for a target remote cluster:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;AWS&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::123456789012:role/some-tenant-role&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;eks:DescribeCluster&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:eks:us-east-1:123456789012:cluster/some-cluster&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It can be attached to IAM Roles or Users.&lt;/p>
&lt;p>EKS clusters do not support resource-based permission policies.&lt;/p>
&lt;h4 id="permissions-inside-the-remote-cluster">Permissions inside the remote cluster&lt;/h4>
&lt;p>The ACK resource kind for creating an EKS Access Entry with associated Access Policies is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/eks/v1alpha1/accessentry/" target="_blank">&lt;code>AccessEntry&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu resources for creating EKS Access Entries and Access Policies are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_entry" target="_blank">&lt;code>aws_eks_access_entry&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_policy_association" target="_blank">&lt;code>aws_eks_access_policy_association&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>aws&lt;/code> CLI command for creating EKS Access Entries and Access Policies are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/eks/create-access-entry.html" target="_blank">&lt;code>aws eks create-access-entry&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/eks/associate-access-policy.html" target="_blank">&lt;code>aws eks associate-access-policy&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For granting Kubernetes RBAC to the Kubernetes username and groups configured in the
Access Entry, simply create the corresponding &lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code>
objects inside the remote cluster.&lt;/p>
&lt;h2 id="authentication">Authentication&lt;/h2>
&lt;p>As mentioned in the
&lt;a href="#identity">Identity&lt;/a> section, AWS supports two types of
identities for Flux: IAM Roles and IAM Users.
This section describes how to authenticate each type of identity.
IAM Roles are the recommended way of authenticating to AWS services, as they
support secret-less authentication. IAM Users are not recommended, as they
require secret-based authentication, which is less secure.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Recommendation&lt;/strong>: Always prefer secret-less over secret-based authentication
if the alternative is available. Secrets can be stolen to abuse the permissions
granted to the identities they represent, and for public clouds like AWS this can
be done by simply having Internet access. This requires secrets to be regularly
rotated and more security controls to be put in place, like audit logs, secret
management tools, etc. Secret-less authentication does not have this problem, as
the identity is authenticated using a token that is not stored anywhere and is
only valid for a short period of time, usually one hour. It&amp;rsquo;s much harder to
steal an identity this way.&lt;/p>
&lt;/blockquote>
&lt;h3 id="with-eks-pod-identity">With EKS Pod Identity&lt;/h3>
&lt;p>
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html" target="_blank">EKS Pod Identity&lt;/a>
can be used to link the Kubernetes Service Account of a Flux controller to a single IAM
Role that will be used for all the AWS operations this Flux controller performs.
This EKS feature can only be used at the controller level.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Pod Identity is an EKS-only feature specifically targeting pods.
It&amp;rsquo;s not possible to support it at the object level, as for a Kubernetes Service
Account token to be accepted by Pod Identity it necessarily needs to be tied to a
pod that is configured to use this Kubernetes Service Account. This is a guarantee
that no Kubernetes controller can provide when issuing a token for a Service
Account configured in a custom resource object.&lt;/p>
&lt;/blockquote>
&lt;p>First, enable Pod Identity in the EKS cluster.&lt;/p>
&lt;p>In EKS Auto Mode, Pod Identity is always enabled, no cluster setup is required.
In standard EKS, follow these
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>Next, to
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html" target="_blank">link an IAM Role with a Kubernetes Service Account of a Flux controller in Pod Identity&lt;/a>,
the following steps are required:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Allow EKS Pod Identity to assume the IAM Role.&lt;/strong>
This is done by adding a trust policy like this to the IAM Role:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Sid&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;AllowEksAuthToAssumeRoleForPodIdentity&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Service&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;pods.eks.amazonaws.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;sts:AssumeRole&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;sts:TagSession&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To create/attach trust policies to IAM Roles, see
&lt;a href="#allowing-kubernetes-service-accounts-to-assume-iam-roles-trust-policies">this&lt;/a> section.&lt;/p>
&lt;ol start="2">
&lt;li>&lt;strong>Link the IAM Role to the Kubernetes Service Account in Pod Identity.&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>To perform this step using ACK, you can use the following custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/eks/v1alpha1/podidentityassociation/" target="_blank">&lt;code>PodIdentityAssociation&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To perform this step using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association" target="_blank">&lt;code>aws_eks_pod_identity_association&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To perform this step using the &lt;code>aws&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/eks/create-pod-identity-association.html" target="_blank">&lt;code>aws eks create-pod-identity-association&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>Restart (delete) the controller pod for the binding to take effect.&lt;/li>
&lt;/ol>
&lt;p>Finally, set the provider field of the Flux resources as described in the
&lt;a href="#at-the-controller-level">controller level&lt;/a> section.&lt;/p>
&lt;h3 id="with-oidc-federation">With OIDC Federation&lt;/h3>
&lt;p>
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html" target="_blank">OIDC Federation&lt;/a>
is an AWS feature that allows external identities to authenticate with AWS services
without the need for a per-identity static credential. This is done by exchanging
a short-lived token issued by the external identity provider (in this case,
Kubernetes) for short-lived AWS credentials. These credentials are then used
to authenticate with AWS services. OIDC Federation is supported only for IAM Roles.&lt;/p>
&lt;h4 id="supported-clusters">Supported clusters&lt;/h4>
&lt;p>AWS supports OIDC Federation for EKS clusters through a feature called
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html" target="_blank">IAM Roles for Service Accounts (IRSA)&lt;/a>,
and also for non-EKS clusters.&lt;/p>
&lt;p>In EKS clusters you need to create an OIDC Provider with the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/#source-cluster-setup">Issuer URL&lt;/a> of the cluster following these
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>In non-EKS clusters you need to create an OIDC Provider with the Issuer URL of the cluster following these
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>To create an OIDC Provider using ACK, you can use the following custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://aws-controllers-k8s.github.io/community/reference/iam/v1alpha1/openidconnectprovider/" target="_blank">&lt;code>OpenIDConnectProvider&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create an OIDC Provider using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider" target="_blank">&lt;code>aws_iam_openid_connect_provider&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>If using this Terraform/OpenTofu resource for EKS clusters, you can
fetch the Issuer URL of the cluster using this data source (look for
the &lt;code>identity.oidc.issuer&lt;/code> attribute):&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster" target="_blank">&lt;code>aws_eks_cluster&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create an OIDC Provider using the &lt;code>aws&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-open-id-connect-provider.html" target="_blank">&lt;code>aws iam create-open-id-connect-provider&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="supported-identity-types">Supported identity types&lt;/h4>
&lt;p>As mentioned before, the only identity type supported by OIDC Federation is IAM Roles.&lt;/p>
&lt;p>Flux acquires the permission policies granted to an IAM Role by using a Kubernetes
Service Account to &lt;em>assume&lt;/em> this IAM Role. We call this process &lt;em>impersonation&lt;/em>.
To configure a Kubernetes Service Account to assume an IAM Role, two steps
are required:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Allow the Kubernetes Service Account to assume the IAM Role.&lt;/strong>
This is done by adding a
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html#_create_and_associate_role_cli" target="_blank">trust policy&lt;/a>
to the IAM Role that allows the Kubernetes Service Account to assume it.&lt;/li>
&lt;/ol>
&lt;p>An IAM Role trust policy for OIDC federation with a Kubernetes cluster looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2012-10-17&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Statement&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Federated&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;arn:aws:iam::ACCOUNT_ID:oidc-provider/ISSUER_URL_WITHOUT_SCHEME&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Action&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;sts:AssumeRoleWithWebIdentity&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;Condition&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;StringEquals&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;ISSUER_URL_WITHOUT_SCHEME:aud&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;sts.amazonaws.com&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;ISSUER_URL_WITHOUT_SCHEME:sub&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;system:serviceaccount:KSA_NAMESPACE:KSA_NAME&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See
&lt;a href="#allowing-kubernetes-service-accounts-to-assume-iam-roles-trust-policies">here&lt;/a> how to
create/attach trust policies to IAM Roles.&lt;/p>
&lt;ol start="2">
&lt;li>&lt;strong>Annotate the Kubernetes Service Account with the IAM Role ARN.&lt;/strong>
This is done by adding the annotation
&lt;code>eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME&lt;/code>
to the Kubernetes Service Account:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KSA_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">eks.amazonaws.com/role-arn&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Configuring Flux to use a Kubernetes Service Account to authenticate with
AWS can be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="with-iam-user-access-keys">With IAM User Access Keys&lt;/h3>
&lt;p>All AWS integrations except for ECR and public ECR support configuring
authentication through an IAM User Access Key.&lt;/p>
&lt;p>IAM Users support static credentials that can be used to get access to AWS services called
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html" target="_blank">Access Keys&lt;/a>.
An Access Key consists of an &lt;em>Access Key ID&lt;/em> and a &lt;em>Secret Access Key&lt;/em>. The Access Key ID is
a public identifier for the Access Key, while the Secret Access Key is a secret used to
sign requests to AWS services that have a short validity period.&lt;/p>
&lt;p>ACK does not support creating Access Keys for IAM Users (see
&lt;a href="https://github.com/aws-controllers-k8s/community/issues/1879" target="_blank">issue&lt;/a>).&lt;/p>
&lt;p>To create an Access Key for an IAM User using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key" target="_blank">&lt;code>aws_iam_access_key&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create an Access Key for an IAM User using the &lt;code>aws&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-access-key.html" target="_blank">&lt;code>aws iam create-access-key&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Configuring Flux to use an IAM User Access Key can be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="at-the-object-level">At the object level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the object level.
This allows users to adhere to the
&lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">Least Privilege Principle&lt;/a>,
as each Flux resource can be configured with its own identity and therefore its own
permissions. This is useful for multi-tenancy scenarios, where different
teams can use the same cluster but need to be isolated from each other
inside their own namespaces.&lt;/p>
&lt;h4 id="for-oidc-federation">For OIDC Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>For configuring authentication through a Kubernetes Service Account
at the object level the following steps are required:&lt;/p>
&lt;ol>
&lt;li>Enable the feature gate &lt;code>ObjectLevelWorkloadIdentity&lt;/code> in the target Flux controller Deployment
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>(some-controller)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/args/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: --feature-gates=ObjectLevelWorkloadIdentity=true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>Set the &lt;code>.spec.provider&lt;/code> field to &lt;code>aws&lt;/code> in the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, this field is not
required/does not exist, SOPS detects the provider from the metadata
in the SOPS-encrypted Secret. For remote cluster access with the
&lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is &lt;code>.data.provider&lt;/code>
inside the referenced &lt;code>ConfigMap&lt;/code> from &lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;li>Use the &lt;code>.spec.serviceAccountName&lt;/code> field to specify the name of the
Kubernetes Service Account in the same namespace as the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, the field is
&lt;code>.spec.decryption.serviceAccountName&lt;/code>. For remote cluster access with
the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is
&lt;code>.data.serviceAccountName&lt;/code> inside the referenced &lt;code>ConfigMap&lt;/code> from
&lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>eks.amazonaws.com/role-arn&lt;/code> annotation is defined by EKS,
but Flux also uses it to identify the IAM Role to assume in non-EKS clusters.
This is for providing users with a seamless experience.&lt;/p>
&lt;/blockquote>
&lt;h4 id="for-iam-user-access-keys">For IAM User Access Keys&lt;/h4>
&lt;p>Only the S3 and KMS integrations support configuring authentication
through an IAM User Access Key at the object level.&lt;/p>
&lt;p>For configuring authentication through an IAM User Access Key, the
&lt;code>.spec.secretRef.name&lt;/code> field must be set to the name of the Kubernetes
Secret in the same namespace as the Flux resource containing the IAM
User Access Key. In the case of the &lt;code>Kustomization&lt;/code> API, the field
is &lt;code>.spec.decryption.secretRef.name&lt;/code>.&lt;/p>
&lt;p>The provider field and the key inside the &lt;code>.data&lt;/code> field of the Secret
depend on the specific Flux API:&lt;/p>
&lt;ul>
&lt;li>For the &lt;code>Bucket&lt;/code> API the &lt;code>.spec.provider&lt;/code> field must be set to &lt;code>aws&lt;/code>,
and the keys inside the &lt;code>.data&lt;/code> field of the Secret must be
&lt;code>accesskey&lt;/code> and &lt;code>secretkey&lt;/code>.&lt;/li>
&lt;li>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, there&amp;rsquo;s no provider field
as SOPS detects the provider from the metadata in the SOPS-encrypted Secret.
The key inside the &lt;code>.data&lt;/code> field of the Secret must be &lt;code>sops.aws-kms&lt;/code> and the
value should look like this:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SECRET_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">data&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">sops.aws-kms&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> aws_access_key_id: some-access-key-id
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> aws_secret_access_key: some-aws-secret-access-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> aws_session_token: some-aws-session-token # this field is optional&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="at-the-controller-level">At the controller level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the controller level.
This is more appropriate for single-tenant scenarios, where all the Flux resources
inside the cluster belong to the same team and hence can share the same identity
and permissions.&lt;/p>
&lt;p>At the controller level, regardless if authenticating with EKS Pod Identity,
OIDC Federation or IAM User Access Keys, all Flux resources must have the
provider field set to &lt;code>aws&lt;/code> according to the rules below.&lt;/p>
&lt;p>For all Flux resource kinds except for &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code>, set
the &lt;code>.spec.provider&lt;/code> field to &lt;code>aws&lt;/code> and leave &lt;code>.spec.serviceAccountName&lt;/code> unset.&lt;/p>
&lt;p>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, leave the
&lt;code>.spec.decryption.serviceAccountName&lt;/code> field unset. There&amp;rsquo;s
no provider field for SOPS decryption.&lt;/p>
&lt;p>For remote cluster access with the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs,
set the &lt;code>.data.provider&lt;/code> field of the &lt;code>ConfigMap&lt;/code> referenced by the
&lt;code>.spec.kubeConfig.configMapRef&lt;/code> field to &lt;code>aws&lt;/code> and leave the
&lt;code>.data.serviceAccountName&lt;/code> field unset.&lt;/p>
&lt;p>The controller-level configuration is described in the following sections.&lt;/p>
&lt;h4 id="for-oidc-federation-1">For OIDC Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>If the cluster is EKS, the Kubernetes Service Account of the controller must
be configured to assume an IAM Role. This is done by adding the
&lt;code>eks.amazonaws.com/role-arn&lt;/code> annotation to the controller Service Account
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> apiVersion: v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> kind: ServiceAccount
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: controller
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> annotations:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the configuration above is done after bootstrap, restart (delete) the controller
for the binding to take effect.&lt;/p>
&lt;p>If the cluster &lt;em>is not&lt;/em> EKS, the controller Deployment must be patched
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>A projected volume must be mounted in the controller Deployment with a Kubernetes
Service Account token whose audience is set to &lt;code>sts.amazonaws.com&lt;/code>.&lt;/li>
&lt;li>The environment variables required by the
&lt;a href="https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html" target="_blank">AWS Go SDK v2&lt;/a>
to authenticate through OIDC Federation must be set in the controller Deployment.
See an exhaustive list of the environment variables
&lt;a href="https://github.com/aws/aws-sdk-go-v2/blob/main/config/env_config.go" target="_blank">here&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>The controller patch should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_REGION
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: AWS_REGION # This is the region of the AWS STS endpoint.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_ROLE_ARN
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_ROLE_SESSION_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: some-controller.flux-system.AWS_REGION.fluxcd.io
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_WEB_IDENTITY_TOKEN_FILE
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: /var/run/service-account/aws-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: aws-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> projected:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> sources:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - serviceAccountToken:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> audience: sts.amazonaws.com
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> expirationSeconds: 3600
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: aws-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: aws-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /var/run/service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="for-iam-user-access-keys-1">For IAM User Access Keys&lt;/h4>
&lt;p>Mount the Kubernetes Secret containing the IAM User Access Key and Secret
as the environment variables &lt;code>AWS_ACCESS_KEY_ID&lt;/code> and &lt;code>AWS_SECRET_ACCESS_KEY&lt;/code>
in the controller Deployment
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_ACCESS_KEY_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> valueFrom:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secretKeyRef:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: some-controller-aws-access-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> key: accesskey
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AWS_SECRET_ACCESS_KEY
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> valueFrom:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secretKeyRef:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: some-controller-aws-access-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> key: secretkey&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Secret should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-controller-aws-access-key&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>flux-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">stringData&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">accesskey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-access-key-id&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">secretkey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-aws-secret-access-key&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="at-the-node-level">At the node level&lt;/h3>
&lt;p>Only for the ECR integrations Flux supports authentication
at the node level for EKS. This is because users often already have to configure
authentication at the node level for EKS to be able to pull container images from
ECR in order to start pods. By supporting this authentication method Flux allows
users to configure ECR authentication in a single way. See how to
&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html#create-worker-node-role" target="_blank">create IAM Roles for EKS worker nodes&lt;/a>
and how to
&lt;a href="https://docs.aws.amazon.com/AmazonECR/latest/userguide/ECR_on_EKS.html" target="_blank">allow them to pull images from ECR&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; Node level authentication may work for other integrations as well,
but Flux only has continuous integration tests for the ECR integration in
order to support the specific use case described above.&lt;/p>
&lt;/blockquote>
&lt;p>For node-level authentication to work, the &lt;code>.spec.provider&lt;/code> field of the Flux
resources must be set to &lt;code>aws&lt;/code>.&lt;/p></description></item><item><title>Flux: Google Cloud Platform</title><link>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/gcp/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/gcp/</guid><description>
&lt;p>The Flux APIs integrate with the following Google Cloud Platform (GCP) services:&lt;/p>
&lt;ul>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/ocirepositories/">OCIRepository&lt;/a> API with
&lt;a href="https://cloud.google.com/artifact-registry/docs/overview" target="_blank">Google Cloud Artifact Registry (GAR)&lt;/a>
for pulling OCI artifacts into the cluster.&lt;/li>
&lt;li>The image-reflector-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagerepositories/">ImageRepository&lt;/a> and
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagepolicies/">ImagePolicy&lt;/a> APIs with GAR for scanning tags and digests of OCI artifacts
and reflecting them into the cluster.&lt;/li>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/buckets/">Bucket&lt;/a> API with
&lt;a href="https://cloud.google.com/storage/docs/introduction" target="_blank">Google Cloud Storage (GCS)&lt;/a>
for pulling manifests from buckets and packaging them as artifacts inside the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/kustomize/kustomizations/">Kustomization&lt;/a> API with
&lt;a href="https://cloud.google.com/kms/docs/key-management-service" target="_blank">Google Cloud Key Management Service (KMS)&lt;/a>
for decrypting SOPS-encrypted secrets when applying manifests in the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the Kustomization API with
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview" target="_blank">Google Kubernetes Engine (GKE)&lt;/a>
for applying manifests in remote GKE clusters.&lt;/li>
&lt;li>The helm-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/helm/helmreleases/">HelmRelease&lt;/a> API with
GKE for applying Helm charts in remote GKE clusters.&lt;/li>
&lt;li>The notification-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/notification/providers/">Provider&lt;/a> API with
&lt;a href="https://cloud.google.com/pubsub/docs/overview" target="_blank">Google Cloud Pub/Sub&lt;/a>
for sending notifications about Flux resources outside the cluster.&lt;/li>
&lt;/ul>
&lt;p>The next sections briefly describe
&lt;a href="https://cloud.google.com/iam/docs/overview" target="_blank">GCP IAM&lt;/a>,
GCP&amp;rsquo;s identity and access management system, and how it can be used to grant Flux access
to resources offered by the services above. Bear in mind that GCP IAM has more features
than the ones described here. We describe only the features that are relevant for the
Flux integrations.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Flux also supports Google Chat webhooks, but Google Chat webhooks do
not support GCP IAM. For more information about the notification-controller
integration with Google Chat, see the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/notification/providers/">Provider&lt;/a> API docs.&lt;/p>
&lt;/blockquote>
&lt;h2 id="identity">Identity&lt;/h2>
&lt;p>For all the integrations with GCP, GCP will authenticate two types of identities for Flux:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/service-account-overview" target="_blank">GCP Service Accounts&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://kubernetes.io/docs/concepts/security/service-accounts/" target="_blank">Kubernetes Service Accounts&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Each has its own methods of authentication. In particular, GCP Service Accounts
support both secret-based and secret-less authentication. Kubernetes Service
Accounts support only secret-less authentication. The latter is more secure and
easier to configure, but has a few limitations (a small number of GCP services
and edge cases do not have support for it, see the list
&lt;a href="https://cloud.google.com/iam/docs/federated-identity-supported-services#list" target="_blank">here&lt;/a>).&lt;/p>
&lt;p>For further understanding how to configure authentication for both types of
identities, refer to the
&lt;a href="#authentication">Authentication&lt;/a> section.&lt;/p>
&lt;h2 id="access-management">Access Management&lt;/h2>
&lt;p>Identities in GCP need
&lt;a href="https://cloud.google.com/iam/docs/overview#permissions" target="_blank">permissions&lt;/a>
to access resources from GCP services. Permissions cannot be granted directly to identities.
Instead, GCP uses
&lt;a href="https://cloud.google.com/iam/docs/overview#permissions" target="_blank">roles&lt;/a> to group
permissions, and only roles can be granted to identities. Each role has a title and a globally
unique ID. For example, the role &lt;code>Storage Object Viewer&lt;/code>, whose ID is &lt;code>roles/storage.objectViewer&lt;/code>,
groups the following permissions (most omitted for brevity):&lt;/p>
&lt;ul>
&lt;li>&lt;code>storage.objects.get&lt;/code>&lt;/li>
&lt;li>&lt;code>storage.objects.list&lt;/code>&lt;/li>
&lt;li>&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>The structure of permissions is usually &lt;code>&amp;lt;service&amp;gt;.&amp;lt;resource type&amp;gt;.&amp;lt;action&amp;gt;&lt;/code>.&lt;/p>
&lt;p>GCP has a large number of
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions" target="_blank">predefined roles&lt;/a>,
but users can also create
&lt;a href="https://cloud.google.com/iam/docs/creating-custom-roles" target="_blank">custom roles&lt;/a>
inside their GCP projects.&lt;/p>
&lt;p>For an identity to be allowed to perform an action on a resource, the identity
needs to be granted, &lt;em>on that resource&lt;/em>, a role that contains the permission
required for that action. The role needs to be granted directly on the resource,
or on a parent resource in the
&lt;a href="https://cloud.google.com/iam/docs/overview#policy-inheritance" target="_blank">resource hierarchy&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>&lt;em>Resource&lt;/em>&lt;/li>
&lt;li>&lt;em>Project&lt;/em> (set of resources)&lt;/li>
&lt;li>&lt;em>Folder&lt;/em> (set of projects)&lt;/li>
&lt;li>&lt;em>Organization&lt;/em> (set of folders)&lt;/li>
&lt;/ul>
&lt;p>If the role is granted on a parent resource, the relationship will be inherited
by all the descendants. For example, if a role is granted on a folder, all the
projects and resources inside that folder will inherit the grant.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Reminder&lt;/strong>: The grant relationship has &lt;em>three&lt;/em> involved entities:&lt;/p>
&lt;ul>
&lt;li>The identity that will use the permissions to perform actions.&lt;/li>
&lt;li>The resource that will be the target of the actions.&lt;/li>
&lt;li>The role containing the permissions required for the actions.&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;h3 id="granting-permissions">Granting permissions&lt;/h3>
&lt;p>When granting roles, GCP IAM uses the term
&lt;a href="https://cloud.google.com/iam/docs/overview#principals" target="_blank">Principal&lt;/a>, formerly
&lt;em>Member&lt;/em>, to refer to the string that globally identifies the identity which
will receive the grant.&lt;/p>
&lt;h4 id="to-gcp-service-accounts">To GCP Service Accounts&lt;/h4>
&lt;p>The IAM Principal for a GCP Service Account is the email address of the Service
Account prefixed with &lt;code>serviceAccount:&lt;/code>:&lt;/p>
&lt;pre tabindex="0">&lt;code>serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com
&lt;/code>&lt;/pre>&lt;h4 id="to-kubernetes-service-accounts">To Kubernetes Service Accounts&lt;/h4>
&lt;p>The IAM Principal for a Kubernetes Service Account from a &lt;em>GKE cluster&lt;/em> has the
following format:&lt;/p>
&lt;pre tabindex="0">&lt;code>serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
&lt;/code>&lt;/pre>&lt;p>Flux running inside non-GKE Kubernetes clusters (e.g. EKS, AKS, &lt;code>kind&lt;/code> running locally
or in CI, etc.) can also get access to GCP resources. For Service Accounts from such
clusters, the IAM Principal has the following format:&lt;/p>
&lt;pre tabindex="0">&lt;code>principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/system:serviceaccount:NAMESPACE:KSA_NAME
&lt;/code>&lt;/pre>&lt;p>Where the portion &lt;code>projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID&lt;/code>
globally identifies the
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation#pools" target="_blank">Workload Identity Pool&lt;/a>
configured for the non-GKE cluster.&lt;/p>
&lt;p>See more details about how this works in the GCP docs
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes" target="_blank">Workload Identity Federation with Kubernetes&lt;/a> and how to configure this
for Flux in the
&lt;a href="#with-workload-identity-federation">Workload Identity Federation&lt;/a> section.&lt;/p>
&lt;h4 id="via-config-connector-iam-custom-resources">Via Config Connector IAM custom resources&lt;/h4>
&lt;p>To use
&lt;a href="https://cloud.google.com/config-connector/docs/overview" target="_blank">Config Connector&lt;/a> for
granting roles you can use one of the following custom resources:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicy" target="_blank">&lt;code>IAMPolicy&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampartialpolicy" target="_blank">&lt;code>IAMPartialPolicy&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember" target="_blank">&lt;code>IAMPolicyMember&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>All of them support both the &lt;code>Organization&lt;/code>, &lt;code>Folder&lt;/code> and &lt;code>Project&lt;/code> high-level hierarchical
resource kinds, and the kinds for all the individual resource types that Flux integrates with.
For the individual resource types, see the
&lt;a href="#authorization">Authorization&lt;/a> section below.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Config Connector is the most GitOps-friendly way of managing GCP
resources. With it you can even use Flux itself to deploy and continuously reconcile
your GCP custom resources (the Kubernetes ones), and Config Connector itself will
&lt;a href="https://cloud.google.com/config-connector/docs/concepts/reconciliation" target="_blank">continuously reconcile&lt;/a>
the actual GCP resources.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-terraformopentofu-iam-resources">Via Terraform/OpenTofu IAM resources&lt;/h4>
&lt;p>To use Terraform/OpenTofu for granting roles you can use one of the following resources:&lt;/p>
&lt;ul>
&lt;li>&lt;code>google_&amp;lt;resource type&amp;gt;_iam_policy&lt;/code>&lt;/li>
&lt;li>&lt;code>google_&amp;lt;resource type&amp;gt;_iam_binding&lt;/code>&lt;/li>
&lt;li>&lt;code>google_&amp;lt;resource type&amp;gt;_iam_member&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>See the docs for the high-level hierarchical resources:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam" target="_blank">&lt;code>organization&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_folder_iam" target="_blank">&lt;code>folder&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam" target="_blank">&lt;code>project&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For the Terraform/OpenTofu resources for the individual resource types that Flux integrates with,
see the
&lt;a href="#authorization">Authorization&lt;/a> section below.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Terraform/OpenTofu is a great declarative way of managing GCP resources,
but it&amp;rsquo;s not as GitOps-friendly as Config Connector, as these tools do not prescribe
continuous reconciliation of the resources. There are alternatives to achieve that,
but they are not a core part of the tools.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-the-gcloud-cli">Via the &lt;code>gcloud&lt;/code> CLI&lt;/h4>
&lt;p>To use the &lt;code>gcloud&lt;/code> CLI for granting roles you can use one of the following commands:&lt;/p>
&lt;ul>
&lt;li>&lt;code>gcloud &amp;lt;resource type command&amp;gt; set-iam-policy&lt;/code>&lt;/li>
&lt;li>&lt;code>gcloud &amp;lt;resource type command&amp;gt; add-iam-policy-binding&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>See the docs for the high-level hierarchical resource commands:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/organizations" target="_blank">&lt;code>organizations&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/resource-manager/folders" target="_blank">&lt;code>resource-manager folders&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/projects" target="_blank">&lt;code>projects&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For the &lt;code>gcloud&lt;/code> commands for the individual resource types that Flux integrates with,
see the
&lt;a href="#authorization">Authorization&lt;/a> section below.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>gcloud&lt;/code> CLI is a great tool for experimenting with GCP resources and
their integrations with Flux, but it&amp;rsquo;s not a GitOps-friendly way of managing GCP
resources. If you need continuous reconciliation of the resources, prefer using
Config Connector or Terraform/OpenTofu.&lt;/p>
&lt;/blockquote>
&lt;h2 id="authorization">Authorization&lt;/h2>
&lt;p>In this section we describe the recommended roles and permissions for
enabling the Flux integrations with GCP services.&lt;/p>
&lt;h3 id="for-google-cloud-artifact-registry">For Google Cloud Artifact Registry&lt;/h3>
&lt;p>The &lt;code>OCIRepository&lt;/code>, &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> Flux APIs are integrated with
GAR. The &lt;code>OCIRepository&lt;/code> API can be used to pull OCI artifacts from GAR repositories
into the cluster, while the &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs
can be used to reflect tags and digests of such artifacts also inside the cluster.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>OCIRepository&lt;/code>,
&lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/artifactregistry#artifactregistry.reader" target="_blank">Artifact Registry Reader (&lt;code>roles/artifactregistry.reader&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Config Connector resource kinds for use with the IAM custom resources are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/artifactregistry/artifactregistryrepository" target="_blank">&lt;code>ArtifactRegistryRepository&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu IAM resource types are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/artifact_registry_repository_iam" target="_blank">&lt;code>artifact_registry_repository&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The commands for the &lt;code>gcloud&lt;/code> CLI are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/artifacts/repositories" target="_blank">&lt;code>artifacts repositories&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-google-cloud-storage">For Google Cloud Storage&lt;/h3>
&lt;p>The &lt;code>Bucket&lt;/code> Flux API is integrated with GCS. The &lt;code>Bucket&lt;/code> API can be used
to pull manifests from GCS buckets and package them as artifacts inside the cluster.&lt;/p>
&lt;p>The recommended roles containing the required permissions for the &lt;code>Bucket&lt;/code> API are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/storage#storage.bucketViewer" target="_blank">Storage Bucket Viewer (&lt;code>roles/storage.bucketViewer&lt;/code>)&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/storage#storage.objectViewer" target="_blank">Storage Object Viewer (&lt;code>roles/storage.objectViewer&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>In the specific case of the &lt;code>Bucket&lt;/code> API, both roles are needed because Flux needs to
confirm the existence of the bucket. If the bucket does not exist Flux can error out
earlier in the reconciliation process and give an error message that is easier to debug.&lt;/p>
&lt;p>Alternatively, you can create a
&lt;a href="https://cloud.google.com/iam/docs/creating-custom-roles" target="_blank">custom role&lt;/a>
containing the following permissions:&lt;/p>
&lt;ul>
&lt;li>&lt;code>storage.buckets.get&lt;/code>&lt;/li>
&lt;li>&lt;code>storage.objects.get&lt;/code>&lt;/li>
&lt;li>&lt;code>storage.objects.list&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>The Config Connector resource kinds for use with the IAM custom resources are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/storage/storagebucket" target="_blank">&lt;code>StorageBucket&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu IAM resource types are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam" target="_blank">&lt;code>storage_bucket&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The commands for the &lt;code>gcloud&lt;/code> CLI are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/storage/buckets" target="_blank">&lt;code>storage buckets&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-google-cloud-key-management-service">For Google Cloud Key Management Service&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> Flux API is integrated with KMS.
The &lt;code>Kustomization&lt;/code> API is used to apply manifests in the cluster, and it can use KMS to
decrypt SOPS-encrypted secrets before applying them.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>Kustomization&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/cloudkms#cloudkms.cryptoKeyDecrypter" target="_blank">Cloud KMS CryptoKey Decrypter (&lt;code>roles/cloudkms.cryptoKeyDecrypter&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>This role can be granted either on a Key Ring (a set of keys), or on an individual Crypto Key.&lt;/p>
&lt;p>The Config Connector resource kinds for use with the IAM custom resources are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/kms/kmskeyring" target="_blank">&lt;code>KMSKeyRing&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/kms/kmscryptokey" target="_blank">&lt;code>KMSCryptoKey&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu IAM resource types are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_kms_key_ring_iam" target="_blank">&lt;code>kms_key_ring&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_kms_crypto_key_iam" target="_blank">&lt;code>kms_crypto_key&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The commands for the &lt;code>gcloud&lt;/code> CLI are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/kms/keyrings" target="_blank">&lt;code>kms keyrings&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/kms/keys" target="_blank">&lt;code>kms keys&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="for-google-kubernetes-engine">For Google Kubernetes Engine&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> Flux APIs can use
&lt;a href="#granting-permissions">IAM Principals&lt;/a>
for applying and managing resources in remote GKE clusters. Two kinds of access must be configured
for this:&lt;/p>
&lt;ul>
&lt;li>The IAM Principal must have permission to call the &lt;code>GetCluster&lt;/code> GKE API for the target
remote cluster. The Flux controllers need to call this API for retrieving details required
for connecting to the remote cluster, like the cluster&amp;rsquo;s API server endpoint and certificate
authority data. This is done by granting an IAM role to the IAM Principal that allows
this action on the target remote cluster.&lt;/li>
&lt;li>The IAM Principal must have permissions inside the remote cluster to apply and manage the target
resources. There are two ways of granting these permissions: via Kubernetes RBAC, or via IAM roles.
The former means simply referencing the IAM Principal in &lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code>
objects inside the remote cluster as the Kubernetes username. The latter means granting
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-interaction" target="_blank">IAM roles&lt;/a>
that grant Kubernetes permissions to the IAM Principal on the target remote cluster.
The resulting set of permissions granted to the IAM Principal will be the union of the
permissions granted via Kubernetes RBAC with the permissions granted via IAM roles.&lt;/li>
&lt;/ul>
&lt;p>In GCP a GKE cluster is regarded as a project-level resource, so IAM roles granting
access to GKE APIs can only be granted at the project level or higher in the
&lt;a href="#access-management">resource hierarchy&lt;/a>.&lt;/p>
&lt;h4 id="permissions-for-the-gke-api">Permissions for the GKE API&lt;/h4>
&lt;p>The recommended role containing the required permissions for calling the &lt;code>GetCluster&lt;/code> GKE API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/container#container.clusterViewer" target="_blank">Kubernetes Engine Cluster Viewer (&lt;code>roles/container.clusterViewer&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Alternatively, you can create a
&lt;a href="https://cloud.google.com/iam/docs/creating-custom-roles" target="_blank">custom role&lt;/a>
containing the following permission:&lt;/p>
&lt;ul>
&lt;li>&lt;code>container.clusters.get&lt;/code>&lt;/li>
&lt;/ul>
&lt;h4 id="permissions-inside-the-remote-cluster">Permissions inside the remote cluster&lt;/h4>
&lt;p>For granting Kubernetes RBAC to the IAM Principal, simply create the corresponding
&lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code> objects inside the remote cluster using the
principal as the Kubernetes username.&lt;/p>
&lt;p>For granting cluster-scoped permissions through IAM roles, you can grant either
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/iam#predefined" target="_blank">built-in roles&lt;/a> or
&lt;a href="https://cloud.google.com/iam/docs/creating-custom-roles" target="_blank">custom roles&lt;/a>.&lt;/p>
&lt;p>For an exhaustive list of the permissions that can be added to a custom IAM role for
cluster-scoped permissions, go to the page of the
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/iam#container.admin" target="_blank">Kubernetes Engine Admin&lt;/a>
role and expand the collapsed section &lt;code>container.*&lt;/code> at the very top of the
&lt;code>Permissions&lt;/code> column.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Namespaced permissions can only be granted via Kubernetes RBAC.
IAM roles can only grant cluster-scoped permissions. See
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/iam#interaction_with_rbac" target="_blank">docs&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="for-google-cloud-pubsub">For Google Cloud Pub/Sub&lt;/h3>
&lt;p>The &lt;code>Provider&lt;/code> Flux API is integrated with Pub/Sub. The &lt;code>Provider&lt;/code> API can be used
to send notifications about Flux resources to Pub/Sub topics.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>Provider&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/pubsub#pubsub.publisher" target="_blank">Pub/Sub Publisher (&lt;code>roles/pubsub.publisher&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Config Connector resource kinds for use with the IAM custom resources are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/pubsub/pubsubtopic" target="_blank">&lt;code>PubSubTopic&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The Terraform/OpenTofu IAM resource types are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic_iam" target="_blank">&lt;code>pubsub_topic&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The commands for the &lt;code>gcloud&lt;/code> CLI are:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/pubsub/topics" target="_blank">&lt;code>pubsub topics&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="authentication">Authentication&lt;/h2>
&lt;p>As mentioned in the
&lt;a href="#identity">Identity&lt;/a> section, GCP supports two types of
identities for Flux: GCP Service Accounts and Kubernetes Service Accounts.
This section describes how to authenticate each type of identity. Both types
support Workload Identity Federation (secret-less), but only GCP Service
Accounts support secret-based authentication.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Recommendation&lt;/strong>: Always prefer secret-less over secret-based authentication
if the alternative is available. Secrets can be stolen to abuse the permissions
granted to the identities they represent, and for public clouds like GCP this can
be done by simply having Internet access. This requires secrets to be regularly
rotated and more security controls to be put in place, like audit logs, secret
management tools, etc. Secret-less authentication does not have this problem, as
the identity is authenticated using a token that is not stored anywhere and is
only valid for a short period of time, usually one hour. It&amp;rsquo;s much harder to
steal an identity this way.&lt;/p>
&lt;/blockquote>
&lt;h3 id="with-workload-identity-federation">With Workload Identity Federation&lt;/h3>
&lt;p>Workload Identity Federation is a GCP feature that allows external identities
to authenticate with GCP services without the need for a per-identity static credential.
This is done by exchanging a short-lived token issued by the external identity
provider (in this case, Kubernetes) for a short-lived Google OAuth 2.0 Access
Token. This access token is then used to authenticate with GCP services.
This process is more broadly known as &lt;em>OIDC federation&lt;/em>.&lt;/p>
&lt;h4 id="supported-clusters">Supported clusters&lt;/h4>
&lt;p>GCP supports Workload Identity Federation for both
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity" target="_blank">GKE&lt;/a>
and
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes" target="_blank">non-GKE&lt;/a>
clusters.&lt;/p>
&lt;p>In GKE Autopilot, Workload Identity Federation is always enabled, no cluster setup is required.
In GKE Standard, follow these
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable_on_clusters_and_node_pools" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>For non-GKE clusters you need to
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes#create_the_workload_identity_pool_and_provider" target="_blank">create a Workload Identity Pool and a Workload Identity Provider&lt;/a>
with the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/#source-cluster-setup">Issuer URL&lt;/a> of the cluster.&lt;/p>
&lt;p>To create a Workload Identity Pool and a Workload Identity Provider using Config Connector,
you can use the following custom resources:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamworkloadidentitypool" target="_blank">&lt;code>IAMWorkloadIdentityPool&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamworkloadidentitypoolprovider" target="_blank">&lt;code>IAMWorkloadIdentityPoolProvider&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create a Workload Identity Pool and a Workload Identity Provider using Terraform/OpenTofu,
you can use the following resources:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool" target="_blank">&lt;code>google_iam_workload_identity_pool&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider" target="_blank">&lt;code>google_iam_workload_identity_pool_provider&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create a Workload Identity Pool and a Workload Identity Provider using the &lt;code>gcloud&lt;/code> CLI,
you can use the following commands:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/iam/workload-identity-pools" target="_blank">&lt;code>iam workload-identity-pools&lt;/code>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/iam/workload-identity-pools/providers" target="_blank">&lt;code>iam workload-identity-pools providers&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="supported-identity-types">Supported identity types&lt;/h4>
&lt;p>When using Workload Identity Federation, Kubernetes Service Accounts are the
identity type used by default. In this case, roles must be granted using the
IAM Principal formats described in
&lt;a href="#to-kubernetes-service-accounts">this&lt;/a>
section, with the appropriate format depending on whether the cluster is GKE
or not.&lt;/p>
&lt;p>You can also optionally use the roles granted to a GCP Service Account
instead of the roles granted to a Kubernetes Service Account with
Workload Identity Federation, but a Kubernetes Service Account is still
required. This is done by a process called &lt;em>impersonation&lt;/em>. To configure
a Kubernetes Service Account to impersonate a GCP Service Account,
two steps are required:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Allow the Kubernetes Service Account to impersonate the GCP Service Account.&lt;/strong>
This is done by granting the
&lt;a href="https://cloud.google.com/iam/docs/roles-permissions/iam#iam.workloadIdentityUser" target="_blank">Workload Identity User (&lt;code>roles/iam.workloadIdentityUser&lt;/code>)&lt;/a>
role to the Kubernetes Service Account on the GCP Service Account. The IAM Principals
required for this are the same described
&lt;a href="#to-kubernetes-service-accounts">here&lt;/a>.&lt;/li>
&lt;/ol>
&lt;p>To perform this step using Config Connector, you can use one of the IAM custom resources
mentioned
&lt;a href="#via-config-connector-iam-custom-resources">here&lt;/a> with the following kind:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccount" target="_blank">&lt;code>IAMServiceAccount&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To perform this step using Terraform/OpenTofu, you can use one of the IAM resources mentioned
&lt;a href="#via-terraformopentofu-iam-resources">here&lt;/a> with the following resource type:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam" target="_blank">&lt;code>service_account&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To perform this step using the &lt;code>gcloud&lt;/code> CLI, you can use one of the IAM commands mentioned
&lt;a href="#via-the-gcloud-cli">here&lt;/a> with the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/iam/service-accounts" target="_blank">&lt;code>iam service-accounts&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>&lt;strong>Annotate the Kubernetes Service Account with the GCP Service Account email.&lt;/strong>
This is done by adding the annotation
&lt;code>iam.gke.io/gcp-service-account: SA_NAME@PROJECT_ID.iam.gserviceaccount.com&lt;/code>
to the Kubernetes Service Account:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KSA_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">iam.gke.io/gcp-service-account&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SA_NAME@PROJECT_ID.iam.gserviceaccount.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Configuring Flux to use a Kubernetes Service Account to authenticate with GCP,
regardless if it&amp;rsquo;s configured to impersonate a GCP Service Account or not, can
be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="with-gcp-service-account-keys">With GCP Service Account Keys&lt;/h3>
&lt;p>All GCP integrations except for GAR support configuring
authentication through a GCP Service Account Key.&lt;/p>
&lt;p>GCP Service Accounts support static
&lt;a href="https://cloud.google.com/iam/docs/service-account-creds#user-managed-keys" target="_blank">private keys&lt;/a>
that can be used to generate temporary access tokens for authenticating with GCP services.
Such a key is exported as a JSON document containing the key itself and other metadata.&lt;/p>
&lt;p>The best way to create a GCP Service Account Key is using the following Config Connector
custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccountkey" target="_blank">&lt;code>IAMServiceAccountKey&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>This custom resource will automatically create a Kubernetes Secret inside the cluster
containing the GCP Service Account Key in the JSON format.&lt;/p>
&lt;p>To create the key using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key" target="_blank">&lt;code>google_service_account_key&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create the key using the &lt;code>gcloud&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cloud.google.com/sdk/gcloud/reference/iam/service-accounts/keys/create" target="_blank">&lt;code>iam service-accounts keys create&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Configuring Flux to use a GCP Service Account Key can be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="at-the-object-level">At the object level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the object level.
This allows users to adhere to the
&lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">Least Privilege Principle&lt;/a>,
as each Flux resource can be configured with its own identity and therefore its own
permissions. This is useful for multi-tenancy scenarios, where different
teams can use the same cluster but need to be isolated from each other
inside their own namespaces.&lt;/p>
&lt;h4 id="for-workload-identity-federation">For Workload Identity Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>For configuring authentication through a Kubernetes Service Account
at the object level, regardless if the Kubernetes Service Account is
configured to impersonate a GCP Service Account or not, the following
steps are required:&lt;/p>
&lt;ol>
&lt;li>Enable the feature gate &lt;code>ObjectLevelWorkloadIdentity&lt;/code> in the target Flux controller Deployment
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>(some-controller)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/args/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: --feature-gates=ObjectLevelWorkloadIdentity=true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>Set the &lt;code>.spec.provider&lt;/code> field to &lt;code>gcp&lt;/code> in the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, this field is not
required/does not exist, SOPS detects the provider from the metadata
in the SOPS-encrypted Secret. For remote cluster access with the
&lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is &lt;code>.data.provider&lt;/code>
inside the referenced &lt;code>ConfigMap&lt;/code> from &lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;li>Use the &lt;code>.spec.serviceAccountName&lt;/code> field to specify the name of the
Kubernetes Service Account in the same namespace as the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, the field is
&lt;code>.spec.decryption.serviceAccountName&lt;/code>. For remote cluster access with
the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is
&lt;code>.data.serviceAccountName&lt;/code> inside the referenced &lt;code>ConfigMap&lt;/code> from
&lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Only if the cluster is not GKE&lt;/strong>, annotate the Kubernetes Service Account
with the fully qualified name of the Workload Identity Provider:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KSA_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">iam.gke.io/gcp-service-account&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SA_NAME@PROJECT_ID.iam.gserviceaccount.com&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#60a0b0;font-style:italic"># GCP Service Account impersonation is optional&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">gcp.auth.fluxcd.io/workload-identity-provider&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>iam.gke.io/gcp-service-account&lt;/code> annotation is defined by GKE,
but Flux also uses it to identify the GCP Service Account to impersonate in
non-GKE clusters. This is for providing users with a seamless experience.&lt;/p>
&lt;/blockquote>
&lt;h4 id="for-gcp-service-account-keys">For GCP Service Account Keys&lt;/h4>
&lt;p>All GCP integrations except for GAR and GKE support configuring
authentication through a GCP Service Account Key at the object
level.&lt;/p>
&lt;p>For configuring authentication through a GCP Service Account Key, the
&lt;code>.spec.secretRef.name&lt;/code> field must be set to the name of the Kubernetes
Secret in the same namespace as the Flux resource containing the GCP
Service Account Key. In the case of the &lt;code>Kustomization&lt;/code> API, the field
is &lt;code>.spec.decryption.secretRef.name&lt;/code>.&lt;/p>
&lt;p>The provider field and the key inside the &lt;code>.data&lt;/code> field of the Secret
depend on the specific Flux API:&lt;/p>
&lt;ul>
&lt;li>For the &lt;code>Bucket&lt;/code> API the &lt;code>.spec.provider&lt;/code> field must be set to &lt;code>gcp&lt;/code>,
and the key inside the &lt;code>.data&lt;/code> field of the Secret must be &lt;code>serviceaccount&lt;/code>.&lt;/li>
&lt;li>For the &lt;code>Provider&lt;/code> API, the &lt;code>.spec.type&lt;/code> field must be set to &lt;code>googlepubsub&lt;/code>
and the key inside the &lt;code>.data&lt;/code> field of the Secret must be &lt;code>token&lt;/code>.&lt;/li>
&lt;li>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, there&amp;rsquo;s no provider field as
SOPS detects the provider from the metadata in the SOPS-encrypted Secret. The
key inside the &lt;code>.data&lt;/code> field of the Secret must be &lt;code>sops.gcp-kms&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="at-the-controller-level">At the controller level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the controller level.
This is more appropriate for single-tenant scenarios, where all the Flux resources
inside the cluster belong to the same team and hence can share the same identity
and permissions.&lt;/p>
&lt;p>At the controller level, regardless if authenticating with Workload Identity Federation
or GCP Service Account Keys, all Flux resources must have the provider field set to &lt;code>gcp&lt;/code>
according to the rules below.&lt;/p>
&lt;p>For all Flux resource kinds except for &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code>, set
the &lt;code>.spec.provider&lt;/code> field to &lt;code>gcp&lt;/code> and leave &lt;code>.spec.serviceAccountName&lt;/code> unset.&lt;/p>
&lt;p>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, leave the
&lt;code>.spec.decryption.serviceAccountName&lt;/code> field unset. There&amp;rsquo;s
no provider field for SOPS decryption.&lt;/p>
&lt;p>For remote cluster access with the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs,
set the &lt;code>.data.provider&lt;/code> field of the &lt;code>ConfigMap&lt;/code> referenced by the
&lt;code>.spec.kubeConfig.configMapRef&lt;/code> field to &lt;code>gcp&lt;/code> and leave the
&lt;code>.data.serviceAccountName&lt;/code> field unset.&lt;/p>
&lt;p>The controller-level configuration is described in the following sections.&lt;/p>
&lt;h4 id="for-workload-identity-federation-1">For Workload Identity Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>If the cluster is GKE, the Kubernetes Service Account of the controller can optionally
be configured to impersonate a GCP Service Account. This is done by adding the
&lt;code>iam.gke.io/gcp-service-account&lt;/code> annotation to the controller Service Account
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> apiVersion: v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> kind: ServiceAccount
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: controller
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> annotations:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> iam.gke.io/gcp-service-account: SA_NAME@PROJECT_ID.iam.gserviceaccount.com # GCP Service Account impersonation is optional&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the configuration above is done after bootstrap, restart (delete) the controller
for the binding to take effect.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Hint&lt;/strong>: As discussed in the
&lt;a href="#with-workload-identity-federation">Workload Identity Federation&lt;/a>
section, impersonating a GCP Service Account is entirely optional. If not configured, the controller
Kubernetes Service Account will be used for authentication, in which case the roles must be granted
directly to it according to what is described in
&lt;a href="#to-kubernetes-service-accounts">this&lt;/a> section.&lt;/p>
&lt;/blockquote>
&lt;p>If the cluster &lt;em>is not&lt;/em> GKE, the controller Deployment must be patched
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a> according to these
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes#deploy" target="_blank">docs&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>A projected volume must be mounted in the controller Deployment with a Kubernetes
Service Account token whose audience is set to the Workload Identity Provider URL.&lt;/li>
&lt;li>A ConfigMap volume must be mounted in the controller Deployment with the JSON
configuration below.&lt;/li>
&lt;li>The environment variable &lt;code>GOOGLE_APPLICATION_CREDENTIALS&lt;/code> must be set to the path
of the mounted JSON configuration file.&lt;/li>
&lt;/ul>
&lt;p>The controller patch should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: GOOGLE_APPLICATION_CREDENTIALS
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: /etc/workload-identity/credential-configuration.json
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: gcp-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> projected:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> sources:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - serviceAccountToken:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> expirationSeconds: 3600
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: gcp-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: workload-identity-credential-configuration
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> configMap:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: some-controller-workload-identity-federation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: gcp-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /var/run/service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: workload-identity-credential-configuration
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /etc/workload-identity
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For direct access using the roles granted to the controller Kubernetes Service account,
the ConfigMap containing the JSON configuration should look like this (it should contain
the &lt;code>token_info_url&lt;/code> field set to &lt;code>https://sts.googleapis.com/v1/introspect&lt;/code>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ConfigMap&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-controller-workload-identity-federation&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>flux-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">data&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">credential-configuration.json&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;universe_domain&amp;#34;: &amp;#34;googleapis.com&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;type&amp;#34;: &amp;#34;external_account&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;audience&amp;#34;: &amp;#34;//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;subject_token_type&amp;#34;: &amp;#34;urn:ietf:params:oauth:token-type:jwt&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;token_url&amp;#34;: &amp;#34;https://sts.googleapis.com/v1/token&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;token_info_url&amp;#34;: &amp;#34;https://sts.googleapis.com/v1/introspect&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;credential_source&amp;#34;: {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;file&amp;#34;: &amp;#34;/var/run/service-account/gcp-token&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;format&amp;#34;: {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;type&amp;#34;: &amp;#34;text&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For impersonating a GCP Service Account using the controller Kubernetes Service Account,
the ConfigMap containing the JSON configuration should look like this (it should contain
the &lt;code>service_account_impersonation_url&lt;/code> field instead of the &lt;code>token_info_url&lt;/code> field):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ConfigMap&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-controller-workload-identity-federation&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>flux-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">data&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">credential-configuration.json&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;universe_domain&amp;#34;: &amp;#34;googleapis.com&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;type&amp;#34;: &amp;#34;external_account&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;audience&amp;#34;: &amp;#34;//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;subject_token_type&amp;#34;: &amp;#34;urn:ietf:params:oauth:token-type:jwt&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;token_url&amp;#34;: &amp;#34;https://sts.googleapis.com/v1/token&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;service_account_impersonation_url&amp;#34;: &amp;#34;https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:generateAccessToken&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;credential_source&amp;#34;: {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;file&amp;#34;: &amp;#34;/var/run/service-account/gcp-token&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;format&amp;#34;: {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> &amp;#34;type&amp;#34;: &amp;#34;text&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> }&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="for-gcp-service-account-keys-1">For GCP Service Account Keys&lt;/h4>
&lt;p>Mount the Kubernetes Secret containing the GCP Service Account Key inside
the controller Deployment as a volume, and set the environment variable
&lt;code>GOOGLE_APPLICATION_CREDENTIALS&lt;/code> to the path of the mounted JSON file
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: GOOGLE_APPLICATION_CREDENTIALS
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: /etc/gcp-service-account/key.json
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: gcp-service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secret:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secretName: some-controller-gcp-service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: gcp-service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /etc/gcp-service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Secret should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>some-controller-gcp-service-account&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>flux-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">stringData&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">key.json&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> JSON_GCP_SERVICE_ACCOUNT_KEY&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="at-the-node-level">At the node level&lt;/h3>
&lt;p>Only for the GAR integrations Flux supports authentication
at the node level for GKE. This is because users often already have to configure
authentication at the node level for GKE to be able to pull container images from
GAR in order to start pods. By supporting this authentication method Flux allows
users to configure GAR authentication in a single way.
See
&lt;a href="https://cloud.google.com/artifact-registry/docs/integrate-gke" target="_blank">docs&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; Node level authentication may work for other integrations as well,
but Flux only has continuous integration tests for the GAR integration in
order to support the specific use case described above.&lt;/p>
&lt;/blockquote>
&lt;p>For node-level authentication to work, the &lt;code>.spec.provider&lt;/code> field of the Flux
resources must be set to &lt;code>gcp&lt;/code>.&lt;/p></description></item><item><title>Flux: Microsoft Azure</title><link>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/azure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/azure/</guid><description>
&lt;p>The Flux APIs integrate with the following Microsoft Azure services:&lt;/p>
&lt;ul>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/ocirepositories/">OCIRepository&lt;/a> API with
&lt;a href="https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro" target="_blank">Azure Container Registry (ACR)&lt;/a>
for pulling OCI artifacts into the cluster.&lt;/li>
&lt;li>The image-reflector-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagerepositories/">ImageRepository&lt;/a> and
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imagepolicies/">ImagePolicy&lt;/a> APIs with ACR for scanning tags and digests of OCI artifacts
and reflecting them into the cluster.&lt;/li>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/gitrepositories/">GitRepository&lt;/a> API with
&lt;a href="https://learn.microsoft.com/en-us/azure/devops/user-guide/services" target="_blank">Azure DevOps (ADO)&lt;/a>
for pulling manifests from Git repositories and packaging them as artifacts inside the cluster.&lt;/li>
&lt;li>The image-automation-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/image/imageupdateautomations/">ImageUpdateAutomation&lt;/a>
API with ADO for automating image updates in Git repositories.&lt;/li>
&lt;li>The notification-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/notification/providers/">Provider&lt;/a> API with ADO
for updating commit statuses in Git repositories upon events related to Flux resources.&lt;/li>
&lt;li>The source-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/source/buckets/">Bucket&lt;/a> API with
&lt;a href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction" target="_blank">Azure Blob Storage (ABS)&lt;/a>
for pulling manifests from containers and packaging them as artifacts inside the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/kustomize/kustomizations/">Kustomization&lt;/a> API with
&lt;a href="https://learn.microsoft.com/en-us/azure/key-vault/general/overview" target="_blank">Azure Key Vault (AKV)&lt;/a>
for decrypting SOPS-encrypted secrets when applying manifests in the cluster.&lt;/li>
&lt;li>The kustomize-controller integrates the Kustomization API with
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/what-is-aks" target="_blank">Azure Kubernetes Service (AKS)&lt;/a>
for applying manifests in remote AKS clusters.&lt;/li>
&lt;li>The helm-controller integrates the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/helm/helmreleases/">HelmRelease&lt;/a> API with
AKS for applying Helm charts in remote AKS clusters.&lt;/li>
&lt;li>The notification-controller integrates the Provider API with
&lt;a href="https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-about" target="_blank">Azure Event Hubs (AEH)&lt;/a>
for sending notifications about Flux resources outside the cluster.&lt;/li>
&lt;/ul>
&lt;p>The next sections briefly describe
&lt;a href="https://learn.microsoft.com/en-us/entra/fundamentals/whatis" target="_blank">Microsoft Entra ID&lt;/a>,
formerly known as &lt;em>Azure Active Directory (AAD)&lt;/em>, and
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" target="_blank">Azure RBAC&lt;/a>,
Azure&amp;rsquo;s identity and access management systems,
and how they can be used to grant Flux access to resources offered by the services above. Bear in
mind that Microsoft Entra ID and Azure RBAC have more features than the ones described here.
We describe only the features that are relevant for the Flux integrations.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Flux also supports Microsoft Teams webhooks, but Microsoft Teams webhooks do
not support Microsoft Entra ID. For more information about the notification-controller
integration with Microsoft Teams, see the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/notification/providers/">Provider&lt;/a> API docs.&lt;/p>
&lt;/blockquote>
&lt;h2 id="identity">Identity&lt;/h2>
&lt;p>For all the integrations with Azure, Microsoft Entra ID will
authenticate two types of identities for Flux:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-manage-user-assigned-managed-identities" target="_blank">User-Assigned Managed Identities&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/howto-create-service-principal-portal" target="_blank">Applications&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For both types a
&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals#service-principal-object" target="_blank">Service Principal&lt;/a>
can be enabled, with each identity having its own Service Principal. The
Service Principal is the entity of an identity that is used to integrate
with other Azure systems, such as Azure RBAC and ADO.&lt;/p>
&lt;p>Also, each identity type has its own methods of authentication. In particular,
Managed Identities support secret-less authentication, while Applications support
secret-based authentication. The former is more secure.&lt;/p>
&lt;p>For further understanding how to configure authentication for both types of
identities, refer to the
&lt;a href="#authentication">Authentication&lt;/a> section.&lt;/p>
&lt;h2 id="access-management">Access Management&lt;/h2>
&lt;p>Azure Role-Based Access Control (RBAC) is the system that Azure employs to
manage access for most of its resources. Some services, such as
&lt;a href="https://learn.microsoft.com/en-us/azure/devops/organizations/security/permissions" target="_blank">ADO&lt;/a>,
do not use Azure RBAC and instead have their own access control system.&lt;/p>
&lt;p>Identities in Azure need &lt;em>permissions&lt;/em> to access resources from Azure services.
Permissions cannot be granted directly to identities. Instead, Azure RBAC uses
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/role-definitions" target="_blank">roles&lt;/a>
to group permissions, and only roles can be granted to identities. Each role has a
display name and a globally unique ID. For example, the role &lt;code>Storage Blob Data Reader&lt;/code>,
whose ID is &lt;code>/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1&lt;/code>,
has the following definition:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;assignableScopes&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;description&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Allows for read access to Azure Storage blob containers and data&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;id&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;2a2b9908-6ea1-4ae2-8e65-a410df84e7d1&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;permissions&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;actions&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;Microsoft.Storage/storageAccounts/blobServices/containers/read&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;notActions&amp;#34;&lt;/span>: [],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;dataActions&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;notDataActions&amp;#34;&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;roleName&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Storage Blob Data Reader&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;roleType&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;BuiltInRole&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;Microsoft.Authorization/roleDefinitions&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The structure of permissions is usually &lt;code>Microsoft.&amp;lt;service&amp;gt;/&amp;lt;resource type&amp;gt;/&amp;lt;action&amp;gt;&lt;/code>
and they are grouped into two categories:&lt;/p>
&lt;ul>
&lt;li>&lt;em>Data actions&lt;/em>: These actions are related to data operations, such as reading or writing data.&lt;/li>
&lt;li>&lt;em>Non-data actions&lt;/em>: These actions are related to management operations, such as creating or deleting resources.&lt;/li>
&lt;/ul>
&lt;p>Azure has a large number of
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles" target="_blank">predefined roles&lt;/a>,
but users can also create
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles" target="_blank">custom roles&lt;/a>
inside their Azure subscriptions.&lt;/p>
&lt;p>For an identity to be allowed to perform an action on a resource, the identity
needs to be granted, &lt;em>on a scope covering that resource&lt;/em>, a role that contains
the permission required for that action. The role needs to be granted directly
on the resource scope, or on the scope of a parent resource in the
&lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-setup-guide/organize-resources#management-levels-and-hierarchy" target="_blank">resource hierarchy&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>&lt;em>Resource&lt;/em>&lt;/li>
&lt;li>&lt;em>Resource Group&lt;/em> (set of resources)&lt;/li>
&lt;li>&lt;em>Subscription&lt;/em> (set of resource groups)&lt;/li>
&lt;li>&lt;em>Management Group&lt;/em> (set of subscriptions)&lt;/li>
&lt;/ul>
&lt;p>If the role is granted on a parent resource, the relationship will be inherited
by all the descendants. For example, if a role is granted on a subscription, all
the resource groups and resources inside that subscription will inherit the grant.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Reminder&lt;/strong>: The grant relationship has &lt;em>three&lt;/em> involved entities:&lt;/p>
&lt;ul>
&lt;li>The identity that will use the permissions to perform actions.&lt;/li>
&lt;li>The scope covering the resource that will be the target of the actions.&lt;/li>
&lt;li>The role containing the permissions required for the actions.&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;h3 id="granting-permissions">Granting permissions&lt;/h3>
&lt;p>Azure RBAC grants roles to Microsoft Entra identities through the Service Principal
of the identity. The &lt;em>principal ID&lt;/em> of an identity can be looked up through the
&lt;em>client ID&lt;/em> (also known as &lt;em>application ID&lt;/em>) of the identity.&lt;/p>
&lt;p>To find a principal ID using Terraform/OpenTofu, use the client ID in the following data source
(look for the &lt;code>object_id&lt;/code> attribute):&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/service_principal" target="_blank">&lt;code>azuread_service_principal&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To find a principal ID using the &lt;code>az&lt;/code> CLI, use the client ID in the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/ad/sp#az-ad-sp-show" target="_blank">&lt;code>az ad sp show --id &amp;lt;client-id&amp;gt; --query id -o tsv&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="via-azure-service-operator-custom-resources">Via Azure Service Operator custom resources&lt;/h4>
&lt;p>To use
&lt;a href="https://azure.github.io/azure-service-operator/" target="_blank">Azure Service Operator (ASO)&lt;/a> for
granting roles you can use the following custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://azure.github.io/azure-service-operator/reference/authorization/" target="_blank">&lt;code>RoleAssignment&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: ASO is the most GitOps-friendly way of managing Azure
resources. With it you can even use Flux itself to deploy and continuously reconcile
your Azure custom resources (the Kubernetes ones), and ASO itself will
&lt;a href="https://azure.github.io/azure-service-operator/guide/aso-controller-settings-options/#azure_sync_period" target="_blank">continuously reconcile&lt;/a>
the actual Azure resources.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-terraformopentofu-resources">Via Terraform/OpenTofu resources&lt;/h4>
&lt;p>To use Terraform/OpenTofu for granting roles you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment" target="_blank">&lt;code>azurerm_role_assignment&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Terraform/OpenTofu is a great declarative way of managing Azure resources,
but it&amp;rsquo;s not as GitOps-friendly as ASO, as these tools do not prescribe
continuous reconciliation of the resources. There are alternatives to achieve that,
but they are not a core part of the tools.&lt;/p>
&lt;/blockquote>
&lt;h4 id="via-the-az-cli">Via the &lt;code>az&lt;/code> CLI&lt;/h4>
&lt;p>To use the &lt;code>az&lt;/code> CLI for granting roles you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/role/assignment#az-role-assignment-create" target="_blank">&lt;code>az role assignment create&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>az&lt;/code> CLI is a great tool for experimenting with Azure resources and
their integrations with Flux, but it&amp;rsquo;s not a GitOps-friendly way of managing Azure
resources. If you need continuous reconciliation of the resources, prefer using
ASO or Terraform/OpenTofu.&lt;/p>
&lt;/blockquote>
&lt;h2 id="authorization">Authorization&lt;/h2>
&lt;p>In this section we describe the recommended roles and permissions for
enabling the Flux integrations with Azure services.&lt;/p>
&lt;h3 id="for-azure-container-registry">For Azure Container Registry&lt;/h3>
&lt;p>The &lt;code>OCIRepository&lt;/code>, &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> Flux APIs are integrated with
ACR. The &lt;code>OCIRepository&lt;/code> API can be used to pull OCI artifacts from ACR repositories
into the cluster, while the &lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs
can be used to reflect tags and digests of such artifacts also inside the cluster.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>OCIRepository&lt;/code>,
&lt;code>ImageRepository&lt;/code> and &lt;code>ImagePolicy&lt;/code> APIs is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/containers#acrpull" target="_blank">AcrPull (&lt;code>/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The scopes on which the &lt;code>AcrPull&lt;/code> role can be granted are:&lt;/p>
&lt;ul>
&lt;li>Registry: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ContainerRegistry/registries/REGISTRY_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="for-azure-devops">For Azure DevOps&lt;/h3>
&lt;p>The &lt;code>GitRepository&lt;/code>, &lt;code>ImageUpdateAutomation&lt;/code> and &lt;code>Provider&lt;/code> Flux APIs are integrated with
ADO. The &lt;code>GitRepository&lt;/code> API can be used to pull manifests from ADO Git repositories
and package them as artifacts inside the cluster, the &lt;code>ImageUpdateAutomation&lt;/code> API
can be used to automate image updates in ADO Git repositories, and the &lt;code>Provider&lt;/code> API
can be used to update commit statuses in ADO Git repositories upon events related to
Flux resources.&lt;/p>
&lt;p>While ADO integrates with Microsoft Entra ID Service Principals, it does not
integrate with Azure RBAC. As mentioned before, ADO has its own access control
system.&lt;/p>
&lt;p>The Service Principal must be onboarded into the ADO organization and
added to a group. For the &lt;code>GitRepository&lt;/code> API, the &lt;code>Readers&lt;/code> group is sufficient,
while for the &lt;code>ImageUpdateAutomation&lt;/code> and &lt;code>Provider&lt;/code> APIs the &lt;code>Contributors&lt;/code> group
is required for pushing commits to the repository and updating commit statuses,
respectively.&lt;/p>
&lt;p>ASO does not support managing ADO resources (see
&lt;a href="https://github.com/Azure/azure-service-operator/issues/3209" target="_blank">issue&lt;/a>).&lt;/p>
&lt;h4 id="via-terraformopentofu-resources-1">Via Terraform/OpenTofu resources&lt;/h4>
&lt;p>To grant access to Service Principals using Terraform/OpenTofu, first you need to
configure the ADO provider with the ADO organization and project:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs#argument-reference" target="_blank">&lt;code>azuredevops&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Then you can use the following resources:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/resources/service_principal_entitlement" target="_blank">&lt;code>azuredevops_service_principal_entitlement&lt;/code>&lt;/a>:
This resource onboards a Service Principal into an ADO organization.&lt;/li>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/resources/group_membership" target="_blank">&lt;code>azuredevops_group_membership&lt;/code>&lt;/a>:
This resource adds the Service Principal to an ADO group.&lt;/li>
&lt;/ul>
&lt;p>Use the &lt;code>descriptor&lt;/code> attribute of the &lt;code>azuredevops_service_principal_entitlement&lt;/code>
in the &lt;code>members&lt;/code> field of the &lt;code>azuredevops_group_membership&lt;/code> resource.&lt;/p>
&lt;p>Use the
&lt;a href="https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/data-sources/group" target="_blank">&lt;code>azuredevops_group&lt;/code>&lt;/a>
data source to find the ID of the desired group, and use it in the
&lt;code>group&lt;/code> field of the &lt;code>azuredevops_group_membership&lt;/code> resource.&lt;/p>
&lt;h4 id="via-the-az-cli-1">Via the &lt;code>az&lt;/code> CLI&lt;/h4>
&lt;p>To grant access to Service Principals using the &lt;code>az&lt;/code> CLI, you can use the following commands:&lt;/p>
&lt;ol>
&lt;li>Login to ADO:
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/devops#az-devops-login" target="_blank">&lt;code>az devops login&lt;/code>&lt;/a>&lt;/li>
&lt;li>Configure the ADO organization and project:
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/devops#az-devops-configure" target="_blank">&lt;code>az devops configure&lt;/code>&lt;/a>&lt;/li>
&lt;li>Onboard the Service Principal into the ADO organization. This doesn&amp;rsquo;t have a dedicated command yet,
so use
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/reference-index#az-rest" target="_blank">&lt;code>az rest&lt;/code>&lt;/a> to call the REST API for
&lt;a href="https://learn.microsoft.com/en-us/rest/api/azure/devops/memberentitlementmanagement/service-principal-entitlements/add" target="_blank">&lt;code>Adding Service Principal Entitlements&lt;/code>&lt;/a>.&lt;/li>
&lt;li>Find the &lt;em>member ID&lt;/em> of the Service Principal in the organization using &lt;code>az rest&lt;/code> with the REST API for
&lt;a href="https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/subject-query/query" target="_blank">&lt;code>Querying Subjects&lt;/code>&lt;/a>,
the &lt;code>query&lt;/code> field of the request body should be set to the principal ID of the Service Principal.
The response should be a list of &lt;code>GraphSubject&lt;/code>, the member ID will be the &lt;code>descriptor&lt;/code> field.&lt;/li>
&lt;li>List the groups in the organization to find the ID of the desired group:
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/devops/security/group#az-devops-security-group-list" target="_blank">&lt;code>az devops security group list&lt;/code>&lt;/a>&lt;/li>
&lt;li>Add the Service Principal to the group:
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/devops/security/group/membership#az-devops-security-group-membership-add" target="_blank">&lt;code>az devops security group membership add&lt;/code>&lt;/a>&lt;/li>
&lt;/ol>
&lt;h3 id="for-azure-blob-storage">For Azure Blob Storage&lt;/h3>
&lt;p>The &lt;code>Bucket&lt;/code> Flux API is integrated with ABS. The &lt;code>Bucket&lt;/code> API can be used
to pull manifests from ABS containers and package them as artifacts inside the cluster.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>Bucket&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-blob-data-reader" target="_blank">Storage Blob Data Reader (&lt;code>/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The scopes on which the &lt;code>Storage Blob Data Reader&lt;/code> role can be granted are:&lt;/p>
&lt;ul>
&lt;li>Container: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/STORAGE_ACCOUNT_NAME/blobServices/default/containers/CONTAINER_NAME&lt;/code>&lt;/li>
&lt;li>Storage Account: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/STORAGE_ACCOUNT_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="for-azure-key-vault">For Azure Key Vault&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> Flux API is integrated with AKV.
The &lt;code>Kustomization&lt;/code> API is used to apply manifests in the cluster, and it can use AKV to
decrypt SOPS-encrypted secrets before applying them.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>Kustomization&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/security#key-vault-crypto-user" target="_blank">Key Vault Crypto User (&lt;code>/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The scopes on which the &lt;code>Key Vault Crypto User&lt;/code> role can be granted are:&lt;/p>
&lt;ul>
&lt;li>Vault: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.KeyVault/vaults/VAULT_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="for-azure-kubernetes-service">For Azure Kubernetes Service&lt;/h3>
&lt;p>The &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> Flux APIs can use Microsoft Entra identities for applying
and managing resources in remote AKS clusters. The AKS cluster must be
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/enable-authentication-microsoft-entra-id" target="_blank">integrated with Microsoft Entra ID&lt;/a>
for this feature work.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: If you have a reason not to enable the Microsoft Entra ID integration in
your cluster, you can still fetch the static &lt;code>cluster-admin&lt;/code> kubeconfig from Azure
and use it with the &lt;code>.spec.kubeConfig.secretRef&lt;/code> field of the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/kustomize/kustomizations/#kubeconfig-remote-clusters">&lt;code>Kustomization&lt;/code>&lt;/a> and
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/components/helm/helmreleases/#kubeconfig-remote-clusters">&lt;code>HelmRelease&lt;/code>&lt;/a> APIs.&lt;/p>
&lt;/blockquote>
&lt;p>Two kinds of access must be configured for the Microsoft Entra identity:&lt;/p>
&lt;ul>
&lt;li>The Microsoft Entra identity must have permission to call the &lt;code>Get&lt;/code> and &lt;code>ListClusterUserCredentials&lt;/code>
AKS APIs for the target remote cluster. The Flux controllers need to call these APIs for retrieving
details required for connecting to the remote cluster, like the cluster&amp;rsquo;s API server endpoint and
certificate authority data. This is done by granting an Azure RBAC role to the Microsoft Entra
identity that allows these actions on the target remote cluster.&lt;/li>
&lt;li>The Microsoft Entra identity must have permissions inside the remote cluster to apply and manage
the target resources. There are two ways of granting these permissions: via Kubernetes RBAC, or
via Azure RBAC. The former means simply referencing the &lt;em>principal ID&lt;/em> of the Microsoft Entra identity
in &lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code> objects inside the remote cluster as the Kubernetes username.
The latter means granting
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac" target="_blank">Azure RBAC roles&lt;/a>
that grant Kubernetes permissions to the Microsoft Entra identity on the target remote cluster.
The resulting set of permissions granted to the Microsoft Entra identity will be the union of
the permissions granted via Kubernetes RBAC with the permissions granted via Azure RBAC.&lt;/li>
&lt;/ul>
&lt;h4 id="permissions-for-the-aks-apis">Permissions for the AKS APIs&lt;/h4>
&lt;p>The recommended role containing the required permissions for calling the &lt;code>Get&lt;/code> and
&lt;code>ListClusterUserCredentials&lt;/code> AKS APIs is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/containers#azure-kubernetes-service-cluster-user-role" target="_blank">Azure Kubernetes Service Cluster User Role (&lt;code>/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The scopes on which the &lt;code>Azure Kubernetes Service Cluster User Role&lt;/code> role can be granted are:&lt;/p>
&lt;ul>
&lt;li>Cluster: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ContainerService/managedClusters/CLUSTER_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;h4 id="permissions-inside-the-remote-cluster">Permissions inside the remote cluster&lt;/h4>
&lt;p>For granting Kubernetes RBAC to the &lt;em>principal ID&lt;/em> of a Microsoft Entra identity,
simply create the corresponding &lt;code>RoleBinding&lt;/code> or &lt;code>ClusterRoleBinding&lt;/code> objects
inside the remote cluster using the principal ID as the Kubernetes username.&lt;/p>
&lt;p>For granting permissions through Azure RBAC roles, you can grant either
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac#aks-built-in-roles" target="_blank">built-in roles&lt;/a> or
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac#create-custom-roles-definitions" target="_blank">custom roles&lt;/a>
to Microsoft Entra identity on the following scopes:&lt;/p>
&lt;ul>
&lt;li>Namespace: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ContainerService/managedClusters/CLUSTER_NAME/namespaces/NAMESPACE_NAME&lt;/code>&lt;/li>
&lt;li>Cluster: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ContainerService/managedClusters/CLUSTER_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Azure RBAC
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac#create-a-new-aks-cluster-with-managed-microsoft-entra-integration-and-azure-rbac-for-kubernetes-authorization" target="_blank">must be enabled&lt;/a>
for the remote AKS cluster.&lt;/p>
&lt;h3 id="for-azure-event-hubs">For Azure Event Hubs&lt;/h3>
&lt;p>The &lt;code>Provider&lt;/code> Flux API is integrated with AEH. The &lt;code>Provider&lt;/code> API can be used
to send notifications about Flux resources to Event Hubs.&lt;/p>
&lt;p>The recommended role containing the required permissions for the &lt;code>Provider&lt;/code> API is:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/analytics#azure-event-hubs-data-sender" target="_blank">Azure Event Hubs Data Sender (&lt;code>/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The scopes on which the &lt;code>Azure Event Hubs Data Sender&lt;/code> role can be granted are:&lt;/p>
&lt;ul>
&lt;li>Event Hub: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.EventHub/namespaces/NAMESPACE_NAME/eventhubs/EVENTHUB_NAME&lt;/code>&lt;/li>
&lt;li>Namespace: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.EventHub/namespaces/NAMESPACE_NAME&lt;/code>&lt;/li>
&lt;li>Resource Group: &lt;code>/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP_NAME&lt;/code>&lt;/li>
&lt;li>Subscription: &lt;code>/subscriptions/SUBSCRIPTION_ID&lt;/code>&lt;/li>
&lt;li>Management Group: &lt;code>/providers/Microsoft.Management/managementGroups/MANAGEMENT_GROUP_NAME&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="authentication">Authentication&lt;/h2>
&lt;p>As mentioned in the
&lt;a href="#identity">Identity&lt;/a> section, Azure supports two types of
identities for Flux: Managed Identities and Applications.
This section describes how to authenticate each type of identity.
Managed Identities are the recommended way of authenticating to Azure services, as they
support secret-less authentication. Applications are not recommended, as they
require secret-based authentication, which is less secure.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Recommendation&lt;/strong>: Always prefer secret-less over secret-based authentication
if the alternative is available. Secrets can be stolen to abuse the permissions
granted to the identities they represent, and for public clouds like Azure this can
be done by simply having Internet access. This requires secrets to be regularly
rotated and more security controls to be put in place, like audit logs, secret
management tools, etc. Secret-less authentication does not have this problem, as
the identity is authenticated using a token that is not stored anywhere and is
only valid for a short period of time, usually one hour. It&amp;rsquo;s much harder to
steal an identity this way.&lt;/p>
&lt;/blockquote>
&lt;h3 id="with-workload-identity-federation">With Workload Identity Federation&lt;/h3>
&lt;p>
&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" target="_blank">Workload Identity Federation&lt;/a>
is an Azure feature that allows external identities to authenticate with Azure services
without the need for a per-identity static credential. This is done by exchanging
a short-lived token issued by the external identity provider (in this case,
Kubernetes) for a short-lived Azure Access Token. This access token is then used
to authenticate with Azure services. This process is more broadly known as
&lt;em>OIDC federation&lt;/em> and is supported only for Managed Identities.&lt;/p>
&lt;h4 id="supported-clusters">Supported clusters&lt;/h4>
&lt;p>Azure supports Workload Identity Federation for both AKS and non-AKS clusters.&lt;/p>
&lt;p>In AKS clusters you need to enable the options
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-an-aks-cluster" target="_blank">OIDC Issuer and Workload Identity&lt;/a>.&lt;/p>
&lt;p>For both AKS and non-AKS clusters you need to know the
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/#source-cluster-setup">Issuer URL&lt;/a> of the cluster,
which is an input required for creating &lt;em>Federated Credentials&lt;/em>
(see
&lt;a href="#supported-identity-types">below&lt;/a>).&lt;/p>
&lt;h4 id="supported-identity-types">Supported identity types&lt;/h4>
&lt;p>As mentioned before, the only identity type supported by Workload Identity Federation is Managed Identities.&lt;/p>
&lt;p>Flux acquires the roles granted to a Managed Identity by using a Kubernetes
Service Account to &lt;em>impersonate&lt;/em> this Managed Identity.
To configure a Kubernetes Service Account to impersonate a Managed Identity, two steps
are required:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Allow the Kubernetes Service Account to impersonate the Managed Identity.&lt;/strong>
This is done by creating a
&lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview" target="_blank">Federated Credential&lt;/a>
that ties together the Kubernetes Service Account and the Managed Identity.&lt;/li>
&lt;/ol>
&lt;p>The inputs identifying the Managed Identity for creating the Federated Credential are:&lt;/p>
&lt;ul>
&lt;li>The Resource Group.&lt;/li>
&lt;li>The Name of the Managed Identity inside the Resource Group.&lt;/li>
&lt;/ul>
&lt;p>The inputs identifying the Kubernetes Service Account for creating the Federated Credential are:&lt;/p>
&lt;ul>
&lt;li>The
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/#source-cluster-setup">Issuer URL&lt;/a> of the cluster.&lt;/li>
&lt;li>The Subject string that Kubernetes uses to identify the Service Account, which is
&lt;code>system:serviceaccount:NAMESPACE:KSA_NAME&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>Additionally, the Federated Credential needs:&lt;/p>
&lt;ul>
&lt;li>A name for itself.&lt;/li>
&lt;li>The &lt;em>Audience&lt;/em> to be set to &lt;code>api://AzureADTokenExchange&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>To create a Federated Credential using ASO, you can use the following custom resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://azure.github.io/azure-service-operator/reference/managedidentity/" target="_blank">&lt;code>FederatedIdentityCredential&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create a Federated Credential using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential" target="_blank">&lt;code>azurerm_federated_identity_credential&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>to create a Federated Credential using the &lt;code>az&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/identity/federated-credential#az-identity-federated-credential-create" target="_blank">&lt;code>az identity federated-credential create&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>&lt;strong>Annotate the Kubernetes Service Account with the Managed Identity Client ID and Tenant ID.&lt;/strong>
This is done by adding the annotations
&lt;code>azure.workload.identity/client-id: CLIENT_ID&lt;/code> and
&lt;code>azure.workload.identity/tenant-id: TENANT_ID&lt;/code>
to the Kubernetes Service Account:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KSA_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">azure.workload.identity/client-id&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>CLIENT_ID&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">azure.workload.identity/tenant-id&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>TENANT_ID&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Configuring Flux to use a Kubernetes Service Account to authenticate with
Azure can be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="with-application-certificates">With Application Certificates&lt;/h3>
&lt;p>All Azure integrations except for ACR support configuring
authentication through an Application Certificate.&lt;/p>
&lt;p>Applications support static
&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/howto-create-service-principal-portal#set-up-authentication" target="_blank">certificates&lt;/a>
that can be used to generate temporary access tokens for authenticating
with Azure services.&lt;/p>
&lt;p>ASO does not support creating Application Certificates (see
&lt;a href="https://github.com/Azure/azure-service-operator/issues/2474" target="_blank">issue&lt;/a>).&lt;/p>
&lt;p>To create an Application Certificate using Terraform/OpenTofu, you can use the following resource:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal_certificate" target="_blank">&lt;code>azuread_service_principal_certificate&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To create or reset an Application Certificate using the &lt;code>az&lt;/code> CLI, you can use the following command:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/ad/sp/credential#az-ad-sp-credential-reset" target="_blank">&lt;code>az ad sp credential reset --create-cert&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Configuring Flux to use an Application Certificate can be done either
&lt;a href="#at-the-object-level">at the object level&lt;/a> or
&lt;a href="#at-the-controller-level">at the controller level&lt;/a>.&lt;/p>
&lt;h3 id="at-the-object-level">At the object level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the object level.
This allows users to adhere to the
&lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">Least Privilege Principle&lt;/a>,
as each Flux resource can be configured with its own identity and therefore its own
permissions. This is useful for multi-tenancy scenarios, where different
teams can use the same cluster but need to be isolated from each other
inside their own namespaces.&lt;/p>
&lt;h4 id="for-workload-identity-federation">For Workload Identity Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; &lt;strong>Attention&lt;/strong>: &lt;em>Only for AKS clusters targeting Azure resources&lt;/em>
object-level workload identity is currently unstable. In its current state
the feature may stop working without notice depending on actions taken by
Azure to meet AKS customers&amp;rsquo; demands. For continued support the feature
may need to evolve in a way that additional configuration steps will be
required for it to continue working in future Flux releases.
See
&lt;a href="https://github.com/fluxcd/flux2/issues/5359" target="_blank">this&lt;/a> issue for more
information.&lt;/p>
&lt;/blockquote>
&lt;p>For configuring authentication through a Kubernetes Service Account
at the object level the following steps are required:&lt;/p>
&lt;ol>
&lt;li>Enable the feature gate &lt;code>ObjectLevelWorkloadIdentity&lt;/code> in the target Flux controller Deployment
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>(some-controller)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/args/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: --feature-gates=ObjectLevelWorkloadIdentity=true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>Set the &lt;code>.spec.provider&lt;/code> field to &lt;code>azure&lt;/code> in the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, this field is not
required/does not exist, SOPS detects the provider from the metadata
in the SOPS-encrypted Secret. For remote cluster access with the
&lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is &lt;code>.data.provider&lt;/code>
inside the referenced &lt;code>ConfigMap&lt;/code> from &lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;li>Use the &lt;code>.spec.serviceAccountName&lt;/code> field to specify the name of the
Kubernetes Service Account in the same namespace as the Flux resource.
For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, the field is
&lt;code>.spec.decryption.serviceAccountName&lt;/code>. For remote cluster access with
the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs the field is
&lt;code>.data.serviceAccountName&lt;/code> inside the referenced &lt;code>ConfigMap&lt;/code> from
&lt;code>.spec.kubeConfig.configMapRef&lt;/code>.&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: The &lt;code>azure.workload.identity/client-id&lt;/code> and &lt;code>azure.workload.identity/tenant-id&lt;/code>
annotations are defined by AKS, but Flux also uses them to identify the Managed Identity
to impersonate in non-AKS clusters. This is for providing users with a seamless experience.&lt;/p>
&lt;/blockquote>
&lt;h4 id="for-application-certificates">For Application Certificates&lt;/h4>
&lt;p>Only the ABS and AKV integrations support configuring
authentication through an Application Certificate at
the object level.&lt;/p>
&lt;p>For configuring authentication through an Application Certificate for
the &lt;code>Bucket&lt;/code> API:&lt;/p>
&lt;ul>
&lt;li>Set the &lt;code>.spec.provider&lt;/code> field to &lt;code>azure&lt;/code>.&lt;/li>
&lt;li>Set the &lt;code>.spec.secretRef.name&lt;/code> field to the name of the Kubernetes
Secret in the same namespace as the &lt;code>Bucket&lt;/code> resource.&lt;/li>
&lt;/ul>
&lt;p>The Secret must looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SECRET_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">stringData&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">tenantId&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;tenant ID&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">clientId&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;client ID&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">clientCertificate&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;certificate and private key&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#60a0b0;font-style:italic"># Plus optionally&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">clientCertificatePassword&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;password if the private key is encrypted&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">clientCertificateSendChain&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#60a0b0;font-style:italic"># this boolean value must be quoted&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API:&lt;/p>
&lt;ul>
&lt;li>Set the &lt;code>.spec.decryption.secretRef.name&lt;/code> field to the name of the Kubernetes
Secret in the same namespace as the &lt;code>Kustomization&lt;/code> resource.&lt;/li>
&lt;/ul>
&lt;p>The Secret must look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SECRET_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NAMESPACE&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">stringData&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">sops.azure-kv&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> tenantId: &amp;lt;tenant ID&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> clientId: &amp;lt;client ID&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> clientCertificate: &amp;lt;certificate and private key&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # Plus optionally
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> clientCertificatePassword: &amp;lt;password if the private key is encrypted&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> clientCertificateSendChain: true # this boolean value must NOT be quoted&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="at-the-controller-level">At the controller level&lt;/h3>
&lt;p>All the Flux APIs support configuring authentication at the controller level.
This is more appropriate for single-tenant scenarios, where all the Flux resources
inside the cluster belong to the same team and hence can share the same identity
and permissions.&lt;/p>
&lt;p>At the controller level, regardless if authenticating with Workload Identity Federation
or Application Certificates, all Flux resources must have the provider field set to
&lt;code>azure&lt;/code> according to the rules below.&lt;/p>
&lt;p>For all Flux resource kinds except for &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code>, set
the &lt;code>.spec.provider&lt;/code> field to &lt;code>azure&lt;/code> and leave &lt;code>.spec.serviceAccountName&lt;/code> unset.&lt;/p>
&lt;p>For SOPS decryption with the &lt;code>Kustomization&lt;/code> API, leave the
&lt;code>.spec.decryption.serviceAccountName&lt;/code> field unset. There&amp;rsquo;s
no provider field for SOPS decryption.&lt;/p>
&lt;p>For remote cluster access with the &lt;code>Kustomization&lt;/code> and &lt;code>HelmRelease&lt;/code> APIs,
set the &lt;code>.data.provider&lt;/code> field of the &lt;code>ConfigMap&lt;/code> referenced by the
&lt;code>.spec.kubeConfig.configMapRef&lt;/code> field to &lt;code>azure&lt;/code> and leave the
&lt;code>.data.serviceAccountName&lt;/code> field unset.&lt;/p>
&lt;p>The controller-level configuration is described in the following sections.&lt;/p>
&lt;h4 id="for-workload-identity-federation-1">For Workload Identity Federation&lt;/h4>
&lt;p>Before following the steps below, make sure to complete the cluster setup
described
&lt;a href="#supported-clusters">here&lt;/a>, and to configure the Kubernetes
Service Account as described
&lt;a href="#supported-identity-types">here&lt;/a>.&lt;/p>
&lt;p>If the cluster is AKS, the controller Kubernetes Service Account and Deployment
must be patched
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>The Kubernetes Service Account of the controller must be configured
to impersonate a Managed Identity. This is done by adding the
&lt;code>azure.workload.identity/client-id&lt;/code> and &lt;code>azure.workload.identity/tenant-id&lt;/code>
annotations.&lt;/li>
&lt;li>The label &lt;code>azure.workload.identity/use: &amp;quot;true&amp;quot;&lt;/code> must be added to the
controller Deployment template metadata. This label is used by the AKS mutating
webhook to automatically configure the controller pod during admission to use
Workload Identity.&lt;/li>
&lt;/ul>
&lt;p>The controller patch should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ServiceAccount&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> apiVersion: v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> kind: ServiceAccount
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: controller
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> annotations:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> azure.workload.identity/client-id: CLIENT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> azure.workload.identity/tenant-id: TENANT_ID&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> apiVersion: apps/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> kind: Deployment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: (some-controller)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> template:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> labels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> azure.workload.identity/use: &amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the configuration above is done after bootstrap, restart (delete) the controller
for the binding to take effect.&lt;/p>
&lt;p>If the cluster &lt;em>is not&lt;/em> AKS, the controller Deployment must be patched
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>A projected volume must be mounted in the controller Deployment with a Kubernetes
Service Account token whose audience is set to &lt;code>api://AzureADTokenExchange&lt;/code>.&lt;/li>
&lt;li>The environment variables shown below must be set in the controller Deployment.&lt;/li>
&lt;/ul>
&lt;p>The controller patch should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_TENANT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: TENANT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_CLIENT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: CLIENT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_AUTHORITY_HOST
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: https://login.microsoftonline.com/
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # or https://login.microsoftonline.us/ for US Gov
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # or https://login.chinacloudapi.cn/ for China
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_FEDERATED_TOKEN_FILE
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: /var/run/service-account/azure-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: azure-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> projected:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> sources:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - serviceAccountToken:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> audience: api://AzureADTokenExchange
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> expirationSeconds: 3600
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: azure-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: azure-token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /var/run/service-account
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="for-application-certificates-1">For Application Certificates&lt;/h4>
&lt;p>Mount the Kubernetes Secret containing the certificate and private key in
the controller Deployment and set the environment variables shown below
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/installation/configuration/bootstrap-customization/">during bootstrap&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kustomize.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Kustomization&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-components.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- gotk-sync.yaml&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">patches&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#062873;font-weight:bold">target&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#4070a0">&amp;#34;(some-controller)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">patch&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_TENANT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: TENANT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_CLIENT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: CLIENT_ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_CLIENT_CERTIFICATE_PATH
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: /var/run/app-cert/cert-and-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/volumes/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: app-cert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secret:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secretName: SECRET_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/volumeMounts/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: app-cert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> mountPath: /var/run/app-cert/cert-and-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> subPath: cert-and-key
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> readOnly: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # ---------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # Plus optionally
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> # ---------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_CLIENT_CERTIFICATE_PASSWORD
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> valueFrom:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> secretKeyRef:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: SECRET_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> key: key-password
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> - op: add
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> path: /spec/template/spec/containers/0/env/-
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> name: AZURE_CLIENT_SEND_CERTIFICATE_CHAIN
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4070a0;font-style:italic"> value: &amp;#34;true&amp;#34; # this boolean value must be quoted&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Secret should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#062873;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>SECRET_NAME&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>flux-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Opaque&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#062873;font-weight:bold">stringData&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">cert-and-key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;certificate and private key&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#60a0b0;font-style:italic"># Plus optionally&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#062873;font-weight:bold">key-password&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;password if the private key is encrypted&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="at-the-node-level">At the node level&lt;/h3>
&lt;p>Only for the ACR integrations Flux supports authentication
at the node level for AKS. This is because users often already have to configure
authentication at the node level for AKS to be able to pull container images from
ACR in order to start pods. By supporting this authentication method Flux allows
users to configure ACR authentication in a single way. See
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/cluster-container-registry-integration" target="_blank">docs&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; Node level authentication may work for other integrations as well,
but Flux only has continuous integration tests for the ACR integration in
order to support the specific use case described above.&lt;/p>
&lt;/blockquote>
&lt;p>For node-level authentication to work, the &lt;code>.spec.provider&lt;/code> field of the Flux
resources must be set to &lt;code>azure&lt;/code>.&lt;/p>
&lt;h2 id="supported-azure-clouds">Supported Azure Clouds&lt;/h2>
&lt;p>Flux integrations described in this document are supported in Azure Public Cloud (the default environment for most Azure users), in specialized environments such as
&lt;a href="https://learn.microsoft.com/en-us/azure/china/overview-operations" target="_blank">Azure in China&lt;/a>,
&lt;a href="https://azure.microsoft.com/en-us/explore/global-infrastructure/government" target="_blank">Azure US Government Cloud&lt;/a> and in private clouds.&lt;/p>
&lt;h3 id="private-cloud-configuration">Private Cloud Configuration&lt;/h3>
&lt;p>To configure Flux for a private cloud, you must set the &lt;code>AZURE_ENVIRONMENT_FILEPATH&lt;/code> environment variable at the controller level. This variable should point to a JSON configuration file mounted into the controller pod that defines the custom Azure endpoints. An example configuration file with the list of custom endpoints supported by Flux is shared below.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;resourceManagerEndpoint&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;https://management.core.private/&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;tokenAudience&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;https://management.core.private/&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;containerRegistryDNSSuffix&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;azurecr.private&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Flux: Support for cross-cloud</title><link>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/cross-cloud/</guid><description>
&lt;p>The tables below show the compatibility matrix for Flux running inside a
&lt;em>source cluster&lt;/em> aiming to get access to resources in a &lt;em>target cloud provider&lt;/em>
using secret-less authentication.&lt;/p>
&lt;p>For each target cloud provider, you can find the authentication docs here:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/aws/#authentication">AWS&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/azure/#authentication">Azure&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/gcp/#authentication">GCP&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="authentication-at-the-object-level-best-for-multi-tenant-use-cases">Authentication at the object level (best for multi-tenant use cases)&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Source Cluster Type&lt;/th>
&lt;th>AWS&lt;/th>
&lt;th>Azure&lt;/th>
&lt;th>GCP&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AKS&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>EKS&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GKE&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Other (e.g. &lt;code>kind&lt;/code>)&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="authentication-at-the-controller-level-best-for-single-tenant-use-cases">Authentication at the controller level (best for single-tenant use cases)&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Source Cluster Type&lt;/th>
&lt;th>AWS&lt;/th>
&lt;th>Azure&lt;/th>
&lt;th>GCP&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AKS&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>EKS&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GKE&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Other (e.g. &lt;code>kind&lt;/code>)&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Secret-based authentication is supported across all combinations, but
should be avoided in favor of secret-less authentication when available. Secrets
can be stolen to abuse the permissions granted to the identities they represent,
and for public clouds this can be done by simply having Internet access. This
requires secrets to be regularly rotated and more security controls to be put in
place, like audit logs, secret management tools, etc. Secret-less authentication
does not have this problem, as the identity is authenticated using a token that
is not stored anywhere and is only valid for a short period of time, usually one
hour. It&amp;rsquo;s much harder to steal an identity this way.&lt;/p>
&lt;/blockquote>
&lt;h2 id="source-cluster-setup">Source cluster setup&lt;/h2>
&lt;p>When configuring access from a source cluster to a target cloud provider, you
need to configure the &lt;em>Issuer URL&lt;/em> of the source cluster as an &lt;em>OIDC Provider&lt;/em> in
the target cloud provider. In this section we show how to obtain the Issuer URL
of the source cluster. For instructions on how to create an OIDC provider with
this URL in the target cloud provider, go to these links:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/aws/#supported-clusters">AWS&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/azure/#supported-clusters">Azure&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-2413--fluxcd.netlify.app/flux/integrations/gcp/#supported-clusters">GCP&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="obtaining-the-issuer-url-of-the-source-cluster">Obtaining the Issuer URL of the source cluster&lt;/h3>
&lt;p>Source cluster setup varies depending on the type of cluster.
For details on how to set up the source cluster, see the sections that follow.
Once this is done, to obtain the Issuer URL you can use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl get --raw /.well-known/openid-configuration | jq
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Example output for a GKE cluster:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;issuer&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;https://container.googleapis.com/v1/projects/&amp;lt;projectID&amp;gt;/locations/&amp;lt;location&amp;gt;/clusters/&amp;lt;name&amp;gt;&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;jwks_uri&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;https://&amp;lt;some-ip-address&amp;gt;:443/openid/v1/jwks&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;response_types_supported&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;id_token&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;subject_types_supported&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;public&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;id_token_signing_alg_values_supported&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4070a0">&amp;#34;RS256&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Issuer URL is:&lt;/p>
&lt;pre tabindex="0">&lt;code>https://container.googleapis.com/v1/projects/&amp;lt;projectID&amp;gt;/locations/&amp;lt;location&amp;gt;/clusters/&amp;lt;name&amp;gt;
&lt;/code>&lt;/pre>&lt;h3 id="for-managed-kubernetes-services-from-cloud-providers">For managed Kubernetes services from cloud providers&lt;/h3>
&lt;p>Depending on the type of source cluster, the Issuer URL may already be public
and no cluster setup will be required. This is usually the case for the managed
Kubernetes services from the cloud providers, e.g. EKS and GKE. AKS needs
&lt;a href="https://learn.microsoft.com/en-us/azure/aks/use-oidc-issuer#create-an-aks-cluster-with-the-oidc-issuer" target="_blank">setup&lt;/a>.&lt;/p>
&lt;h3 id="for-clusters-without-a-built-in-public-issuer-url">For clusters without a built-in public Issuer URL&lt;/h3>
&lt;p>Some clusters do not have a built-in public Issuer URL, like self-managed, on-premises,
or &lt;code>kind&lt;/code> clusters running on a local machine or in CI pipelines.&lt;/p>
&lt;p>The Kubernetes API Server offers a couple of binary flags that allow customizing the
Issuer URL and JWKS URI of the cluster&amp;rsquo;s &lt;em>service account token issuer&lt;/em>. See
&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>These flags are:&lt;/p>
&lt;ul>
&lt;li>&lt;code>--service-account-issuer&lt;/code>: Allows setting the &lt;code>issuer&lt;/code> field returned in the
&lt;code>/.well-known/openid-configuration&lt;/code> endpoint as shown in the example
&lt;a href="#obtaining-the-issuer-url-of-the-source-cluster">above&lt;/a>.&lt;/li>
&lt;li>&lt;code>--service-account-jwks-uri&lt;/code>: Allows setting the &lt;code>jwks_uri&lt;/code> field returned in the
&lt;code>/.well-known/openid-configuration&lt;/code> endpoint as shown in the example
&lt;a href="#obtaining-the-issuer-url-of-the-source-cluster">above&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>This ability to customize the Issuer URL and JWKS URI enables users to host static
discovery documents on public URLs, e.g. with CDNs or object storage systems like
AWS S3, Azure Blob Storage or GCP Cloud Storage.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: This customization is achieved &lt;em>without exposing the Kubernetes API Server
endpoint to the Internet&lt;/em>. Furthermore, JWKS stands for &lt;em>JSON Web Key Set&lt;/em>, which in
the OIDC protocol is a JSON-encoded set of &lt;em>public&lt;/em> keys that cloud providers can use
to verify the signatures of JWTs issued by external identity providers, like the
Kubernetes service account token issuer. In other words, the JWKS document content
is meant to be public.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; When performing this operation, remember to set the &lt;code>--service-account-issuer&lt;/code>
flag with both the new and the previous value, &lt;strong>in this specific order&lt;/strong>, to avoid
disruption in the cluster. This flag is allowed to be set multiple times for this
purpose. The first value will be used to issue new tokens, and all the values will be
used to determine which issuers are accepted by the API Server when authenticating
requests, i.e. when validating existing tokens. Bear in mind that the service account
tokens are used not only by Flux to get access on cloud providers, but also by Flux
and many other core components of Kubernetes to authenticate with the API Server.
You need to be extremely cautious performing this operation. Make sure to update the
API Server flags only after you have successfully uploaded the discovery documents
and confirmed that they are publicly accessible.&lt;/p>
&lt;/blockquote>
&lt;p>Steps to perform this setup:&lt;/p>
&lt;ol>
&lt;li>Run the command &lt;code>kubectl get --raw /.well-known/openid-configuration | jq&lt;/code>
shown
&lt;a href="#obtaining-the-issuer-url-of-the-source-cluster">above&lt;/a> to get
the current discovery document.&lt;/li>
&lt;li>Change the &lt;code>issuer&lt;/code> field to the new Issuer URL you want to use. For example,
if you decide to use AWS S3, the Issuer URL should look like this:
&lt;code>https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;&lt;/code>.&lt;/li>
&lt;li>Change the &lt;code>jwks_uri&lt;/code> field to the new JWKS URI you want to use. For example,
if you decide to use AWS S3, the JWKS URI should look like this:
&lt;code>https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;/openid/v1/jwks&lt;/code>.&lt;/li>
&lt;li>Upload the modified discovery document to the public URL you want to use.
For example, if you decide to use AWS S3, the object key must be
&lt;code>.well-known/openid-configuration&lt;/code> and the bucket must be publicly accessible.&lt;/li>
&lt;li>Test that the discovery document was correctly uploaded by &lt;code>curl&lt;/code>ing the URL
you created. For example, if you decide to use AWS S3, the &lt;code>curl&lt;/code> command
should look like this:
&lt;code>curl https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;/.well-known/openid-configuration&lt;/code>.
The output should be the modified discovery document you uploaded, with the
&lt;code>issuer&lt;/code> field matching &lt;code>https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;&lt;/code> and the
&lt;code>jwks_uri&lt;/code> field matching &lt;code>https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;/openid/v1/jwks&lt;/code>.&lt;/li>
&lt;li>Run the command &lt;code>kubectl get --raw /openid/v1/jwks | jq&lt;/code> to get the JWKS document.&lt;/li>
&lt;li>Upload the JWKS document to the public URL you want to use. For example,
if you decide to use AWS S3, the object key must be &lt;code>openid/v1/jwks&lt;/code> and
the bucket must be publicly accessible.&lt;/li>
&lt;li>Test that the JWKS document was correctly uploaded by &lt;code>curl&lt;/code>ing the URL
you created. For example, if you decide to use AWS S3, the &lt;code>curl&lt;/code> command
should look like this:
&lt;code>curl https://s3.amazonaws.com/&amp;lt;bucket-name&amp;gt;/openid/v1/jwks&lt;/code>. The output
should be the JWKS document you uploaded.&lt;/li>
&lt;li>Finally, update the Kubernetes API Server flags mentioned above to use the new
Issuer URL and JWKS URI.&lt;/li>
&lt;/ol>
&lt;p>Here&amp;rsquo;s an example of the output of &lt;code>kubectl get --raw /openid/v1/jwks&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;keys&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;use&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;sig&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;kty&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;RSA&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;kid&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;BfK54vFk8UqizgJVa1BfRfNl-C5c3mWwQ1o_-bA-yAo&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;alg&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;RS256&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;n&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;qN1iYk24aS&amp;lt;... very long redacted public key string ...&amp;gt;IvUY8e4wSaw&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#062873;font-weight:bold">&amp;#34;e&amp;#34;&lt;/span>: &lt;span style="color:#4070a0">&amp;#34;AQAB&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="rotating-the-private-key-used-by-kubernetes-to-sign-service-account-tokens">Rotating the private key used by Kubernetes to sign service account tokens&lt;/h4>
&lt;p>If you manage the cluster yourself, you may (probably!) want to rotate the private
key used by API Server to issue service account tokens from time to time. When
doing so, &lt;em>you must remember to update the JWKS document upstream&lt;/em>, otherwise
Flux will lose access to your cloud providers.&lt;/p>
&lt;p>See how you can manage/rotate the private key used
by API Server to sign the service account tokens
&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection" target="_blank">here&lt;/a>.
Quote from the docs:&lt;/p>
&lt;ul>
&lt;li>&lt;code>--service-account-signing-key-file string&lt;/code>: &amp;ldquo;Specifies the path to a file that
contains the current private key of the service account token issuer. The issuer
signs issued ID tokens with this private key.&amp;rdquo;&lt;/li>
&lt;li>&lt;code>--service-account-key-file strings&lt;/code>: &amp;ldquo;Specifies the path to a file containing
PEM-encoded X.509 private or public keys (RSA or ECDSA), used to verify
ServiceAccount tokens. The specified file can contain multiple keys, and the
flag can be specified multiple times with different files. If specified multiple
times, tokens signed by any of the specified keys are considered valid by the
Kubernetes API Server.&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;p>The ability to specify multiple public keys for signature verification is
for allowing rotations to take place without disruption. Existing tokens
will be valid until they expire or until the public key that can
verify them is removed from the API Server.&lt;/p>
&lt;blockquote>
&lt;p>&amp;#x26a0;&amp;#xfe0f; Bear in mind that service account tokens are used not only by
Flux to get access on cloud providers, but also by Flux and many other
core components of Kubernetes to authenticate with the API Server.
You need to be extremely cautious when rotating this private key.&lt;/p>
&lt;/blockquote>
&lt;h4 id="special-feature-from-gcp-workload-identity-federation">Special feature from GCP Workload Identity Federation&lt;/h4>
&lt;p>GCP Workload Identity Federation allows you to directly upload the
JWKS document, which frees you from having to customize the API
Server flags and from having to host the discovery documents on
public URLs, &lt;em>but you still need to update the JWKS document if you
rotate the private key of the cluster&lt;/em>.
See
&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes#create_the_workload_identity_pool_and_provider" target="_blank">docs&lt;/a>.&lt;/p>
&lt;p>As of now, GCP is the only cloud provider that supports this feature.&lt;/p></description></item></channel></rss>