acl: remove legacy bootstrap
Return an explicit error from the RPC, and remove the flag from the HTTP API.
This commit is contained in:
parent
d77ea40203
commit
be0358df02
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
|
@ -40,40 +39,18 @@ func (s *HTTPHandlers) ACLBootstrap(resp http.ResponseWriter, req *http.Request)
|
|||
args := structs.DCSpecificRequest{
|
||||
Datacenter: s.agent.config.Datacenter,
|
||||
}
|
||||
|
||||
legacy := false
|
||||
legacyStr := req.URL.Query().Get("legacy")
|
||||
if legacyStr != "" {
|
||||
legacy, _ = strconv.ParseBool(legacyStr)
|
||||
}
|
||||
|
||||
if legacy && s.agent.delegate.UseLegacyACLs() {
|
||||
var out structs.ACL
|
||||
err := s.agent.RPC("ACL.Bootstrap", &args, &out)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), structs.ACLBootstrapNotAllowedErr.Error()) {
|
||||
resp.WriteHeader(http.StatusForbidden)
|
||||
fmt.Fprint(resp, acl.PermissionDeniedError{Cause: err.Error()}.Error())
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
var out structs.ACLToken
|
||||
err := s.agent.RPC("ACL.BootstrapTokens", &args, &out)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), structs.ACLBootstrapNotAllowedErr.Error()) {
|
||||
resp.WriteHeader(http.StatusForbidden)
|
||||
fmt.Fprint(resp, acl.PermissionDeniedError{Cause: err.Error()}.Error())
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
return &aclBootstrapResponse{ID: out.ID}, nil
|
||||
} else {
|
||||
var out structs.ACLToken
|
||||
err := s.agent.RPC("ACL.BootstrapTokens", &args, &out)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), structs.ACLBootstrapNotAllowedErr.Error()) {
|
||||
resp.WriteHeader(http.StatusForbidden)
|
||||
fmt.Fprint(resp, acl.PermissionDeniedError{Cause: err.Error()}.Error())
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &aclBootstrapResponse{ID: out.SecretID, ACLToken: out}, nil
|
||||
}
|
||||
return &aclBootstrapResponse{ID: out.SecretID, ACLToken: out}, nil
|
||||
}
|
||||
|
||||
func (s *HTTPHandlers) ACLReplicationStatus(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
|
|
|
@ -21,65 +21,8 @@ var ACLEndpointLegacySummaries = []prometheus.SummaryDefinition{
|
|||
},
|
||||
}
|
||||
|
||||
// Bootstrap is used to perform a one-time ACL bootstrap operation on
|
||||
// a cluster to get the first management token.
|
||||
func (a *ACL) Bootstrap(args *structs.DCSpecificRequest, reply *structs.ACL) error {
|
||||
if done, err := a.srv.ForwardRPC("ACL.Bootstrap", args, reply); done {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify we are allowed to serve this request
|
||||
if !a.srv.InACLDatacenter() {
|
||||
return acl.ErrDisabled
|
||||
}
|
||||
|
||||
if err := a.srv.aclBootstrapAllowed(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// By doing some pre-checks we can head off later bootstrap attempts
|
||||
// without having to run them through Raft, which should curb abuse.
|
||||
state := a.srv.fsm.State()
|
||||
allowed, _, err := state.CanBootstrapACLToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !allowed {
|
||||
return structs.ACLBootstrapNotAllowedErr
|
||||
}
|
||||
|
||||
// Propose a new token.
|
||||
token, err := lib.GenerateUUID(a.srv.checkTokenUUID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to make random token: %v", err)
|
||||
}
|
||||
|
||||
// Attempt a bootstrap.
|
||||
req := structs.ACLRequest{
|
||||
Datacenter: a.srv.config.PrimaryDatacenter,
|
||||
Op: structs.ACLBootstrapNow,
|
||||
ACL: structs.ACL{
|
||||
ID: token,
|
||||
Name: "Bootstrap Token",
|
||||
Type: structs.ACLTokenTypeManagement,
|
||||
},
|
||||
}
|
||||
resp, err := a.srv.raftApply(structs.ACLRequestType, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch v := resp.(type) {
|
||||
case *structs.ACL:
|
||||
*reply = *v
|
||||
|
||||
default:
|
||||
// Just log this, since it looks like the bootstrap may have
|
||||
// completed.
|
||||
a.logger.Error("Unexpected response during bootstrap", "type", fmt.Sprintf("%T", v))
|
||||
}
|
||||
|
||||
a.logger.Info("ACL bootstrap completed")
|
||||
return nil
|
||||
func (a *ACL) Bootstrap(*structs.DCSpecificRequest, *structs.ACL) error {
|
||||
return fmt.Errorf("ACL.Bootstrap: the legacy ACL system has been removed")
|
||||
}
|
||||
|
||||
// aclApplyInternal is used to apply an ACL request after it has been vetted that
|
||||
|
|
|
@ -25,42 +25,6 @@ import (
|
|||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||
)
|
||||
|
||||
func TestACLEndpoint_Bootstrap(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("too slow for testing.Short")
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
|
||||
c.Build = "0.8.0" // Too low for auto init of bootstrap.
|
||||
c.PrimaryDatacenter = "dc1"
|
||||
c.ACLsEnabled = true
|
||||
// remove the default as we want to bootstrap
|
||||
c.ACLMasterToken = ""
|
||||
}, false)
|
||||
waitForLeaderEstablishment(t, srv)
|
||||
|
||||
// Expect an error initially since ACL bootstrap is not initialized.
|
||||
arg := structs.DCSpecificRequest{
|
||||
Datacenter: "dc1",
|
||||
}
|
||||
var out structs.ACL
|
||||
// We can only do some high
|
||||
// level checks on the ACL since we don't have control over the UUID or
|
||||
// Raft indexes at this level.
|
||||
err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, out.ID, len("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"))
|
||||
require.True(t, strings.HasPrefix(out.Name, "Bootstrap Token"))
|
||||
require.Equal(t, structs.ACLTokenTypeManagement, out.Type)
|
||||
require.NotEqual(t, uint64(0), out.CreateIndex)
|
||||
require.NotEqual(t, uint64(0), out.ModifyIndex)
|
||||
|
||||
// Finally, make sure that another attempt is rejected.
|
||||
err = msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out)
|
||||
testutil.RequireErrorContains(t, err, structs.ACLBootstrapNotAllowedErr.Error())
|
||||
}
|
||||
|
||||
func TestACLEndpoint_BootstrapTokens(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("too slow for testing.Short")
|
||||
|
|
Loading…
Reference in New Issue