Adds auth middleware for all rpcs with tests.
This commit is contained in:
parent
fd53846238
commit
64e6faecae
4 changed files with 146 additions and 4 deletions
|
|
@ -4,17 +4,41 @@ import (
|
|||
"context"
|
||||
|
||||
api "github.com/AYM1607/proglog/api/v1"
|
||||
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
objectWildCard = "*"
|
||||
produceAction = "produce"
|
||||
consumeAction = "consume"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
CommitLog CommitLog
|
||||
CommitLog CommitLog
|
||||
Authorizer Authorizer
|
||||
}
|
||||
|
||||
// This comes from the book, why is this needed?
|
||||
var _ api.LogServer = (*grpcServer)(nil)
|
||||
|
||||
func NewGRPCServer(config *Config, opts ...grpc.ServerOption) (*grpc.Server, error) {
|
||||
opts = append(opts,
|
||||
// Streaming interceptors.
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||
grpc_auth.StreamServerInterceptor(authenticate),
|
||||
)),
|
||||
// Unary interceptors.
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||
grpc_auth.UnaryServerInterceptor(authenticate),
|
||||
)),
|
||||
)
|
||||
gsrv := grpc.NewServer(opts...)
|
||||
srv, err := newgrpcServer(config)
|
||||
if err != nil {
|
||||
|
|
@ -38,6 +62,13 @@ func newgrpcServer(config *Config) (srv *grpcServer, err error) {
|
|||
|
||||
func (s *grpcServer) Produce(ctx context.Context, req *api.ProduceRequest) (
|
||||
*api.ProduceResponse, error) {
|
||||
if err := s.Authorizer.Authorize(
|
||||
subject(ctx),
|
||||
objectWildCard,
|
||||
produceAction,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := s.CommitLog.Append(req.Record)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -47,6 +78,13 @@ func (s *grpcServer) Produce(ctx context.Context, req *api.ProduceRequest) (
|
|||
|
||||
func (s *grpcServer) Consume(ctx context.Context, req *api.ConsumeRequest) (
|
||||
*api.ConsumeResponse, error) {
|
||||
if err := s.Authorizer.Authorize(
|
||||
subject(ctx),
|
||||
objectWildCard,
|
||||
consumeAction,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
record, err := s.CommitLog.Read(req.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -99,7 +137,35 @@ func (s *grpcServer) ConsumeStream(
|
|||
}
|
||||
}
|
||||
|
||||
func authenticate(ctx context.Context) (context.Context, error) {
|
||||
peer, ok := peer.FromContext(ctx)
|
||||
if !ok {
|
||||
return ctx, status.New(
|
||||
codes.Unknown,
|
||||
"could not find peer info",
|
||||
).Err()
|
||||
}
|
||||
if peer.AuthInfo == nil {
|
||||
return context.WithValue(ctx, subjectContextKey{}, ""), nil
|
||||
}
|
||||
tlsInfo := peer.AuthInfo.(credentials.TLSInfo)
|
||||
subject := tlsInfo.State.VerifiedChains[0][0].Subject.CommonName
|
||||
ctx = context.WithValue(ctx, subjectContextKey{}, subject)
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func subject(ctx context.Context) string {
|
||||
return ctx.Value(subjectContextKey{}).(string)
|
||||
}
|
||||
|
||||
type subjectContextKey struct{}
|
||||
|
||||
type CommitLog interface {
|
||||
Append(*api.Record) (uint64, error)
|
||||
Read(uint64) (*api.Record, error)
|
||||
}
|
||||
|
||||
type Authorizer interface {
|
||||
Authorize(subject, object, action string) error
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue