diff --git a/internal/mesh/exports.go b/internal/mesh/exports.go index c73ebdb097f5..78056db0d1d7 100644 --- a/internal/mesh/exports.go +++ b/internal/mesh/exports.go @@ -19,12 +19,14 @@ var ( ProxyConfigurationKind = types.ProxyConfigurationKind UpstreamsKind = types.UpstreamsKind + ProxyStateKind = types.ProxyStateTemplateKind // Resource Types for the v1alpha1 version. - ProxyConfigurationV1Alpha1Type = types.ProxyConfigurationV1Alpha1Type - UpstreamsV1Alpha1Type = types.UpstreamsV1Alpha1Type - UpstreamsConfigurationV1Alpha1Type = types.UpstreamsConfigurationV1Alpha1Type + ProxyConfigurationV1Alpha1Type = types.ProxyConfigurationV1Alpha1Type + UpstreamsV1Alpha1Type = types.UpstreamsV1Alpha1Type + UpstreamsConfigurationV1Alpha1Type = types.UpstreamsConfigurationV1Alpha1Type + ProxyStateTemplateConfigurationV1Alpha1Type = types.ProxyStateTemplateV1Alpha1Type ) // RegisterTypes adds all resource types within the "catalog" API group diff --git a/internal/mesh/internal/types/proxy_state_template.go b/internal/mesh/internal/types/proxy_state_template.go new file mode 100644 index 000000000000..7f46190ea015 --- /dev/null +++ b/internal/mesh/internal/types/proxy_state_template.go @@ -0,0 +1,59 @@ +package types + +import ( + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/internal/resource" + pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + ProxyStateTemplateKind = "ProxyStateTemplate" +) + +var ( + ProxyStateTemplateV1Alpha1Type = &pbresource.Type{ + Group: GroupName, + GroupVersion: VersionV1Alpha1, + Kind: ProxyStateTemplateKind, + } + + ProxyStateTemplateType = ProxyStateTemplateV1Alpha1Type +) + +func RegisterProxyStateTemplate(r resource.Registry) { + r.Register(resource.Registration{ + Type: ProxyStateTemplateV1Alpha1Type, + Proto: &pbmesh.ProxyStateTemplate{}, + Validate: nil, + ACLs: &resource.ACLHooks{ + Read: func(authorizer acl.Authorizer, id *pbresource.ID) error { + // Check service:read and operator:read permissions. + // If service:read is not allowed, check operator:read. We want to allow both as this + // resource is mostly useful for debuggability and we want to cover + // the most cases that serve that purpose. + serviceReadErr := authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.Name, resource.AuthorizerContext(id.Tenancy)) + operatorReadErr := authorizer.ToAllowAuthorizer().OperatorReadAllowed(resource.AuthorizerContext(id.Tenancy)) + + switch { + case serviceReadErr != nil: + return serviceReadErr + case operatorReadErr != nil: + return operatorReadErr + } + + return nil + }, + Write: func(authorizer acl.Authorizer, p *pbresource.Resource) error { + // Require operator:write only for "break-glass" scenarios as this resource should be mostly + // managed by a controller. + return authorizer.ToAllowAuthorizer().OperatorWriteAllowed(resource.AuthorizerContext(p.Id.Tenancy)) + }, + List: func(authorizer acl.Authorizer, tenancy *pbresource.Tenancy) error { + // No-op List permission as we want to default to filtering resources + // from the list using the Read enforcement. + return nil + }, + }, + }) +} diff --git a/internal/mesh/internal/types/types.go b/internal/mesh/internal/types/types.go index 3a7c6a329ac4..d1ca23b09528 100644 --- a/internal/mesh/internal/types/types.go +++ b/internal/mesh/internal/types/types.go @@ -17,4 +17,5 @@ func Register(r resource.Registry) { RegisterProxyConfiguration(r) RegisterUpstreams(r) RegisterUpstreamsConfiguration(r) + RegisterProxyStateTemplate(r) } diff --git a/proto-public/pbmesh/v1alpha1/proxy_state.pb.go b/proto-public/pbmesh/v1alpha1/proxy_state.pb.go index ab763966485f..cb858b6d1d78 100644 --- a/proto-public/pbmesh/v1alpha1/proxy_state.pb.go +++ b/proto-public/pbmesh/v1alpha1/proxy_state.pb.go @@ -105,7 +105,8 @@ type ProxyState struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // identity is a reference to the WorkloadIdentity associated with this proxy. + // id is this proxy's identity. This should correspond to the workload identity that this proxy of + // the workload this proxy represents. Identity *pbresource.Reference `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` // listeners is a list of listeners for this proxy. Listeners []*pbproxystate.Listener `protobuf:"bytes,2,rep,name=listeners,proto3" json:"listeners,omitempty"` diff --git a/proto-public/pbmesh/v1alpha1/proxy_state.proto b/proto-public/pbmesh/v1alpha1/proxy_state.proto index e00ae00446c5..46ef458e5711 100644 --- a/proto-public/pbmesh/v1alpha1/proxy_state.proto +++ b/proto-public/pbmesh/v1alpha1/proxy_state.proto @@ -30,7 +30,8 @@ message ProxyStateTemplate { } message ProxyState { - // identity is a reference to the WorkloadIdentity associated with this proxy. + // id is this proxy's identity. This should correspond to the workload identity that this proxy of + // the workload this proxy represents. hashicorp.consul.resource.Reference identity = 1; // listeners is a list of listeners for this proxy. repeated pbproxystate.Listener listeners = 2;