When deploying applications I try to separate the components by the frequency that they change. Low frequency items like kube clusters, ingress, databases etc will be handled by the infra
pipeline and high frequency items like the app will be handled by the app
pipeline.
In the app
pipeline I want to use a credential with least privilege to perform the deployment.
The setup:
- Application on Google cloud (GCP)
- Deployed on Google Kubernetes Engine (GKE)
- Deployed via Github Actions
The simple (but less than ideal) way to do this is to set up github actions to use a gcp service account with the gcp permission of container.admin
or container.clusterAdmin
. However, assuming the deploy action only needs to edit an apps/v1/deployment
, this would give the service account far too many permissions.
Here is a simple way to setup a gcp service account with minimum/least privilege to deploy applications.
resource "google_service_account" "github-deployer" {
account_id = "github-deployer"
display_name = "github-deployer"
}
resource "google_project_iam_member" "kube_connector" {
project = var.project_id
role = "roles/container.clusterViewer"
member = "serviceAccount:${google_service_account.github-deployer.email}"
}
This roles/container.clusterViewer
only provides the ability to connect to the cluster not to do anything in that cluster. Authentication, not authorization.
Then you extend that with a kubernetes RBAC configuration:
The role
:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app
name: deployer
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list", "update", "delete", "create", "patch"]
The roleBinding
:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: deployer
namespace: app
subjects:
# IAM service account
- kind: User
name: github-deployer@my-simple-test-project-derp.iam.gserviceaccount.com
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
With this in place, the google service account can edit pods and deployments, but can’t even see let alone edit secrets, ingress, services, or other resources in the app
or other namespaces.
Effectively creating a least privilege ci/cd setup for use in github actions or any other system.
References: