Add managed service provider token (#7218)
Stubs for enterprise-only ACL token to be used by managed service providers.
This commit is contained in:
parent
a9f9ed83cb
commit
67e02a0752
|
@ -16,8 +16,6 @@ var (
|
|||
|
||||
// manageAll is a singleton policy which allows all
|
||||
// actions, including management
|
||||
// TODO (acls) - Do we need to keep this around? Our config parsing doesn't allow
|
||||
// specifying a default "manage" policy so I believe nothing will every use this.
|
||||
manageAll Authorizer = &staticAuthorizer{
|
||||
allowManage: true,
|
||||
defaultAllow: true,
|
||||
|
|
|
@ -400,6 +400,7 @@ func (a *Agent) Start() error {
|
|||
// load the tokens - this requires the logger to be setup
|
||||
// which is why we can't do this in New
|
||||
a.loadTokens(a.config)
|
||||
a.loadEnterpriseTokens(a.config)
|
||||
|
||||
// create the local state
|
||||
a.State = local.NewState(LocalConfig(c), a.logger, a.tokens)
|
||||
|
@ -3991,6 +3992,7 @@ func (a *Agent) ReloadConfig(newCfg *config.RuntimeConfig) error {
|
|||
// to ensure the correct tokens are available for attaching to
|
||||
// the checks and service registrations.
|
||||
a.loadTokens(newCfg)
|
||||
a.loadEnterpriseTokens(newCfg)
|
||||
|
||||
if err := a.tlsConfigurator.Update(newCfg.ToTLSUtilConfig()); err != nil {
|
||||
return fmt.Errorf("Failed reloading tls configuration: %s", err)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/agent/config"
|
||||
"github.com/hashicorp/consul/agent/consul"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/api"
|
||||
|
@ -16,3 +17,6 @@ func fillHealthCheckEnterpriseMeta(_ *api.HealthCheck, _ *structs.EnterpriseMeta
|
|||
|
||||
func (a *Agent) initEnterprise(consulCfg *consul.Config) {
|
||||
}
|
||||
|
||||
func (a *Agent) loadEnterpriseTokens(conf *config.RuntimeConfig) {
|
||||
}
|
||||
|
|
|
@ -1197,12 +1197,6 @@ func (b *Builder) Validate(rt RuntimeConfig) error {
|
|||
}
|
||||
}
|
||||
|
||||
if rt.AutoEncryptAllowTLS {
|
||||
if !rt.VerifyIncoming && !rt.VerifyIncomingRPC {
|
||||
b.warn("if auto_encrypt.allow_tls is turned on, either verify_incoming or verify_incoming_rpc should be enabled. It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards.")
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// warnings
|
||||
//
|
||||
|
@ -1223,6 +1217,12 @@ func (b *Builder) Validate(rt RuntimeConfig) error {
|
|||
b.warn("bootstrap_expect > 0: expecting %d servers", rt.BootstrapExpect)
|
||||
}
|
||||
|
||||
if rt.AutoEncryptAllowTLS {
|
||||
if !rt.VerifyIncoming && !rt.VerifyIncomingRPC {
|
||||
b.warn("if auto_encrypt.allow_tls is turned on, either verify_incoming or verify_incoming_rpc should be enabled. It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards.")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ func Parse(data string, format string) (c Config, err error) {
|
|||
"services.proxy.upstreams",
|
||||
"service.proxy.expose.paths",
|
||||
"services.proxy.expose.paths",
|
||||
"acl.tokens.managed_service_provider",
|
||||
|
||||
// Need all the service(s) exceptions also for nested sidecar service.
|
||||
"service.connect.sidecar_service.checks",
|
||||
|
@ -707,11 +708,17 @@ type ACL struct {
|
|||
}
|
||||
|
||||
type Tokens struct {
|
||||
Master *string `json:"master,omitempty" hcl:"master" mapstructure:"master"`
|
||||
Replication *string `json:"replication,omitempty" hcl:"replication" mapstructure:"replication"`
|
||||
AgentMaster *string `json:"agent_master,omitempty" hcl:"agent_master" mapstructure:"agent_master"`
|
||||
Default *string `json:"default,omitempty" hcl:"default" mapstructure:"default"`
|
||||
Agent *string `json:"agent,omitempty" hcl:"agent" mapstructure:"agent"`
|
||||
Master *string `json:"master,omitempty" hcl:"master" mapstructure:"master"`
|
||||
Replication *string `json:"replication,omitempty" hcl:"replication" mapstructure:"replication"`
|
||||
AgentMaster *string `json:"agent_master,omitempty" hcl:"agent_master" mapstructure:"agent_master"`
|
||||
Default *string `json:"default,omitempty" hcl:"default" mapstructure:"default"`
|
||||
Agent *string `json:"agent,omitempty" hcl:"agent" mapstructure:"agent"`
|
||||
ManagedServiceProvider []ServiceProviderToken `json:"managed_service_provider,omitempty" hcl:"managed_service_provider" mapstructure:"managed_service_provider"`
|
||||
}
|
||||
|
||||
type ServiceProviderToken struct {
|
||||
AccessorID *string `json:"accessor_id,omitempty" hcl:"accessor_id" mapstructure:"accessor_id"`
|
||||
SecretID *string `json:"secret_id,omitempty" hcl:"secret_id" mapstructure:"secret_id"`
|
||||
}
|
||||
|
||||
type ConfigEntries struct {
|
||||
|
|
|
@ -3694,7 +3694,17 @@ func TestFullConfig(t *testing.T) {
|
|||
"agent_master" : "64fd0e08",
|
||||
"replication" : "5795983a",
|
||||
"agent" : "bed2377c",
|
||||
"default" : "418fdff1"
|
||||
"default" : "418fdff1",
|
||||
"managed_service_provider": [
|
||||
{
|
||||
"accessor_id": "first",
|
||||
"secret_id": "fb0cee1f-2847-467c-99db-a897cff5fd4d"
|
||||
},
|
||||
{
|
||||
"accessor_id": "second",
|
||||
"secret_id": "1046c8da-e166-4667-897a-aefb343db9db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"addresses": {
|
||||
|
@ -4302,7 +4312,17 @@ func TestFullConfig(t *testing.T) {
|
|||
agent_master = "64fd0e08",
|
||||
replication = "5795983a",
|
||||
agent = "bed2377c",
|
||||
default = "418fdff1"
|
||||
default = "418fdff1",
|
||||
managed_service_provider = [
|
||||
{
|
||||
accessor_id = "first",
|
||||
secret_id = "fb0cee1f-2847-467c-99db-a897cff5fd4d"
|
||||
},
|
||||
{
|
||||
accessor_id = "second",
|
||||
secret_id = "1046c8da-e166-4667-897a-aefb343db9db"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
addresses = {
|
||||
|
|
|
@ -211,10 +211,14 @@ func (s *Server) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error
|
|||
}
|
||||
|
||||
func (s *Server) ResolveToken(token string) (acl.Authorizer, error) {
|
||||
return s.acls.ResolveToken(token)
|
||||
_, authz, err := s.ResolveTokenToIdentityAndAuthorizer(token)
|
||||
return authz, err
|
||||
}
|
||||
|
||||
func (s *Server) ResolveTokenToIdentityAndAuthorizer(token string) (structs.ACLIdentity, acl.Authorizer, error) {
|
||||
if id, authz := s.ResolveEntTokenToIdentityAndAuthorizer(token); id != nil && authz != nil {
|
||||
return id, authz, nil
|
||||
}
|
||||
return s.acls.ResolveTokenToIdentityAndAuthorizer(token)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// +build !consulent
|
||||
|
||||
package consul
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// Consul-enterprise only
|
||||
func (s *Server) ResolveEntTokenToIdentityAndAuthorizer(token string) (structs.ACLIdentity, acl.Authorizer) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Consul-enterprise only
|
||||
func (s *Server) validateEnterpriseToken(identity structs.ACLIdentity) error {
|
||||
return nil
|
||||
}
|
|
@ -158,10 +158,13 @@ func (m *Internal) KeyringOperation(
|
|||
reply *structs.KeyringResponses) error {
|
||||
|
||||
// Check ACLs
|
||||
rule, err := m.srv.ResolveToken(args.Token)
|
||||
identity, rule, err := m.srv.ResolveTokenToIdentityAndAuthorizer(args.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := m.srv.validateEnterpriseToken(identity); err != nil {
|
||||
return err
|
||||
}
|
||||
if rule != nil {
|
||||
switch args.Operation {
|
||||
case structs.KeyringList:
|
||||
|
|
|
@ -15,10 +15,13 @@ func (op *Operator) AutopilotGetConfiguration(args *structs.DCSpecificRequest, r
|
|||
}
|
||||
|
||||
// This action requires operator read access.
|
||||
rule, err := op.srv.ResolveToken(args.Token)
|
||||
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
|
||||
}
|
||||
|
@ -44,10 +47,13 @@ func (op *Operator) AutopilotSetConfiguration(args *structs.AutopilotSetConfigRe
|
|||
}
|
||||
|
||||
// This action requires operator write access.
|
||||
rule, err := op.srv.ResolveToken(args.Token)
|
||||
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
|
||||
}
|
||||
|
@ -80,10 +86,13 @@ func (op *Operator) ServerHealth(args *structs.DCSpecificRequest, reply *autopil
|
|||
}
|
||||
|
||||
// This action requires operator read access.
|
||||
rule, err := op.srv.ResolveToken(args.Token)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -80,10 +80,13 @@ func (op *Operator) RaftRemovePeerByAddress(args *structs.RaftRemovePeerRequest,
|
|||
|
||||
// This is a super dangerous operation that requires operator write
|
||||
// access.
|
||||
rule, err := op.srv.ResolveToken(args.Token)
|
||||
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
|
||||
}
|
||||
|
@ -149,10 +152,13 @@ func (op *Operator) RaftRemovePeerByID(args *structs.RaftRemovePeerRequest, repl
|
|||
|
||||
// This is a super dangerous operation that requires operator write
|
||||
// access.
|
||||
rule, err := op.srv.ResolveToken(args.Token)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ type Store struct {
|
|||
|
||||
// replicationTokenSource indicates where this token originated from
|
||||
replicationTokenSource TokenSource
|
||||
|
||||
// enterpriseTokens contains tokens only used in consul-enterprise
|
||||
enterpriseTokens
|
||||
}
|
||||
|
||||
// UpdateUserToken replaces the current user token in the store.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// +build !consulent
|
||||
|
||||
package token
|
||||
|
||||
// Stub for enterpriseTokens
|
||||
type enterpriseTokens struct {
|
||||
}
|
|
@ -662,6 +662,18 @@ default will automatically work with some tooling.
|
|||
token replication is enabled then it must have "write" permissions. This also enables
|
||||
Connect replication, for which the token will require both operator
|
||||
"write" and intention "read" permissions for replicating CA and Intention data.
|
||||
|
||||
* <a name="acl_tokens_managed_service_provider"></a><a href="#acl_tokens_managed_service_provider">`managed_service_provider`</a> -
|
||||
**(Enterprise Only)** An array of ACL tokens used by Consul managed service providers for cluster operations.
|
||||
|
||||
```javascript
|
||||
"managed_service_provider": [
|
||||
{
|
||||
"accessor_id": "ed22003b-0832-4e48-ac65-31de64e5c2ff",
|
||||
"secret_id": "cb6be010-bba8-4f30-a9ed-d347128dde17"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
* <a name="acl_datacenter"></a><a href="#acl_datacenter">`acl_datacenter`</a> - **This field is
|
||||
deprecated in Consul 1.4.0. See the [`primary_datacenter`](#primary_datacenter) field instead.**
|
||||
|
|
Loading…
Reference in New Issue