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

Authentication & Authorisation #24

Open
rcrowe opened this issue Jun 21, 2018 · 1 comment
Open

Authentication & Authorisation #24

rcrowe opened this issue Jun 21, 2018 · 1 comment

Comments

@rcrowe
Copy link
Member

rcrowe commented Jun 21, 2018

Two use cases identified

  • Who is consuming (authentication)
  • Restrict who can publish (authorisation)

Authentication

As the number of consumers has grown & the ability to do so is not restricted we've been unable to keep track. When an issue arises or we have to coordinate changes (for example, as we've been making changes to the underlying nats streaming cluster) it's been helpful to chat with other teams/consumers.

An identifier could also be used in metrics (who's consuming/publishing the most) or logs (which client caused a repeatable server panic).

I played with 2 ideas for identifying a client

  1. Client ID. An identifying token over a gRPC TLS connection.
  2. Mutual TLS. Identify the client through the cert.

ACL

The main driver for authentication has been to implement ACL on the publishing side of things. We should be able to restrict who can publish back into the stream.

An example spike looks like...

func NewStreamServerInterceptor(auth authorisor) grpc.StreamServerInterceptor {
	return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
		newCtx, err := auth.Authorise(stream.Context(), info.FullMethod)
		if err != nil {
			return err
		}

		wrapped := grpc_middleware.WrapServerStream(stream)
		wrapped.WrappedContext = newCtx
		return handler(srv, wrapped)
	}
}

func (a *BasicAuthorisor) Authorise(ctx context.Context, method string) (context.Context, error) {
	if !a.SecureConsume && !a.SecurePublish {
		return ctx, nil
	}

	token, err := grpc_auth.AuthFromMD(ctx, "basic")
	if err != nil {
		return nil, err
	}

	client, err := a.clientFromToken(token)
	if err != nil {
		return ctx, grpc.Errorf(codes.Unauthenticated, "Unable to identifiy client with token `%s`", token)
	}

	// Client has been authenticated, that's enough to consume
	// Now check client is authorised to publish
	if a.SecurePublish && strings.Contains(strings.ToLower(method), "publish") && !client.acl.publish {
		return ctx, grpc.Errorf(codes.PermissionDenied, "Client `%s` has no permission to publish", token)
	}

	return ctx, nil
}
@simonhdickson
Copy link
Contributor

Am I interested in reviving this issue, but also introducing the ability to lock down consume/publish on a per-topic basis as well.

Potentially have some kind of config file that would have contain access rights for different roles clients? (being optional if you choose not to use this feature)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants