Skip to content

Instantly share code, notes, and snippets.

@craftyc0der
Last active November 28, 2020 22:25
Show Gist options
  • Save craftyc0der/3ec5998bbd5f03bd9bd3cb8ac3b02e88 to your computer and use it in GitHub Desktop.
Save craftyc0der/3ec5998bbd5f03bd9bd3cb8ac3b02e88 to your computer and use it in GitHub Desktop.
Helm v3 Security

RBAC Helm Security for Kubernetes

It is critical to note that Helm v3 is required for a secure helm environment.

Helm v2 used Tiller to facilitate installation of charts and this had its own security.

Helm v3 uses RBAC security to do this.

https://helm.sh/docs/faq/

https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/

In this example we will create a user with limited capabilities that will install the charts the developers modify. These cannot contain ingress for example.

Create an AWS Role

aws iam create-role --role-name Kubernetes-Deployment \
--assume-role-policy-document file://tr.json

tr.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxx:user/josh",
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Update K8S aws-auth

with kubectl user with system:masters group

kubectl edit cm -n kube-system aws-auth

append to mapRoles array the new role

apiVersion: v1
data:
  mapRoles: |
    - rolearn: arn:aws:iam::xxx:role/Kubernetes-Deployment
      username: kubernetes-deployment

Add Role and RoleBinding

with kubectl user with system:masters group

kubectl create namespace deploy-test
kubectl apply -f deployment-role.yaml

deployment-role.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: deployment-only
  namespace: deploy-test
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - services
  - services/finalizers
  - endpoints
  - persistentvolumeclaims
  - events
  - configmaps
  - secrets
  - serviceaccounts
  - namespaces
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - apps
  resources:
  - deployments
  - daemonsets
  - replicasets
  - statefulsets
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: deployment-only-binding
  namespace: deploy-test
subjects:
- kind: User
  name: kubernetes-deployment
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: deployment-only
  apiGroup: rbac.authorization.k8s.io

It would be fair to dsecribe these permissions as overly permissive. Feel free to truncate unnecessary capabilities.

Create kube_config to test role

duplicate a working kube-config in your ~/.kube/config-test folder

replace users section with

users:
- name: your-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      Args:
      - token
      - -i
      - your-cluster
      - -r
      - arn:aws:iam::xxx:role/Kubernetes-Deployment
      command: aws-iam-authenticator
      env:
      - name: AWS_PROFILE
        value: default

Test Helm Install

https://hub.helm.sh/charts/bitnami/nginx

helm --kubeconfig=/home/user/.kube/config-test install \
nginx-test bitnami/nginx --version 5.7.0 --namespace deploy-test \
--set ingress.enabled=true

This returns an error because we requested an Ingress

Error: rendered manifests contain a resource that already exists. 
Unable to continue with install: could not get information about the resource: ingresses.
extensions "nginx-test" is forbidden: User "kubernetes-deployment" cannot get resource
"ingresses" in API group "extensions" in the namespace "deploy-test"
helm --kubeconfig=/home/user/.kube/config-test \
install nginx-test bitnami/nginx --version 5.7.0 \
--namespace deploy-test --set ingress.enabled=false
NAME: nginx-test
LAST DEPLOYED: Sat Jun  6 15:32:22 2020
NAMESPACE: deploy-test
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get the NGINX URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace deploy-test -w nginx-test'

  export SERVICE_IP=$(kubectl get svc --namespace deploy-test nginx-test --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo "NGINX URL: http://$SERVICE_IP/"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment