webhook

package module
v0.1.1-0...-e59f25e Latest Latest
Warning

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

Go to latest
Published: Feb 10, 2021 License: BSD-3-Clause Imports: 25 Imported by: 0

README

k8s-athenz-webhook GoDoc Build Status Coverage Status Go Report Card

An API for a Kubernetes authentication and authorization webhook that integrates with Athenz for access checks. It allows flexible resource mapping from Kubernetes resources to Athenz.

Architecture

The diagram below shows the end to end flow of how the webhook integrates into Kubernetes. Screenshot

The following steps occur during any access check:

  1. The user, pipeline, or service authenticates with the Kubernetes API server through the use of X.509 certificates or through a ntoken.
  2. The authorization check goes to the auth webhook to validate if the user, service, or pipeline has access.
  3. If the caching feature (described further down) is turned on, the webhook will validate the access check against the Athenz domain data it has stored in memory.
  4. If the caching feature return false or if it's not turned on, the check will call Athenz.

Note: You can use just the authorization hook without also using the authentication hook.

Authentication

There are two ways to authenticate with Athenz, using X.509 certificates or using ntokens.

Ntoken (deprecated)

To use ntokens for clients in the kube config, the auth webhook must be configured as an authentication endpoint for the Kubernetes API server. The auth webhook contains a public key cache which has the public keys of Athenz hosts which are used to validate the ntoken signatures. If there is a cache miss, the webhook will call Athenz on the principal API endpoint.

The recommended approach for authentication is to attach the Athenz CA to the Kubernetes API CA. This will mean clients will specify Athenz certificates for their connection in the kube config and be authenticated through the use of a common CA.

Authorization

Authorization is done by calling Athenz to check if the client has access to the requested action. Athenz internally will check the client identity against the role and policies in the domain to verify if the action is allowed. The default behavior is for the auth webhook to call the Athenz ZTS server on the access API endpoint and fallback to ZMS if the ZTS calls fail.

Caching feature (Alpha)

The auth webhook supports a caching features for authorization which utilizes the Athenz domain custom resource which are created by the k8s-athenz-syncer. If this feature is turned on, the webhook will check if the requested action for the identity is authorized to access the resource by checking against an in memory cache of Athenz domains. This is a huge performance improvement as network calls to ZTS / ZMS are avoided and it also allows the webhook to continue running in the case Athenz servers go down.

Note: This feature is currently in alpha mode and is being tested in a dry run mode. Some edge cases may not be fully covered yet while it's being developed to be on parity with the access Athenz API.

Prerequisites

There are a variety of prerequisites required in order to run this controller, they are specified below.

  • Kubernetes cluster - A running Kubernetes cluster is required with access to the control plane. More information on how to setup a cluster can be found in the official documentation here.
  • Athenz - Athenz ZTS and ZMS servers must be fully deployed. More information and setup steps can be found here.
  • Athenz syncer (optional) - The Athenz syncer must be fully deployed and syncing Athenz domain data into custom resources for this webhook to watch if using the caching feature. The repo can be found here.

Usage

Configuring the auth webhook with the Kubernetes API server

To configure the Kubernetes API server to use a custom auth webhook server, follow the steps defined on their official documentation which can be found here.

Implement client library

This repo does not provide a main program that you can run out of the box. See the following sections for reference implementations that can be customized to suit your needs. The source code can be found in the example directory.

The primary implementation the client must provide is to create a struct which implements the ResourceMapper interface.

// ResourceMapper allows for mapping from an authorization request to Athenz entities.
type ResourceMapper interface {
	// MapResource maps a subject review spec into a principal and a list of Athenz
	// authz checks at least one of which must succeed. An empty list implies no
	// authorization. An error must be returned if the mapper is not able or
	// unwilling to map the supplied spec into Athenz checks.
	// Returning multiple items allows the implementor to add a secondary
	// authz request for superuser access, for example.
	MapResource(ctx context.Context, spec authz.SubjectAccessReviewSpec) (principal string, checks []AthenzAccessCheck, err error)
}

