34140ff3e0
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.
89 lines
2.9 KiB
Go
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)
|
|
})
|
|
}
|