From 33694367417bbbe6893aec8e4850c3bb88b9c9ad Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Mon, 25 Oct 2021 09:17:34 -0300 Subject: [PATCH] Remove policies yaml for now and apply policies in preview (#2644) --- cmd/fleetctl/apply.go | 30 +++++---------------- cmd/fleetctl/apply_test.go | 41 ----------------------------- cmd/fleetctl/preview.go | 43 +++++++++++++++++++++++++++++++ server/service/client_policies.go | 11 ++++++++ server/service/client_queries.go | 17 ++++++++++++ 5 files changed, 78 insertions(+), 64 deletions(-) create mode 100644 server/service/client_policies.go diff --git a/cmd/fleetctl/apply.go b/cmd/fleetctl/apply.go index dfa6be0b94..fde90d5ec2 100644 --- a/cmd/fleetctl/apply.go +++ b/cmd/fleetctl/apply.go @@ -23,11 +23,10 @@ type specMetadata struct { } type specGroup struct { - Queries []*fleet.QuerySpec - Teams []*fleet.TeamSpec - Packs []*fleet.PackSpec - Labels []*fleet.LabelSpec - Policies []*fleet.PolicySpec + Queries []*fleet.QuerySpec + Teams []*fleet.TeamSpec + Packs []*fleet.PackSpec + Labels []*fleet.LabelSpec // This needs to be interface{} to allow for the patch logic. Otherwise we send a request that looks to the // server like the user explicitly set the zero values. AppConfig interface{} @@ -41,10 +40,9 @@ type TeamSpec struct { func specGroupFromBytes(b []byte) (*specGroup, error) { specs := &specGroup{ - Queries: []*fleet.QuerySpec{}, - Packs: []*fleet.PackSpec{}, - Labels: []*fleet.LabelSpec{}, - Policies: []*fleet.PolicySpec{}, + Queries: []*fleet.QuerySpec{}, + Packs: []*fleet.PackSpec{}, + Labels: []*fleet.LabelSpec{}, } for _, spec := range splitYaml(string(b)) { @@ -117,13 +115,6 @@ func specGroupFromBytes(b []byte) (*specGroup, error) { } specs.Teams = append(specs.Teams, teamSpec.Team) - case fleet.PolicyKind: - var policySpec *fleet.PolicySpec - if err := yaml.Unmarshal(s.Spec, &policySpec); err != nil { - return nil, errors.Wrap(err, "unmarshaling "+kind+" spec") - } - specs.Policies = append(specs.Policies, policySpec) - default: return nil, errors.Errorf("unknown kind %q", s.Kind) } @@ -222,13 +213,6 @@ func applyCommand() *cli.Command { log(c, "[+] applied user roles\n") } - if len(specs.Policies) > 0 { - if err := fleetClient.ApplyPolicies(specs.Policies); err != nil { - return errors.Wrap(err, "applying policies") - } - logf(c, "[+] applied %d policies\n", len(specs.Policies)) - } - return nil }, } diff --git a/cmd/fleetctl/apply_test.go b/cmd/fleetctl/apply_test.go index 0878980311..84ec2fa996 100644 --- a/cmd/fleetctl/apply_test.go +++ b/cmd/fleetctl/apply_test.go @@ -234,44 +234,3 @@ spec: assert.True(t, savedAppConfig.HostSettings.EnableHostUsers) assert.True(t, savedAppConfig.HostSettings.EnableSoftwareInventory) } - -func TestApplyPolicySpecs(t *testing.T) { - _, ds := runServerWithMockedDS(t) - - var gotPolicies []*fleet.PolicySpec - - ds.TeamByNameFunc = func(ctx context.Context, name string) (*fleet.Team, error) { - assert.Equal(t, "team1", name) - return &fleet.Team{ID: 123, Name: "team1"}, nil - } - ds.ApplyPolicySpecsFunc = func(ctx context.Context, specs []*fleet.PolicySpec) error { - gotPolicies = specs - return nil - } - - name := writeTmpYml(t, `--- -apiVersion: v1 -kind: policy -spec: - query: some query ---- -apiVersion: v1 -kind: policy -spec: - query: some other query - team: team1 - resolution: something something -`) - - assert.Equal(t, "[+] applied 2 policies\n", runAppForTest(t, []string{"apply", "-f", name})) - assert.Equal(t, []*fleet.PolicySpec{ - { - QueryName: "some query", - }, - { - QueryName: "some other query", - Team: "team1", - Resolution: "something something", - }, - }, gotPolicies) -} diff --git a/cmd/fleetctl/preview.go b/cmd/fleetctl/preview.go index 488a123aa6..be0cffc278 100644 --- a/cmd/fleetctl/preview.go +++ b/cmd/fleetctl/preview.go @@ -221,6 +221,11 @@ Use the stop and reset subcommands to manage the server and dependencies once st return errors.Wrap(err, "failed to apply updated app config") } + fmt.Println("Applying Policies...") + if err := loadPolicies(client); err != nil { + fmt.Println("WARNING: Couldn't load policies:", err) + } + secrets, err := client.GetEnrollSecretSpec() if err != nil { return errors.Wrap(err, "Error retrieving enroll secret") @@ -588,3 +593,41 @@ func stopOrbit(destDir string) error { } return nil } + +func loadPolicies(client *service.Client) error { + policies := []struct { + name, query, description, resolution string + }{ + { + "Is Gatekeeper enabled on macOS devices?", + "SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;", + "Checks to make sure that the Gatekeeper feature is enabled on macOS devices. Gatekeeper tries to ensure only trusted software is run on a mac machine.", + "Run the following command in the Terminal app: /usr/sbin/spctl --master-enable", + }, + { + "Is disk encryption enabled on Windows devices?", + "SELECT 1 FROM bitlocker_info where protection_status = 1;", + "Checks to make sure that device encryption is enabled on Windows devices.", + "Option 1: Select the Start button. Select Settings > Update & Security > Device encryption. If Device encryption doesn't appear, skip to Option 2. If device encryption is turned off, select Turn on. Option 2: Select the Start button. Under Windows System, select Control Panel. Select System and Security. Under BitLocker Drive Encryption, select Manage BitLocker. Select Turn on BitLocker and then follow the instructions.", + }, + { + "Is Filevault enabled on macOS devices?", + `SELECT 1 FROM disk_encryption WHERE user_uuid IS NOT "" AND filevault_status = 'on' LIMIT 1;`, + "Checks to make sure that the Filevault feature is enabled on macOS devices.", + "Choose Apple menu > System Preferences, then click Security & Privacy. Click the FileVault tab. Click the Lock icon, then enter an administrator name and password. Click Turn On FileVault.", + }, + } + + for _, policy := range policies { + q, err := client.CreateQuery(policy.name, policy.query, policy.description) + if err != nil { + return errors.Wrap(err, "creating query") + } + err = client.CreatePolicy(q.ID, policy.resolution) + if err != nil { + return errors.Wrap(err, "creating policy") + } + } + + return nil +} diff --git a/server/service/client_policies.go b/server/service/client_policies.go new file mode 100644 index 0000000000..2eb02c69a5 --- /dev/null +++ b/server/service/client_policies.go @@ -0,0 +1,11 @@ +package service + +func (c *Client) CreatePolicy(queryID uint, resolution string) error { + req := globalPolicyRequest{ + QueryID: queryID, + Resolution: resolution, + } + verb, path := "POST", "/api/v1/fleet/global/policies" + var responseBody globalPolicyResponse + return c.authenticatedRequest(req, verb, path, &responseBody) +} diff --git a/server/service/client_queries.go b/server/service/client_queries.go index 4619e8f476..f2f302cbfe 100644 --- a/server/service/client_queries.go +++ b/server/service/client_queries.go @@ -136,3 +136,20 @@ func (c *Client) DeleteQuery(name string) error { return nil } + +func (c *Client) CreateQuery(name, query, description string) (*fleet.Query, error) { + req := createQueryRequest{ + payload: fleet.QueryPayload{ + Name: &name, + Description: &description, + Query: &query, + }, + } + verb, path := "POST", "/api/v1/fleet/queries" + var responseBody createQueryResponse + err := c.authenticatedRequest(req.payload, verb, path, &responseBody) + if err != nil { + return nil, err + } + return responseBody.Query, nil +}