Browse Source

Enforce operator:write acl on `WriteStatus` endpoint (#17019)

pull/17060/head^2
Semir Patel 2 years ago committed by GitHub
parent
commit
53f49b2fa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      agent/grpc-external/services/resource/write_status.go
  2. 48
      agent/grpc-external/services/resource/write_status_test.go

17
agent/grpc-external/services/resource/write_status.go vendored

@ -13,16 +13,31 @@ import (
"github.com/oklog/ulid/v2"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/internal/storage"
"github.com/hashicorp/consul/proto-public/pbresource"
)
func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error) {
authz, err := s.getAuthorizer(tokenFromContext(ctx))
if err != nil {
return nil, err
}
// check acls
err = authz.ToAllowAuthorizer().OperatorWriteAllowed(&acl.AuthorizerContext{})
switch {
case acl.IsErrPermissionDenied(err):
return nil, status.Error(codes.PermissionDenied, err.Error())
case err != nil:
return nil, status.Errorf(codes.Internal, "failed operator:write allowed acl: %v", err)
}
if err := validateWriteStatusRequest(req); err != nil {
return nil, err
}
_, err := s.resolveType(req.Id.Type)
_, err = s.resolveType(req.Id.Type)
if err != nil {
return nil, err
}

48
agent/grpc-external/services/resource/write_status_test.go vendored

@ -8,15 +8,63 @@ import (
"testing"
"github.com/oklog/ulid/v2"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hashicorp/consul/acl/resolver"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/proto-public/pbresource"
)
func TestWriteStatus_ACL(t *testing.T) {
type testCase struct {
authz resolver.Result
assertErrFn func(error)
}
testcases := map[string]testCase{
"denied": {
authz: AuthorizerFrom(t, demo.ArtistV2WritePolicy),
assertErrFn: func(err error) {
require.Error(t, err)
require.Equal(t, codes.PermissionDenied.String(), status.Code(err).String())
},
},
"allowed": {
authz: AuthorizerFrom(t, demo.ArtistV2WritePolicy, `operator = "write"`),
assertErrFn: func(err error) {
require.NoError(t, err)
},
},
}
for desc, tc := range testcases {
t.Run(desc, func(t *testing.T) {
server := testServer(t)
client := testClient(t, server)
mockACLResolver := &MockACLResolver{}
mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(tc.authz, nil)
server.ACLResolver = mockACLResolver
demo.Register(server.Registry)
artist, err := demo.GenerateV2Artist()
require.NoError(t, err)
rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: artist})
require.NoError(t, err)
artist = rsp.Resource
// exercise ACL
_, err = client.WriteStatus(testContext(t), validWriteStatusRequest(t, artist))
tc.assertErrFn(err)
})
}
}
func TestWriteStatus_InputValidation(t *testing.T) {
server := testServer(t)
client := testClient(t, server)

Loading…
Cancel
Save