Skip to content

Agent Auto Configuration: Change auto config authorizer to allow for future extension #8148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4594,19 +4594,21 @@ func TestAutoConfig_Integration(t *testing.T) {
connect { enabled = true }
auto_encrypt { allow_tls = true }
auto_config {
authorizer {
authorization {
enabled = true
claim_mappings = {
consul_node_name = "node"
static {
claim_mappings = {
consul_node_name = "node"
}
claim_assertions = [
"value.node == \"${node}\""
]
bound_issuer = "consul"
bound_audiences = [
"consul"
]
jwt_validation_pub_keys = ["` + strings.ReplaceAll(pub, "\n", "\\n") + `"]
}
claim_assertions = [
"value.node == \"${node}\""
]
bound_issuer = "consul"
bound_audiences = [
"consul"
]
jwt_validation_pub_keys = ["` + strings.ReplaceAll(pub, "\n", "\\n") + `"]
}
}
`
Expand Down
56 changes: 28 additions & 28 deletions agent/config/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1937,41 +1937,41 @@ func (b *Builder) autoConfigVal(raw AutoConfigRaw) AutoConfig {
val.IPSANs = append(val.IPSANs, ip)
}

val.Authorizer = b.autoConfigAuthorizerVal(raw.Authorizer)
val.Authorizer = b.autoConfigAuthorizerVal(raw.Authorization)

return val
}

func (b *Builder) autoConfigAuthorizerVal(raw AutoConfigAuthorizerRaw) AutoConfigAuthorizer {
func (b *Builder) autoConfigAuthorizerVal(raw AutoConfigAuthorizationRaw) AutoConfigAuthorizer {
// Our config file syntax wraps the static authorizer configuration in a "static" stanza. However
// internally we do not support multiple configured authorization types so the RuntimeConfig just
// inlines the static one. While we can and probably should extend the authorization types in the
// future to support dynamic authorizers (ACL Auth Methods configured via normal APIs) its not
// needed right now so the configuration types will remain simplistic until they need to be otherwise.
var val AutoConfigAuthorizer

val.Enabled = b.boolValWithDefault(raw.Enabled, false)
val.ClaimAssertions = raw.ClaimAssertions
val.AllowReuse = b.boolValWithDefault(raw.AllowReuse, false)
val.ClaimAssertions = raw.Static.ClaimAssertions
val.AllowReuse = b.boolValWithDefault(raw.Static.AllowReuse, false)
val.AuthMethod = structs.ACLAuthMethod{
Name: "Auto Config Authorizer",
Type: "jwt",
// TODO (autoconf) - Configurable token TTL
MaxTokenTTL: 72 * time.Hour,
Name: "Auto Config Authorizer",
Type: "jwt",
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
Config: map[string]interface{}{
"JWTSupportedAlgs": raw.JWTSupportedAlgs,
"BoundAudiences": raw.BoundAudiences,
"ClaimMappings": raw.ClaimMappings,
"ListClaimMappings": raw.ListClaimMappings,
"OIDCDiscoveryURL": b.stringVal(raw.OIDCDiscoveryURL),
"OIDCDiscoveryCACert": b.stringVal(raw.OIDCDiscoveryCACert),
"JWKSURL": b.stringVal(raw.JWKSURL),
"JWKSCACert": b.stringVal(raw.JWKSCACert),
"JWTValidationPubKeys": raw.JWTValidationPubKeys,
"BoundIssuer": b.stringVal(raw.BoundIssuer),
"ExpirationLeeway": b.durationVal("auto_config.authorizer.expiration_leeway", raw.ExpirationLeeway),
"NotBeforeLeeway": b.durationVal("auto_config.authorizer.not_before_leeway", raw.NotBeforeLeeway),
"ClockSkewLeeway": b.durationVal("auto_config.authorizer.clock_skew_leeway", raw.ClockSkewLeeway),
"JWTSupportedAlgs": raw.Static.JWTSupportedAlgs,
"BoundAudiences": raw.Static.BoundAudiences,
"ClaimMappings": raw.Static.ClaimMappings,
"ListClaimMappings": raw.Static.ListClaimMappings,
"OIDCDiscoveryURL": b.stringVal(raw.Static.OIDCDiscoveryURL),
"OIDCDiscoveryCACert": b.stringVal(raw.Static.OIDCDiscoveryCACert),
"JWKSURL": b.stringVal(raw.Static.JWKSURL),
"JWKSCACert": b.stringVal(raw.Static.JWKSCACert),
"JWTValidationPubKeys": raw.Static.JWTValidationPubKeys,
"BoundIssuer": b.stringVal(raw.Static.BoundIssuer),
"ExpirationLeeway": b.durationVal("auto_config.authorization.static.expiration_leeway", raw.Static.ExpirationLeeway),
"NotBeforeLeeway": b.durationVal("auto_config.authorization.static.not_before_leeway", raw.Static.NotBeforeLeeway),
"ClockSkewLeeway": b.durationVal("auto_config.authorization.static.clock_skew_leeway", raw.Static.ClockSkewLeeway),
},
// should be unnecessary as we aren't using the typical login process to create tokens but this is our
// desired mode regardless so if it ever did matter its probably better to be explicit.
TokenLocality: "local",
}

return val
Expand Down Expand Up @@ -2018,15 +2018,15 @@ func (b *Builder) validateAutoConfigAuthorizer(rt RuntimeConfig) error {
}
// Auto Config Authorization is only supported on servers
if !rt.ServerMode {
return fmt.Errorf("auto_config.authorizer.enabled cannot be set to true for client agents")
return fmt.Errorf("auto_config.authorization.enabled cannot be set to true for client agents")
}

// build out the validator to ensure that the given configuration was valid
null := hclog.NewNullLogger()
validator, err := ssoauth.NewValidator(null, &authz.AuthMethod)

if err != nil {
return fmt.Errorf("auto_config.authorizer has invalid configuration: %v", err)
return fmt.Errorf("auto_config.authorization.static has invalid configuration: %v", err)
}

// create a blank identity for use to validate the claim assertions.
Expand All @@ -2041,14 +2041,14 @@ func (b *Builder) validateAutoConfigAuthorizer(rt RuntimeConfig) error {
// validate any HIL
filled, err := libtempl.InterpolateHIL(raw, varMap, true)
if err != nil {
return fmt.Errorf("auto_config.claim_assertion %q is invalid: %v", raw, err)
return fmt.Errorf("auto_config.authorization.static.claim_assertion %q is invalid: %v", raw, err)
}

// validate the bexpr syntax - note that for now all the keys mapped by the claim mappings
// are not validateable due to them being put inside a map. Some bexpr updates to setup keys
// from current map keys would probably be nice here.
if _, err := bexpr.CreateEvaluatorForType(filled, nil, blankID.SelectableFields); err != nil {
return fmt.Errorf("auto_config.claim_assertion %q is invalid: %v", raw, err)
return fmt.Errorf("auto_config.authorization.static.claim_assertion %q is invalid: %v", raw, err)
}
}
return nil
Expand Down
20 changes: 12 additions & 8 deletions agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,17 +689,21 @@ type AuditSink struct {
}

type AutoConfigRaw struct {
Enabled *bool `json:"enabled,omitempty" hcl:"enabled" mapstructure:"enabled"`
IntroToken *string `json:"intro_token,omitempty" hcl:"intro_token" mapstructure:"intro_token"`
IntroTokenFile *string `json:"intro_token_file,omitempty" hcl:"intro_token_file" mapstructure:"intro_token_file"`
ServerAddresses []string `json:"server_addresses,omitempty" hcl:"server_addresses" mapstructure:"server_addresses"`
DNSSANs []string `json:"dns_sans,omitempty" hcl:"dns_sans" mapstructure:"dns_sans"`
IPSANs []string `json:"ip_sans,omitempty" hcl:"ip_sans" mapstructure:"ip_sans"`
Authorizer AutoConfigAuthorizerRaw `json:"authorizer,omitempty" hcl:"authorizer" mapstructure:"authorizer"`
Enabled *bool `json:"enabled,omitempty" hcl:"enabled" mapstructure:"enabled"`
IntroToken *string `json:"intro_token,omitempty" hcl:"intro_token" mapstructure:"intro_token"`
IntroTokenFile *string `json:"intro_token_file,omitempty" hcl:"intro_token_file" mapstructure:"intro_token_file"`
ServerAddresses []string `json:"server_addresses,omitempty" hcl:"server_addresses" mapstructure:"server_addresses"`
DNSSANs []string `json:"dns_sans,omitempty" hcl:"dns_sans" mapstructure:"dns_sans"`
IPSANs []string `json:"ip_sans,omitempty" hcl:"ip_sans" mapstructure:"ip_sans"`
Authorization AutoConfigAuthorizationRaw `json:"authorization,omitempty" hcl:"authorization" mapstructure:"authorization"`
}

type AutoConfigAuthorizationRaw struct {
Enabled *bool `json:"enabled,omitempty" hcl:"enabled" mapstructure:"enabled"`
Static AutoConfigAuthorizerRaw `json:"static,omitempty" hcl:"static" mapstructure:"static"`
}

type AutoConfigAuthorizerRaw struct {
Enabled *bool `json:"enabled,omitempty" hcl:"enabled" mapstructure:"enabled"`
ClaimAssertions []string `json:"claim_assertions,omitempty" hcl:"claim_assertions" mapstructure:"claim_assertions"`
AllowReuse *bool `json:"allow_reuse,omitempty" hcl:"allow_reuse" mapstructure:"allow_reuse"`

Expand Down
Loading