Skip to content

Commit

Permalink
Expose smtp and sso settings to team admins (#25322)
Browse files Browse the repository at this point in the history
## For #25320

- [x] Added/updated automated tests
- [ ] A detailed QA plan exists on the associated ticket (if it isn't
there, work with the product group's QA engineer to add it)
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
  • Loading branch information
jacobshandling and Jacob Shandling authored Jan 10, 2025
1 parent 18bdab7 commit d26afe3
Show file tree
Hide file tree
Showing 4 changed files with 328 additions and 41 deletions.
124 changes: 86 additions & 38 deletions cmd/fleetctl/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/fleetdm/fleet/v4/server/config"
"github.com/fleetdm/fleet/v4/server/fleet"
nanodep_client "github.com/fleetdm/fleet/v4/server/mdm/nanodep/client"
"github.com/fleetdm/fleet/v4/server/mock"
nanodep_mock "github.com/fleetdm/fleet/v4/server/mock/nanodep"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/service"
Expand Down Expand Up @@ -65,6 +66,23 @@ var userRoleList = []*fleet.User{
},
}

var setCurrentUserSession = func(t *testing.T, ds *mock.Store, user *fleet.User) {
user, err := ds.NewUser(context.Background(), user)
require.NoError(t, err)
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
return &fleet.Session{
CreateTimestamp: fleet.CreateTimestamp{CreatedAt: time.Now()},
ID: 1,
AccessedAt: time.Now(),
UserID: user.ID,
Key: key,
}, nil
}
ds.UserByIDFunc = func(ctx context.Context, id uint) (*fleet.User, error) {
return user, nil
}
}

func TestGetUserRoles(t *testing.T) {
_, ds := runServerWithMockedDS(t)

Expand Down Expand Up @@ -627,6 +645,70 @@ func TestGetConfig(t *testing.T) {
assert.YAMLEq(t, expectedYAML, runAppForTest(t, []string{"get", "config", "--include-server-config", "--yaml"}))
require.JSONEq(t, expectedJSON, runAppForTest(t, []string{"get", "config", "--include-server-config", "--json"}))
})

t.Run("AppConfigAsTeamUsers", func(t *testing.T) {
// test as team admin
setCurrentUserSession(t, ds, &fleet.User{
ID: 5,
Name: "Admin of team 1",
Password: []byte("p4ssw0rd.123"),
Email: "omt2@example.com",
GlobalRole: nil,
Teams: []fleet.UserTeam{
{
Team: fleet.Team{ID: 1},
Role: fleet.RoleAdmin,
},
{
Team: fleet.Team{ID: 2},
Role: fleet.RoleMaintainer,
},
},
})

b, err := os.ReadFile(filepath.Join("testdata", "expectedGetConfigAppConfigYaml.yml"))
require.NoError(t, err)
expectedYaml := string(b)

b, err = os.ReadFile(filepath.Join("testdata", "expectedGetConfigAppConfigJson.json"))
require.NoError(t, err)
expectedJson := string(b)

assert.YAMLEq(t, expectedYaml, runAppForTest(t, []string{"get", "config"}))
assert.YAMLEq(t, expectedYaml, runAppForTest(t, []string{"get", "config", "--yaml"}))
assert.JSONEq(t, expectedJson, runAppForTest(t, []string{"get", "config", "--json"}))

// test as team maintainer
setCurrentUserSession(t, ds, &fleet.User{
ID: 6,
Name: "Maintainer of team 1",
Password: []byte("p4ssw0rd.123"),
Email: "omt3@example.com",
GlobalRole: nil,
Teams: []fleet.UserTeam{
{
Team: fleet.Team{ID: 1},
Role: fleet.RoleMaintainer,
},
{
Team: fleet.Team{ID: 2},
Role: fleet.RoleMaintainer,
},
},
})

b, err = os.ReadFile(filepath.Join("testdata", "expectedGetConfigAppConfigTeamMaintainerYaml.yml"))
require.NoError(t, err)
expectedYaml = string(b)

b, err = os.ReadFile(filepath.Join("testdata", "expectedGetConfigAppConfigTeamMaintainerJson.json"))
require.NoError(t, err)
expectedJson = string(b)

assert.YAMLEq(t, expectedYaml, runAppForTest(t, []string{"get", "config"}))
assert.YAMLEq(t, expectedYaml, runAppForTest(t, []string{"get", "config", "--yaml"}))
assert.JSONEq(t, expectedJson, runAppForTest(t, []string{"get", "config", "--json"}))
})
}

