Cluster Portal

Cluster Portal is a collection of dashboards that expose several services behind an OAuth2 proxy

Cluster portal allows to access internal dashboards after authorization with a third party OAuth2 service like GitHub or Okta.

Cluster Portal follows the BeyondCorp security model and uses the Bitly oauth2-proxy as an Identity Aware Proxy (“IAP”).

Dependencies

Installation

To install the portal, you will need to define the hostname, which is the FQHN used to access the portal.

In our example, we use portal.us-west-2.staging.example.com as the FQHN. Replace this with an appropriate value to suit your specific project.

Create OAuth2 Application

For authentication we’ll need to create an OAuth2 application with one of the supported external providers.

The OAuth2 callback URL should be https://portal.us-west-2.staging.example.com/oauth2/callback

Replace the FQHN to suit your specific project.

GitHub Auth Provider

To create OAuth2 application, follow these instructions:

  1. Create a GitHub OAuth2 App to obtain Client ID and Client Secret
  2. Configure OAuth2 Proxy with GitHub to configure OAuth2 proxy using the Client ID and Client Secret from the previous step

Create Team

With GitHub OAuth provider you need to restrict access to the portal by user membership in the GitHub organization and in the team belonging to it.

For more details read Creating organization and Organizing members into teams

In our example we will use example-com as the organization and staging-team as the team.

Installing on Kubernetes

You can install portal in a few different ways, but we recommend using the Master Helmfile.

Install with Master Helmfile

Master Helmfile uses GitHub OAuth provider and is configured to expose the following dashboards:

Adding Additional Tabs

If you want to add some additional tabs, follow these instructions:

  1. Exit the Geodesic Module Shell
  2. Create file /conf/kops/values/portal.backends.yaml with config for your tabs. For example

/conf/kops/values/portal.backends.yaml

backends:
  api:
    name: "API Docs"
    endpoint: "https://api.us-west-2.staging.example.com/api-docs/"
    external: true
  rabbit:
    name: "RabbitMQ"
    endpoint: "http://example-rabbitmq.example-staging:15672"
    external: false

  1. Rebuild the Geodesic Module
  2. Run into the Geodesic Module shell
  3. Proceed to Helmfile sync

Helmfile sync

These environment variables are required:

Customize the portal UI appearance with these environment variables:

This image shows a customized portal UI

Example: Customized Cluster Portal

These environment variables you may want to update:

Use these environment variables to configure the backends:

Environment variables can be specified in the Geodesic module’s Dockerfile or using Chamber storage, which is recommended for all secrets.

Install the portal using helmfile sync

Install portal using helmfile sync

chamber write kops PORTAL_HOSTNAME portal.us-west-2.staging.example.com
chamber write kops PORTAL_INGRESS ingress.us-west-2.staging.example.com
chamber write kops PORTAL_OAUTH2_PROXY_GITHUB_CLIENT_ID e76XXXXXXXXXXXXXX9a0
chamber write kops PORTAL_OAUTH2_PROXY_GITHUB_CLIENT_SECRET b24XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXa1c
chamber write kops PORTAL_OAUTH2_PROXY_GITHUB_ORGANIZATION example-com
chamber write kops PORTAL_OAUTH2_PROXY_GITHUB_TEAM staging-team
chamber write kops PORTAL_OAUTH2_PROXY_COOKIE_NAME $(uuidgen)
chamber write kops PORTAL_OAUTH2_PROXY_COOKIE_SECRET $(uuidgen)
chamber write kops PORTAL_TITLE "Staging Example"
chamber write kops PORTAL_BRAND "Staging Cluster"
chamber write kops PORTAL_BRAND_IMAGE_URL "https://cloudposse.com/wp-content/uploads/sites/29/2018/02/SquareLogo2.png"
chamber write kops PORTAL_BRAND_IMAGE_FAVICON_URL "https://cloudposse.com/wp-content/uploads/sites/29/2018/04/favicon-57.png"
chamber exec kops -- helmfile -f /conf/kops/helmfile.yaml --selector namespace=monitoring,chart=portal sync

Install with Custom Helmfile

Add the following code to your Kubernetes Backing Services Helmfile:

helmfile.yaml

repositories:
- name: "cloudposse-incubator"
  url: "https://charts.cloudposse.com/incubator/"

