ProficientNowTechRFCs

7. GitOps Identity

RFC-WORKLOAD-IDENTITY-0001                                      Section 7
Category: Standards Track                                 GitOps Identity

7. GitOps Identity

← Previous: CI/CD Identity | Index | Next: Operator Identity →


7.1 GitOps Operator Overview

7.1.1 GitOps Operators in the Platform

OperatorFunctionIdentity Needs
ArgoCDApplication deploymentGit repos, Kubernetes clusters, Vault
FluxApplication deploymentGit repos, Kubernetes clusters, cloud resources
KargoProgressive deliveryGit repos, image registries, Kubernetes

7.1.2 Identity Requirements

GitOps operators need access to:

ResourceAccess Type
Git repositoriesRead manifests, write status
Kubernetes clustersApply manifests (RBAC)
Image registriesPull image metadata
Secret storesRead secrets for deployments
Cloud APIsDeploy cloud resources (IaC)

7.2 ArgoCD Identity Model

7.2.1 ArgoCD Components

ComponentServiceAccountIdentity Scope
argocd-serverargocd-serverAPI, UI, webhook handling
argocd-repo-serverargocd-repo-serverGit operations, manifest rendering
argocd-application-controllerargocd-application-controllerKubernetes deployment, sync
argocd-applicationset-controllerargocd-applicationset-controllerApplicationSet generation

7.2.2 Repository Credentials

ArgoCD needs credentials to access Git repositories:

MethodConfigurationRecommendation
SSH KeyStored in SecretUse for private repos (rotate regularly)
GitHub AppApp installation tokenPreferred for GitHub
HTTPS TokenPAT or deploy tokenAvoid (use App instead)

Credential storage via ESO:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: argocd-repo-creds
  namespace: argocd
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault
    kind: ClusterSecretStore
  target:
    name: argocd-repo-creds
    template:
      metadata:
        labels:
          argocd.argoproj.io/secret-type: repo-creds
  data:
    - secretKey: sshPrivateKey
      remoteRef:
        key: secret/platform/argocd/github-deploy-key
        property: private_key

7.2.3 Cluster Access

ArgoCD application-controller needs Kubernetes RBAC:

# In-cluster access (same cluster)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: argocd-application-controller
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]  # Required for deployment
---
# Multi-cluster: External cluster credentials via ESO
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: cluster-staging
  namespace: argocd
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault
    kind: ClusterSecretStore
  target:
    name: cluster-staging
    template:
      metadata:
        labels:
          argocd.argoproj.io/secret-type: cluster
      data:
        name: staging
        server: "{{ .server }}"
        config: |
          {
            "bearerToken": "{{ .token }}",
            "tlsClientConfig": {
              "caData": "{{ .ca }}"
            }
          }
  data:
    - secretKey: server
      remoteRef:
        key: secret/platform/clusters/staging
        property: server
    - secretKey: token
      remoteRef:
        key: secret/platform/clusters/staging
        property: token
    - secretKey: ca
      remoteRef:
        key: secret/platform/clusters/staging
        property: ca

7.2.4 Vault Access for Secrets

ArgoCD Vault Plugin (AVP) or ESO for secret injection:

# ArgoCD repo-server with Vault access
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-repo-server
  namespace: argocd
---
# Vault role for ArgoCD
# vault write auth/kubernetes-prod/role/argocd-repo-server \
#     bound_service_account_names=argocd-repo-server \
#     bound_service_account_namespaces=argocd \
#     policies=argocd-secrets \
#     ttl=1h

7.2.5 ArgoCD Identity Flow


7.3 Flux Identity Model

7.3.1 Flux Components

ComponentIdentityPurpose
source-controllerServiceAccountFetch Git/Helm/OCI sources
kustomize-controllerServiceAccountApply Kustomize manifests
helm-controllerServiceAccountDeploy Helm releases
image-automation-controllerServiceAccountUpdate image tags in Git

7.3.2 Workload Identity for Cloud

Flux 2.6+ supports cloud workload identity:

# AWS: IAM Role for Service Account (IRSA)
apiVersion: v1
kind: ServiceAccount
metadata:
  name: source-controller
  namespace: flux-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/flux-source
---
# GCP: Workload Identity
apiVersion: v1
kind: ServiceAccount
metadata:
  name: source-controller
  namespace: flux-system
  annotations:
    iam.gke.io/gcp-service-account: flux-source@project.iam.gserviceaccount.com

