Skip to content

Proposal: Explicitly Authorized Services #17890

Open
@GeorgeMac

Description

@GeorgeMac

There is ongoing work to define what we call a service and how these services are structured as packaged and built into binaries. I want to propose a further standard for how we define what is and what isn't authorized from a service perspective.

Today, authorization is often implemented as a middleware (decorator) with the identical signature to the type it decorates. This has the perceived convenience that types don't need to care whether they need authorization to call the service or not. Along with the ability to swap out non-authorized or authorized versions in an ad hock fashion.

I want to contest the notion that this is advantageous and that it leads to more authorization related errors that it solves.
Due to this lax contract design, we put a lot of responsibility on the careful composition of services and their middleware layers (often in a main.go). If you fail to pass the correctly decorated service to another service or transport layer, then to leave it wide open for anyone who is purely authenticated, but not necessarily authorized.

My proposal is this:

Where we consume services we explicitly define whether we want an authorized or non-authorized version via having an interface for both. For example:

type BucketService interface {
    FindBucket(context.Context, influxdb.ID) (*influxdb.Bucket, error)
    // ...
}

type AuthorizedBucketService interface {
    FindBucket(context.Context, influxdb.Authorizer, influxdb.ID) (*influxdb.Bucket, error)
    // ...
}

At the transport layer, we would mostly consume the Authorized* interface. Wherever we deem it safe to use the non-authorized, we would user the former interface.

The existing types currently defined in the authorizer package would implement the latter (e.g. AuthorizedBucketService) consume the former interface (e.g. BucketService) and delegate to it. Same goes for all the new locations.

Any services which consume other services would also be expected to consume services with or without explicit auth.

This makes authorization a consumer contract and not a configuration one. Forcing us to consider wherever we delegate to another service whether we have authority and to handle the error case.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions