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

Fix creation of containing directories for files in tar packages #4100

Merged
merged 6 commits into from
Jan 19, 2024

Conversation

pchila
Copy link
Member

@pchila pchila commented Jan 18, 2024

What does this PR do?

This change fixes the creation of destination directories for file contained in a tar package.
If a file needs to be extracted to a destination directory that does not yet exist we create the necessary directories on the fly with permission 0750.
If we encounter the same directories after the file, we fix the permissions according to what is specified in the tar archive

Why is it important?

When running without superuser privileges we need to create a directory structure that has permissions that do not block access to the current user

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • [ ] I have made corresponding changes to the documentation
  • [ ] I have made corresponding change to the default configuration files
  • [x] I have added tests that prove my fix is effective or that my feature works
  • [ ] I have added an entry in ./changelog/fragments using the changelog tool
  • [ ] I have added an integration test or an E2E test

Author's Checklist

  • [ ]

How to test this PR locally

Related issues

Use cases

Screenshots

Logs

Questions to ask yourself

  • How are we going to support this in production?
  • How are we going to measure its adoption?
  • How are we going to debug this?
  • What are the metrics I should take care of?
  • ...

@pchila pchila added bug Something isn't working Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team Team:Elastic-Agent Label for the Agent team labels Jan 18, 2024
@pchila pchila requested a review from blakerouse January 18, 2024 16:40
@pchila pchila self-assigned this Jan 18, 2024
@pchila pchila requested a review from a team as a code owner January 18, 2024 16:40
@pchila pchila requested a review from AndersonQ January 18, 2024 16:40
@elasticmachine
Copy link
Contributor

Pinging @elastic/elastic-agent (Team:Elastic-Agent)

@elasticmachine
Copy link
Contributor

Pinging @elastic/elastic-agent-control-plane (Team:Elastic-Agent-Control-Plane)

Copy link
Contributor

mergify bot commented Jan 18, 2024

This pull request does not have a backport label. Could you fix it @pchila? 🙏
To fixup this pull request, you need to add the backport labels for the needed
branches, such as:

  • backport-v./d./d./d is the label to automatically backport to the 8./d branch. /d is the digit

NOTE: backport-skip has been added to this pull request.

Copy link
Contributor

@blakerouse blakerouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks for the change to remove the need for path adjustments in the unit tests.

@cmacknz
Copy link
Member

cmacknz commented Jan 18, 2024

This should have a changelog entry shouldn't it? It's a bug fix. It's not one anyone is hitting today, that doesn't mean we shouldn't document the change.

@pchila pchila force-pushed the fix-dir-creation-in-unpack branch from bc49554 to b019c4c Compare January 18, 2024 19:20

type createArchiveFunc func(*testing.T, []files) (string, error)

func TestUpgrader_unpack(t *testing.T) {
Copy link
Member

@cmacknz cmacknz Jan 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Thank you for this, this is great.
  2. This test still passes if you take out the os.Stat call and associated logic
diff --git a/internal/pkg/agent/application/upgrade/step_unpack.go b/internal/pkg/agent/application/upgrade/step_unpack.go
index 4f5b0bd744..82551616dc 100644
--- a/internal/pkg/agent/application/upgrade/step_unpack.go
+++ b/internal/pkg/agent/application/upgrade/step_unpack.go
@@ -10,7 +10,6 @@ import (
        "compress/gzip"
        "fmt"
        "io"
-       "io/fs"
        "os"
        "path/filepath"
        "runtime"
@@ -213,20 +212,8 @@ func untar(log *logger.Logger, version string, archivePath, dataDir string) (str
                        }
                case mode.IsDir():
                        log.Debugw("Unpacking directory", "archive", "tar", "file.path", abs)
-                       // remove any world permissions from the directory
-                       _, err = os.Stat(abs)
-                       if errors.Is(err, fs.ErrNotExist) {
-                               if err := os.MkdirAll(abs, mode.Perm()&0770); err != nil {
-                                       return "", errors.New(err, "TarInstaller: creating directory for file "+abs, errors.TypeFilesystem, errors.M(errors.MetaKeyPath, abs))
-                               }
-                       } else if err != nil {
-                               return "", errors.New(err, "TarInstaller: stat() directory for file "+abs, errors.TypeFilesystem, errors.M(errors.MetaKeyPath, abs))
-                       } else {
-                               // set the appropriate permissions
-                               err = os.Chmod(abs, mode.Perm()&0o770)
-                               if err != nil {
-                                       return "", errors.New(err, fmt.Sprintf("TarInstaller: setting permissions %O for directory %q", mode.Perm()&0o770, abs), errors.TypeFilesystem, errors.M(errors.MetaKeyPath, abs))
-                               }
+                       if err := os.MkdirAll(abs, mode.Perm()&0770); err != nil {
+                               return "", errors.New(err, "TarInstaller: creating directory for file "+abs, errors.TypeFilesystem, errors.M(errors.MetaKeyPath, abs))
                        }
                default:
                        return "", errors.New(fmt.Sprintf("tar file entry %s contained unsupported file type %v", fileName, mode), errors.TypeFilesystem, errors.M(errors.MetaKeyPath, fileName))
go test ./internal/pkg/agent/application/upgrade/... -run TestUpgrader_unpack -count 1 -v
?       github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact/download/localremote     [no test files]
=== RUN   TestUpgrader_unpack
=== RUN   TestUpgrader_unpack/targz_with_file_before_containing_folder
--- PASS: TestUpgrader_unpack (0.00s)
    --- PASS: TestUpgrader_unpack/targz_with_file_before_containing_folder (0.00s)
PASS
ok      github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade 0.591s

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test passes because of the default 0750 permission when we create the directory on the fly (so we are able to write the file anyways). The code you removed is needed to restore permissions once we come across the directory in the tar archive, but that is not in the assertions. I will modify the test

@pchila pchila force-pushed the fix-dir-creation-in-unpack branch from 9198ef5 to 9b6fb22 Compare January 19, 2024 10:59
@pchila
Copy link
Member Author

pchila commented Jan 19, 2024

This should have a changelog entry shouldn't it? It's a bug fix. It's not one anyone is hitting today, that doesn't mean we shouldn't document the change.

@cmacknz not sure about the changelog as the change that introduced the issue is related to the unprivileged elastic-agent feature. Before such change, directories created on the fly would always have 0755 permissions and that would not be corrected if we encountered the directory with different permission later in the tar.gz archive. So a customer cannot have encountered the exact same bug in the released versions.
I added a changelog regardless as we improve on the previous behavior by fixing the permissions as specified in the tar.gz (minus the world ones, which I think was the original intention of the unprivileged change)

@pchila pchila force-pushed the fix-dir-creation-in-unpack branch from 9b6fb22 to 2d03226 Compare January 19, 2024 13:10
Copy link

Quality Gate passed Quality Gate passed

The SonarQube Quality Gate passed, but some issues were introduced.

2 New issues
0 Security Hotspots
66.7% 66.7% Coverage on New Code
0.0% 0.0% Duplication on New Code

See analysis details on SonarQube

@pchila pchila merged commit e37d4df into elastic:main Jan 19, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-skip bug Something isn't working Team:Elastic-Agent Label for the Agent team Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Unprivileged] Upgrade broken due to permission issues
4 participants