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

fix(rpc/flipt): implement Requester for evaluation data snapshot #3439

Merged
merged 3 commits into from
Sep 7, 2024
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
30 changes: 15 additions & 15 deletions internal/server/authz/middleware/grpc/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,21 @@ func AuthorizationRequiredInterceptor(logger *zap.Logger, policyVerifier authz.V
return ctx, errUnauthorized
}

request := requester.Request()

allowed, err := policyVerifier.IsAllowed(ctx, map[string]interface{}{
"request": request,
"authentication": auth,
})

if err != nil {
logger.Error("unauthorized", zap.Error(err))
return ctx, errUnauthorized
}

if !allowed {
logger.Error("unauthorized", zap.String("reason", "permission denied"))
return ctx, errUnauthorized
for _, request := range requester.Request() {
allowed, err := policyVerifier.IsAllowed(ctx, map[string]interface{}{
"request": request,
"authentication": auth,
})

if err != nil {
logger.Error("unauthorized", zap.Error(err))
return ctx, errUnauthorized
}

if !allowed {
logger.Error("unauthorized", zap.String("reason", "permission denied"))
return ctx, errUnauthorized
}
}

return handler(ctx, req)
Expand Down
4 changes: 0 additions & 4 deletions internal/server/evaluation/data/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,3 @@ func (srv *Server) EvaluationSnapshotNamespace(ctx context.Context, r *evaluatio

return resp, nil
}

func (srv *Server) SkipsAuthorization(ctx context.Context) bool {
return true
}
5 changes: 0 additions & 5 deletions internal/server/evaluation/data/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,3 @@ func TestEvaluationSnapshotNamespace(t *testing.T) {
store.AssertExpectations(t)
})
}

func Test_Server_SkipsAuthorization(t *testing.T) {
server := &Server{}
assert.True(t, server.SkipsAuthorization(context.Background()))
}
99 changes: 50 additions & 49 deletions internal/server/middleware/grpc/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,77 +239,78 @@
// AuditEventUnaryInterceptor captures events and adds them to the trace span to be consumed downstream.
func AuditEventUnaryInterceptor(logger *zap.Logger, eventPairChecker audit.EventPairChecker) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
var request flipt.Request
var requests []flipt.Request
r, ok := req.(flipt.Requester)

if !ok {
return handler(ctx, req)
}

request = r.Request()
requests = r.Request()

var event *audit.Event
var events []*audit.Event

actor := authn.ActorFromContext(ctx)

