kuberos

package module
v0.0.0-...-7bc1e72 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2018 License: Apache-2.0 Imports: 17 Imported by: 0

README

kuberos Docker Pulls Godoc Travis Codecov

An OIDC authentication helper for Kubernetes' kubectl.

The kuberos UI

Status

This project is effectively unmaintained. I have not used OIDC authentication for some time, instead having switched to using Kubehook. I will do my best to shepherd pull requests, but cannot guarantee a prompt response and do not have bandwidth to address issues or add new features. Please let me know via an issue if you'd be interested in taking ownership of Kuberos.

Purpose

Kubernetes supports several authentication methods, a popular one of which is OIDC. The kubectl commandline tool can be configured to use OIDC authentication, including automatically refreshing its token on invocation. In order to enable this functionality kubectl must be configured with the following parameters:

  • A client ID
  • A client secret
  • An issuer URL
  • An ID token
  • A refresh token

The latter two of these parameters must be aquired by performing an initial OIDC authentication outside of kubectl. OIDC is an awkward authentication method for a commandline tool as it is entirely browser based. Existing implementations (see Alternatives) provide CLI tools to handle this initial authentication. These CLIs will typically require the user connect to localhost in their Browser to perform the initial authentication.

Kuberos is designed to instead run as a hosted service. It authenticates users against an OIDC provider, returning a JSON payload of the parameters required by kubectl. Kuberos provides a simple frontend that links to a ~/.kube/config file generated from a supplied template of clusters. It also details how to manually add a user and context to a cluster, and how to use kubectl.

Usage

Before using Kuberos you must enable OIDC at the Kubernetes API server. Refer to this guide for details on how to get an OIDC client ID and secret from Google.

Kuberos is published to the Docker Hub. It must be configured with an OIDC issuer, client ID, and secret, as well as a partial kubeconfig file. For example:

export OIDC_CLIENT_ID=woo
export OIDC_CLIENT_SECRET=supersecret

echo $OIDC_CLIENT_SECRET >/tmp/cfg/secret
cat <<EOF >/tmp/cfg/template
apiVersion: v1
kind: Config
current-context: kuberos  # Optional - must be the name of one of the template's clusters.
clusters:
- name: kuberos
  cluster:
    certificate-authority-data: REDACTED
    server: https://kuberos.example.org
EOF

docker run -d -p 10003:10003 -v /tmp/cfg:/cfg "negz/kuberos:latest" \
  /kuberos https://accounts.google.com $OIDC_CLIENT_ID /cfg/secret /cfg/template

Kuberos supports the following arguments:

$ docker run negz/kuberos:latest /kuberos --help
usage: kuberos [<flags>] [<oidc-issuer-url>] [<client-id>] [<client-secret-file>] [<kubecfg-template>]

Provides OIDC authentication configuration for kubectl.

Flags:
      --help                   Show context-sensitive help (also try --help-long
                               and --help-man).
      --listen=":10003"        Address at which to expose HTTP webhook.
  -d, --debug                  Run with debug logging.
      --scopes=profile... ...  List of additional scopes to provide in token.
      --email-domain=EMAIL-DOMAIN
                               The eamil domain to restrict access to.
      --shutdown-grace-period=1m
                               Wait this long for sessions to end before
                               shutting down.
      --shutdown-endpoint=SHUTDOWN-ENDPOINT
                               Insecure HTTP endpoint path (e.g., /quitquitquit)
                               that responds to a GET to shut down kuberos.

Args:
  [<oidc-issuer-url>]     OpenID Connect issuer URL.
  [<client-id>]           OAuth2 client ID.
  [<client-secret-file>]  File containing OAuth2 client secret.
  [<kubecfg-template>]    A kubecfg file containing clusters to populate with a user and contexts.

The partial kubeconfig template should contain only cluster entries and optionally a current (i.e. default) context, which must be the name of one of the clusters. For example:

apiVersion: v1
kind: Config
current-context: staging
clusters:
- name: production
  cluster:
    certificate-authority-data: REDACTED
    server: https://prod.example.org
- name: staging
  cluster:
    certificate-authority-data: REDACTED
    server: https://staging.example.org

Given the above template Kuberos will generate a kubeconfig file containing the two supplied clusters, the authenticated OIDC user, and a context for each cluster associating them with the OIDC user. These contexts inherit the name of the clusters, thus a user could interact with the production cluster by running:

kubectl --context production cluster-info

If the current-context is set to the name of one of the clusters then the --context argument may be omitted, and the cluster named by current-context will be used.

Deploying to Kubernetes

Kuberos can be run inside a cluster as long as it can still communicate with your OIDC provider from inside the pod and your OIDC provider is set to redirect to your Kuberos endpoint (NodePort, LoadBalancer, etc).

