Skip to content

Commit

Permalink
Authorizer with Casbin. Clients: root and nobody. Interceptors to aut…
Browse files Browse the repository at this point in the history
…henticate and read client's cert
  • Loading branch information
Brijeshlakkad committed Jun 11, 2022
1 parent 32ce9c0 commit 283982d
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 129 deletions.
24 changes: 23 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,33 @@ gencert:
-config=test/ca-config.json \
-profile=client \
test/client-csr.json | cfssljson -bare client

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=test/ca-config.json \
-profile=client \
-cn="root" \
test/client-csr.json | cfssljson -bare root-client

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=test/ca-config.json \
-profile=client \
-cn="nobody" \
test/client-csr.json | cfssljson -bare nobody-client

mv *.pem *.csr ${CONFIG_PATH}

$(CONFIG_PATH)/model.conf:
cp test/model.conf $(CONFIG_PATH)/model.conf

$(CONFIG_PATH)/policy.csv:
cp test/policy.csv $(CONFIG_PATH)/policy.csv

.PHONY: test
test:
test: $(CONFIG_PATH)/policy.csv $(CONFIG_PATH)/model.conf
go test -race ./...

.PHONY: compile
Expand Down
30 changes: 10 additions & 20 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,26 @@ module github.com/Brijeshlakkad/distributedlogging
go 1.17

require (
github.com/casbin/casbin v1.9.1
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/stretchr/testify v1.7.2
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.28.0
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
launchpad.net/gocheck v0.0.0-20140225173054-000000000087
)

require (
github.com/GeertJohan/go.rice v1.0.0 // indirect
github.com/cloudflare/cfssl v1.4.1 // indirect
github.com/daaku/go.zipexe v1.0.0 // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-sql-driver/mysql v1.3.0 // indirect
github.com/golang/protobuf v1.5.0 // indirect
github.com/google/certificate-transparency-go v1.0.21 // indirect
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 // indirect
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade // indirect
github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49 // indirect
github.com/lib/pq v0.0.0-20180201184707-88edab080323 // indirect
github.com/mattn/go-sqlite3 v1.10.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/kr/text v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/weppos/publicsuffix-go v0.5.0 // indirect
github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e // indirect
github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect
google.golang.org/grpc v1.32.0 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
golang.org/x/text v0.3.3 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
136 changes: 55 additions & 81 deletions go.sum

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions internal/auth/authorizer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package auth

import (
"fmt"

"github.com/casbin/casbin"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

type Authorizer struct {
enforcer *casbin.Enforcer
}

func (a *Authorizer) Authorize(subject, object, action string) error {
if !a.enforcer.Enforce(subject, object, action) {
msg := fmt.Sprintf(
"%s not to %s to %s",
subject,
action,
object,
)
st := status.New(codes.PermissionDenied, msg)
return st.Err()
}
return nil
}

func New(model, policy string) *Authorizer {
enforcer := casbin.NewEnforcer(model, policy)
return &Authorizer{
enforcer: enforcer,
}
}
16 changes: 11 additions & 5 deletions internal/config/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ import (
)

var (
CAFile = configFile("ca.pem")
ServerCertFile = configFile("server.pem")
ServerKeyFile = configFile("server-key.pem")
ClientCertFile = configFile("client.pem")
ClientKeyFile = configFile("client-key.pem")
CAFile = configFile("ca.pem")
ServerCertFile = configFile("server.pem")
ServerKeyFile = configFile("server-key.pem")
ClientCertFile = configFile("client.pem")
ClientKeyFile = configFile("client-key.pem")
RootClientCertFile = configFile("root-client.pem")
RootClientKeyFile = configFile("root-client-key.pem")
NobodyClientCertFile = configFile("nobody-client.pem")
NobodyClientKeyFile = configFile("nobody-client-key.pem")
ACLModelFile = configFile("model.conf")
ACLPolicyFile = configFile("policy.csv")
)

func configFile(filename string) string {
Expand Down
68 changes: 67 additions & 1 deletion internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,28 @@ import (
"context"

api "github.com/Brijeshlakkad/distributedlogging/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"
)

type Config struct {
CommitLog CommitLog
CommitLog CommitLog
Authorizer Authorizer
}

const (
objectWildCard = "*"
produceAction = "produce"
consumeAction = "consume"
)

type Authorizer interface {
Authorize(subject, object, action string) error
}

var _ api.LogServer = (*grpcServer)(nil)
Expand All @@ -27,6 +44,14 @@ func newgrpcServer(config *Config) (srv *grpcServer, err error) {

// To enable user to pass their own listener implementation.
func NewGRPCServer(config *Config, opts ...grpc.ServerOption) (*grpc.Server, error) {
opts = append(opts, grpc.StreamInterceptor(
grpc_middleware.ChainStreamServer(
grpc_auth.StreamServerInterceptor(authenticate),
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_auth.UnaryServerInterceptor(authenticate),
)),
)
gsrv := grpc.NewServer(opts...)
srv, err := newgrpcServer(config)
if err != nil {
Expand All @@ -37,6 +62,13 @@ func NewGRPCServer(config *Config, opts ...grpc.ServerOption) (*grpc.Server, err
}

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
Expand All @@ -45,6 +77,13 @@ func (s *grpcServer) Produce(ctx context.Context, req *api.ProduceRequest) (*api
}

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
Expand Down Expand Up @@ -97,3 +136,30 @@ type CommitLog interface {
Append(*api.Record) (uint64, error)
Read(uint64) (*api.Record, error)
}

// Interceptor reading the subject out of the client’s cert and writing it to the RPC’s context.
func authenticate(ctx context.Context) (context.Context, error) {
peer, ok := peer.FromContext(ctx)
if !ok {
return ctx, status.New(
codes.Unknown,
"couldn't 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{}
Loading

0 comments on commit 283982d

Please sign in to comment.