mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
use only the UUID part of external_host_identifier for Puppet runs (#13176)
related to #12483, we have found out that in distributed scenarios, the URL of the Puppet server used for the request is appended to the identifier, and it can be different between `/preassign` and `/match` calls. to account for this, we're only grabbing the first 36 characters of the identifier.
This commit is contained in:
parent
9ae3aa8036
commit
8fda48db8b
4 changed files with 43 additions and 4 deletions
1
changes/12483-puppet-run-id
Normal file
1
changes/12483-puppet-run-id
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
* Fix delays applying profiles when the Puppet module is used in distributed scenarios.
|
||||||
|
|
@ -18,6 +18,11 @@ const (
|
||||||
// must be reasonably longer than the expected time to make all
|
// must be reasonably longer than the expected time to make all
|
||||||
// PreassignProfile calls and the final matcher call.
|
// PreassignProfile calls and the final matcher call.
|
||||||
preassignKeyExpiration = 1 * time.Hour
|
preassignKeyExpiration = 1 * time.Hour
|
||||||
|
// in distributed scenarios, the external host identifier might come up
|
||||||
|
// with a suffix that varies from server to server. To account for that
|
||||||
|
// we only take into account the first 36 runes from the identifier.
|
||||||
|
// See https://github.com/fleetdm/fleet/issues/12483 for more info.
|
||||||
|
preassignKeySuffixMaxLen = 36
|
||||||
)
|
)
|
||||||
|
|
||||||
type profileMatcher struct {
|
type profileMatcher struct {
|
||||||
|
|
@ -151,5 +156,17 @@ func (p *profileMatcher) RetrieveProfiles(ctx context.Context, externalHostIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyForExternalHostIdentifier(externalHostIdentifier string) string {
|
func keyForExternalHostIdentifier(externalHostIdentifier string) string {
|
||||||
return preassignKeyPrefix + externalHostIdentifier
|
return preassignKeyPrefix + firstNRunes(externalHostIdentifier, preassignKeySuffixMaxLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// firstNRunes grabs the first N runes from the provided string
|
||||||
|
func firstNRunes(s string, n int) string {
|
||||||
|
i := 0
|
||||||
|
for j := range s {
|
||||||
|
if i == n {
|
||||||
|
return s[:j]
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,23 @@ func TestPreassignProfileValidation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeyForExternalHostIdentifier(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"", ""},
|
||||||
|
{"abcd", "abcd"},
|
||||||
|
{"6f36ab2c-1a40-429b-9c9d-07c9029f4aa8", "6f36ab2c-1a40-429b-9c9d-07c9029f4aa8"},
|
||||||
|
{"6f36ab2c-1a40-429b-9c9d-07c9029f4aa8-puppetcompiler06.test.example.com", "6f36ab2c-1a40-429b-9c9d-07c9029f4aa8"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
got := keyForExternalHostIdentifier(c.in)
|
||||||
|
require.Equal(t, preassignKeyPrefix+c.want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func generateProfile(name, ident, typ, uuid string) []byte {
|
func generateProfile(name, ident, typ, uuid string) []byte {
|
||||||
return []byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
return []byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
|
|
||||||
|
|
@ -672,11 +672,15 @@ func (s *integrationMDMTestSuite) TestPuppetMatchPreassignProfiles() {
|
||||||
}}, http.StatusNoContent, "team_id", fmt.Sprint(tm4.ID))
|
}}, http.StatusNoContent, "team_id", fmt.Sprint(tm4.ID))
|
||||||
|
|
||||||
// preassign the MDM host to prof1 and prof4, should match existing team tm2
|
// preassign the MDM host to prof1 and prof4, should match existing team tm2
|
||||||
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/preassign", preassignMDMAppleProfileRequest{MDMApplePreassignProfilePayload: fleet.MDMApplePreassignProfilePayload{ExternalHostIdentifier: "mdm1", HostUUID: mdmHost.UUID, Profile: prof1, Group: "g1"}}, http.StatusNoContent)
|
//
|
||||||
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/preassign", preassignMDMAppleProfileRequest{MDMApplePreassignProfilePayload: fleet.MDMApplePreassignProfilePayload{ExternalHostIdentifier: "mdm1", HostUUID: mdmHost.UUID, Profile: prof4, Group: "g4"}}, http.StatusNoContent)
|
// additionally, use external host identifiers with different
|
||||||
|
// suffixes to simulate real world distributed scenarios where more
|
||||||
|
// than one puppet server might be running at the time.
|
||||||
|
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/preassign", preassignMDMAppleProfileRequest{MDMApplePreassignProfilePayload: fleet.MDMApplePreassignProfilePayload{ExternalHostIdentifier: "6f36ab2c-1a40-429b-9c9d-07c9029f4aa8-puppetcompiler06.test.example.com", HostUUID: mdmHost.UUID, Profile: prof1, Group: "g1"}}, http.StatusNoContent)
|
||||||
|
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/preassign", preassignMDMAppleProfileRequest{MDMApplePreassignProfilePayload: fleet.MDMApplePreassignProfilePayload{ExternalHostIdentifier: "6f36ab2c-1a40-429b-9c9d-07c9029f4aa8-puppetcompiler01.test.example.com", HostUUID: mdmHost.UUID, Profile: prof4, Group: "g4"}}, http.StatusNoContent)
|
||||||
|
|
||||||
// match with the mdm host succeeds and assigns it to tm2
|
// match with the mdm host succeeds and assigns it to tm2
|
||||||
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/match", matchMDMApplePreassignmentRequest{ExternalHostIdentifier: "mdm1"}, http.StatusNoContent)
|
s.Do("POST", "/api/latest/fleet/mdm/apple/profiles/match", matchMDMApplePreassignmentRequest{ExternalHostIdentifier: "6f36ab2c-1a40-429b-9c9d-07c9029f4aa8-puppetcompiler03.test.example.com"}, http.StatusNoContent)
|
||||||
|
|
||||||
// the host is now part of that team
|
// the host is now part of that team
|
||||||
h, err = s.ds.Host(ctx, mdmHost.ID)
|
h, err = s.ds.Host(ctx, mdmHost.ID)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue