mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 18:35:44 +03:00
auth: use ACLsDisabledACL when ACLs are disabled (#18754)
The RPC handlers expect to see `nil` ACL objects whenever ACLs are disabled. By using `nil` as a sentinel value, we have the risk of nil pointer exceptions and improper handling of `nil` when returned from our various auth methods that can lead to privilege escalation bugs. This is the final patch in a series to eliminate the use of `nil` ACLs as a sentinel value for when ACLs are disabled. This patch adds a new virtual ACL policy field for when ACLs are disabled and updates our authentication logic to use it. Included: * Extends auth package tests to demonstrate that nil ACLs are treated as failed auth and disabled ACLs succeed auth. * Adds a new `AllowDebug` ACL check for the weird special casing we have for pprof debugging when ACLs are disabled. * Removes the remaining unexported methods (and repeated tests) from the `nomad/acl.go` file. * Update the semgrep rules to detect improper nil ACL checking and remove the old invalid ACL checks. * Update the contributing guide for RPC authentication. Ref: https://github.com/hashicorp/nomad-enterprise/pull/1218 Ref: https://github.com/hashicorp/nomad/pull/18703 Ref: https://github.com/hashicorp/nomad/pull/18715 Ref: https://github.com/hashicorp/nomad/pull/16799 Ref: https://github.com/hashicorp/nomad/pull/18730 Ref: https://github.com/hashicorp/nomad/pull/18744
This commit is contained in:
@@ -67,9 +67,7 @@ func (s *HTTPServer) AgentSelfRequest(resp http.ResponseWriter, req *http.Reques
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check agent read permissions
|
||||
if aclObj != nil && !aclObj.AllowAgentRead() {
|
||||
if !aclObj.AllowAgentRead() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -322,7 +320,7 @@ func (s *HTTPServer) AgentForceLeaveRequest(resp http.ResponseWriter, req *http.
|
||||
// Check agent write permissions
|
||||
if aclObj, err := s.agent.Server().ResolveToken(secret); err != nil {
|
||||
return nil, err
|
||||
} else if aclObj != nil && !aclObj.AllowAgentWrite() {
|
||||
} else if !aclObj.AllowAgentWrite() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -458,7 +456,7 @@ func (s *HTTPServer) listServers(resp http.ResponseWriter, req *http.Request) (i
|
||||
// Check agent read permissions
|
||||
if aclObj, err := s.agent.Client().ResolveToken(secret); err != nil {
|
||||
return nil, err
|
||||
} else if aclObj != nil && !aclObj.AllowAgentRead() {
|
||||
} else if !aclObj.AllowAgentRead() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -485,7 +483,7 @@ func (s *HTTPServer) updateServers(resp http.ResponseWriter, req *http.Request)
|
||||
// Check agent write permissions
|
||||
if aclObj, err := s.agent.Client().ResolveToken(secret); err != nil {
|
||||
return nil, err
|
||||
} else if aclObj != nil && !aclObj.AllowAgentWrite() {
|
||||
} else if !aclObj.AllowAgentWrite() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -512,7 +510,7 @@ func (s *HTTPServer) KeyringOperationRequest(resp http.ResponseWriter, req *http
|
||||
// Check agent write permissions
|
||||
if aclObj, err := srv.ResolveToken(secret); err != nil {
|
||||
return nil, err
|
||||
} else if aclObj != nil && !aclObj.AllowAgentWrite() {
|
||||
} else if !aclObj.AllowAgentWrite() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -690,8 +688,7 @@ func (s *HTTPServer) AgentHostRequest(resp http.ResponseWriter, req *http.Reques
|
||||
enableDebug = s.agent.Client().GetConfig().EnableDebug
|
||||
}
|
||||
|
||||
if (aclObj != nil && !aclObj.AllowAgentRead()) ||
|
||||
(aclObj == nil && !enableDebug) {
|
||||
if !aclObj.AllowAgentDebug(enableDebug) {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
@@ -763,7 +760,7 @@ func (s *HTTPServer) AgentSchedulerWorkerInfoRequest(resp http.ResponseWriter, r
|
||||
// Check agent read permissions
|
||||
if aclObj, err := s.agent.Server().ResolveToken(secret); err != nil {
|
||||
return nil, CodedError(http.StatusInternalServerError, err.Error())
|
||||
} else if aclObj != nil && !aclObj.AllowAgentRead() {
|
||||
} else if !aclObj.AllowAgentRead() {
|
||||
return nil, CodedError(http.StatusForbidden, structs.ErrPermissionDenied.Error())
|
||||
}
|
||||
|
||||
@@ -817,7 +814,7 @@ func (s *HTTPServer) getScheduleWorkersConfig(resp http.ResponseWriter, req *htt
|
||||
// Check agent read permissions
|
||||
if aclObj, err := s.agent.Server().ResolveToken(secret); err != nil {
|
||||
return nil, CodedError(http.StatusInternalServerError, err.Error())
|
||||
} else if aclObj != nil && !aclObj.AllowAgentRead() {
|
||||
} else if !aclObj.AllowAgentRead() {
|
||||
return nil, CodedError(http.StatusForbidden, structs.ErrPermissionDenied.Error())
|
||||
}
|
||||
|
||||
@@ -843,7 +840,7 @@ func (s *HTTPServer) updateScheduleWorkersConfig(resp http.ResponseWriter, req *
|
||||
// Check agent write permissions
|
||||
if aclObj, err := srv.ResolveToken(secret); err != nil {
|
||||
return nil, CodedError(http.StatusInternalServerError, err.Error())
|
||||
} else if aclObj != nil && !aclObj.AllowAgentWrite() {
|
||||
} else if !aclObj.AllowAgentWrite() {
|
||||
return nil, CodedError(http.StatusForbidden, structs.ErrPermissionDenied.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -1453,8 +1453,8 @@ func TestHTTPServer_ResolveToken(t *testing.T) {
|
||||
t.Run("acl disabled", func(t *testing.T) {
|
||||
req := &http.Request{Body: http.NoBody}
|
||||
got, err := noACLServer.Server.ResolveToken(req)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, got)
|
||||
must.NoError(t, err)
|
||||
must.Eq(t, got, acl.ACLsDisabledACL)
|
||||
})
|
||||
|
||||
t.Run("token not found", func(t *testing.T) {
|
||||
|
||||
@@ -763,14 +763,12 @@ func (s *HTTPServer) JobsParseRequest(resp http.ResponseWriter, req *http.Reques
|
||||
}
|
||||
|
||||
// Check job parse permissions
|
||||
if aclObj != nil {
|
||||
hasParseJob := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityParseJob)
|
||||
hasSubmitJob := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilitySubmitJob)
|
||||
hasParseJob := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityParseJob)
|
||||
hasSubmitJob := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilitySubmitJob)
|
||||
|
||||
allowed := hasParseJob || hasSubmitJob
|
||||
if !allowed {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
allowed := hasParseJob || hasSubmitJob
|
||||
if !allowed {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
args := &api.JobsParseRequest{}
|
||||
|
||||
Reference in New Issue
Block a user