DUSW: Allow user-scoped SCEP profiles on Windows (#35672)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #35503 

For this one I opted for a simple approach of just duplicating the
arrays one for user, and one for device, then with the first loc uri
that checks in of either device or user, sets the respective arrays, I
thought while this was more LOC's it was easier to look at and maintain
compared to regex matches etc, let me know if you think otherwise.

# 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

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
This commit is contained in:
Magnus Jensen
2025-11-14 12:44:14 -03:00
committed by GitHub
parent e919ab53b0
commit 4a416722a4
8 changed files with 309 additions and 42 deletions
@@ -0,0 +1 @@
* Add ability to deploy user-scoped SCEP profiles for Windows hosts
+109 -23
View File
@@ -204,7 +204,7 @@ func validateFleetProvidedLocURI(locURI string, enableCustomOSUpdates bool) erro
// and then based on it being marked Optional, or Required in the description.
// A list containg all valid SCEP Profile LocURIs, a combination of optional and required to validate for non-SCEP LocURIs.
var validSCEPProfileLocURIs = slices.Concat([]string{
var validDeviceSCEPProfileLocURIs = slices.Concat([]string{
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/AADKeyIdentifierList", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ContainerName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/CustomTextToShowInPrompt", FleetVarSCEPWindowsCertificateID.WithPrefix()),
@@ -215,9 +215,22 @@ var validSCEPProfileLocURIs = slices.Concat([]string{
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/TemplateName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ValidPeriod", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ValidPeriodUnits", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}, requiredSCEPProfileLocURIs)
}, requiredDeviceSCEPProfileLocURIs)
var requiredSCEPProfileLocURIs = []string{
var validUserSCEPProfileLocURIs = slices.Concat([]string{
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/AADKeyIdentifierList", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ContainerName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/CustomTextToShowInPrompt", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/KeyProtection", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/RetryCount", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/RetryDelay", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/SubjectAlternativeNames", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/TemplateName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ValidPeriod", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ValidPeriodUnits", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}, requiredUserSCEPProfileLocURIs)
var requiredDeviceSCEPProfileLocURIs = []string{
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/CAThumbprint", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/Challenge", FleetVarSCEPWindowsCertificateID.WithPrefix()),
@@ -229,15 +242,34 @@ var requiredSCEPProfileLocURIs = []string{
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/SubjectName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}
var validExecSCEPProfileLocURIs = []string{
var requiredUserSCEPProfileLocURIs = []string{
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/CAThumbprint", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/Challenge", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/EKUMapping", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/HashAlgorithm", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/KeyLength", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/KeyUsage", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/ServerURL", FleetVarSCEPWindowsCertificateID.WithPrefix()),
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/SubjectName", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}
var validDeviceExecSCEPProfileLocURIs = []string{
fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/Enroll", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}
var validUserExecSCEPProfileLocURIs = []string{
fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s/Install/Enroll", FleetVarSCEPWindowsCertificateID.WithPrefix()),
}
type windowsSCEPProfileValidator struct {
totalLocURIs int
totalExecLocURIs int
foundLocURIs map[string]bool
foundExecLocURIs map[string]bool
totalLocURIs int
totalExecLocURIs int
foundLocURIs map[string]bool
foundExecLocURIs map[string]bool
requiredSCEPProfileLocURIs *[]string
validSCEPProfileLocURIs *[]string
validExecSCEPProfileLocURIs *[]string
}
func newWindowsSCEPProfileValidator() *windowsSCEPProfileValidator {
@@ -254,12 +286,16 @@ func (v *windowsSCEPProfileValidator) isSCEPProfile() bool {
func (v *windowsSCEPProfileValidator) validateLocURI(locURI string) error {
sanitizedLocURI := strings.TrimSpace(locURI)
// If we see a LocURI with SCEP prefix, but no Fleet Var we fail early.
if v.isSCEPLocURIWithoutFleetVar(sanitizedLocURI) {
return fmt.Errorf("You must use %q after \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID.WithPrefix())
if err := v.setLocURIArrays(sanitizedLocURI); err != nil {
return err
}
if slices.Contains(validSCEPProfileLocURIs, sanitizedLocURI) {
// If we see a LocURI with SCEP prefix, but no Fleet Var we fail early.
if v.isSCEPLocURIWithoutFleetVar(sanitizedLocURI) {
return fmt.Errorf("You must use %q after \"ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID.WithPrefix())
}
if slices.Contains(*v.validSCEPProfileLocURIs, sanitizedLocURI) {
v.foundLocURIs[sanitizedLocURI] = true
}
@@ -270,12 +306,16 @@ func (v *windowsSCEPProfileValidator) validateLocURI(locURI string) error {
func (v *windowsSCEPProfileValidator) validateExecLocURI(locURI string) error {
sanitizedLocURI := strings.TrimSpace(locURI)
// If we see a LocURI with SCEP prefix, but no Fleet Var we fail early.
if v.isSCEPLocURIWithoutFleetVar(sanitizedLocURI) {
return fmt.Errorf("You must use %q after \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID.WithPrefix())
if err := v.setLocURIArrays(sanitizedLocURI); err != nil {
return err
}
if slices.Contains(validExecSCEPProfileLocURIs, sanitizedLocURI) {
// If we see a LocURI with SCEP prefix, but no Fleet Var we fail early.
if v.isSCEPLocURIWithoutFleetVar(sanitizedLocURI) {
return fmt.Errorf("You must use %q after \"ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID.WithPrefix())
}
if slices.Contains(*v.validExecSCEPProfileLocURIs, sanitizedLocURI) {
v.foundExecLocURIs[sanitizedLocURI] = true
}
@@ -283,17 +323,53 @@ func (v *windowsSCEPProfileValidator) validateExecLocURI(locURI string) error {
return nil
}
func (v *windowsSCEPProfileValidator) setLocURIArrays(locURI string) error {
switch {
case IsWindowsSCEPLocURI(locURI) && v.validExecSCEPProfileLocURIs == nil:
if strings.HasPrefix(locURI, "./User") {
v.requiredSCEPProfileLocURIs = &requiredUserSCEPProfileLocURIs
v.validSCEPProfileLocURIs = &validUserSCEPProfileLocURIs
v.validExecSCEPProfileLocURIs = &validUserExecSCEPProfileLocURIs
} else {
v.requiredSCEPProfileLocURIs = &requiredDeviceSCEPProfileLocURIs
v.validSCEPProfileLocURIs = &validDeviceSCEPProfileLocURIs
v.validExecSCEPProfileLocURIs = &validDeviceExecSCEPProfileLocURIs
}
case !IsWindowsSCEPLocURI(locURI) && v.validExecSCEPProfileLocURIs == nil:
// Not a SCEP profile, set empty arrays to avoid nil pointer dereference later.
emptyArray := []string{}
v.requiredSCEPProfileLocURIs = &emptyArray
v.validSCEPProfileLocURIs = &emptyArray
v.validExecSCEPProfileLocURIs = &emptyArray
case IsWindowsSCEPLocURI(locURI) && v.validExecSCEPProfileLocURIs != nil:
// Check against mixing Device and User SCEP LocURIs.
firstValidLocURI := (*v.validSCEPProfileLocURIs)[0]
if strings.HasPrefix(firstValidLocURI, "./Device") && strings.HasPrefix(locURI, "./User") ||
strings.HasPrefix(firstValidLocURI, "./User") && strings.HasPrefix(locURI, "./Device") {
return errors.New("All <LocURI> elements in the SCEP profile must start either with \"./Device\" or \"./User\".")
}
}
return nil
}
// isSCEPLocURIWithoutFleetVar checks that the provided locURI starts with the SCEP prefix
// and that it includes the required Fleet Var for SCEP Windows Certificate ID.
// Skips any locURI that does not start with the SCEP prefix.
func (v windowsSCEPProfileValidator) isSCEPLocURIWithoutFleetVar(locURI string) bool {
if strings.HasPrefix(locURI, "./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/") &&
!strings.HasPrefix(locURI, fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s", FleetVarSCEPWindowsCertificateID.WithPrefix())) {
if (strings.HasPrefix(locURI, "./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/") &&
!strings.HasPrefix(locURI, fmt.Sprintf("./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/%s", FleetVarSCEPWindowsCertificateID.WithPrefix()))) || (strings.HasPrefix(locURI, "./User/Vendor/MSFT/ClientCertificateInstall/SCEP/") &&
!strings.HasPrefix(locURI, fmt.Sprintf("./User/Vendor/MSFT/ClientCertificateInstall/SCEP/%s", FleetVarSCEPWindowsCertificateID.WithPrefix()))) {
return true
}
return false
}
func IsWindowsSCEPLocURI(locURI string) bool {
return strings.HasPrefix(locURI, "./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/") ||
strings.HasPrefix(locURI, "./User/Vendor/MSFT/ClientCertificateInstall/SCEP/")
}
func (v *windowsSCEPProfileValidator) finalizeValidation() error {
if !v.isSCEPProfile() {
// Cheeky validation here, to only allow Exec elements in SCEP profiles.
@@ -303,20 +379,30 @@ func (v *windowsSCEPProfileValidator) finalizeValidation() error {
return nil // Not a SCEP profile, nothing to validate here.
}
// If we reach here with empty arrays something has gone wrong.
if len(*v.validExecSCEPProfileLocURIs) == 0 || len(*v.validSCEPProfileLocURIs) == 0 || len(*v.requiredSCEPProfileLocURIs) == 0 {
return errors.New("Internal error validating SCEP profile LocURIs.")
}
// ADD CODE HERE
// Verify that we do not have any non-scep loc URIs present
if v.totalLocURIs != len(v.foundLocURIs) {
return errors.New("Only options that have <LocURI> starting with \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/\" can be added to SCEP profile.")
return errors.New("Only options that have <LocURI> starting with \"ClientCertificateInstall/SCEP/\" can be added to SCEP profile.")
}
// Check that at least one Exec LocURI is present and it matches the only one we have in the array.
if len(v.foundExecLocURIs) != 1 && !v.foundExecLocURIs[validExecSCEPProfileLocURIs[0]] {
return errors.New("Couldn't add. \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.")
validExecLocURIs := *v.validExecSCEPProfileLocURIs
if len(v.foundExecLocURIs) != 1 && !v.foundExecLocURIs[validExecLocURIs[0]] {
return errors.New("Couldn't add. \"ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.")
}
// Check that all required LocURIs are present
for _, requiredLocURI := range requiredSCEPProfileLocURIs {
for _, requiredLocURI := range *v.requiredSCEPProfileLocURIs {
if !v.foundLocURIs[requiredLocURI] {
return fmt.Errorf("%q is missing. Please add and try again", requiredLocURI)
trimmedPrefix := strings.TrimPrefix(requiredLocURI, "./Device/Vendor/MSFT/")
trimmedPrefix = strings.TrimPrefix(trimmedPrefix, "./User/Vendor/MSFT/")
return fmt.Errorf("%q is missing. Please add and try again.", trimmedPrefix)
}
}
+27 -5
View File
@@ -613,7 +613,7 @@ func TestValidateUserProvided(t *testing.T) {
</Replace>
`),
},
wantErr: "Only options that have <LocURI> starting with \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/\" can be added to SCEP profile.",
wantErr: "Only options that have <LocURI> starting with \"ClientCertificateInstall/SCEP/\" can be added to SCEP profile.",
},
{
name: "SCEP profile without Exec block",
@@ -626,7 +626,7 @@ func TestValidateUserProvided(t *testing.T) {
</Replace>
`),
},
wantErr: "\"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.",
wantErr: "\"ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.",
},
{
name: "SCEP profile with Exec block, but worng LocURI ",
@@ -646,7 +646,7 @@ func TestValidateUserProvided(t *testing.T) {
</Exec>
`),
},
wantErr: "Couldn't add. \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.",
wantErr: "Couldn't add. \"ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll\" must be included within <Exec>. Please add and try again.",
},
{
name: fmt.Sprintf("SCEP profile with missing $FLEET_VAR_%s after SCEP LocURI", FleetVarSCEPWindowsCertificateID),
@@ -666,7 +666,7 @@ func TestValidateUserProvided(t *testing.T) {
</Add>
`),
},
wantErr: fmt.Sprintf("You must use \"$FLEET_VAR_%s\" after \"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID),
wantErr: fmt.Sprintf("You must use \"$FLEET_VAR_%s\" after \"ClientCertificateInstall/SCEP/\".", FleetVarSCEPWindowsCertificateID),
},
{
name: "SCEP Profile with missing required LocURI",
@@ -688,7 +688,7 @@ func TestValidateUserProvided(t *testing.T) {
</Exec>
`),
},
wantErr: fmt.Sprintf("\"./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_%s/Install/CAThumbprint\" is missing.", FleetVarSCEPWindowsCertificateID),
wantErr: fmt.Sprintf("\"ClientCertificateInstall/SCEP/$FLEET_VAR_%s/Install/CAThumbprint\" is missing. Please add and try again.", FleetVarSCEPWindowsCertificateID),
},
{
name: "Only SCEP profiles can have Exec elements",
@@ -705,6 +705,28 @@ func TestValidateUserProvided(t *testing.T) {
},
wantErr: "Only SCEP profiles can include <Exec> elements.",
},
{
name: "Either device or user SCEP profiles, not both",
profile: MDMWindowsConfigProfile{
SyncML: []byte(`
<Replace>
<Item>
<Target>
<LocURI>./Device/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID</LocURI>
</Target>
</Item>
</Replace>
<Exec>
<Item>
<Target>
<LocURI>./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll</LocURI>
</Target>
</Item>
</Exec>
`),
},
wantErr: "All <LocURI> elements in the SCEP profile must start either with \"./Device\" or \"./User\".",
},
}
for _, tt := range tests {
+1 -1
View File
@@ -170,7 +170,7 @@ func compareResultsToExpectedProfiles(ctx context.Context, logger kitlog.Logger,
}
err = LoopOverExpectedHostProfiles(ctx, logger, ds, host, func(profile *fleet.ExpectedMDMProfile, ref, locURI, wantData string) {
if strings.HasPrefix(strings.TrimSpace(locURI), "./Device/Vendor/MSFT/ClientCertificateInstall/SCEP") {
if strings.Contains(strings.TrimSpace(locURI), "/Vendor/MSFT/ClientCertificateInstall/SCEP") {
verified[profile.Name] = struct{}{}
// We delete here if by some accident it was marked as missing before
delete(missing, profile.Name)
+14 -1
View File
@@ -605,6 +605,14 @@ func TestVerifyHostMDMProfilesHappyPaths(t *testing.T) {
Data: "non related data",
},
}), 0},
{"N2", syncml.ForTestWithData([]syncml.TestCommand{
{
Verb: "Replace",
LocURI: `
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/bogus-key-value`,
Data: "non related data",
},
}), 0},
},
existingProfiles: []fleet.HostMDMWindowsProfile{
{
@@ -612,8 +620,13 @@ func TestVerifyHostMDMProfilesHappyPaths(t *testing.T) {
Name: "N1",
Status: &fleet.MDMDeliveryPending,
},
{
ProfileUUID: "uuid-N2",
Name: "N2",
Status: &fleet.MDMDeliveryPending,
},
},
toVerify: []string{"N1"},
toVerify: []string{"N1", "N2"},
},
}
+17 -12
View File
@@ -7909,10 +7909,21 @@ func (s *integrationMDMTestSuite) TestWindowsProfilesFleetVariableSubstitution()
"Profile should be verified in host details API for no-vars host")
}
//go:embed testdata/profiles/windows-scep.xml
var windowsSCEPProfileBytes []byte
//go:embed testdata/profiles/windows-device-scep.xml
var windowsDeviceSCEPProfileBytes []byte
func (s *integrationMDMTestSuite) TestWindowsSCEPProfile() {
func (s *integrationMDMTestSuite) TestWindowsDeviceSCEPProfile() {
testWindowsSCEPProfile(s, windowsDeviceSCEPProfileBytes)
}
//go:embed testdata/profiles/windows-user-scep.xml
var windowsUserSCEPProfileBytes []byte
func (s *integrationMDMTestSuite) TestWindowsUserSCEPProfile() {
testWindowsSCEPProfile(s, windowsUserSCEPProfileBytes)
}
func testWindowsSCEPProfile(s *integrationMDMTestSuite, windowsScepProfile []byte) {
t := s.T()
ctx := context.Background()
scepServer := scep_server.StartTestSCEPServer(t)
@@ -7953,7 +7964,7 @@ func (s *integrationMDMTestSuite) TestWindowsSCEPProfile() {
// Upload SCEP profile with missing CA
resp := s.Do("POST", "/api/v1/fleet/mdm/profiles/batch",
batchSetMDMProfilesRequest{Profiles: []fleet.MDMProfileBatchPayload{
{Name: "WindowsSCEPProfile", Contents: windowsSCEPProfileBytes},
{Name: "WindowsSCEPProfile", Contents: windowsScepProfile},
}},
http.StatusBadRequest)
errMsg := extractServerErrorText(resp.Body)
@@ -7972,7 +7983,7 @@ func (s *integrationMDMTestSuite) TestWindowsSCEPProfile() {
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch",
batchSetMDMProfilesRequest{Profiles: []fleet.MDMProfileBatchPayload{
{Name: "WindowsSCEPProfile", Contents: windowsSCEPProfileBytes},
{Name: "WindowsSCEPProfile", Contents: windowsScepProfile},
}},
http.StatusNoContent)
@@ -8022,17 +8033,11 @@ func (s *integrationMDMTestSuite) TestWindowsSCEPProfile() {
foundProfile = true
profileUUID = p.ProfileUUID
require.NotNil(t, p.Status)
assert.Equal(t, fleet.MDMDeliveryVerified, *p.Status)
require.Equal(t, fleet.MDMDeliveryVerified, *p.Status)
}
}
require.True(t, foundProfile, "WindowsSCEPProfile not found for host")
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
mysql.DumpTable(t, q, "host_mdm_windows_profiles")
mysql.DumpTable(t, q, "host_mdm_managed_certificates")
return nil
})
// Attempt simple SCEP call with GetCACaps operation to verify SCEP server is reachable
identifier := host.UUID + "," + profileUUID + "," + "INTEGRATION"
scepRes := s.DoRawWithHeaders("GET", apple_mdm.SCEPProxyPath+identifier+"/pkiclient.exe", nil, http.StatusOK, nil, "operation", "GetCACaps")
+140
View File
@@ -0,0 +1,140 @@
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">node</Format>
</Meta>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/RetryCount</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">int</Format>
</Meta>
<Data>3</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/RetryDelay</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">int</Format>
</Meta>
<Data>10</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/KeyUsage</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">int</Format>
</Meta>
<Data>160</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/KeyLength</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">int</Format>
</Meta>
<Data>1024</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/HashAlgorithm</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>SHA-1</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/SubjectName</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>CN=$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/EKUMapping</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>1.3.6.1.5.5.7.3.2</Data>
</Item>
</Add>
<Add>
<CmdID>10</CmdID>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/ServerURL</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>$FLEET_VAR_CUSTOM_SCEP_PROXY_URL_INTEGRATION</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Challenge</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>$FLEET_VAR_CUSTOM_SCEP_CHALLENGE_INTEGRATION</Data>
</Item>
</Add>
<Add>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/CAThumbprint</LocURI>
</Target>
<Meta>
<Format xmlns="syncml:metinf">chr</Format>
</Meta>
<Data>2133EC6A3CFB8418837BB395188D1A62CA2B96A6</Data>
</Item>
</Add>
<Exec>
<Item>
<Target>
<LocURI>
./User/Vendor/MSFT/ClientCertificateInstall/SCEP/$FLEET_VAR_SCEP_WINDOWS_CERTIFICATE_ID/Install/Enroll</LocURI>
</Target>
</Item>
</Exec>