in internal/pkg/api/auth.go [90:182]
func authAgent(r *http.Request, id *string, bulker bulk.Bulk, c cache.Cache) (*model.Agent, error) {
span, ctx := apm.StartSpan(r.Context(), "authAgent", "auth")
defer span.End()
r = r.WithContext(ctx)
start := time.Now()
// authenticate
key, err := authAPIKey(r, bulker, c)
if err != nil {
return nil, err
}
w := hlog.FromRequest(r).With().
Str(LogAccessAPIKeyID, key.ID)
if id != nil {
w = w.Str(LogAgentID, *id)
}
zlog := w.Logger()
authTime := time.Now()
if authTime.Sub(start) > time.Second {
zlog.Debug().
Int64(ECSEventDuration, authTime.Sub(start).Nanoseconds()).
Msg("authApiKey slow")
}
var agent *model.Agent
// If we have the agentID retrieve the agent document with a get (more performant) instead of triggering a search
if id != nil {
agent, err = getAgentAndVerifyAPIKeyID(ctx, bulker, *id, key.ID)
} else {
agent, err = findAgentByAPIKeyID(ctx, bulker, key.ID)
}
if err != nil {
return nil, err
}
tx := apm.TransactionFromContext(ctx)
if tx != nil {
tx.Context.SetLabel("agent_id", agent.Id)
}
if agent.Agent == nil {
zlog.Warn().
Err(ErrAgentCorrupted).
Msg("agent record does not contain required metadata section")
return nil, ErrAgentCorrupted
}
findTime := time.Now()
if findTime.Sub(authTime) > time.Second {
zlog.Debug().
Int64(ECSEventDuration, findTime.Sub(authTime).Nanoseconds()).
Msg("findAgentByApiKeyId slow")
}
// validate that the Access ApiKey identifier stored in the agent's record
// is in alignment when the authenticated key provided on this transaction
if agent.AccessAPIKeyID != key.ID {
zlog.Warn().
Err(ErrAgentCorrupted).
Str("agent.AccessApiKeyId", agent.AccessAPIKeyID).
Msg("agent access ApiKey id mismatch agent record")
return nil, ErrAgentCorrupted
}
// validate that the id in the header is equal to the agent id record
if id != nil && *id != agent.Id {
zlog.Warn().
Err(ErrAgentIdentity).
Str("agent.Id", agent.Id).
Msg("agent id mismatch against http header")
return nil, ErrAgentIdentity
}
// validate active, an api key can be valid for an inactive agent record
// if it is in our cache and has not timed out.
if !agent.Active {
zlog.Info().
Err(ErrAgentInactive).
Msg("agent record inactive")
// Update the cache to mark the api key id associated with this agent as not enabled
c.SetAPIKey(*key, false)
return agent, ErrAgentInactive
}
return agent, nil
}