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:
@@ -0,0 +1 @@
|
||||
* Add ability to deploy user-scoped SCEP profiles for Windows hosts
|
||||
+109
-23
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user