@@ -39,6 +39,7 @@ import (
3939 "github.com/google/go-containerregistry/pkg/v1/tarball"
4040 "github.com/google/go-containerregistry/pkg/v1/types"
4141 "github.com/google/ko/internal/sbom"
42+ "github.com/google/ko/pkg/caps"
4243 specsv1 "github.com/opencontainers/image-spec/specs-go/v1"
4344 "github.com/sigstore/cosign/v2/pkg/oci"
4445 ocimutate "github.com/sigstore/cosign/v2/pkg/oci/mutate"
@@ -486,7 +487,7 @@ func appFilename(importpath string) string {
486487// owner: BUILTIN/Users group: BUILTIN/Users ($sddlValue="O:BUG:BU")
487488const userOwnerAndGroupSID = "AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAhAgAAAQIAAAAAAAUgAAAAIQIAAA=="
488489
489- func tarBinary (name , binary string , platform * v1.Platform ) (* bytes.Buffer , error ) {
490+ func tarBinary (name , binary string , platform * v1.Platform , opts * layerOptions ) (* bytes.Buffer , error ) {
490491 buf := bytes .NewBuffer (nil )
491492 tw := tar .NewWriter (buf )
492493 defer tw .Close ()
@@ -533,13 +534,21 @@ func tarBinary(name, binary string, platform *v1.Platform) (*bytes.Buffer, error
533534 // Use a fixed Mode, so that this isn't sensitive to the directory and umask
534535 // under which it was created. Additionally, windows can only set 0222,
535536 // 0444, or 0666, none of which are executable.
536- Mode : 0555 ,
537+ Mode : 0555 ,
538+ PAXRecords : map [string ]string {},
537539 }
538- if platform .OS == "windows" {
540+ switch platform .OS {
541+ case "windows" :
539542 // This magic value is for some reason needed for Windows to be
540543 // able to execute the binary.
541- header .PAXRecords = map [string ]string {
542- "MSWINDOWS.rawsd" : userOwnerAndGroupSID ,
544+ header .PAXRecords ["MSWINDOWS.rawsd" ] = userOwnerAndGroupSID
545+ case "linux" :
546+ if opts .linuxCapabilities != nil {
547+ xattr , err := opts .linuxCapabilities .ToXattrBytes ()
548+ if err != nil {
549+ return nil , fmt .Errorf ("caps.FileCaps.ToXattrBytes: %w" , err )
550+ }
551+ header .PAXRecords ["SCHILY.xattr.security.capability" ] = string (xattr )
543552 }
544553 }
545554 // write the header to the tarball archive
@@ -826,7 +835,8 @@ func (g *gobuild) buildOne(ctx context.Context, refStr string, base v1.Image, pl
826835 return nil , fmt .Errorf ("base image platform %q does not match desired platforms %v" , platform , g .platformMatcher .platforms )
827836 }
828837 // Do the build into a temporary file.
829- file , err := g .build (ctx , ref .Path (), g .dir , * platform , g .configForImportPath (ref .Path ()))
838+ config := g .configForImportPath (ref .Path ())
839+ file , err := g .build (ctx , ref .Path (), g .dir , * platform , config )
830840 if err != nil {
831841 return nil , fmt .Errorf ("build: %w" , err )
832842 }
@@ -862,11 +872,24 @@ func (g *gobuild) buildOne(ctx context.Context, refStr string, base v1.Image, pl
862872 appFileName := appFilename (ref .Path ())
863873 appPath := path .Join (appDir , appFileName )
864874
875+ var lo layerOptions
876+ lo .linuxCapabilities , err = caps .NewFileCaps (config .LinuxCapabilities ... )
877+ if err != nil {
878+ return nil , fmt .Errorf ("linux_capabilities: %w" , err )
879+ }
880+
865881 miss := func () (v1.Layer , error ) {
866- return buildLayer (appPath , file , platform , layerMediaType )
882+ return buildLayer (appPath , file , platform , layerMediaType , & lo )
867883 }
868884
869- binaryLayer , err := g .cache .get (ctx , file , miss )
885+ var binaryLayer v1.Layer
886+ switch {
887+ case lo .linuxCapabilities != nil :
888+ log .Printf ("Some options prevent us from using layer cache" )
889+ binaryLayer , err = miss ()
890+ default :
891+ binaryLayer , err = g .cache .get (ctx , file , miss )
892+ }
870893 if err != nil {
871894 return nil , fmt .Errorf ("cache.get(%q): %w" , file , err )
872895 }
@@ -946,9 +969,14 @@ func (g *gobuild) buildOne(ctx context.Context, refStr string, base v1.Image, pl
946969 return si , nil
947970}
948971
949- func buildLayer (appPath , file string , platform * v1.Platform , layerMediaType types.MediaType ) (v1.Layer , error ) {
972+ // layerOptions captures additional options to apply when authoring layer
973+ type layerOptions struct {
974+ linuxCapabilities * caps.FileCaps
975+ }
976+
977+ func buildLayer (appPath , file string , platform * v1.Platform , layerMediaType types.MediaType , opts * layerOptions ) (v1.Layer , error ) {
950978 // Construct a tarball with the binary and produce a layer.
951- binaryLayerBuf , err := tarBinary (appPath , file , platform )
979+ binaryLayerBuf , err := tarBinary (appPath , file , platform , opts )
952980 if err != nil {
953981 return nil , fmt .Errorf ("tarring binary: %w" , err )
954982 }
0 commit comments