defer func() {
if event != nil {
eventPair := fmt.Sprintf("%s:%s", event.Type, event.Action)

exists := eventPairChecker.Check(eventPair)
if exists {
span := trace.SpanFromContext(ctx)
span.AddEvent("event", trace.WithAttributes(event.DecodeToAttributes()...))
if events != nil {

Check failure on line 256 in internal/server/middleware/grpc/middleware.go

View workflow job for this annotation

GitHub Actions / Lint Go

S1031: unnecessary nil check around range (gosimple)
for _, event := range events {
eventPair := fmt.Sprintf("%s:%s", event.Type, event.Action)

exists := eventPairChecker.Check(eventPair)
if exists {
span := trace.SpanFromContext(ctx)
span.AddEvent("event", trace.WithAttributes(event.DecodeToAttributes()...))
}
}
}
}()

resp, err := handler(ctx, req)
if err != nil {
var uerr errs.ErrUnauthorized
if errors.As(err, &uerr) {
request.Status = flipt.StatusDenied
event = audit.NewEvent(request, actor, nil)
for _, request := range requests {
if err != nil {
var uerr errs.ErrUnauthorized
if errors.As(err, &uerr) {
request.Status = flipt.StatusDenied
events = append(events, audit.NewEvent(request, actor, nil))

Check warning on line 275 in internal/server/middleware/grpc/middleware.go

View check run for this annotation

Codecov / codecov/patch

internal/server/middleware/grpc/middleware.go#L272-L275

Added lines #L272 - L275 were not covered by tests
}

continue

Check warning on line 278 in internal/server/middleware/grpc/middleware.go

View check run for this annotation

Codecov / codecov/patch

internal/server/middleware/grpc/middleware.go#L278

Added line #L278 was not covered by tests
}

// Delete and Order request(s) have to be handled separately because they do not
// return the concrete type but rather an *empty.Empty response.
if request.Action == flipt.ActionDelete {
events = append(events, audit.NewEvent(request, actor, r))
continue
}
return resp, err
}

// Delete and Order request(s) have to be handled separately because they do not
// return the concrete type but rather an *empty.Empty response.
if request.Action == flipt.ActionDelete {
event = audit.NewEvent(request, actor, r)
} else {
switch r := req.(type) {
case *flipt.OrderRulesRequest, *flipt.OrderRolloutsRequest:
event = audit.NewEvent(request, actor, r)
events = append(events, audit.NewEvent(request, actor, r))
continue
}
}

// Short circuiting the middleware here since we have a non-nil event from
// detecting a delete.
if event != nil {
return resp, err
}

switch r := resp.(type) {
case *flipt.Flag:
event = audit.NewEvent(request, actor, audit.NewFlag(r))
case *flipt.Variant:
event = audit.NewEvent(request, actor, audit.NewVariant(r))
case *flipt.Segment:
event = audit.NewEvent(request, actor, audit.NewSegment(r))
case *flipt.Distribution:
event = audit.NewEvent(request, actor, audit.NewDistribution(r))
case *flipt.Constraint:
event = audit.NewEvent(request, actor, audit.NewConstraint(r))
case *flipt.Namespace:
event = audit.NewEvent(request, actor, audit.NewNamespace(r))
case *flipt.Rollout:
event = audit.NewEvent(request, actor, audit.NewRollout(r))
case *flipt.Rule:
event = audit.NewEvent(request, actor, audit.NewRule(r))
case *auth.CreateTokenResponse:
event = audit.NewEvent(request, actor, r.Authentication.Metadata)
switch r := resp.(type) {
case *flipt.Flag:
events = append(events, audit.NewEvent(request, actor, audit.NewFlag(r)))
case *flipt.Variant:
events = append(events, audit.NewEvent(request, actor, audit.NewVariant(r)))
case *flipt.Segment:
events = append(events, audit.NewEvent(request, actor, audit.NewSegment(r)))
case *flipt.Distribution:
events = append(events, audit.NewEvent(request, actor, audit.NewDistribution(r)))
case *flipt.Constraint:
events = append(events, audit.NewEvent(request, actor, audit.NewConstraint(r)))
case *flipt.Namespace:
events = append(events, audit.NewEvent(request, actor, audit.NewNamespace(r)))
case *flipt.Rollout:
events = append(events, audit.NewEvent(request, actor, audit.NewRollout(r)))
case *flipt.Rule:
events = append(events, audit.NewEvent(request, actor, audit.NewRule(r)))
case *auth.CreateTokenResponse:
events = append(events, audit.NewEvent(request, actor, r.Authentication.Metadata))
}
}

return resp, err
Expand Down
16 changes: 8 additions & 8 deletions rpc/flipt/auth/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import (
"go.flipt.io/flipt/rpc/flipt"
)

func (req *CreateTokenRequest) Request() flipt.Request {
return flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionCreate, flipt.WithSubject(flipt.SubjectToken))
func (req *CreateTokenRequest) Request() []flipt.Request {
return []flipt.Request{flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionCreate, flipt.WithSubject(flipt.SubjectToken))}
}

func (req *ListAuthenticationsRequest) Request() flipt.Request {
return flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionRead)
func (req *ListAuthenticationsRequest) Request() []flipt.Request {
return []flipt.Request{flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionRead)}
}

func (req *GetAuthenticationRequest) Request() flipt.Request {
return flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionRead)
func (req *GetAuthenticationRequest) Request() []flipt.Request {
return []flipt.Request{flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionRead)}
}

func (req *DeleteAuthenticationRequest) Request() flipt.Request {
return flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionDelete)
func (req *DeleteAuthenticationRequest) Request() []flipt.Request {
return []flipt.Request{flipt.NewRequest(flipt.ResourceAuthentication, flipt.ActionDelete)}
}
10 changes: 10 additions & 0 deletions rpc/flipt/evaluation/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package evaluation

import "go.flipt.io/flipt/rpc/flipt"

func (r *EvaluationNamespaceSnapshotRequest) Request() []flipt.Request {
return []flipt.Request{
flipt.NewRequest(flipt.ResourceFlag, flipt.ActionRead, flipt.WithNamespace(r.Key)),
flipt.NewRequest(flipt.ResourceSegment, flipt.ActionRead, flipt.WithNamespace(r.Key)),
}
}
Loading
Loading