7.3.3 Git Repository Authentication

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: platform
  namespace: flux-system
spec:
  interval: 1m
  url: ssh://git@github.com/myorg/platform.git
  ref:
    branch: main
  secretRef:
    name: github-deploy-key
---
# Secret from ESO
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: github-deploy-key
  namespace: flux-system
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault
    kind: ClusterSecretStore
  target:
    name: github-deploy-key
  data:
    - secretKey: identity
      remoteRef:
        key: secret/platform/flux/github-deploy-key
        property: private_key
    - secretKey: known_hosts
      remoteRef:
        key: secret/platform/flux/github-deploy-key
        property: known_hosts

7.3.4 Cross-Cluster Deployment

Flux uses kubeconfig secrets for multi-cluster:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: app-staging
  namespace: flux-system
spec:
  interval: 10m
  path: ./apps/staging
  prune: true
  sourceRef:
    kind: GitRepository
    name: platform
  kubeConfig:
    secretRef:
      name: staging-kubeconfig

7.4 Kargo Identity Model

7.4.1 Kargo Components

ComponentIdentityPurpose
kargo-controllerServiceAccountManage Freight, Stages, Promotions
kargo-apiServiceAccountAPI server for UI/CLI
kargo-webhooksServiceAccountAdmission webhooks

7.4.2 Freight Sources

Kargo needs access to artifact sources:

Source TypeAuthentication
GitDeploy key or GitHub App
Image RegistryRegistry credentials
Helm ChartOCI/HTTP credentials

7.4.3 Promotion Credentials

apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
  name: myapp
spec:
  promotionPolicies:
    - stage: staging
      autoPromotionEnabled: true
    - stage: production
      autoPromotionEnabled: false
---
# Credentials secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: kargo-repo-creds
  namespace: kargo
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault
    kind: ClusterSecretStore
  target:
    name: kargo-repo-creds
  data:
    - secretKey: sshPrivateKey
      remoteRef:
        key: secret/platform/kargo/github-deploy-key
        property: private_key

7.5 Automation Token Management

7.5.1 Token Lifecycle

GitOps automation tokens require careful lifecycle management:

PhaseAction
ProvisioningGenerate in Vault, distribute via ESO
RotationAutomatic refresh via ESO (1h-24h)
RevocationRemove from Vault, ESO syncs deletion
AuditVault audit log tracks access

7.5.2 Token Hierarchy

7.5.3 Break-Glass Procedures

Emergency access when GitOps operators fail:

ScenarioProcedure
ArgoCD downManual kubectl apply with break-glass credentials
Vault unavailablePre-staged emergency secrets (encrypted at rest)
Git unavailableLocal manifest cache, manual sync

Break-glass credentials:

# Stored outside normal GitOps flow
apiVersion: v1
kind: Secret
metadata:
  name: break-glass-kubeconfig
  namespace: kube-system
  annotations:
    description: "Emergency access only. Usage is audited."
type: Opaque
data:
  kubeconfig: <base64-encoded-emergency-kubeconfig>

7.6 Security Considerations

7.6.1 Least Privilege

OperatorMinimum Permissions
ArgoCDOnly target namespaces, not cluster-admin
FluxNamespace-scoped where possible
KargoOnly managed project namespaces

7.6.2 Secret Isolation

PrincipleImplementation
Repo creds separate from cluster credsDifferent Vault paths
Per-environment credentialsEnvironment-specific secrets
Audit all accessVault audit enabled

7.6.3 Attack Surface

Attack VectorMitigation
Compromised Git repoSigned commits, branch protection
Stolen deploy keyRotate regularly, scope narrowly
Compromised operator podNetwork policies, minimal RBAC
Vault token theftShort TTL, Kubernetes auth binding

7.7 Compliance Mapping

7.7.1 Invariant Enforcement

InvariantGitOps Implementation
INV-2ESO refresh < 24h, Vault tokens ≤ 1h
INV-4All operators use Kubernetes auth to Vault
INV-7Namespace-scoped Vault policies
INV-10All credential access audited in Vault

7.7.2 Audit Trail

GitOps creates an inherent audit trail:

EventAudit Source
Manifest changeGit commit history
Secret accessVault audit log
DeploymentArgoCD/Flux events
PromotionKargo promotion history

Document Navigation


End of Section 7