This allows the client to implement authorization checks which are specific to their own Athenz to Kubernetes mapping inside of their cluster.

Examples
Simple Client implementation

The sample auth webhook in the example directory provides an implementation which maps Athenz domains to Kubernetes namespaces using a '.' to '-' and '-' to '--' conversion. For example, the backend.db domain would translate to the backend-db namespace.

The example implementation does the following checks.

  1. Checks if the users are not part of the denied users list which automatically are denied such as system:anonymous.
  2. Checks if the resources being accessed are part of the denied resource list such as podsecuritypolicies.
  3. If cluster scoped resources are being accessed such as resourcequotas, limitranges, namespaces then use a separate admin domain to check access.
  4. If the action being done is read only access then also check against the admin domain.
  5. Check if the user is allowed the action through the Athenz policy.
Garm implementation

Please see the readme for the garm repo here to see implementation specific details.

Contribute

Please refer to the contributing file for information about how to get involved. We welcome issues, questions, and pull requests.

Maintainers/Contacts

Core Team: omega-core@verizonmedia.com

License

Copyright 2019 Verizon Media Inc. Licensed under the terms of the 3-Clause BSD License.

Documentation

Overview

Package webhook provides the handlers and customization points for implementing a K8s webhook for authentication and authorization using Athenz.

Index

Constants

View Source
const (
	CacheActive = true
	CacheStale  = false
)

Variables

View Source
var DefaultClientTimeout = 10 * time.Second

DefaultClientTimeout is used when no timeout is supplied in the config.

Functions

func IsLogEnabled

func IsLogEnabled(ctx context.Context, flag LogFlags) bool

IsLogEnabled returns true if the supplied flag is set in the configuration log flags bitmask.

func NewAuthenticator

func NewAuthenticator(c AuthenticationConfig) http.Handler

NewAuthenticator returns a handler that can service an authentication request.

func NewAuthorizer

func NewAuthorizer(c AuthorizationConfig) http.Handler

NewAuthorizer returns a handler that can service an authorization request.

func VerifyToken

func VerifyToken(token string, checkExpiry bool) error

VerifyToken returns an error if the supplied ntoken was not well-formed. When checkExpiry is true, an expiry check on the token is also performed.

Types

type AthenzAccessCheck

type AthenzAccessCheck struct {
	Action   string // the action to authorize
	Resource string // fully qualified Athenz resource name including domain prefix (e.g. "my.domain:the-resource")
}

AthenzAccessCheck encapsulates the parameters for an authz check against Athenz.

func (AthenzAccessCheck) String

func (a AthenzAccessCheck) String() string

type AthenzPrincipal

type AthenzPrincipal struct {
	Domain  string // Athenz domain
	Service string // local name
	Token   string // the token
}

AthenzPrincipal represents a valid Athenz principal.

type AuthenticationConfig

type AuthenticationConfig struct {
	Config            // base config
	Mapper UserMapper // user mapper
}

AuthenticationConfig is the authentication configuration

type AuthorizationConfig

type AuthorizationConfig struct {
	Config                                       // the base config
	HelpMessage               string             // additional message for the user on internal authz errors
	Token                     IdentityToken      // the token provider for calls to Athenz
	AthenzX509                IdentityAthenzX509 // the x509 provider for calls to Athenz
	AthenzClientAuthnx509Mode bool               // enable/disable x509 mode for Identity athenz x509
	Mapper                    ResourceMapper     // the resource mapper
}

AuthorizationConfig is the authorization configuration

type AuthzError

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

AuthzError is an error implementation that can provide custom messages for the reason field in the SubjectAccessReviewStatus object.

func NewAuthzError

func NewAuthzError(delegate error, reason string) *AuthzError

NewAuthzError returns an error implementation whose reason member is copied into the returned status object.