releases:
- name: "portal"
  namespace: "monitoring"
  labels:
    chart: "portal"
    component: "monitoring"
    namespace: "monitoring"
    vendor: "cloudposse"
    default: "true"
  chart: "cloudposse-incubator/portal"
  version: "0.1.0"
  values:
    - "values-portal.yaml"
  set:
    ## oauth2-proxy
    - name: "oauth2-proxy.app.useSSL"
      value: "false"

    - name: "oauth2-proxy.app.upstreams[0]"
      value: "file:///dev/null"

    - name: "oauth2-proxy.app.provider"
      value: "github"

    - name: "oauth2-proxy.app.clientID"
      value: '{{ env "PORTAL_OAUTH2_PROXY_GITHUB_CLIENT_ID" }}'

    - name: "oauth2-proxy.app.clientSecret"
      value: '{{ env "PORTAL_OAUTH2_PROXY_GITHUB_CLIENT_SECRET" }}'

    - name: "oauth2-proxy.app.githubOrg"
      value: '{{ env "PORTAL_OAUTH2_PROXY_GITHUB_ORGANIZATION" }}'

    - name: "oauth2-proxy.app.githubTeam"
      value: '{{ env "PORTAL_OAUTH2_PROXY_GITHUB_TEAM" }}'

    - name: "oauth2-proxy.app.requestLogging"
      value: "false"

    - name: "oauth2-proxy.app.passAccessToken"
      value: "false"

    - name: "oauth2-proxy.app.passBasicAuth"
      value: "false"

    - name: "oauth2-proxy.app.passHostHeader"
      value: "true"

    - name: "oauth2-proxy.app.cookieName"
      value: '{{ env "PORTAL_OAUTH2_PROXY_COOKIE_NAME" }}'

    - name: "oauth2-proxy.app.cookieSecret"
      value: '{{ env "PORTAL_OAUTH2_PROXY_COOKIE_SECRET" }}'

    - name: "oauth2-proxy.app.cookieDomain"
      value: '.{{ env "PORTAL_HOSTNAME" }}'

    - name: "oauth2-proxy.app.cookieSecure"
      value: "true"

    - name: "oauth2-proxy.app.cookieHttponly"
      value: "false"

values/portal.yaml

---
## Internal backends exposed with portal
backends:
  dashboard:
    ## Name for menu item
    name: "Kubernetes"
    ## Endpoint
    endpoint: "https://ui-kubernetes-dashboard.kube-system:443"
    ## Set to true if endpoint is external (would be redirect instead of proxy)
    external: false
  grafana:
    name: "Grafana"
    endpoint: "http://prom-grafana.monitoring:80"
    external: false
  alerts:
    name: "Alerts"
    endpoint: "http://prom-alertmanager.monitoring:9093"
    external: false
  prometheus:
    name: "Prometheus"
    endpoint: "http://prom-prometheus.monitoring:9090"
    external: false
  docs:
    name: "Documentation"
    endpoint: "https://docs.cloudposse.com/docs"
    external: true

config:
  title: "Staging Example"
  brand: "Staging Cluster"
  image:
    favicon: https://cloudposse.com/wp-content/uploads/sites/29/2018/04/favicon-57.png
    url: https://cloudposse.com/wp-content/uploads/sites/29/2018/02/SquareLogo2.png
    width: 35

  ## Base portal hostname
  basehost: portal.us-west-2.staging.example.com

dashboard:
  replicaCount: 2
  resources:
    limits:
      cpu: 5m
      memory: 16Mi
    requests:
      cpu: 2m
      memory: 8Mi

proxy:
  enabled: true
  replicaCount: 2
  resources:
    limits:
      cpu: 5m
      memory: 64Mi
    requests:
      cpu: 2m
      memory: 32Mi

oauth2-proxy:
  app:
  replicaCount: 2
  resources:
    limits:
      cpu: 10m
      memory: 16Mi
    requests:
      cpu: 5m
      memory: 8Mi

ingress:
  enabled: true
  tls:
    enabled: true
  dns:
    enabled: false
  annotations:
    kubernetes.io/ingress.class: nginx
    external-dns.alpha.kubernetes.io/ttl: "60"
    external-dns.alpha.kubernetes.io/target: "internal.us-west-2.staging.example.com"

Then follow the instructions for running helmfile sync.

Usage

To access the portal, open https://portal.us-west-2.staging.example.com and authenticate using your GitHub credentials.