Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Elastic Agent] Set permissions during installation #26665

Merged
merged 12 commits into from
Jul 22, 2021
7 changes: 2 additions & 5 deletions libbeat/api/npipe/listener_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,8 @@ func DefaultSD(forUser string) (string, error) {
if u.Username == "NT AUTHORITY\\SYSTEM" {
// running as SYSTEM, include Administrators group so Administrators can talk over
// the named pipe to the running Elastic Agent system process
admin, err := user.LookupGroup("Administrators")
if err != nil {
return "", errors.Wrap(err, "failed to lookup Administrators group")
}
descriptor += "(A;;GA;;;" + admin.Gid + ")"
// https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
descriptor += "(A;;GA;;;S-1-5-32-544)" // Administrators group
}
return descriptor, nil
}
1 change: 1 addition & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
- Do not log Elasticsearch configuration for monitoring output when running with debug. {pull}26583[26583]
- Fix issue where proxy enrollment options broke enrollment command. {pull}26749[26749]
- Remove symlink.prev from previously failed upgrade {pull}26785[26785]
- Set permissions during installation {pull}26665[26665]

==== New features

Expand Down
1 change: 1 addition & 0 deletions x-pack/elastic-agent/pkg/agent/cmd/enroll.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error {
Insecure: insecure,
UserProvidedMetadata: make(map[string]interface{}),
Staging: staging,
FixPermissions: fromInstall,
FleetServer: enrollCmdFleetServerOption{
ConnStr: fServer,
ElasticsearchCA: fElasticSearchCA,
Expand Down
9 changes: 9 additions & 0 deletions x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/control/client"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/control/proto"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/install"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/storage"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/authority"
Expand Down Expand Up @@ -99,6 +100,7 @@ type enrollCmdOption struct {
UserProvidedMetadata map[string]interface{}
EnrollAPIKey string
Staging string
FixPermissions bool
FleetServer enrollCmdFleetServerOption
}

Expand Down Expand Up @@ -236,6 +238,13 @@ func (c *enrollCmd) Execute(ctx context.Context) error {
return errors.New(err, "fail to enroll")
}

if c.options.FixPermissions {
err = install.FixPermissions()
if err != nil {
return errors.New(err, "failed to fix permissions")
}
}

if c.agentProc == nil {
if c.daemonReload(ctx) != nil {
c.log.Info("Elastic Agent might not be running; unable to trigger restart")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,8 @@ func securityDescriptor() (string, error) {
if u.Username == "NT AUTHORITY\\SYSTEM" {
// running as SYSTEM, include Administrators group so Administrators can talk over
// the named pipe to the running Elastic Agent system process
admin, err := user.LookupGroup("Administrators")
if err != nil {
return "", errors.Wrap(err, "failed to lookup Administrators group")
}
descriptor += "(A;;GA;;;" + admin.Gid + ")"
// https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
descriptor += "(A;;GA;;;S-1-5-32-544)" // Administrators group
}
return descriptor, nil
}
14 changes: 14 additions & 0 deletions x-pack/elastic-agent/pkg/agent/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ func Install(cfgFile string) error {
return err
}

// fix permissions
err = FixPermissions()
if err != nil {
return errors.New(
err,
"failed to perform permission changes",
errors.M("destination", paths.InstallPath))
}

// install service
svc, err := newService()
if err != nil {
Expand Down Expand Up @@ -120,6 +129,11 @@ func StopService() error {
return nil
}

// FixPermissions fixes the permissions on the installed system.
func FixPermissions() error {
return fixPermissions()
}

// findDirectory returns the directory to copy into the installation location.
//
// This also verifies that the discovered directory is a valid directory for installation.
Expand Down
35 changes: 35 additions & 0 deletions x-pack/elastic-agent/pkg/agent/install/perms_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

// +build !windows

package install

import (
"io/fs"
"os"
"path/filepath"

"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths"
)

// fixPermissions fixes the permissions so only root:root is the owner and no world read-able permissions
func fixPermissions() error {
return recursiveRootPermissions(paths.InstallPath)
}

func recursiveRootPermissions(path string) error {
return filepath.Walk(path, func(name string, info fs.FileInfo, err error) error {
if err == nil {
// all files should be owned by root:root
err = os.Chown(name, 0, 0)
if err != nil {
return err
}
// remove any world permissions from the file
err = os.Chmod(name, info.Mode().Perm()&0770)
}
return err
})
}
54 changes: 54 additions & 0 deletions x-pack/elastic-agent/pkg/agent/install/perms_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

// +build windows

package install

import (
"io/fs"
"path/filepath"

"github.com/hectane/go-acl"
"golang.org/x/sys/windows"

"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths"
)

// fixPermissions fixes the permissions so only SYSTEM and Administrators have access to the files in the install path
func fixPermissions() error {
return recursiveSystemAdminPermissions(paths.InstallPath)
}

func recursiveSystemAdminPermissions(path string) error {
return filepath.Walk(path, func(name string, info fs.FileInfo, err error) error {
if err == nil {
// first level doesn't inherit
inherit := true
if path == name {
inherit = false
}
err = systemAdministratorsOnly(name, inherit)
}
return err
})
}

func systemAdministratorsOnly(path string, inherit bool) error {
// https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
systemSID, err := windows.StringToSid("S-1-5-18")
if err != nil {
return err
}
administratorsSID, err := windows.StringToSid("S-1-5-32-544")
if err != nil {
return err
}

// https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask
return acl.Apply(
path, true, inherit,
acl.GrantSid(0xF10F0000, systemSID), // full control of all acl's
blakerouse marked this conversation as resolved.
Show resolved Hide resolved
acl.GrantSid(0xF10F0000, administratorsSID))
}