Skip to content

Commit

Permalink
fix: reset token team assignments to defaults (#22326)
Browse files Browse the repository at this point in the history
> Related issue: #22198

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

<!-- Note that API documentation changes are now addressed by the
product design team. -->

- [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/Committing-Changes.md#changes-files)
for more information.
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
  • Loading branch information
jahzielv authored Oct 1, 2024
1 parent cfd4159 commit 80f0fd8
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 11 deletions.
2 changes: 2 additions & 0 deletions changes/22198-defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fixes a bug where removing a VPP or ABM token from a GitOps YAML file would leave the team
assignments unchanged.
91 changes: 91 additions & 0 deletions cmd/fleetctl/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,18 @@ func TestApplyAppConfig(t *testing.T) {
return []*fleet.TeamSummary{{Name: "team1", ID: 1}}, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{{OrganizationName: t.Name()}}, nil
}

name := writeTmpYml(t, `---
apiVersion: v1
kind: config
Expand Down Expand Up @@ -782,6 +794,18 @@ func TestApplyAppConfigDryRunIssue(t *testing.T) {
return nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

// first, set the default app config's agent options as set after fleetctl setup
name := writeTmpYml(t, `---
apiVersion: v1
Expand Down Expand Up @@ -914,6 +938,18 @@ func TestApplyAppConfigDeprecatedFields(t *testing.T) {
return nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

name := writeTmpYml(t, `---
apiVersion: v1
kind: config
Expand Down Expand Up @@ -1316,6 +1352,14 @@ func TestApplyAsGitOps(t *testing.T) {
return []*fleet.ABMToken{{ID: 1}}, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

// Apply global config.
name := writeTmpYml(t, `---
apiVersion: v1
Expand Down Expand Up @@ -1873,6 +1917,18 @@ func TestCanApplyIntervalsInNanoseconds(t *testing.T) {
return nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

name := writeTmpYml(t, `---
apiVersion: v1
kind: config
Expand Down Expand Up @@ -1908,6 +1964,18 @@ func TestCanApplyIntervalsUsingDurations(t *testing.T) {
return nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

name := writeTmpYml(t, `---
apiVersion: v1
kind: config
Expand Down Expand Up @@ -2091,6 +2159,18 @@ func TestApplyMacosSetup(t *testing.T) {
return []*fleet.ABMToken{{ID: 1}}, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

return ds
}

Expand Down Expand Up @@ -2764,6 +2844,17 @@ func TestApplySpecs(t *testing.T) {
ds.DeleteMDMWindowsConfigProfileByTeamAndNameFunc = func(ctx context.Context, teamID *uint, profileName string) error {
return nil
}

// VPP/AMB
ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}
ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}
ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}
}

cases := []struct {
Expand Down
80 changes: 80 additions & 0 deletions cmd/fleetctl/gitops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ func TestGitOpsBasicGlobalFree(t *testing.T) {
return nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

tmpFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)

Expand Down Expand Up @@ -238,6 +250,18 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) {
return nil, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

tmpFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)

Expand Down Expand Up @@ -591,6 +615,17 @@ func TestGitOpsFullGlobal(t *testing.T) {
return nil
}

// Needed for checking tokens
ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}
ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}
ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

const (
fleetServerURL = "https://fleet.example.com"
orgName = "GitOps Test"
Expand Down Expand Up @@ -1079,6 +1114,18 @@ func TestGitOpsBasicGlobalAndTeam(t *testing.T) {
return nil, 0, nil, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

globalFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)

Expand Down Expand Up @@ -1345,6 +1392,18 @@ func TestGitOpsBasicGlobalAndNoTeam(t *testing.T) {
return nil, 0, nil, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

globalFileBasic, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)

Expand Down Expand Up @@ -1604,6 +1663,18 @@ func TestGitOpsFullGlobalAndTeam(t *testing.T) {
return team, nil
}

ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}

ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}

ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

apnsCert, apnsKey, err := mysql.GenerateTestCertBytes()
require.NoError(t, err)
crt, key, err := apple_mdm.NewSCEPCACertKey()
Expand Down Expand Up @@ -2234,6 +2305,15 @@ func setupFullGitOpsPremiumServer(t *testing.T) (*mock.Store, **fleet.AppConfig,
ds.ListSoftwareTitlesFunc = func(ctx context.Context, opt fleet.SoftwareTitleListOptions, tmFilter fleet.TeamFilter) ([]fleet.SoftwareTitleListResult, int, *fleet.PaginationMetadata, error) {
return nil, 0, nil, nil
}
ds.SaveABMTokenFunc = func(ctx context.Context, tok *fleet.ABMToken) error {
return nil
}
ds.ListVPPTokensFunc = func(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
return []*fleet.VPPTokenDB{}, nil
}
ds.ListABMTokensFunc = func(ctx context.Context) ([]*fleet.ABMToken, error) {
return []*fleet.ABMToken{}, nil
}

t.Setenv("FLEET_SERVER_URL", fleetServerURL)
t.Setenv("ORG_NAME", orgName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const generateCell = (teams: ITokenTeam[] | null) => {
}

if (teams.length === 0) {
return <TextCell value="All Teams" />;
return <TextCell value="All teams" />;
}

let text = "";
Expand Down Expand Up @@ -83,7 +83,7 @@ const TeamsCell = ({ teams, className }: ITeamsCellProps) => {
}

if (teams.length === 0) {
return <TextCell value="All Teams" />;
return <TextCell value="All teams" />;
}

if (teams.length === 1) {
Expand Down
42 changes: 41 additions & 1 deletion server/service/appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,15 +545,55 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
}
}

// Reset teams for ABM tokens that exist in Fleet but aren't present in the config being passed
tokensInCfg := make(map[string]struct{})
for _, t := range newAppConfig.MDM.AppleBusinessManager.Value {
tokensInCfg[t.OrganizationName] = struct{}{}
}

toks, err := svc.ds.ListABMTokens(ctx)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "listing ABM tokens")
}
for _, tok := range toks {
if _, ok := tokensInCfg[tok.OrganizationName]; !ok {
tok.MacOSDefaultTeamID = nil
tok.IOSDefaultTeamID = nil
tok.IPadOSDefaultTeamID = nil
if err := svc.ds.SaveABMToken(ctx, tok); err != nil {
return nil, ctxerr.Wrap(ctx, err, "saving ABM token assignments")
}
}
}

