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 a9f9ed83cb
commit 67e02a0752
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

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