add additional logging for SCEP proxy and SCEP profiles (#39501)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #36361 This PR adds some additional debug logging to log hostUUID:profileUUID when renewing MDM managed certificates. Also adds log statements when processing a profile, when hitting NDES or Smallstep (not SCEP as it's a static challenge, that is fetched and replaced, no external calls). NDES: If we get a successful call (which is the standard, with errors on the HTML page), we debug log, the entire HTML response, and the request duration. Smallstep: Normal API errors, non OK we log: status code, the status text, the request duration, and spit out the entire body (max 2mb), if more than 2mb we don't log the response body. I tried looking for more relevant places, but couldn't really find any that would make sense to log for this ticket. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [ ] Added/updated automated tests - [x] QA'd all new/changed functionality manually -> Did a quick test for some of the logs, but the NDES one is not really easy to verify.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
- Added additional logging for SCEP proxy requests and SCEP profile renewals.
|
||||
@@ -15,12 +15,14 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Azure/go-ntlmssp"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
scepclient "github.com/fleetdm/fleet/v4/server/mdm/scep/client"
|
||||
scepserver "github.com/fleetdm/fleet/v4/server/mdm/scep/server"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/net/html/charset"
|
||||
@@ -518,7 +520,9 @@ func (s *SCEPConfigService) GetNDESSCEPChallenge(ctx context.Context, proxy flee
|
||||
return "", ctxerr.Wrap(ctx, err, "creating request")
|
||||
}
|
||||
req.SetBasicAuth(username, password)
|
||||
startRequestTime := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
endRequestTime := time.Now()
|
||||
if err != nil {
|
||||
return "", ctxerr.Wrap(ctx, err, "sending request")
|
||||
}
|
||||
@@ -551,6 +555,9 @@ func (s *SCEPConfigService) GetNDESSCEPChallenge(ctx context.Context, proxy flee
|
||||
return "", ctxerr.Wrap(ctx,
|
||||
NewNDESInsufficientPermissionsError("this account does not have sufficient permissions to enroll with SCEP. Please use a different account with NDES SCEP enroll permissions."))
|
||||
}
|
||||
|
||||
// If we can't find a specific error, we log more context in terms of the request to further diagnose
|
||||
level.Debug(s.logger).Log("msg", "failed to parse NDES challenge from admin URL response", "ca_type", fleet.CATypeNDESSCEPProxy, "raw_response", htmlString, "request_duration", endRequestTime.Sub(startRequestTime).Seconds())
|
||||
return "", ctxerr.Wrap(ctx,
|
||||
NewNDESInvalidError("could not retrieve the enrollment challenge password; invalid admin URL or credentials; please correct and try again"))
|
||||
}
|
||||
@@ -602,11 +609,19 @@ func (s *SCEPConfigService) GetSmallstepSCEPChallenge(ctx context.Context, ca fl
|
||||
return "", ctxerr.Wrap(ctx, err, "creating request")
|
||||
}
|
||||
req.SetBasicAuth(ca.Username, ca.Password)
|
||||
startRequestTime := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
endRequestTime := time.Now()
|
||||
if err != nil {
|
||||
return "", ctxerr.Wrap(ctx, err, "sending request")
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
reader := io.LimitReader(resp.Body, units.MiB*2)
|
||||
if b, err := io.ReadAll(reader); err == nil {
|
||||
level.Debug(s.logger).Log("msg", "failed to get Smallstep SCEP challenge", "status_code", resp.StatusCode, "status", resp.Status, "ca_type", fleet.CATypeSmallstep, "raw_response", string(b), "request_duration", endRequestTime.Sub(startRequestTime).Seconds())
|
||||
} else {
|
||||
level.Debug(s.logger).Log("msg", "failed to get Smallstep SCEP challenge and failed to read response body", "status_code", resp.StatusCode, "status", resp.Status, "ca_type", fleet.CATypeSmallstep, "read_error", err.Error(), "request_duration", endRequestTime.Sub(startRequestTime).Seconds())
|
||||
}
|
||||
return "", ctxerr.Wrap(ctx, fmt.Errorf("status code %d", resp.StatusCode), "getting Smallstep SCEP challenge")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
@@ -2851,13 +2851,17 @@ func (ds *Datastore) RenewMDMManagedCertificates(ctx context.Context) error {
|
||||
limit -= len(hostCertsToRenew)
|
||||
totalHostCertsToRenew += len(hostCertsToRenew)
|
||||
|
||||
allHostAndProfileIdsToRenew := make([]string, len(hostCertsToRenew))
|
||||
for _, hostCertToRenew := range hostCertsToRenew {
|
||||
hostProfileClause += `(host_uuid = ? AND profile_uuid = ?) OR `
|
||||
values = append(values, hostCertToRenew.HostUUID, hostCertToRenew.ProfileUUID)
|
||||
|
||||
allHostAndProfileIdsToRenew = append(allHostAndProfileIdsToRenew, hostCertToRenew.HostUUID+":"+hostCertToRenew.ProfileUUID)
|
||||
}
|
||||
hostProfileClause = strings.TrimSuffix(hostProfileClause, " OR ")
|
||||
|
||||
level.Info(ds.logger).Log("msg", "Renewing MDM managed certificates", "len", len(hostCertsToRenew), "type", hostCertType, "platform", hostPlatform)
|
||||
level.Debug(ds.logger).Log("msg", "Host and profile IDs for certificates to renew", "host_profile_ids", allHostAndProfileIdsToRenew)
|
||||
err = ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error {
|
||||
_, err := tx.ExecContext(ctx, updateQuery+hostProfileClause+")", values...)
|
||||
if err != nil {
|
||||
|
||||
@@ -5573,6 +5573,7 @@ func preprocessProfileContents(
|
||||
if ndesConfig == nil {
|
||||
ndesConfig = groupedCAs.NDESSCEP
|
||||
}
|
||||
level.Debug(logger).Log("msg", "fetching NDES challenge", "host_uuid", hostUUID, "profile_uuid", profUUID)
|
||||
// Insert the SCEP challenge into the profile contents
|
||||
challenge, err := scepConfig.GetNDESSCEPChallenge(ctx, *ndesConfig)
|
||||
if err != nil {
|
||||
@@ -5661,6 +5662,7 @@ func preprocessProfileContents(
|
||||
"This error should never happen since we validated/populated CAs earlier", "ca_name", caName)
|
||||
continue
|
||||
}
|
||||
level.Debug(logger).Log("msg", "fetching Smallstep SCEP challenge", "host_uuid", hostUUID, "profile_uuid", profUUID)
|
||||
challenge, err := scepConfig.GetSmallstepSCEPChallenge(ctx, *ca)
|
||||
if err != nil {
|
||||
detail := fmt.Sprintf("Fleet couldn't populate $FLEET_VAR_%s. %s", fleet.FleetVarSmallstepSCEPChallengePrefix, err.Error())
|
||||
|
||||
Reference in New Issue
Block a user