Add managed service provider token (#7218)

Stubs for enterprise-only ACL token to be used by managed service providers.
This commit is contained in:
Freddy 2020-02-04 13:58:56 -07:00 committed by GitHub
parent f6ec8ed92b
commit cb77fc6d01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 115 additions and 22 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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) {
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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 = {

View File

@ -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)
}

View File

@ -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
}

View File

@ -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:

View File

@ -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
}

View File

@ -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
}

View File

@ -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.

7
agent/token/store_oss.go Normal file
View File

@ -0,0 +1,7 @@
// +build !consulent
package token
// Stub for enterpriseTokens
type enterpriseTokens struct {
}

View File

@ -663,6 +663,18 @@ default will automatically work with some tooling.
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.**