Teleport for EKS Dev Build Guide


#1

Caveat emptor

This is a dev build of Teleport with EKS support. Use at your own risk. DO NOT USE IN PRODUCTION

Deployment

Example deployment object (with a relevant dev image referenced):

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: teleport
  name: teleport
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: teleport
  template:
    metadata:
      labels:
        app: teleport
    spec:
      containers:
      - image: quay.io/gravitational/teleport-ent-dev:20190318112900
        imagePullPolicy: IfNotPresent
        name: teleport
        ports:
        - containerPort: 3025
          name: authssh
          protocol: TCP
        - containerPort: 3022
          name: nodessh
          protocol: TCP
        - containerPort: 3026
          name: proxykube
          protocol: TCP
        - containerPort: 3023
          name: proxyssh
          protocol: TCP
        - containerPort: 3024
          name: proxytunnel
          protocol: TCP
        - containerPort: 3080
          name: proxyweb
          protocol: TCP
        volumeMounts:
        - mountPath: /var/lib/certs
          name: tls-web
          readOnly: true
        - mountPath: /etc/teleport
          name: config
          readOnly: true
        - mountPath: /var/lib/license
          name: license
          readOnly: true
        - mountPath: /var/lib/teleport
          name: storage
      restartPolicy: Always
      serviceAccount: teleport
      serviceAccountName: teleport
      terminationGracePeriodSeconds: 30
      volumes:
      - name: tls-web
        secret:
          defaultMode: 420
          secretName: tls-web
      - name: license
        secret:
          defaultMode: 420
          secretName: license
      - configMap:
          defaultMode: 420
          name: teleport
        name: config
      - emptyDir: {}
        name: storage

It uses empty dir as a temporary storage, it means that all data will be lost during pod restart,
but should be good enough to try it out.

There is a more advanced helm chart that could be modified:

Configuration

This config map provides a sample configuration that uses OIDC auth by default:

apiVersion: v1
kind: ConfigMap
metadata:
  name: teleport
  namespace: default
data:
  teleport.yaml: |
    auth_service:
      authentication:
        type: oidc
      cluster_name: teleport.example.com
      enabled: true
      license_file: /var/lib/license/license-enterprise.pem
      public_addr: teleport.example.com:3025
    proxy_service:
      enabled: true
      https_cert_file: /var/lib/certs/crt
      https_key_file: /var/lib/certs/key
      kubernetes:
        enabled: true
        listen_addr: 0.0.0.0:3026
      listen_addr: 0.0.0.0:3023
      public_addr: teleport.example.com:443
      web_listen_addr: 0.0.0.0:3080
    ssh_service:
      enabled: true
      public_addr: teleport.example.com:3022
    teleport:
      data_dir: /var/lib/teleport
      log:
        output: stderr
        severity: DEBUG
      storage:
        type: dir

License

If you have a license, create if from file, so it looks like this:

apiVersion: v1
data:
  license-enterprise.pem: base64=
kind: Secret
metadata:
  name: license
  namespace: default
type: Opaque

Certs

This example is using a secret with X509 certs referenced by proxy:

apiVersion: v1
data:
  crt: crtdata
  key: keydata
kind: Secret
metadata
  name: tls-web
  namespace: default
type: Opaque

Security

The deployment uses special service account that is authorized to do only one thing: to use impersonation API:

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: teleport
  name: teleport
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app: teleport
  name: teleport
rules:
- apiGroups:
  - ""
  resources:
  - users
  - groups
  - serviceaccounts
  verbs:
  - impersonate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app: teleport
  name: teleport
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: teleport
subjects:
- kind: ServiceAccount
  name: teleport
  namespace: default

Service

This service will create a load balancer for in-EKS teleport proxy:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: teleport
  name: teleport
  namespace: default
spec:
  ports:
  - name: authssh
    nodePort: 30112
    port: 3025
    protocol: TCP
    targetPort: 3025
  - name: proxykube
    nodePort: 32343
    port: 3026
    protocol: TCP
    targetPort: 3026
  - name: proxyssh
    nodePort: 31276
    port: 3023
    protocol: TCP
    targetPort: 3023
  - name: proxytunnel
    nodePort: 31485
    port: 3024
    protocol: TCP
    targetPort: 3024
  - name: proxyweb
    nodePort: 32639
    port: 443
    protocol: TCP
    targetPort: 3080
  selector:
    app: teleport
  sessionAffinity: None
  type: LoadBalancer

Setting up Teleport running in Kubernetes

Because this teleport instance is running in Kubernetes, kubectl exec could be used
to access a running Teleport Pod and set up the auth, here is example Makefile that copies a connector and admin specs and sets them up right in the pod

.PHONY: setup-auth
setup-auth:
	$(eval POD := $(shell kubectl get pods --selector=app=teleport -o jsonpath='{.items[*].metadata.name}'))
	kubectl cp ./teleport/admin.yaml $(POD):/tmp/admin.yaml
	kubectl cp ./teleport/connector.yaml $(POD):/tmp/connector.yaml

	kubectl exec -i $(POD) -- /usr/local/bin/tctl create -f /tmp/admin.yaml
	kubectl exec -i $(POD) -- /usr/local/bin/tctl create -f /tmp/connector.yaml

Example teleport role

To quickly test the role, create a sample cluster admin referencing system:masters group:

kind: role
version: v3
metadata:
  name: clusteradmin
spec:
  # SSH options used for user sessions 
  options:
    # max_session_ttl defines the TTL (time to live) of SSH certificates 
    # issued to the users with this role.
    max_session_ttl: 10m

    # forward_agent controls either users are allowed to use SSH agent forwarding
    forward_agent: true

    # port_forwarding
    port_forwarding: true

  # allow section declares a list of resource/verb combinations that are
  # allowed for the users of this role. by default nothing is allowed.
  allow:
    # logins array defines the OS logins a user is allowed to use.
    # A few special variables are supported here (see below)
    logins: [root, '{{internal.logins}}']

    # a list of kubernetes groups to assign
    kubernetes_groups: ['system:masters']

    # node labels that a user can connect to. The wildcard ('*') means "any node"
    node_labels:
      '*': '*'

    # see below.
    rules:
    - resources: ['*']
      verbs: ['*']

  # the deny section uses the identical format as the 'allow' section.
  # the deny rules always override allow rules.
  deny: {}

Other roles

Now, you can create other generic Kubernetes groups and reference them in teleport roles, for example:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: editor
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: edit
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: editor

Feedback

Folks are welcome to provide feedback here or in slack.