func (*AuthzError) Reason

func (a *AuthzError) Reason() string

Reason returns the string that should be copied into the `reason` field of the status object.

type Cache

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

Cache - cache for athenzdomains CR

func NewZpeClient

func NewZpeClient(crIndexInformer cache.SharedIndexInformer, cmIndexInformer cache.SharedIndexInformer, maxContactTime time.Duration, log Logger) *Cache

NewZpeClient - generate new athenzdomains cr cache

type Config

type Config struct {
	ZMSEndpoint string                     // ZMS endpoint including version specific (e.g. /v1) path
	ZTSEndpoint string                     // ZTS endpoint including version specific (e.g. /v1) path
	AuthHeader  string                     // header name for ntoken in Athenz requests
	Timeout     time.Duration              // timeout for all Athenz requests
	LogProvider LogProvider                // the log provider
	LogFlags    LogFlags                   // logging flags
	Validator   zmssvctoken.TokenValidator // token validator
	Cache       *Cache                     // AthenzDomain Cache
	UseCache    bool                       // UseCache flag
	DryRun      bool                       // DryRun mode flag
}

Config is the common configuration for authn and authz

type Cron

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

Cron type for cache status updates, after a sync interval, compare last update time stored in the cache and current time, update the cache status

func NewCron

func NewCron(syncInterval time.Duration, cache *Cache, log Logger) *Cron

NewCron - creates new cron object

func (*Cron) CronSync

func (c *Cron) CronSync(stopCh <-chan struct{})

CronSync - for every sync interval, update the cache status to ensure it is up to date

type IdentityAthenzX509

type IdentityAthenzX509 func() (*tls.Config, error)

IdentityAthenzX509 provides x509 certs for Athenz access

type IdentityToken

type IdentityToken func() (string, error)

IdentityToken provides an ntoken for Athenz access for the authorization handler itself.

type LogFlags

type LogFlags int

LogFlags is a bitwise mask of additional logging that is required. The zero value produces standard logs that produce one line of the outcome for both authn and authz.

const (
	LogVerboseMapping LogFlags // user mapping code can use this for verbosity
	LogTraceServer             // log details of server requests, insecure
	LogTraceAthenz             // log details of Athenz HTTP calls, insecure
)

Log flag constants

type LogProvider

type LogProvider func(requestID string) Logger

LogProvider produces a Logger given a request identifier.

type Logger

type Logger interface {
	// Println has the same semantics as the log package.
	Println(args ...interface{})
	// Printf has the same semantics as the log package.
	Printf(format string, args ...interface{})
}

Logger is the minimal logging interface required by the API.

func GetLogger

func GetLogger(ctx context.Context) Logger

GetLogger returns the logger for the supplied context.

type ResourceMapper

type ResourceMapper interface {
	// MapResource maps a subject review spec into a principal and a list of Athenz
	// authz checks at least one of which must succeed. An empty list implies no
	// authorization. An error must be returned  if the mapper is not able or
	// unwilling to map the supplied spec into Athenz checks.
	// Returning multiple items allows the implementor to add a secondary
	// authz request for superuser access, for example.
	MapResource(ctx context.Context, spec authz.SubjectAccessReviewSpec) (principal string, checks []AthenzAccessCheck, err error)
}

ResourceMapper allows for mapping from an authorization request to Athenz entities.

type UserMapper

type UserMapper interface {
	// MapUser maps an Athenz principal to a user info object.
	// Returning an error will cause an authentication failure.
	MapUser(ctx context.Context, domain, service string) (authn.UserInfo, error)
}

UserMapper allows for mapping from Athenz principals to k8s objects.

Directories

Path Synopsis
example
auth-webhook
Command auth-webhook provides a reference implementation for the K8s Athenz web hook for authentication and authorization.
Command auth-webhook provides a reference implementation for the K8s Athenz web hook for authentication and authorization.

Jump to

Keyboard shortcuts

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