Skip to content
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

Using v1/agent/check/register requires node:write when registering a check for a specific service. #5705

Closed
mkeeler opened this issue Apr 24, 2019 · 0 comments · Fixed by #5756
Labels
good first issue A well-defined bug or improvement with sufficient context which should be approachable for new contr theme/acls ACL and token generation theme/api Relating to the HTTP API interface theme/health-checks Health Check functionality type/bug Feature does not function as expected

Comments

@mkeeler
Copy link
Member

mkeeler commented Apr 24, 2019

Overview of the Issue

Consul is requiring node:write on the agent node for check registration even though a service level check is being registered.

Code Deep Dive

Decoding of Request

First we decode the structs.CheckDefinition

var args structs.CheckDefinition
// Fixup the type decode of TTL or Interval.
decodeCB := func(raw interface{}) error {
return FixupCheckType(raw)
}
if err := decodeBody(req, &args, decodeCB); err != nil {
resp.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(resp, "Request decode failed: %v", err)
return nil, nil
}

The check definition contains a service id in it but not a service name.

Type Conversion

Then we convert the structs.CheckDefinition into a structs.HealthCheck here:

health := args.HealthCheck(s.agent.config.NodeName)

This is implemented here:

func (c *CheckDefinition) HealthCheck(node string) *HealthCheck {
health := &HealthCheck{
Node: node,
CheckID: c.ID,
Name: c.Name,
Status: api.HealthCritical,
Notes: c.Notes,
ServiceID: c.ServiceID,
}
if c.Status != "" {
health.Status = c.Status
}
if health.CheckID == "" && health.Name != "" {
health.CheckID = types.CheckID(health.Name)
}
return health
}

Basically it copies the ServiceID in the CheckDefinition to the ServiceID in the HealthCheck but leaves the ServiceName in the HealthCheck untouched.

Check ACLs

Back in the AgentRegisterCheck function we need to verify that the entity making the check registration request has adequate privileges so we invoke vetCheckRegister here:

// Get the provided token, if any, and vet against any ACL policies.
var token string
s.parseToken(req, &token)
if err := s.agent.vetCheckRegister(token, health); err != nil {
return nil, err
}

Then within vetCheckRegister we check specifically for the ServiceName on the HealthCheck here:

consul/agent/acl.go

Lines 151 to 160 in f2213f6

// Vet the check itself.
if len(check.ServiceName) > 0 {
if !rule.ServiceWrite(check.ServiceName, nil) {
return acl.ErrPermissionDenied
}
} else {
if !rule.NodeWrite(a.config.NodeName, nil) {
return acl.ErrPermissionDenied
}
}

End Result

Because the ServiceName was never set, the ServiceID is ignored and we are treating this as a node level check and requiring node:write instead of treating it as a service level check and only requiring service:write.

Possible solution

Before calling vetCheckRegister we could look up the ServiceID within the local state and fixup the ServiceName on the HealthCheck structure.

@mkeeler mkeeler assigned mkeeler and unassigned mkeeler Apr 24, 2019
@mkeeler mkeeler added type/bug Feature does not function as expected theme/acls ACL and token generation theme/api Relating to the HTTP API interface theme/health-checks Health Check functionality good first issue A well-defined bug or improvement with sufficient context which should be approachable for new contr labels Apr 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue A well-defined bug or improvement with sufficient context which should be approachable for new contr theme/acls ACL and token generation theme/api Relating to the HTTP API interface theme/health-checks Health Check functionality type/bug Feature does not function as expected
Projects
None yet
1 participant