From 243afd2f86da430ccf087db4249145ae325c472d Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Tue, 3 Aug 2021 13:11:58 +0200 Subject: [PATCH 1/5] Factor out xattr handling to extra package Signed-off-by: Roman Mohr --- pkg/rpm/BUILD.bazel | 1 + pkg/rpm/cpio2tar.go | 24 +++--------------------- pkg/xattr/BUILD.bazel | 8 ++++++++ pkg/xattr/xattr.go | 29 +++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 pkg/xattr/BUILD.bazel create mode 100644 pkg/xattr/xattr.go diff --git a/pkg/rpm/BUILD.bazel b/pkg/rpm/BUILD.bazel index ab59ba8..dcadfc7 100644 --- a/pkg/rpm/BUILD.bazel +++ b/pkg/rpm/BUILD.bazel @@ -11,6 +11,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/api", + "//pkg/xattr", "@com_github_sassoftware_go_rpmutils//:go_default_library", "@com_github_sassoftware_go_rpmutils//cpio:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", diff --git a/pkg/rpm/cpio2tar.go b/pkg/rpm/cpio2tar.go index 00b25b1..5999094 100644 --- a/pkg/rpm/cpio2tar.go +++ b/pkg/rpm/cpio2tar.go @@ -23,18 +23,10 @@ import ( "io/ioutil" "time" + "github.com/rmohr/bazeldnf/pkg/xattr" "github.com/sassoftware/go-rpmutils/cpio" ) -const ( - capabilities_header = "SCHILY.xattr.security.capability" -) - -var cap_empty_bitmask = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -var supported_capabilities = map[string][]byte{ - "cap_net_bind_service": {1, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -} - // Extract the contents of a cpio stream from and writes it as a tar file into the provided writer func Tar(rs io.Reader, tarfile *tar.Writer, noSymlinksAndDirs bool, capabilities map[string][]string) error { hardLinks := map[int][]*tar.Header{} @@ -54,18 +46,8 @@ func Tar(rs io.Reader, tarfile *tar.Writer, noSymlinksAndDirs bool, capabilities pax := map[string]string{} if caps, exists := capabilities[entry.Header.Filename()]; exists { - for _, cap := range caps { - if _, supported := supported_capabilities[cap]; !supported { - return fmt.Errorf("Requested capability '%s' for file '%s' is not supported", cap, entry.Header.Filename()) - } - if _, exists := pax[capabilities_header]; !exists { - pax[capabilities_header] = string(cap_empty_bitmask) - } - val := []byte(pax[capabilities_header]) - for i, b := range supported_capabilities[cap] { - val[i] = val[i] | b - } - pax[capabilities_header] = string(val) + if err := xattr.AddCapabilities(pax, caps); err != nil { + return fmt.Errorf("failed setting capabilities on %s: %v", entry.Header.Filename(), err) } } diff --git a/pkg/xattr/BUILD.bazel b/pkg/xattr/BUILD.bazel new file mode 100644 index 0000000..0b8833a --- /dev/null +++ b/pkg/xattr/BUILD.bazel @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "xattr", + srcs = ["xattr.go"], + importpath = "github.com/rmohr/bazeldnf/pkg/xattr", + visibility = ["//visibility:public"], +) diff --git a/pkg/xattr/xattr.go b/pkg/xattr/xattr.go new file mode 100644 index 0000000..101ffae --- /dev/null +++ b/pkg/xattr/xattr.go @@ -0,0 +1,29 @@ +package xattr + +import "fmt" + +const ( + capabilities_header = "SCHILY.xattr.security.capability" +) + +var cap_empty_bitmask = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +var supported_capabilities = map[string][]byte{ + "cap_net_bind_service": {1, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +} + +func AddCapabilities(pax map[string]string, capabilities []string) error { + for _, cap := range capabilities { + if _, supported := supported_capabilities[cap]; !supported { + return fmt.Errorf("requested capability '%s' is not supported", cap) + } + if _, exists := pax[capabilities_header]; !exists { + pax[capabilities_header] = string(cap_empty_bitmask) + } + val := []byte(pax[capabilities_header]) + for i, b := range supported_capabilities[cap] { + val[i] = val[i] | b + } + pax[capabilities_header] = string(val) + } + return nil +} From 87927db9fb9236aff3a990d24e7fe473a1d19620 Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Tue, 3 Aug 2021 13:28:06 +0200 Subject: [PATCH 2/5] Add selinux-label to rpmtree rules Signed-off-by: Roman Mohr --- cmd/rpm2tar.go | 14 ++++++++------ internal/rpmtree.bzl | 9 ++++++++- pkg/rpm/cpio2tar.go | 7 ++++++- pkg/rpm/tar.go | 4 ++-- pkg/rpm/tar_test.go | 4 ++-- pkg/xattr/xattr.go | 9 +++++++++ 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/cmd/rpm2tar.go b/cmd/rpm2tar.go index c35f8a1..aede9dd 100644 --- a/cmd/rpm2tar.go +++ b/cmd/rpm2tar.go @@ -12,10 +12,11 @@ import ( ) type rpm2tarOpts struct { - output string - input []string - symlinks map[string]string - capabilities map[string]string + output string + input []string + symlinks map[string]string + capabilities map[string]string + selinuxLabels map[string]string } var rpm2taropts = rpm2tarOpts{} @@ -79,13 +80,13 @@ func NewRpm2TarCmd() *cobra.Command { return fmt.Errorf("could not open rpm at %s: %v", i, err) } defer rpmStream.Close() - err = rpm.RPMToTar(rpmStream, tarWriter, true, cap) + err = rpm.RPMToTar(rpmStream, tarWriter, true, cap, rpm2taropts.selinuxLabels) if err != nil { return fmt.Errorf("could not convert rpm at %s: %v", i, err) } } } else { - err := rpm.RPMToTar(rpmStream, tarWriter, false, cap) + err := rpm.RPMToTar(rpmStream, tarWriter, false, cap, rpm2taropts.selinuxLabels) if err != nil { return fmt.Errorf("could not convert rpm : %v", err) } @@ -98,6 +99,7 @@ func NewRpm2TarCmd() *cobra.Command { rpm2tarCmd.Flags().StringArrayVarP(&rpm2taropts.input, "input", "i", []string{}, "location from where to read the rpm file (defaults to stdin)") rpm2tarCmd.Flags().StringToStringVarP(&rpm2taropts.symlinks, "symlinks", "s", map[string]string{}, "symlinks to add. Relative or absolute.") rpm2tarCmd.Flags().StringToStringVarP(&rpm2taropts.capabilities, "capabilities", "c", map[string]string{}, "capabilities of files (--capabilities=/bin/ls=cap_net_bind_service)") + rpm2tarCmd.Flags().StringToStringVar(&rpm2taropts.selinuxLabels, "selinux-labels", map[string]string{}, "selinux labels of files (--selinux-labels=/bin/ls=unconfined_u:object_r:default_t:s0)") // deprecated options rpm2tarCmd.Flags().StringToStringVar(&rpm2taropts.capabilities, "capabilties", map[string]string{}, "capabilities of files (-c=/bin/ls=cap_net_bind_service)") rpm2tarCmd.Flags().MarkDeprecated("capabilties", "use --capabilities instead") diff --git a/internal/rpmtree.bzl b/internal/rpmtree.bzl index 02e025f..ade5300 100644 --- a/internal/rpmtree.bzl +++ b/internal/rpmtree.bzl @@ -30,7 +30,13 @@ def _rpm2tar_impl(ctx): capabilities = [] for k, v in ctx.attr.capabilities.items(): capabilities += [k + "=" + ":".join(v)] - args += ["-c", ",".join(capabilities)] + args += ["--capabilities", ",".join(capabilities)] + + if ctx.attr.selinux_labels: + selinux_labels = [] + for k, v in ctx.attr.selinux_labels.items(): + selinux_labels += [k + "=" + v] + args += ["--selinux-labels", ",".join(selinux_labels)] args += rpms @@ -71,6 +77,7 @@ _rpm2tar_attrs = { ), "symlinks": attr.string_dict(), "capabilities": attr.string_list_dict(), + "selinux_labels": attr.string_list_dict(), "out": attr.output(mandatory = True), } diff --git a/pkg/rpm/cpio2tar.go b/pkg/rpm/cpio2tar.go index 5999094..647b365 100644 --- a/pkg/rpm/cpio2tar.go +++ b/pkg/rpm/cpio2tar.go @@ -28,7 +28,7 @@ import ( ) // Extract the contents of a cpio stream from and writes it as a tar file into the provided writer -func Tar(rs io.Reader, tarfile *tar.Writer, noSymlinksAndDirs bool, capabilities map[string][]string) error { +func Tar(rs io.Reader, tarfile *tar.Writer, noSymlinksAndDirs bool, capabilities map[string][]string, selinuxLabels map[string]string) error { hardLinks := map[int][]*tar.Header{} inodes := map[int]string{} @@ -50,6 +50,11 @@ func Tar(rs io.Reader, tarfile *tar.Writer, noSymlinksAndDirs bool, capabilities return fmt.Errorf("failed setting capabilities on %s: %v", entry.Header.Filename(), err) } } + if label, exists := selinuxLabels[entry.Header.Filename()]; exists { + if err := xattr.SetSELinuxLabel(pax, label); err != nil { + return fmt.Errorf("failed setting selinux label on %s: %v", entry.Header.Filename(), err) + } + } tarHeader := &tar.Header{ Name: entry.Header.Filename(), diff --git a/pkg/rpm/tar.go b/pkg/rpm/tar.go index a4d7922..e585bd4 100644 --- a/pkg/rpm/tar.go +++ b/pkg/rpm/tar.go @@ -15,7 +15,7 @@ import ( log "github.com/sirupsen/logrus" ) -func RPMToTar(rpmReader io.Reader, tarWriter *tar.Writer, noSymlinksAndDirs bool, capabilities map[string][]string) error { +func RPMToTar(rpmReader io.Reader, tarWriter *tar.Writer, noSymlinksAndDirs bool, capabilities map[string][]string, selinuxLabels map[string]string) error { rpm, err := rpmutils.ReadRpm(rpmReader) if err != nil { return fmt.Errorf("failed to read rpm: %s", err) @@ -24,7 +24,7 @@ func RPMToTar(rpmReader io.Reader, tarWriter *tar.Writer, noSymlinksAndDirs bool if err != nil { return fmt.Errorf("failed to open the payload reader: %s", err) } - return Tar(payloadReader, tarWriter, noSymlinksAndDirs, capabilities) + return Tar(payloadReader, tarWriter, noSymlinksAndDirs, capabilities, selinuxLabels) } func RPMToCPIO(rpmReader io.Reader) (*cpio.CpioStream, error) { diff --git a/pkg/rpm/tar_test.go b/pkg/rpm/tar_test.go index 40f496f..a31d083 100644 --- a/pkg/rpm/tar_test.go +++ b/pkg/rpm/tar_test.go @@ -48,7 +48,7 @@ func TestRPMToTar(t *testing.T) { g.Expect(err).ToNot(HaveOccurred()) defer tarWriter.Close() - err = RPMToTar(f, tar.NewWriter(tarWriter), false, nil) + err = RPMToTar(f, tar.NewWriter(tarWriter), false, nil, nil) g.Expect(err).ToNot(HaveOccurred()) tarWriter.Close() @@ -125,7 +125,7 @@ func TestTar2Files(t *testing.T) { defer pipeWriter.Close() go func() { - _ = RPMToTar(f, tar.NewWriter(pipeWriter), false, nil) + _ = RPMToTar(f, tar.NewWriter(pipeWriter), false, nil, nil) pipeWriter.Close() }() diff --git a/pkg/xattr/xattr.go b/pkg/xattr/xattr.go index 101ffae..622f0f4 100644 --- a/pkg/xattr/xattr.go +++ b/pkg/xattr/xattr.go @@ -4,6 +4,7 @@ import "fmt" const ( capabilities_header = "SCHILY.xattr.security.capability" + selinux_header = "SCHILY.xattr.security.selinux" ) var cap_empty_bitmask = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -27,3 +28,11 @@ func AddCapabilities(pax map[string]string, capabilities []string) error { } return nil } + +func SetSELinuxLabel(pax map[string]string, label string) error { + if label == "" { + return fmt.Errorf("label must not be empty, but got '%s'", label) + } + pax[selinux_header] = fmt.Sprintf("%s\x00", label) + return nil +} From 728fde1536029c672a0e4a1df1edf267ff5e3da5 Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Tue, 3 Aug 2021 13:47:45 +0200 Subject: [PATCH 3/5] Add xattr command Signed-off-by: Roman Mohr --- cmd/BUILD.bazel | 2 ++ cmd/root.go | 1 + cmd/xattr.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++ pkg/xattr/xattr.go | 37 ++++++++++++++++++++++++- 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 cmd/xattr.go diff --git a/cmd/BUILD.bazel b/cmd/BUILD.bazel index ca58246..c46eb35 100644 --- a/cmd/BUILD.bazel +++ b/cmd/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "sandbox.go", "tar2files.go", "verify.go", + "xattr.go", ], importpath = "github.com/rmohr/bazeldnf/cmd", visibility = ["//visibility:private"], @@ -31,6 +32,7 @@ go_library( "//pkg/repo", "//pkg/rpm", "//pkg/sat", + "//pkg/xattr", "@com_github_sassoftware_go_rpmutils//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_spf13_cobra//:go_default_library", diff --git a/cmd/root.go b/cmd/root.go index f9d3f72..67d6b38 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,7 @@ var rootCmd = &cobra.Command{ } func Execute() { + rootCmd.AddCommand(NewXATTRCmd()) rootCmd.AddCommand(NewSandboxCmd()) rootCmd.AddCommand(NewFetchCmd()) rootCmd.AddCommand(NewInitCmd()) diff --git a/cmd/xattr.go b/cmd/xattr.go new file mode 100644 index 0000000..fe3e224 --- /dev/null +++ b/cmd/xattr.go @@ -0,0 +1,67 @@ +package main + +import ( + "archive/tar" + "os" + "strings" + + "github.com/rmohr/bazeldnf/pkg/xattr" + "github.com/spf13/cobra" +) + +type xattrOpts struct { + filePrefix string + tarFileInput string + tarFileOutput string + capabilities map[string]string + selinuxLabels map[string]string +} + +var xattropts = xattrOpts{} + +func NewXATTRCmd() *cobra.Command { + xattrCmd := &cobra.Command{ + Use: "xattr", + Short: "Modify xattrs on tar file members", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + capabilityMap := map[string][]string{} + for file, caps := range xattropts.capabilities { + split := strings.Split(caps, ":") + if len(split) > 0 { + capabilityMap["./"+strings.TrimPrefix(file, "/")] = split + } + } + labelMap := map[string]string{} + for file, label := range xattropts.selinuxLabels { + labelMap["./"+strings.TrimPrefix(file, "/")] = label + } + + streamInput := os.Stdin + if xattropts.tarFileInput != "" { + streamInput, err = os.Open(xattropts.tarFileInput) + if err != nil { + return err + } + defer streamInput.Close() + } + + streamOutput := os.Stdout + if xattropts.tarFileOutput != "" { + streamOutput, err = os.OpenFile(xattropts.tarFileOutput, os.O_WRONLY|os.O_CREATE, os.ModePerm) + if err != nil { + return err + } + } + tarWriter := tar.NewWriter(streamOutput) + defer tarWriter.Close() + return xattr.Apply(tar.NewReader(streamInput), tarWriter , capabilityMap, labelMap) + }, + } + + xattrCmd.Flags().StringVarP(&xattropts.tarFileInput, "input", "i", "", "location from where to read the tar file (defaults to stdin)") + xattrCmd.Flags().StringVarP(&xattropts.tarFileOutput, "output", "o", "", "where to write the file to (defaults to stdout)") + xattrCmd.Flags().StringToStringVarP(&xattropts.capabilities, "capabilities", "c", map[string]string{}, "capabilities of files (--capabilities=/bin/ls=cap_net_bind_service)") + xattrCmd.Flags().StringToStringVar(&xattropts.selinuxLabels, "selinux-labels", map[string]string{}, "selinux labels of files (--selinux-labels=/bin/ls=unconfined_u:object_r:default_t:s0)") + return xattrCmd +} diff --git a/pkg/xattr/xattr.go b/pkg/xattr/xattr.go index 622f0f4..9b73327 100644 --- a/pkg/xattr/xattr.go +++ b/pkg/xattr/xattr.go @@ -1,6 +1,10 @@ package xattr -import "fmt" +import ( + "archive/tar" + "fmt" + "io" +) const ( capabilities_header = "SCHILY.xattr.security.capability" @@ -36,3 +40,34 @@ func SetSELinuxLabel(pax map[string]string, label string) error { pax[selinux_header] = fmt.Sprintf("%s\x00", label) return nil } + +func Apply(reader *tar.Reader, writer *tar.Writer, capabilties map[string][]string, labels map[string]string) error { + for { + entry, err := reader.Next() + if err == io.EOF { + break + } else if err != nil { + return err + } + + if caps, exists := capabilties[entry.Name]; exists { + if err := AddCapabilities(entry.PAXRecords, caps); err != nil { + return err + } + } + if l, exists := labels[entry.Name]; exists { + if err := SetSELinuxLabel(entry.PAXRecords, l); err != nil { + return err + } + } + + entry.Format = tar.FormatPAX + if err := writer.WriteHeader(entry); err != nil { + return err + } + if _, err := io.Copy(writer, reader); err != nil { + return err + } + } + return nil +} From 62262a51e1b19572c10510b615b4c3a7f78ff415 Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Fri, 6 Aug 2021 10:43:15 +0200 Subject: [PATCH 4/5] Add xattr stream package test Ensure that the selinux header has the right format. The included minimal tar test data contains a file with a selinux header captured via `tar` as a reference. Signed-off-by: Roman Mohr --- pkg/xattr/BUILD.bazel | 10 +++++++- pkg/xattr/testdata/xattr.tar | Bin 0 -> 10240 bytes pkg/xattr/xattr.go | 31 ++++++++++++++++-------- pkg/xattr/xattr_test.go | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 pkg/xattr/testdata/xattr.tar create mode 100644 pkg/xattr/xattr_test.go diff --git a/pkg/xattr/BUILD.bazel b/pkg/xattr/BUILD.bazel index 0b8833a..de1588c 100644 --- a/pkg/xattr/BUILD.bazel +++ b/pkg/xattr/BUILD.bazel @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "xattr", @@ -6,3 +6,11 @@ go_library( importpath = "github.com/rmohr/bazeldnf/pkg/xattr", visibility = ["//visibility:public"], ) + +go_test( + name = "xattr_test", + srcs = ["xattr_test.go"], + data = glob(["testdata/**"]), + embed = [":xattr"], + deps = ["@com_github_onsi_gomega//:go_default_library"], +) diff --git a/pkg/xattr/testdata/xattr.tar b/pkg/xattr/testdata/xattr.tar new file mode 100644 index 0000000000000000000000000000000000000000..019cac52b425269fe5a226357635826d8a0e5c65 GIT binary patch literal 10240 zcmeIyy=ucS5C?G0c?v&)qqAhWHDv0NLWe@9PR4dr?BEZOC2-%qa!M#lhAe3t$p02u zK4eb6;~cMF%XzEIoi@|D>RiRHAKZtMk}a!`)0HQZ7)j!S6v>PjCnAxtXuf_a=U;S_ zEsZbfJaZRs1dn>#_Ig7qc}RpzQxW?v&?8T!T={GnWR;4!?-U6o#FDLpY;ZQC=~&%DiL=#Rbm9Ll z`AZ`oTxc13r4I8?S$dfNJ?o zbk~g-vYYJ>3WERyAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= Hmju25wWC;g literal 0 HcmV?d00001 diff --git a/pkg/xattr/xattr.go b/pkg/xattr/xattr.go index 9b73327..74915e2 100644 --- a/pkg/xattr/xattr.go +++ b/pkg/xattr/xattr.go @@ -37,7 +37,7 @@ func SetSELinuxLabel(pax map[string]string, label string) error { if label == "" { return fmt.Errorf("label must not be empty, but got '%s'", label) } - pax[selinux_header] = fmt.Sprintf("%s\x00", label) + pax[selinux_header] = fmt.Sprintf("%s\x00",label) return nil } @@ -50,15 +50,8 @@ func Apply(reader *tar.Reader, writer *tar.Writer, capabilties map[string][]stri return err } - if caps, exists := capabilties[entry.Name]; exists { - if err := AddCapabilities(entry.PAXRecords, caps); err != nil { - return err - } - } - if l, exists := labels[entry.Name]; exists { - if err := SetSELinuxLabel(entry.PAXRecords, l); err != nil { - return err - } + if err := enrichEntry(entry, capabilties, labels); err != nil { + return err } entry.Format = tar.FormatPAX @@ -71,3 +64,21 @@ func Apply(reader *tar.Reader, writer *tar.Writer, capabilties map[string][]stri } return nil } + +func enrichEntry(entry *tar.Header, capabilties map[string][]string, labels map[string]string) error { + if entry.PAXRecords == nil { + entry.PAXRecords = map[string]string{} + } + + if caps, exists := capabilties[entry.Name]; exists { + if err := AddCapabilities(entry.PAXRecords, caps); err != nil { + return err + } + } + if l, exists := labels[entry.Name]; exists { + if err := SetSELinuxLabel(entry.PAXRecords, l); err != nil { + return err + } + } + return nil +} diff --git a/pkg/xattr/xattr_test.go b/pkg/xattr/xattr_test.go new file mode 100644 index 0000000..779dab3 --- /dev/null +++ b/pkg/xattr/xattr_test.go @@ -0,0 +1,45 @@ +package xattr + +import ( + "archive/tar" + "fmt" + "io" + "os" + "testing" + + . "github.com/onsi/gomega" +) + +var g *GomegaWithT + +func TestSettingSELinuxLabel(t *testing.T) { + g = NewGomegaWithT(t) + referenceEntry, err := getHeader("blub") + g.Expect(err).ToNot(HaveOccurred()) + + generatedEntry := &tar.Header{Name: "blub"} + labels := map[string]string{"blub": "unconfined_u:object_r:user_home_t:s0", "somethingelse": "something"} + + g.Expect(enrichEntry(generatedEntry, nil, labels)).To(Succeed()) + + g.Expect(generatedEntry.PAXRecords[selinux_header]).To(Equal(referenceEntry.PAXRecords[selinux_header])) +} + +func getHeader(name string) (*tar.Header, error) { + f, err := os.Open("testdata/xattr.tar") + g.Expect(err).ToNot(HaveOccurred()) + defer f.Close() + r := tar.NewReader(f) + for { + entry, err := r.Next() + if err == io.EOF { + break + } else if err != nil { + g.Expect(err).ToNot(HaveOccurred()) + } + if entry.Name == name { + return entry, nil + } + } + return nil, fmt.Errorf("entry %v does not exist", name) +} From 9ac99823ce73fcdc49071128de4ba758dfb11aa5 Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Fri, 6 Aug 2021 10:57:41 +0200 Subject: [PATCH 5/5] Add xattrs rule Signed-off-by: Roman Mohr --- deps.bzl | 5 ++++ internal/xattrs.bzl | 65 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 internal/xattrs.bzl diff --git a/deps.bzl b/deps.bzl index 2d808da..a5876af 100644 --- a/deps.bzl +++ b/deps.bzl @@ -14,10 +14,15 @@ load( "@bazeldnf//internal:rpmtree.bzl", _tar2files = "tar2files", ) +load( + "@bazeldnf//internal:xattrs.bzl", + _xattrs = "xattrs", +) rpm = _rpm rpmtree = _rpmtree tar2files = _tar2files +xattrs = _xattrs def bazeldnf_dependencies(): _maybe( diff --git a/internal/xattrs.bzl b/internal/xattrs.bzl new file mode 100644 index 0000000..8fa1643 --- /dev/null +++ b/internal/xattrs.bzl @@ -0,0 +1,65 @@ +# Copyright 2014 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def _xattrs_impl(ctx): + out = ctx.outputs.out + args = ["xattr", "-i", ctx.files.tar[0].path, "-o", out.path] + + if ctx.attr.capabilities: + capabilities = [] + for k, v in ctx.attr.capabilities.items(): + capabilities += [k + "=" + ":".join(v)] + args += ["--capabilities", ",".join(capabilities)] + + if ctx.attr.selinux_labels: + selinux_labels = [] + for k, v in ctx.attr.selinux_labels.items(): + selinux_labels += [k + "=" + v] + args += ["--selinux-labels", ",".join(selinux_labels)] + + ctx.actions.run( + inputs = ctx.files.tar, + outputs = [out], + arguments = args, + progress_message = "Enriching %s with xattrs" % ctx.label.name, + executable = ctx.executable._bazeldnf, + ) + + return [DefaultInfo(files = depset([ctx.outputs.out]))] + +_xattrs_attrs = { + "tar": attr.label(allow_single_file = True), + "_bazeldnf": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//cmd:cmd"), + ), + "capabilities": attr.string_list_dict(), + "selinux_labels": attr.string_dict(), + "out": attr.output(mandatory = True), +} + +_xattrs = rule( + implementation = _xattrs_impl, + attrs = _xattrs_attrs, +) + +def xattrs(**kwargs): + basename = kwargs["name"] + tarname = basename + ".tar" + _xattrs( + out = tarname, + **kwargs + )