67e02a0752
Stubs for enterprise-only ACL token to be used by managed service providers.
113 lines
3.2 KiB
Go
113 lines
3.2 KiB
Go
package consul
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/consul/acl"
|
|
"github.com/hashicorp/consul/agent/consul/autopilot"
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
)
|
|
|
|
// AutopilotGetConfiguration is used to retrieve the current Autopilot configuration.
|
|
func (op *Operator) AutopilotGetConfiguration(args *structs.DCSpecificRequest, reply *autopilot.Config) error {
|
|
if done, err := op.srv.forward("Operator.AutopilotGetConfiguration", args, args, reply); done {
|
|
return err
|
|
}
|
|
|
|
// This action requires operator read access.
|
|
identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := op.srv.validateEnterpriseToken(identity); err != nil {
|
|
return err
|
|
}
|
|
if rule != nil && rule.OperatorRead(nil) != acl.Allow {
|
|
return acl.ErrPermissionDenied
|
|
}
|
|
|
|
state := op.srv.fsm.State()
|
|
_, config, err := state.AutopilotConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if config == nil {
|
|
return fmt.Errorf("autopilot config not initialized yet")
|
|
}
|
|
|
|
*reply = *config
|
|
|
|
return nil
|
|
}
|
|
|
|
// AutopilotSetConfiguration is used to set the current Autopilot configuration.
|
|
func (op *Operator) AutopilotSetConfiguration(args *structs.AutopilotSetConfigRequest, reply *bool) error {
|
|
if done, err := op.srv.forward("Operator.AutopilotSetConfiguration", args, args, reply); done {
|
|
return err
|
|
}
|
|
|
|
// This action requires operator write access.
|
|
identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := op.srv.validateEnterpriseToken(identity); err != nil {
|
|
return err
|
|
}
|
|
if rule != nil && rule.OperatorWrite(nil) != acl.Allow {
|
|
return acl.ErrPermissionDenied
|
|
}
|
|
|
|
// Apply the update
|
|
resp, err := op.srv.raftApply(structs.AutopilotRequestType, args)
|
|
if err != nil {
|
|
op.logger.Error("Raft apply failed", "error", err)
|
|
return err
|
|
}
|
|
if respErr, ok := resp.(error); ok {
|
|
return respErr
|
|
}
|
|
|
|
// Check if the return type is a bool.
|
|
if respBool, ok := resp.(bool); ok {
|
|
*reply = respBool
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ServerHealth is used to get the current health of the servers.
|
|
func (op *Operator) ServerHealth(args *structs.DCSpecificRequest, reply *autopilot.OperatorHealthReply) error {
|
|
// This must be sent to the leader, so we fix the args since we are
|
|
// re-using a structure where we don't support all the options.
|
|
args.RequireConsistent = true
|
|
args.AllowStale = false
|
|
if done, err := op.srv.forward("Operator.ServerHealth", args, args, reply); done {
|
|
return err
|
|
}
|
|
|
|
// This action requires operator read access.
|
|
identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := op.srv.validateEnterpriseToken(identity); err != nil {
|
|
return err
|
|
}
|
|
if rule != nil && rule.OperatorRead(nil) != acl.Allow {
|
|
return acl.ErrPermissionDenied
|
|
}
|
|
|
|
// Exit early if the min Raft version is too low
|
|
minRaftProtocol, err := op.srv.autopilot.MinRaftProtocol()
|
|
if err != nil {
|
|
return fmt.Errorf("error getting server raft protocol versions: %s", err)
|
|
}
|
|
if minRaftProtocol < 3 {
|
|
return fmt.Errorf("all servers must have raft_protocol set to 3 or higher to use this endpoint")
|
|
}
|
|
|
|
*reply = op.srv.autopilot.GetClusterHealth()
|
|
|
|
return nil
|
|
}
|