func TestGetSoftwareTitles(t *testing.T) {
Expand Down Expand Up @@ -1546,23 +1628,6 @@ spec:
func TestGetQueriesAsObserver(t *testing.T) {
_, ds := runServerWithMockedDS(t)

setCurrentUserSession := func(user *fleet.User) {
user, err := ds.NewUser(context.Background(), user)
require.NoError(t, err)
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
return &fleet.Session{
CreateTimestamp: fleet.CreateTimestamp{CreatedAt: time.Now()},
ID: 1,
AccessedAt: time.Now(),
UserID: user.ID,
Key: key,
}, nil
}
ds.UserByIDFunc = func(ctx context.Context, id uint) (*fleet.User, error) {
return user, nil
}
}

ds.ListQueriesFunc = func(ctx context.Context, opt fleet.ListQueryOptions) ([]*fleet.Query, int, *fleet.PaginationMetadata, error) {
return []*fleet.Query{
{
Expand Down Expand Up @@ -1636,7 +1701,7 @@ func TestGetQueriesAsObserver(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
setCurrentUserSession(tc.user)
setCurrentUserSession(t, ds, tc.user)

expected := `+--------+-------------+-----------+-----------+----------------------------+
| NAME | DESCRIPTION | QUERY | TEAM | SCHEDULE |
Expand Down Expand Up @@ -1678,7 +1743,7 @@ spec:
}

// Test with a user that is observer of a team, but maintainer of another team (should not filter the queries).
setCurrentUserSession(&fleet.User{
setCurrentUserSession(t, ds, &fleet.User{
ID: 4,
Name: "Not observer of all teams",
Password: []byte("p4ssw0rd.123"),
Expand Down Expand Up @@ -1786,7 +1851,7 @@ spec:
assert.Equal(t, expectedJson, runAppForTest(t, []string{"get", "queries", "--json"}))

// No queries are returned if none is observer_can_run.
setCurrentUserSession(&fleet.User{
setCurrentUserSession(t, ds, &fleet.User{
ID: 2,
Name: "Team observer",
Password: []byte("p4ssw0rd.123"),
Expand Down Expand Up @@ -2948,23 +3013,6 @@ func TestGetConfigAgentOptionsSSOAndSMTP(t *testing.T) {
}, nil
}

setCurrentUserSession := func(user *fleet.User) {
user, err := ds.NewUser(context.Background(), user)
require.NoError(t, err)
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
return &fleet.Session{
CreateTimestamp: fleet.CreateTimestamp{CreatedAt: time.Now()},
ID: 1,
AccessedAt: time.Now(),
UserID: user.ID,
Key: key,
}, nil
}
ds.UserByIDFunc = func(ctx context.Context, id uint) (*fleet.User, error) {
return user, nil
}
}

for _, tc := range []struct {
name string
user *fleet.User
Expand Down Expand Up @@ -3012,7 +3060,7 @@ func TestGetConfigAgentOptionsSSOAndSMTP(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
setCurrentUserSession(tc.user)
setCurrentUserSession(t, ds, tc.user)

ok := tc.checkOutput(runAppForTest(t, []string{"get", "config"}))
require.True(t, ok)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"kind": "config",
"apiVersion": "v1",
"spec": {
"org_info": {
"org_name": "",
"org_logo_url": "",
"org_logo_url_light_background": "",
"contact_url": "https://fleetdm.com/company/contact"
},
"server_settings": {
"server_url": "",
"live_query_disabled": false,
"query_report_cap": 0,
"query_reports_disabled": false,
"enable_analytics": false,
"deferred_save_host": false,
"scripts_disabled": false,
"ai_features_disabled": false
},
"host_expiry_settings": {
"host_expiry_enabled": false,
"host_expiry_window": 0
},
"activity_expiry_settings": {
"activity_expiry_enabled": false,
"activity_expiry_window": 0
},
"features": {
"enable_host_users": true,
"enable_software_inventory": false
},
"fleet_desktop": {
"transparency_url": "https://fleetdm.com/transparency"
},
"vulnerability_settings": {
"databases_path": "/some/path"
},
"webhook_settings": {
"activities_webhook": {
"enable_activities_webhook": false,
"destination_url": ""
},
"host_status_webhook": {
"enable_host_status_webhook": false,
"destination_url": "",
"host_percentage": 0,
"days_count": 0
},
"failing_policies_webhook": {
"enable_failing_policies_webhook": false,
"destination_url": "",
"policy_ids": null,
"host_batch_size": 0
},
"vulnerabilities_webhook": {
"enable_vulnerabilities_webhook": false,
"destination_url": "",
"host_batch_size": 0
},
"interval": "0s"
},
"integrations": {
"jira": null,
"zendesk": null,
"google_calendar": null,
"ndes_scep_proxy": null
},
"mdm": {
"apple_bm_terms_expired": false,
"apple_server_url": "",
"apple_bm_enabled_and_configured": false,
"enabled_and_configured": false,
"apple_business_manager": null,
"volume_purchasing_program": null,
"windows_enabled_and_configured": false,
"enable_disk_encryption": false,
"macos_updates": {
"minimum_version": null,
"deadline": null
},
"ios_updates": {
"minimum_version": null,
"deadline": null
},
"ipados_updates": {
"minimum_version": null,
"deadline": null
},
"windows_updates": {
"deadline_days": 7,
"grace_period_days": 3
},
"windows_migration_enabled": false,
"macos_migration": {
"enable": false,
"mode": "",
"webhook_url": ""
},
"macos_settings": {
"custom_settings": null
},
"macos_setup": {
"bootstrap_package": null,
"enable_end_user_authentication": false,
"macos_setup_assistant": null,
"enable_release_device_manually": false,
"script": null,
"software": null
},
"windows_settings": {
"custom_settings": null
},
"end_user_authentication": {
"entity_id": "",
"issuer_uri": "",
"metadata": "",
"metadata_url": "",
"idp_name": ""
}
},
"scripts": null
}
}
Loading

0 comments on commit d26afe3

Please sign in to comment.