if (appConfig.MDM.AppleBusinessManager.Set && appConfig.MDM.AppleBusinessManager.Valid) || appConfig.MDM.DeprecatedAppleBMDefaultTeam != "" {
for _, tok := range abmAssignments {
fmt.Println(tok.EncryptedToken)
if err := svc.ds.SaveABMToken(ctx, tok); err != nil {
return nil, ctxerr.Wrap(ctx, err, "saving ABM token assignments")
}
}
}

// Reset teams for VPP tokens that exist in Fleet but aren't present in the config being passed
clear(tokensInCfg)

for _, t := range newAppConfig.MDM.VolumePurchasingProgram.Value {
tokensInCfg[t.Location] = struct{}{}
}

vppToks, err := svc.ds.ListVPPTokens(ctx)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "listing VPP tokens")
}
for _, tok := range vppToks {
if _, ok := tokensInCfg[tok.Location]; !ok {
tok.Teams = nil
if _, err := svc.ds.UpdateVPPTokenTeams(ctx, tok.ID, nil); err != nil {
return nil, ctxerr.Wrap(ctx, err, "saving VPP token teams")
}
}
}

if appConfig.MDM.VolumePurchasingProgram.Set && appConfig.MDM.VolumePurchasingProgram.Valid {
for tokenID, tokenTeams := range vppAssignments {
if _, err := svc.ds.UpdateVPPTokenTeams(ctx, tokenID, tokenTeams); err != nil {
Expand Down
Loading

0 comments on commit 80f0fd8

Please sign in to comment.