open-consul/agent/grpc-external/services/acl/server.go
Dan Upton 34140ff3e0
grpc: rename public/private directories to external/internal (#13721)
Previously, public referred to gRPC services that are both exposed on
the dedicated gRPC port and have their definitions in the proto-public
directory (so were considered usable by 3rd parties). Whereas private
referred to services on the multiplexed server port that are only usable
by agents and other servers.

Now, we're splitting these definitions, such that external/internal
refers to the port and public/private refers to whether they can be used
by 3rd parties.

This is necessary because the peering replication API needs to be
exposed on the dedicated port, but is not (yet) suitable for use by 3rd
parties.
2022-07-13 16:33:48 +01:00

89 lines
2.9 KiB
Go

package acl
import (
"context"
"github.com/hashicorp/go-hclog"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/consul/authmethod"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/proto-public/pbacl"
)
type Config struct {
ACLsEnabled bool
Logger hclog.Logger
LoadAuthMethod func(authMethod string, entMeta *acl.EnterpriseMeta) (*structs.ACLAuthMethod, Validator, error)
NewLogin func() Login
ForwardRPC func(structs.RPCInfo, func(*grpc.ClientConn) error) (bool, error)
ValidateEnterpriseRequest func(*acl.EnterpriseMeta, bool) error
LocalTokensEnabled func() bool
InPrimaryDatacenter bool
PrimaryDatacenter string
NewTokenWriter func() TokenWriter
}
//go:generate mockery --name Login --inpackage
type Login interface {
TokenForVerifiedIdentity(identity *authmethod.Identity, authMethod *structs.ACLAuthMethod, description string) (*structs.ACLToken, error)
}
//go:generate mockery --name Validator --inpackage
type Validator interface {
ValidateLogin(ctx context.Context, loginToken string) (*authmethod.Identity, error)
}
//go:generate mockery --name TokenWriter --inpackage
type TokenWriter interface {
Delete(secretID string, fromLogout bool) error
}
type Server struct {
Config
}
func NewServer(cfg Config) *Server {
return &Server{cfg}
}
func (s *Server) Register(grpcServer *grpc.Server) {
pbacl.RegisterACLServiceServer(grpcServer, s)
}
func (s *Server) requireACLsEnabled(logger hclog.Logger) error {
if s.ACLsEnabled {
return nil
}
logger.Warn("request blocked ACLs are disabled")
return status.Error(codes.FailedPrecondition, acl.ErrDisabled.Error())
}
func (s *Server) requireLocalTokens(logger hclog.Logger) error {
if s.LocalTokensEnabled() {
return nil
}
logger.Warn("request blocked because we're in a non-primary datacenter and token replication is disabled")
return status.Error(codes.FailedPrecondition, "token replication is required for auth methods to function")
}
func (s *Server) forwardWriteDC(dc string, fn func(*grpc.ClientConn) error, logger hclog.Logger) (bool, error) {
// For private/internal gRPC handlers, protoc-gen-rpc-glue generates the
// requisite methods to satisfy the structs.RPCInfo interface using fields
// from the pbcommon package. This service is public, so we can't use those
// fields in our proto definition. Instead, we construct our RPCInfo manually.
var rpcInfo struct {
structs.WriteRequest // Ensure RPCs are forwarded to the leader.
structs.DCSpecificRequest // Ensure RPCs are forwarded to the correct datacenter.
}
rpcInfo.Datacenter = dc
return s.ForwardRPC(&rpcInfo, func(conn *grpc.ClientConn) error {
logger.Trace("forwarding RPC", "datacenter", dc)
return fn(conn)
})
}