The configuration below is meant to serve as a template and not something that is plug-and-play. You will need to adjust your DNS / nameserver helpers, Dex information, and optionally how you ingress your traffic.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: kuberos
  name: kuberos
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: kuberos
    spec:
      # hostAliases are optional, to help route traffic to Dex / OIDC
      hostAliases:
      - ip: "192.168.1.1"
        hostnames:
        - "dex.oidc.example.com"
      containers:
      - image: negz/kuberos:latest
        name: kuberos
        command: ["/kuberos", "https://dex.oidc.example.com", "example-app", "/cfg/secret", "/cfg/template"]
        ports:
        - name: http
          containerPort: 10003
        volumeMounts:
        - name: config
          mountPath: /cfg
      volumes:
      - name: config
        configMap:
          name: kuberos
          items:
          - key: template
            path: template
          - key: secret
            path: secret
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kuberos
data:
  template: |
    apiVersion: v1
    kind: Config
    current-context: staging
    clusters:
    - name: production
      cluster:
        certificate-authority-data: REDACTED
        server: https://prod.example.org
    - name: staging
      cluster:
        certificate-authority-data: REDACTED
        server: https://staging.example.org
  secret: REDACTED

Alternatives

OIDC/LDAP/static helper specifically for dex (Helm charts for dex+helper included)

OIDC helpers that run locally to setup kubectl:

A Kubernetes JWT webhook helper with a similar UX to Kuberos

Contributors

Nic Cope - Creator

Rajat Sharma - Frontend

Maxime Guyot

Ripta Pasay

John Delivuk

Aaron Roydhouse

keattang

jimangel

arnoldbechtoldt

Documentation

Index

Constants

View Source
const (
	// DefaultKubeCfgEndpoint is the default endpoint to which clients should
	// be redirected after authentication.
	DefaultKubeCfgEndpoint = "ui"

	// DefaultAPITokenMountPath is the default mount path for API tokens
	DefaultAPITokenMountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
)

Variables

View Source
var (
	// DefaultScopes are the minimum required oauth2 scopes for every
	// authentication request.
	DefaultScopes = []string{oidc.ScopeOpenID}

	// ErrInvalidKubeCfgEndpoint indicates an unparseable redirect endpoint.
	ErrInvalidKubeCfgEndpoint = errors.New("invalid redirect endpoint")

	// ErrInvalidState indicates the provided state param was not as expected.
	ErrInvalidState = errors.New("invalid state parameter: user agent or IP address changed between requests")

	// ErrMissingCode indicates a response without an OAuth 2.0 authorization
	// code
	ErrMissingCode = errors.New("response missing authorization code")

	// ErrNoYAMLSerializer indicates we're unable to serialize Kubernetes
	// objects as YAML.
	ErrNoYAMLSerializer = errors.New("no YAML serializer registered")
)

Functions

func OfflineAsScope

func OfflineAsScope(p *oidc.Provider) bool

OfflineAsScope determines whether an offline refresh token is requested via a scope per the spec or via Google's custom access_type=offline method.

See http://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess and https://developers.google.com/identity/protocols/OAuth2WebServer#offline

func Template

func Template(cfg *api.Config) http.HandlerFunc

Template returns an HTTP handler that returns a new kubecfg by taking a template with existing clusters and adding a user and context for each based on the URL parameters passed to it.

Types

type Handlers

type Handlers struct {
	// contains filtered or unexported fields
}

Handlers provides HTTP handlers for the Kubernary service.

func NewHandlers

func NewHandlers(c *oauth2.Config, e extractor.OIDC, ho ...Option) (*Handlers, error)

NewHandlers returns a new set of Kuberos HTTP handlers.

func (*Handlers) KubeCfg

func (h *Handlers) KubeCfg(w http.ResponseWriter, r *http.Request)

KubeCfg returns a handler that forms helpers for kubecfg authentication.

func (*Handlers) Login

func (h *Handlers) Login(w http.ResponseWriter, r *http.Request)

Login redirects to an OIDC provider per the supplied oauth2 config.

type Option

type Option func(*Handlers) error

An Option represents a Handlers option.

func AuthCodeOptions

func AuthCodeOptions(oo []oauth2.AuthCodeOption) Option

AuthCodeOptions allows the use of bespoke OAuth2 options.

func HTTPClient

func HTTPClient(c *http.Client) Option

HTTPClient allows the use of a bespoke HTTP client for OIDC requests.

func Logger

func Logger(l *zap.Logger) Option

Logger allows the use of a bespoke Zap logger.

func StateFunction

func StateFunction(fn StateFn) Option

StateFunction allows the use of a bespoke state generator function.

type ScopeRequests

type ScopeRequests struct {
	OfflineAsScope bool
	Scopes         []string
}

ScopeRequests configures the oauth2 scopes to request during authentication.

func (*ScopeRequests) Get

func (r *ScopeRequests) Get() []string

Get the scopes to request during authentication.

type StateFn

type StateFn func(*http.Request) string

A StateFn should take an HTTP request and return a difficult to predict yet deterministic state string.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL