From 56c965e5df563fa19dc0124fb2f58e7890c3b29b Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 18 Feb 2019 13:51:43 +0100 Subject: [PATCH] cli: chmod 755 for backend plugin binaries Fixes #15500. Does a simple filename check if the binary names ends with _linux_amd64 or _darwin_amd64 then sets the file mode to 755. --- .../grafana-cli/commands/install_command.go | 20 +++++++-- .../commands/install_command_test.go | 41 ++++++++++++++++++ ...18fa4da8096a952608a7e4c7782b4260b41bcf.zip | Bin 0 -> 910 bytes 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 pkg/cmd/grafana-cli/commands/testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip diff --git a/pkg/cmd/grafana-cli/commands/install_command.go b/pkg/cmd/grafana-cli/commands/install_command.go index f88bb9bbfff..d758633fea5 100644 --- a/pkg/cmd/grafana-cli/commands/install_command.go +++ b/pkg/cmd/grafana-cli/commands/install_command.go @@ -57,6 +57,8 @@ func installCommand(c CommandLine) error { return InstallPlugin(pluginToInstall, version, c) } +// InstallPlugin downloads the plugin code as a zip file from the Grafana.com API +// and then extracts the zip into the plugins directory. func InstallPlugin(pluginName, version string, c CommandLine) error { pluginFolder := c.PluginDirectory() downloadURL := c.PluginURL() @@ -152,6 +154,10 @@ func downloadFile(pluginName, filePath, url string) (err error) { return err } + return extractFiles(body, pluginName, filePath) +} + +func extractFiles(body []byte, pluginName string, filePath string) error { r, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) if err != nil { return err @@ -161,12 +167,18 @@ func downloadFile(pluginName, filePath, url string) (err error) { if zf.FileInfo().IsDir() { err := os.Mkdir(newFile, 0777) - if PermissionsError(err) { + if permissionsError(err) { return fmt.Errorf(permissionsDeniedMessage, newFile) } } else { - dst, err := os.Create(newFile) - if PermissionsError(err) { + fileMode := zf.Mode() + + if strings.HasSuffix(newFile, "_linux_amd64") || strings.HasSuffix(newFile, "_darwin_amd64") { + fileMode = os.FileMode(0755) + } + + dst, err := os.OpenFile(newFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileMode) + if permissionsError(err) { return fmt.Errorf(permissionsDeniedMessage, newFile) } @@ -184,6 +196,6 @@ func downloadFile(pluginName, filePath, url string) (err error) { return nil } -func PermissionsError(err error) bool { +func permissionsError(err error) bool { return err != nil && strings.Contains(err.Error(), "permission denied") } diff --git a/pkg/cmd/grafana-cli/commands/install_command_test.go b/pkg/cmd/grafana-cli/commands/install_command_test.go index 52b329adf7f..3554dda82a9 100644 --- a/pkg/cmd/grafana-cli/commands/install_command_test.go +++ b/pkg/cmd/grafana-cli/commands/install_command_test.go @@ -1,6 +1,8 @@ package commands import ( + "io/ioutil" + "os" "testing" . "github.com/smartystreets/goconvey/convey" @@ -37,3 +39,42 @@ func TestFoldernameReplacement(t *testing.T) { }) }) } + +func TestExtractFiles(t *testing.T) { + Convey("Should preserve file permissions for plugin backend binaries for linux and darwin", t, func() { + err := os.RemoveAll("testdata/fake-plugins-dir") + So(err, ShouldBeNil) + + err = os.MkdirAll("testdata/fake-plugins-dir", 0774) + So(err, ShouldBeNil) + + body, err := ioutil.ReadFile("testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip") + So(err, ShouldBeNil) + + err = extractFiles(body, "grafana-simple-json-datasource", "testdata/fake-plugins-dir") + So(err, ShouldBeNil) + + //File in zip has permissions 777 + fileInfo, err := os.Stat("testdata/fake-plugins-dir/grafana-simple-json-datasource/simple-plugin_darwin_amd64") + So(err, ShouldBeNil) + So(fileInfo.Mode().String(), ShouldEqual, "-rwxr-xr-x") + + //File in zip has permission 664 + fileInfo, err = os.Stat("testdata/fake-plugins-dir/grafana-simple-json-datasource/simple-plugin_linux_amd64") + So(err, ShouldBeNil) + So(fileInfo.Mode().String(), ShouldEqual, "-rwxr-xr-x") + + //File in zip has permission 644 + fileInfo, err = os.Stat("testdata/fake-plugins-dir/grafana-simple-json-datasource/simple-plugin_windows_amd64.exe") + So(err, ShouldBeNil) + So(fileInfo.Mode().String(), ShouldEqual, "-rw-r--r--") + + //File in zip has permission 755 + fileInfo, err = os.Stat("testdata/fake-plugins-dir/grafana-simple-json-datasource/non-plugin-binary") + So(err, ShouldBeNil) + So(fileInfo.Mode().String(), ShouldEqual, "-rwxr-xr-x") + + err = os.RemoveAll("testdata/fake-plugins-dir") + So(err, ShouldBeNil) + }) +} diff --git a/pkg/cmd/grafana-cli/commands/testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip b/pkg/cmd/grafana-cli/commands/testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip new file mode 100644 index 0000000000000000000000000000000000000000..f9263ab3e78a36cf40339c296db344db1ed2e4c7 GIT binary patch literal 910 zcmWIWW@h1H0D((oL4IHclwf6$VMxg=F3}GS;bdTz*_jms!lf1542&!C$rL;z0h zDlqNEnYjfysk#L@rRkY@@#UF$Df#8a@rk)9W+r;66{&F3qe(Gc4!h|&nR%rZ5VMIh z_avI9#bD;<<>x`2tecdXmsnH@HjfMFMv~kq4>J!n6jBn4fB`{_Lm8Rmm~q9A1T>}u z82&nfn9$f_g~S#{OyM?4g#l(11H+O=dzewEZpIRGq}wEiWYgQmx!7$&iABP8V8$WB zH*Xui!tB5jqd>DkF-k&6$)mX6l@S`~s3C