feat(handlers): Implement Policy Service
This also includes adding new grant and type primitives, as well as package domain names.
This commit is contained in:
1 parent
1c3b1b42f7
commit
edbb33de5b
15 files changed
+194
-5
No files matched your search
@@ -315,6 +315,11 @@ var prefixToResourceType = map[string]ResourceInfo{
|
||||
Type: resource.SessionRecording,
|
||||
Subtype: UnknownSubtype,
|
||||
},
|
||||
|
||||
StoragePolicyPrefix: {
|
||||
Type: resource.Policy,
|
||||
Subtype: UnknownSubtype,
|
||||
},
|
||||
}
|
||||
|
||||
var resourceTypeToPrefixes map[resource.Type][]string = func() map[resource.Type][]string {
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/host_sets"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/hosts"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/managed_groups"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/policies"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/roles"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/scopes"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/session_recordings"
|
||||
@@ -222,6 +223,17 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error {
|
||||
}
|
||||
services.RegisterStorageBucketServiceServer(s, sbs)
|
||||
}
|
||||
if _, ok := currentServices[services.PolicyService_ServiceDesc.ServiceName]; !ok {
|
||||
ps, err := policies.NewServiceFn(
|
||||
c.baseContext,
|
||||
c.IamRepoFn,
|
||||
c.ControllerExtension,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create policy handler service: %w", err)
|
||||
}
|
||||
services.RegisterPolicyServiceServer(s, ps)
|
||||
}
|
||||
if _, ok := currentServices[services.SessionRecordingService_ServiceDesc.ServiceName]; !ok {
|
||||
srs, err := session_recordings.NewServiceFn(
|
||||
c.baseContext,
|
||||
@@ -403,6 +415,9 @@ func registerGrpcGatewayEndpoints(ctx context.Context, gwMux *runtime.ServeMux,
|
||||
if err := services.RegisterSessionRecordingServiceHandlerFromEndpoint(ctx, gwMux, gatewayTarget, dialOptions); err != nil {
|
||||
return fmt.Errorf("failed to register session recording handler: %w", err)
|
||||
}
|
||||
if err := services.RegisterPolicyServiceHandlerFromEndpoint(ctx, gwMux, gatewayTarget, dialOptions); err != nil {
|
||||
return fmt.Errorf("failed to register policy handler: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package policies
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/common"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
internalglobals "github.com/hashicorp/boundary/internal/globals"
|
||||
"github.com/hashicorp/boundary/internal/types/action"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var (
|
||||
_ pbs.PolicyServiceServer = (*Service)(nil)
|
||||
|
||||
// idActions contains the set of actions that can be performed on individual
|
||||
// resources.
|
||||
idActions = action.NewActionSet(
|
||||
action.NoOp,
|
||||
action.Read,
|
||||
action.Update,
|
||||
action.Delete,
|
||||
)
|
||||
// CollectionActions contains the set of actions that can be performed on
|
||||
// this collection.
|
||||
CollectionActions = action.NewActionSet(
|
||||
action.Create,
|
||||
action.List,
|
||||
)
|
||||
)
|
||||
|
||||
// NewServiceFn returns a policy service which is not implemented in OSS
|
||||
var NewServiceFn = func(ctx context.Context,
|
||||
iamRepoFn common.IamRepoFactory,
|
||||
controllerExt internalglobals.ControllerExtension,
|
||||
) (pbs.PolicyServiceServer, error) {
|
||||
return &Service{}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
action.RegisterResource(resource.Policy, idActions, CollectionActions)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
pbs.UnimplementedPolicyServiceServer
|
||||
}
|
||||
|
||||
// GetPolicy implements the interface pbs.PolicyServiceServer.
|
||||
func (s *Service) GetPolicy(ctx context.Context, req *pbs.GetPolicyRequest) (*pbs.GetPolicyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "Policies are an Enterprise-only feature")
|
||||
}
|
||||
|
||||
// ListPolicies implements the interface pbs.PolicyServiceServer.
|
||||
func (s *Service) ListPolicies(ctx context.Context, req *pbs.ListPoliciesRequest) (*pbs.ListPoliciesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "Policies are an Enterprise-only feature")
|
||||
}
|
||||
|
||||
// CreatePolicy implements the interface pbs.PolicyServiceServer.
|
||||
func (s *Service) CreatePolicy(ctx context.Context, req *pbs.CreatePolicyRequest) (*pbs.CreatePolicyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "Policies are an Enterprise-only feature")
|
||||
}
|
||||
|
||||
// UpdatePolicy implements the interface pbs.PolicyServiceServer.
|
||||
func (s *Service) UpdatePolicy(ctx context.Context, req *pbs.UpdatePolicyRequest) (*pbs.UpdatePolicyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "Policies are an Enterprise-only feature")
|
||||
}
|
||||
|
||||
func (s *Service) DeletePolicy(ctx context.Context, req *pbs.DeletePolicyRequest) (*pbs.DeletePolicyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "Policies are an Enterprise-only feature")
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package policies
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestPolicyService(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
s := Service{}
|
||||
|
||||
gotCreate, err := s.CreatePolicy(ctx, &pbs.CreatePolicyRequest{})
|
||||
require.Nil(gotCreate)
|
||||
require.Error(err)
|
||||
gotStatus, ok := status.FromError(err)
|
||||
require.True(ok)
|
||||
assert.Equal(gotStatus.Code(), codes.Unimplemented)
|
||||
assert.Equal(gotStatus.Message(), "Policies are an Enterprise-only feature")
|
||||
|
||||
gotUpdate, err := s.UpdatePolicy(ctx, &pbs.UpdatePolicyRequest{})
|
||||
require.Nil(gotUpdate)
|
||||
require.Error(err)
|
||||
gotStatus, ok = status.FromError(err)
|
||||
require.True(ok)
|
||||
assert.Equal(gotStatus.Code(), codes.Unimplemented)
|
||||
assert.Equal(gotStatus.Message(), "Policies are an Enterprise-only feature")
|
||||
|
||||
gotGet, err := s.GetPolicy(ctx, &pbs.GetPolicyRequest{})
|
||||
require.Nil(gotGet)
|
||||
require.Error(err)
|
||||
gotStatus, ok = status.FromError(err)
|
||||
require.True(ok)
|
||||
assert.Equal(gotStatus.Code(), codes.Unimplemented)
|
||||
assert.Equal(gotStatus.Message(), "Policies are an Enterprise-only feature")
|
||||
|
||||
gotDelete, err := s.DeletePolicy(ctx, &pbs.DeletePolicyRequest{})
|
||||
require.Nil(gotDelete)
|
||||
require.Error(err)
|
||||
gotStatus, ok = status.FromError(err)
|
||||
require.True(ok)
|
||||
assert.Equal(gotStatus.Code(), codes.Unimplemented)
|
||||
assert.Equal(gotStatus.Message(), "Policies are an Enterprise-only feature")
|
||||
|
||||
gotList, err := s.ListPolicies(ctx, &pbs.ListPoliciesRequest{})
|
||||
require.Nil(gotList)
|
||||
require.Error(err)
|
||||
gotStatus, ok = status.FromError(err)
|
||||
require.True(ok)
|
||||
assert.Equal(gotStatus.Code(), codes.Unimplemented)
|
||||
assert.Equal(gotStatus.Message(), "Policies are an Enterprise-only feature")
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentialstores"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/groups"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/host_catalogs"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/policies"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/roles"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/session_recordings"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/sessions"
|
||||
@@ -81,6 +82,7 @@ var (
|
||||
resource.User: users.CollectionActions,
|
||||
resource.Worker: workers.CollectionActions,
|
||||
resource.SessionRecording: session_recordings.CollectionActions,
|
||||
resource.Policy: policies.CollectionActions,
|
||||
},
|
||||
|
||||
scope.Org.String(): {
|
||||
@@ -92,6 +94,7 @@ var (
|
||||
resource.Scope: CollectionActions,
|
||||
resource.User: users.CollectionActions,
|
||||
resource.SessionRecording: session_recordings.CollectionActions,
|
||||
resource.Policy: policies.CollectionActions,
|
||||
},
|
||||
|
||||
scope.Project.String(): {
|
||||
|
||||
@@ -93,6 +93,12 @@ var globalAuthorizedCollectionActions = map[string]*structpb.ListValue{
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
"policies": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
"roles": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
@@ -155,6 +161,12 @@ var orgAuthorizedCollectionActions = map[string]*structpb.ListValue{
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
"policies": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
"roles": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
|
||||
@@ -63,7 +63,7 @@ func Test_newRateLimiterConfig(t *testing.T) {
|
||||
ratelimit.DefaultLimiterMaxQuotas(),
|
||||
false,
|
||||
&rateLimiterConfig{
|
||||
maxSize: 296148,
|
||||
maxSize: 308154,
|
||||
configs: nil,
|
||||
disabled: false,
|
||||
limits: defaultLimits,
|
||||
|
||||
+1
-1
@@ -3893,7 +3893,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"max_size": 296148,
|
||||
"max_size": 308154,
|
||||
"msg": "controller api rate limiter"
|
||||
},
|
||||
"op": "controller.(rateLimiterConfig).writeSysEvent",
|
||||
|
||||
+1
-1
@@ -3893,7 +3893,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"max_size": 296148,
|
||||
"max_size": 308154,
|
||||
"msg": "controller api rate limiter"
|
||||
},
|
||||
"op": "controller.(rateLimiterConfig).writeSysEvent",
|
||||
|
||||
@@ -928,7 +928,7 @@ func Test_AnonRestrictions(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
require, assert := require.New(t), assert.New(t)
|
||||
for i := resource.Type(1); i <= resource.StorageBucket; i++ {
|
||||
for i := resource.Type(1); i <= resource.Policy; i++ {
|
||||
if i == resource.Controller || i == resource.Worker {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func Test_ValidateType(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
var g Grant
|
||||
for i := resource.Unknown; i <= resource.StorageBucket; i++ {
|
||||
for i := resource.Unknown; i <= resource.Policy; i++ {
|
||||
g.typ = i
|
||||
if i == resource.Controller {
|
||||
assert.Error(t, g.validateType(ctx))
|
||||
|
||||
@@ -5,6 +5,9 @@ package policy
|
||||
|
||||
import "github.com/hashicorp/boundary/internal/boundary"
|
||||
|
||||
// Domain defines the domain for this package.
|
||||
const Domain = "policy"
|
||||
|
||||
// Policy contains the common methods across all the different types of policies.
|
||||
type Policy interface {
|
||||
boundary.Resource
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/host_sets"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/hosts"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/managed_groups"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/policies"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/roles"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/scopes"
|
||||
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/session_recordings"
|
||||
|
||||
@@ -34,6 +34,7 @@ const (
|
||||
CredentialLibrary
|
||||
Credential
|
||||
StorageBucket
|
||||
Policy
|
||||
// NOTE: When adding a new type, be sure to update:
|
||||
//
|
||||
// * The Grant.validateType function and test
|
||||
@@ -72,6 +73,7 @@ func (r Type) String() string {
|
||||
"credential-library",
|
||||
"credential",
|
||||
"storage-bucket",
|
||||
"policy",
|
||||
}[r]
|
||||
}
|
||||
|
||||
@@ -79,6 +81,8 @@ func (r Type) PluralString() string {
|
||||
switch r {
|
||||
case CredentialLibrary:
|
||||
return "credential-libraries"
|
||||
case Policy:
|
||||
return "policies"
|
||||
default:
|
||||
return r.String() + "s"
|
||||
}
|
||||
@@ -88,6 +92,8 @@ func FromPlural(s string) (Type, bool) {
|
||||
switch s {
|
||||
case "credential-libraries":
|
||||
return CredentialLibrary, true
|
||||
case "policies":
|
||||
return Policy, true
|
||||
default:
|
||||
t, ok := Map[strings.TrimSuffix(s, "s")]
|
||||
return t, ok
|
||||
@@ -117,6 +123,7 @@ var Map = map[string]Type{
|
||||
CredentialLibrary.String(): CredentialLibrary,
|
||||
Credential.String(): Credential,
|
||||
StorageBucket.String(): StorageBucket,
|
||||
Policy.String(): Policy,
|
||||
}
|
||||
|
||||
// Parent returns the parent type for a given type; if there is no parent, it
|
||||
@@ -159,6 +166,7 @@ func TopLevelType(typ Type) bool {
|
||||
Target,
|
||||
User,
|
||||
StorageBucket,
|
||||
Policy,
|
||||
Worker:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -122,6 +122,11 @@ func Test_Resource(t *testing.T) {
|
||||
want: Credential,
|
||||
parent: CredentialStore,
|
||||
},
|
||||
{
|
||||
typeString: "policy",
|
||||
want: Policy,
|
||||
topLevelType: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.typeString, func(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user