EKS with ArgoCD
Argo CD is an open-source declarative, GitOps continuous delivery tool for Kubernetes applications. It enables developers to manage and deploy applications on Kubernetes clusters using Git repositories as the source of truth for configuration and definitions. Argo CD follows the GitOps methodology, which means that the entire application configuration, including manifests, parameters, and even application state, is stored in a Git repository.
SAML Security Considerations
SAML is an industry-standard but security concerns have been raised by Dex, Mastadon, and others, due to the inherent difficulty of validating XML documents and inconsistent handling by SAML libraries in various languages. Our ArgoCD implementation by default uses SAML authentication with Dex and ArgoCD.
For more information, please see:
- SAML is insecure by design
- SAML Raider - SAML2 Burp Extension
- Proposal: deprecate the SAML connector
- Mattermost blog post of July 28, 2021 where
@jupenur
states:If you maintain an application in Ruby, JavaScript, .NET, or Java and rely on SAML or other security-critical XML use-cases, the question burning in the back of your mind should be: “How do I patch this?” The good news is that you should already be patched if you use Ruby or JavaScript and update your dependencies regularly. And if you use .NET or Java, there’s probably nothing to worry about.
Overview
Argo CD simplifies the deployment and management of applications on Kubernetes by leveraging GitOps principles, providing a clear separation between the desired state of applications and the operational state of the cluster. This approach enhances collaboration, repeatability, and traceability in the deployment process.
Deployment
Application repository will create a deployment when a workflow is triggered and call the relevant shared workflow.
Check out our example app-on-eks-with-argocd for the latest example of how to use ArgoCD with GitHub Actions.
- Feature
- Main
- Release
name: Feature Branch
on:
pull_request:
branches: [ 'main' ]
types: [opened, synchronize, reopened, closed, labeled, unlabeled]
permissions:
pull-requests: write
deployments: write
id-token: write
contents: read
jobs:
do:
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/feature-branch.yml@main
with:
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
open: ${{ github.event.pull_request.state == 'open' }}
labels: ${{ toJSON(github.event.pull_request.labels.*.name) }}
ref: ${{ github.event.pull_request.head.ref }}
secrets:
github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}"
registry: "${{ secrets.ECR_REGISTRY }}"
secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}"
ecr-region: "${{ secrets.ECR_REGION }}"
ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}"
name: Main Branch
on:
push:
branches: [ main ]
permissions:
contents: write
id-token: write
jobs:
do:
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/main-branch.yml@main
with:
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
secrets:
github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}"
registry: "${{ secrets.ECR_REGISTRY }}"
secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}"
ecr-region: "${{ secrets.ECR_REGION }}"
ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}"
name: Release
on:
release:
types: [published]
permissions:
id-token: write
contents: write
jobs:
perform:
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/release.yml@main
with:
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
version: ${{ github.event.release.tag_name }}
secrets:
github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}"
registry: "${{ secrets.ECR_REGISTRY }}"
secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}"
ecr-region: "${{ secrets.ECR_REGION }}"
ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}"
That workflow calls a Reusable Workflow, cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd
, that is designed to deploy a
dockerized application from ECR to EKS using ArgoCD specifically.
Hotfix Workflows
Hotfix workflows are designed to push changes directly to a released version in production. Ideally we want any change to move through the standard release lifecycle, but in reality there are times when we need the ability to push a hotfix directly to production.
In order to enable hotfix workflows, create two additional workflows and modify the existing release workflow. See each of the following workflows:
- Release Branch
- Hotfix Branch
- Hotfix Release
Before running any hotfix workflows, we must first create release branches with any release. Modify the existing release workflow to include the hotfix
job below.
name: Release
on:
release:
types: [published]
permissions:
id-token: write
contents: write
jobs:
perform:
...
hotfix:
name: release / branch
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-mixin.yml@main
with:
version: ${{ github.event.release.tag_name }}
This hotfix-branch.yaml
workflow will deploy a duplicate app in the production cluster to a new namespace. We need to deploy to production to validate a hotfix directly for production.
Deploy this workflow by creating a Pull Request into the a release branch and adding the deploy
label.
name: Hotfix Branch
on:
pull_request:
branches: [ 'release/**' ]
types: [opened, synchronize, reopened, closed, labeled, unlabeled]
permissions:
pull-requests: write
deployments: write
id-token: write
contents: read
jobs:
do:
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-branch.yml@main
with:
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
open: ${{ github.event.pull_request.state == 'open' }}
labels: ${{ toJSON(github.event.pull_request.labels.*.name) }}
ref: ${{ github.event.pull_request.head.ref }}
path: deploy
secrets:
github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}"
registry: "${{ secrets.ECR_REGISTRY }}"
secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}"
ecr-region: "${{ secrets.ECR_REGION }}"
ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}"
Once we've validated a Pull Request for a given hotfix, we can merge that change into the release branch. When changes are pushed to a release branch, the "Hotfix Release" workflow is triggered. This workflow will deploy the given change directly to production.
Before deploying, the workflow will create a minor version release and test it. After the deployment, it will create a reintegration pull request to bring the hotfix back into the main branch and lower environments.
In order to enable the "Hotfix Release" workflow, add the following:
name: Hotfix Release
on:
push:
branches: [ 'release/**' ]
permissions:
contents: write
id-token: write
jobs:
do:
uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-release.yml@main
with:
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
path: deploy
secrets:
github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}"
registry: "${{ secrets.ECR_REGISTRY }}"
secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}"
ecr-region: "${{ secrets.ECR_REGION }}"
ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}"
These workflows also call the same Reusuable Workflow repository, cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd
, as well as several of the same Reusuable Workflows called from that repository. For example, cloudposse/github-actions-workflows
and cloudposse/actions-private
.
Be sure the environment configuration mapping includes hotfix
. This typically lives with your private configuration repository, for example cloudposse/actions-private
, and is called by the cloudposse/github-action-interface-environment
action.
For example, add the following:
runs:
using: "composite"
steps:
- name: Environment info
uses: cloudposse/github-action-yaml-config-[email protected]
id: result
with:
query: .${{ inputs.environment }}
config: |
...
hotfix:
cluster: https://github.com/GH_ORG/argocd-deploy-prod/blob/main/plat/use2-prod/apps
cluster-role: arn:aws:iam::PRODUCTION_ACCOUNT_ID:role/acme-plat-use2-prod-eks-cluster-gha
namespace: ${{ inputs.namespace }}
ssm-path: platform/acme-plat-use2-prod-eks-cluster
Implementation
eks/argocd
: This component is responsible for provisioning ArgoCD.argocd-repo
: This component is responsible for creating and managing an ArgoCD desired state repository.sso-saml-provider
: This component reads sso credentials from SSM Parameter store and provides them as outputs