Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'notify' becomes 'callbacks' #371

Merged
merged 1 commit into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,18 @@ Under the hood, Authorino is based on Kubernetes [Custom Resource Definitions](h

**Request-time:**

![How it works](http://www.plantuml.com/plantuml/png/VP51ImD138NlyojoB-BTWrHBHIZOejMBUeWpsMwmawoPZ51_lOFAKXNs-lAzF7XlNXpDQzw7yieoe666hAAnDyq4RfL2mEegDR-GXOLAgPaCJivXAUzwW3EutcutOFHMgNZu5jlredglngADsDrk5c5dMeSlkJtfU1S0u8ZwOtaWu-u0d4YS_J0DNv777Z8v9dISPfVIgKK2RDe73Bhdo5IcFPULzmbYBQuPZCgWKcZQSaUIGDIvuuZEpH2Q4exuemRNgzERzGgUPFOlPEppVYXkXBdXZ-lLyw_MOGQO4YNe2HDP2IFSKc3SR9pgv_US9BNfFm40)
<picture>
<source media="(prefers-color-scheme: light)" srcset="http://www.plantuml.com/plantuml/png/VP51IyH038NlyojoNyIx1rbTLeI2NMJreXwodRGTx4ngaX7ghtTGALMXrvVllS1xMpKKot5mc8rJZYSIj-EaEPB0sINiqpjFS06tn-C1XDuogRbliLolilKi8N4Xkll3pdN2UVoIIqWREWS02-gFvP4aj1C4Jyc2JUlm3LdJGoH3ZuRhx3wrB0q15kq3HXv24qZNFTSv31wQhCOHX7JafBHksU4mdB1vLKV9kmMsAAwkpk_g2fxJvb_sNEF3g2Q4iU1FTVNogspO07fF7df2Jw9kXiiNcAVwMMZEtbBoPTPF">
<img alt="How it works" src="http://www.plantuml.com/plantuml/dpng/VP51IyH038NlyojoNyIx1rbTLeI2NMJreXwodRGTx4ngaX7ghtTGALMXrvVllS1xMpKKot5mc8rJZYSIj-EaEPB0sINiqpjFS06tn-C1XDuogRbliLolilKi8N4Xkll3pdN2UVoIIqWREWS02-gFvP4aj1C4Jyc2JUlm3LdJGoH3ZuRhx3wrB0q15kq3HXv24qZNFTSv31wQhCOHX7JafBHksU4mdB1vLKV9kmMsAAwkpk_g2fxJvb_sNEF3g2Q4iU1FTVNogspO07fF7df2Jw9kXiiNcAVwMMZEtbBoPTPF">
</picture>

1. A user or service account (_"Consumer"_) obtains an access token to consume resources of the _Upstream_ service, and sends a request to the _Envoy_ ingress endpoint
2. The Envoy proxy establishes fast gRPC connection with _Authorino_ carrying data of the HTTP request (context info), which causes Authorino to lookup for an `AuthConfig` Custom Resource to enforce (pre-cached)
3. **Identity verification (authentication) phase** - Authorino verifies the identity of the the consumer, where at least one authentication method/identity provider must go through
4. **External metadata phase** - Authorino fetches aditional metadata for the authorization from external sources (optional)
5. **Policy enforcement (authorization) phase** - Authorino takes as input a JSON composed out of context data, resolved identity object and fetched additional metadata from previous phases, and triggers the evaluation of user-defined authorization policies
6. **Response (metadata-out) phase** – Authorino builds user-defined custom responses (dynamic JSON objects and/or _Festival Wristband_ OIDC tokens), to be supplied back to the client and/or upstream service within added HTTP headers or as Envoy Dynamic Metadata (optional)
7. **Notification phase** – Authorino sends notification messages to specified HTTP endpoints (optional)
7. **Callbacks phase** – Authorino sends callbacks to specified HTTP endpoints (optional)
8. Authorino and Envoy settle the authorization protocol with either OK/NOK response
9. If authorized, Envoy triggers other HTTP filters in the chain (if any), pre-injecting eventual dynamic metadata returned by Authorino, and ultimately redirects the request to the _Upstream_
10. The _Upstream_ serves the requested resource to the consumer
Expand Down Expand Up @@ -178,7 +181,7 @@ Under the hood, Authorino is based on Kubernetes [Custom Resource Definitions](h
<td><i>Ready</i></td>
</tr>
<tr>
<td>Notifications</td>
<td>Callbacks</td>
<td>HTTP endpoints</td>
<td><i>Ready</i></td>
</tr>
Expand Down
28 changes: 14 additions & 14 deletions api/v1beta1/auth_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const (
AuthorizationKubernetesAuthz = "AUTHORIZATION_KUBERNETESAUTHZ"
ResponseWristband = "RESPONSE_WRISTBAND"
ResponseDynamicJSON = "RESPONSE_DYNAMIC_JSON"
NotifyHTTP = "NOTIFY_HTTP"
CallbackHTTP = "CALLBACK_HTTP"
EvaluatorDefaultCacheTTL = 60

// Status conditions
Expand Down Expand Up @@ -137,9 +137,9 @@ type AuthConfigSpec struct {
// Authorino gathers data from the auth pipeline to build custom responses for the client.
Response []*Response `json:"response,omitempty"`

// List of notification configs.
// Authorino sends notification messages to specified endpoints at the end of the auth pipeline.
Notify []*Notify `json:"notify,omitempty"`
// List of callback configs.
// Authorino sends callbacks to specified endpoints at the end of the auth pipeline.
Callbacks []*Callback `json:"callbacks,omitempty"`

// Custom denial response codes, statuses and headers to override default 40x's.
DenyWith *DenyWith `json:"denyWith,omitempty"`
Expand Down Expand Up @@ -557,32 +557,32 @@ func (r *Response) GetType() string {
return TypeUnknown
}

// Endpoints to notify at the end of each auth pipeline.
type Notify struct {
// Name of the notification.
// It can be used to refer to the resolved notification response in other configs.
// Endpoints to callback at the end of each auth pipeline.
type Callback struct {
// Name of the callback.
// It can be used to refer to the resolved callback response in other configs.
Name string `json:"name"`

// Priority group of the config.
// All configs in the same priority group are evaluated concurrently; consecutive priority groups are evaluated sequentially.
// +kubebuilder:default:=0
Priority int `json:"priority,omitempty"`

// Whether this notification config should generate individual observability metrics
// Whether this callback config should generate individual observability metrics
// +kubebuilder:default:=false
Metrics bool `json:"metrics,omitempty"`

// Conditions for Authorino to perform this notification.
// If omitted, the notification will be attempted for all requests.
// If present, all conditions must match for the notification to be attempted; otherwise, the notification will be skipped.
// Conditions for Authorino to perform this callback.
// If omitted, the callback will be attempted for all requests.
// If present, all conditions must match for the callback to be attempted; otherwise, the callback will be skipped.
Conditions []JSONPattern `json:"when,omitempty"`

HTTP *Metadata_GenericHTTP `json:"http"` // make this 'omitempty' if other alternate methods are added
}

func (r *Notify) GetType() string {
func (r *Callback) GetType() string {
if r.HTTP != nil {
return NotifyHTTP
return CallbackHTTP
}
return TypeUnknown
}
Expand Down
58 changes: 29 additions & 29 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions controllers/auth_config_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,30 +524,30 @@ func (r *AuthConfigReconciler) translateAuthConfig(ctx context.Context, authConf
interfacedResponseConfigs = append(interfacedResponseConfigs, translatedResponse)
}

interfacedNotifyConfigs := make([]auth.AuthConfigEvaluator, 0)

for _, notify := range authConfig.Spec.Notify {
translatedNotify := &evaluators.NotifyConfig{
Name: notify.Name,
Priority: notify.Priority,
Conditions: buildJSONPatternExpressions(authConfig, notify.Conditions),
Metrics: notify.Metrics,
interfacedCallbackConfigs := make([]auth.AuthConfigEvaluator, 0)

for _, callback := range authConfig.Spec.Callbacks {
translatedCallback := &evaluators.CallbackConfig{
Name: callback.Name,
Priority: callback.Priority,
Conditions: buildJSONPatternExpressions(authConfig, callback.Conditions),
Metrics: callback.Metrics,
}

switch notify.GetType() {
switch callback.GetType() {
// http
case api.NotifyHTTP:
ev, err := r.buildGenericHttpEvaluator(ctx, notify.HTTP, authConfig.Namespace)
case api.CallbackHTTP:
ev, err := r.buildGenericHttpEvaluator(ctx, callback.HTTP, authConfig.Namespace)
if err != nil {
return nil, err
}
translatedNotify.HTTP = ev
translatedCallback.HTTP = ev

case api.TypeUnknown:
return nil, fmt.Errorf("unknown notify type %v", notify)
return nil, fmt.Errorf("unknown callback type %v", callback)
}

interfacedNotifyConfigs = append(interfacedNotifyConfigs, translatedNotify)
interfacedCallbackConfigs = append(interfacedCallbackConfigs, translatedCallback)
}

translatedAuthConfig := &evaluators.AuthConfig{
Expand All @@ -556,7 +556,7 @@ func (r *AuthConfigReconciler) translateAuthConfig(ctx context.Context, authConf
MetadataConfigs: interfacedMetadataConfigs,
AuthorizationConfigs: interfacedAuthorizationConfigs,
ResponseConfigs: interfacedResponseConfigs,
NotifyConfigs: interfacedNotifyConfigs,
CallbackConfigs: interfacedCallbackConfigs,
Labels: map[string]string{"namespace": authConfig.Namespace, "name": authConfig.Name},
}

Expand Down
Binary file modified docs/architecture.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ When Authorino is triggered by Envoy via the **gRPC** interface, it starts evalu

Apart from static rules, these parameters can include instructions to contact online with external identity verifiers, external sources of **metadata** and policy decision points (**PDPs**).

On every request, Authorino's "working memory" is called [**Authorization JSON**](#the-authorization-json), a data structure that holds information about the context (the HTTP request) and objects from each phase of the auth pipeline: i.e., identity verification (phase i), ad-hoc metadata fetching (phase ii), authorization policy enforcement (phase iii), dynamic response (phase iv), and notification (phase v). The evaluators in each of these phases can both read and write from the Authorization JSON for dynamic steps and decisions of authN/authZ.
On every request, Authorino's "working memory" is called [**Authorization JSON**](#the-authorization-json), a data structure that holds information about the context (the HTTP request) and objects from each phase of the auth pipeline: i.e., identity verification (phase i), ad-hoc metadata fetching (phase ii), authorization policy enforcement (phase iii), dynamic response (phase iv), and callbacks (phase v). The evaluators in each of these phases can both read and write from the Authorization JSON for dynamic steps and decisions of authN/authZ.

## Topologies

Expand Down Expand Up @@ -131,9 +131,9 @@ spec:
# - Envoy Dynamic Metadata
response: […]

# List of notification targets:
# List of callback targets:
# - Endpoints for HTTP requests
notify: […]
callbacks: […]

# Custom HTTP status code, message and headers to replace the default `401 Unauthorized` and `403 Forbidden` (optional)
denyWith:
Expand Down Expand Up @@ -177,10 +177,10 @@ Authorino only watches events related to `Secret`s whose `metadata.labels` match
In each request to the protected API, Authorino triggers the so-called "Auth Pipeline", a set of configured *evaluators* that are organized in a 5-phase pipeline:

- **(i) Identity phase:** at least one source of identity (i.e., one identity evaluator) must resolve the supplied credential in the request into a valid identity or Authorino will otherwise reject the request as unauthenticated (401 HTTP response status).
- **(ii) Metadata phase:** optional fetching of additional data from external sources, to add up to context and identity information, and used in authorization policies, dynamic responses and notification requests (phases iii to v).
- **(ii) Metadata phase:** optional fetching of additional data from external sources, to add up to context and identity information, and used in authorization policies, dynamic responses and callback requests (phases iii to v).
- **(iii) Authorization phase:** all unskipped policies must evaluate to a positive result ("authorized"), or Authorino will otherwise reject the request as unauthorized (403 HTTP response code).
- **(iv) Response phase** – Authorino builds all user-defined response items (dynamic JSON objects and/or _Festival Wristband_ OIDC tokens), which are supplied back to the external authorization client within added HTTP headers or as Envoy Dynamic Metadata
- **(v) Notification phase** – Authorino sends notification messages to specified HTTP endpoints.
- **(v) Callbacks phase** – Authorino sends callbacks to specified HTTP endpoints.

Each phase is sequential to the other, from (i) to (v), while the evaluators within each phase are triggered concurrently or as prioritized. The **Identity** phase (i) is the only one required to list at least one evaluator (i.e. one identity source or more); **Metadata**, **Authorization** and **Response** phases can have any number of evaluators (including zero, and even be omitted in this case).

Expand Down
Binary file modified docs/auth-pipeline.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
- [Added HTTP headers](#added-http-headers)
- [Envoy Dynamic Metadata](#envoy-dynamic-metadata)
- [_Extra:_ Custom denial status (`denyWith`)](#extra-custom-denial-status-denywith)
- [Notifications (`notify`)](#notifications-notify)
- [HTTP notifications (`notify.http`)](#http-notifications-notifyhttp)
- [Callbacks (`callbacks`)](#callbacks-callbacks)
- [HTTP endpoints (`callbacks.http`)](#http-endpoints-callbackshttp)
- [Common feature: Priorities](#common-feature-priorities)
- [Common feature: Conditions (`when`)](#common-feature-conditions-when)
- [Common feature: Caching (`cache`)](#common-feature-caching-cache)
Expand Down Expand Up @@ -674,11 +674,11 @@ rate_limits:

By default, Authorino will inform Envoy to respond with `401 Unauthorized` or `403 Forbidden` respectively when the identity verification (phase i of the [Auth Pipeline](./architecture.md#the-auth-pipeline)) or authorization (phase ii) fail. These can be customized by specifying `spec.denyWith` in the `AuthConfig`.

## Notifications (`notify`)
## Callbacks (`callbacks`)

### HTTP notifications (`notify.http`)
### HTTP endpoints (`callbacks.http`)

Sends notification requests to specified HTTP endpoints at the end of the auth pipeline.
Sends requests to specified HTTP endpoints at the end of the auth pipeline.

Example:

Expand All @@ -687,7 +687,7 @@ spec:
identity: […]
authorization: […]

notify:
callbacks:
- name: log
http:
endpoint: http://logsys
Expand Down
Loading