implement fleetctl apply new team with secret (#13062)

relates to #12907

implement adding an enroll secret when creating a new team with
`fleetctl apply` if none is provided.

- [x] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [ ] Added/updated tests
- [x] Manual QA for all new/changed functionality
This commit is contained in:
Gabriel Hernandez 2023-08-02 17:42:01 +01:00 committed by GitHub
parent 9d105a4d12
commit cb89b725ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 1 deletions

View file

@ -0,0 +1 @@
- add enroll secret for a new team created with `fleetctl apply` if none is provided.

View file

@ -706,6 +706,18 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
}
if create {
// create a new team enroll secret if none is provided for a new team.
if len(secrets) == 0 {
secret, err := server.GenerateRandomText(fleet.EnrollSecretDefaultLength)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "generate enroll secret string")
}
secrets = append(secrets, &fleet.EnrollSecret{
Secret: secret,
})
}
team, err := svc.createTeamFromSpec(ctx, spec, appConfig, secrets, applyOpts.DryRun)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "creating team from spec")

View file

@ -355,7 +355,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
appConfig, err := s.ds.AppConfig(context.Background())
require.NoError(t, err)
defaultOpts := `{"config": {"options": {"logger_plugin": "tls", "pack_delimiter": "/", "logger_tls_period": 10, "distributed_plugin": "tls", "disable_distributed": false, "logger_tls_endpoint": "/api/osquery/log", "distributed_interval": 10, "distributed_tls_max_attempts": 3}, "decorators": {"load": ["SELECT uuid AS host_uuid FROM system_info;", "SELECT hostname AS hostname FROM system_info;"]}}, "overrides": {}}`
assert.Len(t, team.Secrets, 0) // no secret gets created automatically when creating a team via apply spec
assert.Len(t, team.Secrets, 1) // secret gets created automatically for a new team when none is supplied.
require.NotNil(t, team.Config.AgentOptions)
require.JSONEq(t, defaultOpts, string(*team.Config.AgentOptions))
require.Equal(t, appConfig.Features, team.Config.Features)

View file

@ -371,6 +371,58 @@ func TestApplyTeamSpecs(t *testing.T) {
})
}
// Tests that a new enroll secret is created for new teams when none are provided
func TestApplyTeamSpecEnrollSecretForNewTeams(t *testing.T) {
ds := new(mock.Store)
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
svc, ctx := newTestService(t, ds, nil, nil, &TestServerOpts{License: license, SkipCreateTestUsers: true})
user := &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}
ctx = viewer.NewContext(ctx, viewer.Viewer{User: user})
ds.TeamByNameFunc = func(ctx context.Context, name string) (*fleet.Team, error) {
return nil, newNotFoundError()
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
t.Run("creates enroll secret when not included for a new team spec", func(t *testing.T) {
ds.NewTeamFunc = func(ctx context.Context, team *fleet.Team) (*fleet.Team, error) {
require.Len(t, team.Secrets, 1)
require.NotEmpty(t, team.Secrets[0])
return &fleet.Team{ID: 1}, nil
}
_, err := svc.ApplyTeamSpecs(ctx, []*fleet.TeamSpec{{Name: "Foo"}}, fleet.ApplySpecOptions{})
require.NoError(t, err)
require.True(t, ds.TeamByNameFuncInvoked)
require.True(t, ds.NewTeamFuncInvoked)
})
t.Run("does not create enroll secret when one is included for a new team spec", func(t *testing.T) {
enrollSecret := fleet.EnrollSecret{Secret: "test"}
ds.NewTeamFunc = func(ctx context.Context, team *fleet.Team) (*fleet.Team, error) {
require.Len(t, team.Secrets, 1)
require.Equal(t, enrollSecret.Secret, team.Secrets[0].Secret)
return &fleet.Team{ID: 1}, nil
}
_, err := svc.ApplyTeamSpecs(ctx, []*fleet.TeamSpec{{Name: "Foo", Secrets: []fleet.EnrollSecret{enrollSecret}}}, fleet.ApplySpecOptions{})
require.NoError(t, err)
require.True(t, ds.TeamByNameFuncInvoked)
require.True(t, ds.NewTeamFuncInvoked)
})
ds.TeamByNameFuncInvoked = false
ds.NewTeamFuncInvoked = false
}
// TestApplyTeamSpecsErrorInTeamByName tests that an error in ds.TeamByName will
// result in a proper error returned (instead of the authorization check missing error).
func TestApplyTeamSpecsErrorInTeamByName(t *testing.T) {