mirror of https://github.com/status-im/consul.git
Enforce operator:write acl on `WriteStatus` endpoint (#17019)
This commit is contained in:
parent
b1fae05983
commit
53f49b2fa1
|
@ -13,16 +13,31 @@ import (
|
||||||
|
|
||||||
"github.com/oklog/ulid/v2"
|
"github.com/oklog/ulid/v2"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/acl"
|
||||||
"github.com/hashicorp/consul/internal/storage"
|
"github.com/hashicorp/consul/internal/storage"
|
||||||
"github.com/hashicorp/consul/proto-public/pbresource"
|
"github.com/hashicorp/consul/proto-public/pbresource"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error) {
|
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 {
|
if err := validateWriteStatusRequest(req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.resolveType(req.Id.Type)
|
_, err = s.resolveType(req.Id.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,63 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/oklog/ulid/v2"
|
"github.com/oklog/ulid/v2"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/acl/resolver"
|
||||||
"github.com/hashicorp/consul/internal/resource"
|
"github.com/hashicorp/consul/internal/resource"
|
||||||
"github.com/hashicorp/consul/internal/resource/demo"
|
"github.com/hashicorp/consul/internal/resource/demo"
|
||||||
"github.com/hashicorp/consul/proto-public/pbresource"
|
"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) {
|
func TestWriteStatus_InputValidation(t *testing.T) {
|
||||||
server := testServer(t)
|
server := testServer(t)
|
||||||
client := testClient(t, server)
|
client := testClient(t, server)
|
||||||
|
|
Loading…
Reference in New Issue