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

BUILD-87: secret configmap volume mounts in builds #245

Merged
merged 2 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@ require (
github.com/fsouza/go-dockerclient v1.7.2
github.com/opencontainers/runc v1.0.0-rc93
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360
github.com/openshift/client-go v0.0.0-20210331195552-cf6c2669e01f
github.com/openshift/api v0.0.0-20210621103532-064fc2f78417
github.com/openshift/client-go v0.0.0-20210521082421-73d9475a9142
github.com/openshift/imagebuilder v1.2.0
github.com/openshift/library-go v0.0.0-20210430084706-e555322cb708
github.com/openshift/source-to-image v1.3.1
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
golang.org/x/sys v0.0.0-20210324051608-47abb6519492
k8s.io/api v0.21.0
k8s.io/apimachinery v0.21.0
k8s.io/client-go v0.21.0
k8s.io/component-base v0.21.0
k8s.io/api v0.21.1
k8s.io/apimachinery v0.21.1
k8s.io/client-go v0.21.1
k8s.io/component-base v0.21.1
k8s.io/klog/v2 v2.8.0
k8s.io/kubectl v0.21.0
k8s.io/kubernetes v1.21.0
)

replace (
// temporary replacement for development purposes
github.com/containerd/containerd => github.com/containerd/containerd v1.5.0
github.com/docker/docker => github.com/openshift/moby-moby v1.4.2-0.20190308215630-da810a85109d
github.com/docker/libnetwork => github.com/docker/libnetwork v0.8.0-dev.2.0.20171107005402-dcf79f8c7fcb
Expand Down
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreydaley/api v0.0.0-20210503194902-7d6b95ffe991 h1:TM9/JNSPFqFJgv06JvkzMfvWz3qZyy7rY84t+ord4zM=
github.com/coreydaley/api v0.0.0-20210503194902-7d6b95ffe991/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/coreydaley/api v0.0.0-20210514120109-3d6c0b496499 h1:j5IaJwVLI2c9aGolUnie6I7UUyb+y0+Cu/ttG2lV3Ys=
github.com/coreydaley/api v0.0.0-20210514120109-3d6c0b496499/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/coreydaley/api v0.0.0-20210601202943-0831aff4bb03 h1:+fK4vDdtHXc9FQxGPUmwLNoIg4aAeb3wbBh2QcOX2/E=
github.com/coreydaley/api v0.0.0-20210601202943-0831aff4bb03/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/coreydaley/library-go v0.0.0-20210602171744-556e49f9ced8 h1:kwSAumkPM310ufdtQ1WZA8enYYxMyKKYdpZ4YL8SYok=
github.com/coreydaley/library-go v0.0.0-20210602171744-556e49f9ced8/go.mod h1:87ZYjEncF0YNUKNzncb8Fiw8yFNevpIWZW83C/etzpw=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
Expand Down Expand Up @@ -705,9 +713,15 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
github.com/openshift/api v0.0.0-20210331162552-3e31249e6a55/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360 h1:EGWKZ4foeELg9R+0OaLXKUoqHmtUwAMq0fCBUirbKwY=
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/openshift/api v0.0.0-20210521075222-e273a339932a/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/api v0.0.0-20210621103532-064fc2f78417 h1:l+ELGk0NBRPjdlvaNFgDnKA6wRvI8QwurVOQWTQNHlQ=
github.com/openshift/api v0.0.0-20210621103532-064fc2f78417/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/build-machinery-go v0.0.0-20210209125900-0da259a2c359/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/openshift/build-machinery-go v0.0.0-20210423112049-9415d7ebd33e/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/openshift/client-go v0.0.0-20210331195552-cf6c2669e01f h1:MAFVN4yW6pPSaTa1i+4Xp6FfVzZRFRETsnPfwz6VBXM=
github.com/openshift/client-go v0.0.0-20210331195552-cf6c2669e01f/go.mod h1:hHaRJ6vp2MRd/CpuZ1oJkqnMGy5eEnoAkQmKPZKcUPI=
github.com/openshift/client-go v0.0.0-20210521082421-73d9475a9142 h1:ZHRIMCFIJN1p9LsJt4HQ+akDrys4PrYnXzOWI5LK03I=
github.com/openshift/client-go v0.0.0-20210521082421-73d9475a9142/go.mod h1:fjS8r9mqDVsPb5td3NehsNOAWa4uiFkYEfVZioQ2gH0=
github.com/openshift/imagebuilder v1.2.0 h1:uoZFjJICLlTMjlAL/UG2PA2kM8RjAsVflGfHJK7MMDk=
github.com/openshift/imagebuilder v1.2.0/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/openshift/library-go v0.0.0-20210430084706-e555322cb708 h1:Xnx252xAZag9fk8IhWdgqkfVkF2c1jMIM5cq4/y8mmM=
Expand Down
14 changes: 4 additions & 10 deletions pkg/build/builder/cmd/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
restclient "k8s.io/client-go/rest"

buildapiv1 "github.com/openshift/api/build/v1"
buildutil "github.com/openshift/builder/pkg/build/builder/util"
buildscheme "github.com/openshift/client-go/build/clientset/versioned/scheme"
buildclientv1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1"
"github.com/openshift/library-go/pkg/git"
Expand Down Expand Up @@ -66,19 +67,12 @@ func newBuilderConfigFromEnvironment(out io.Writer, needsDocker bool) (*builderC

cfg.out = out

buildStr := os.Getenv("BUILD")

cfg.build = &buildapiv1.Build{}

obj, _, err := buildJSONCodec.Decode([]byte(buildStr), nil, cfg.build)
if err != nil {
return nil, fmt.Errorf("unable to parse build string: %v", err)
}
ok := false
cfg.build, ok = obj.(*buildapiv1.Build)
if !ok {
return nil, fmt.Errorf("build string %s is not a build: %#v", buildStr, obj)
if err := buildutil.GetBuildFromEnv(cfg.build); err != nil {
return nil, err
}

if log.Is(4) {
redactedBuild := builderutil.SafeForLoggingBuild(cfg.build)
bytes, err := runtime.Encode(buildJSONCodec, redactedBuild)
Expand Down
4 changes: 4 additions & 0 deletions pkg/build/builder/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ const (
secretBuildSourceBaseMountPath = "/var/run/secrets/openshift.io/build"
// BuildWorkDirMount is the working directory within the build pod, mounted as a volume.
buildWorkDirMount = "/tmp/build"
// buildVolumeMountPath is where user defined BuildVolumes get mounted
buildVolumeMountPath = "/var/run/openshift.io/volumes"
// buildVolumeSuffix is a suffix for BuildVolume names
buildVolumeSuffix = "user-build-volume"
)

var (
Expand Down
150 changes: 110 additions & 40 deletions pkg/build/builder/daemonless.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ import (
"github.com/pkg/errors"
"golang.org/x/sys/unix"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/pkg/credentialprovider"

buildapiv1 "github.com/openshift/api/build/v1"
buildscheme "github.com/openshift/client-go/build/clientset/versioned/scheme"
s2ifs "github.com/openshift/source-to-image/pkg/util/fs"

"github.com/openshift/builder/pkg/build/builder/cmd/dockercfg"
builderutil "github.com/openshift/builder/pkg/build/builder/util"
s2ifs "github.com/openshift/source-to-image/pkg/util/fs"
buildutil "github.com/openshift/builder/pkg/build/builder/util"
)

const (
Expand All @@ -45,15 +48,22 @@ const (

var (
nodeCredentialsFile = "/var/lib/kubelet/config.json"
buildScheme = runtime.NewScheme()
buildCodecFactory = serializer.NewCodecFactory(buildscheme.Scheme)
buildJSONCodec runtime.Codec
)

func init() {
buildJSONCodec = buildCodecFactory.LegacyCodec(buildapiv1.SchemeGroupVersion)
}

// The build controller doesn't expect the CAP_ prefix to be used in the
// entries in the list in the environment, but our runtime configuration
// expects it to be provided, so massage the values into a suitabe list.
func dropCapabilities() []string {
var dropCapabilities []string
if dropCaps, ok := os.LookupEnv(builderutil.DropCapabilities); ok && dropCaps != "" {
dropCapabilities = strings.Split(os.Getenv(builderutil.DropCapabilities), ",")
if dropCaps, ok := os.LookupEnv(buildutil.DropCapabilities); ok && dropCaps != "" {
dropCapabilities = strings.Split(os.Getenv(buildutil.DropCapabilities), ",")
for i := range dropCapabilities {
dropCapabilities[i] = strings.ToUpper(dropCapabilities[i])
if !strings.HasPrefix(dropCapabilities[i], "CAP_") {
Expand Down Expand Up @@ -272,7 +282,10 @@ func buildDaemonlessImage(sc types.SystemContext, store storage.Store, isolation
}
}

transientMounts := generateTransientMounts()
transientMounts, err := generateTransientMounts()
if err != nil {
return err
}

// Use a profile provided in the image instead of the default provided
// in runtime-tools's generator logic.
Expand Down Expand Up @@ -311,118 +324,175 @@ func buildDaemonlessImage(sc types.SystemContext, store storage.Store, isolation
PullPushRetryDelay: DefaultPushOrPullRetryDelay,
}

_, _, err := imagebuildah.BuildDockerfiles(opts.Context, store, options, opts.Dockerfile)
_, _, err = imagebuildah.BuildDockerfiles(opts.Context, store, options, opts.Dockerfile)
return err
}

func generateTransientMounts() []string {
mounts := []string{}
mounts = appendRHSMMount(defaultMountStart, mounts)
mounts = appendETCPKIMount(defaultMountStart, mounts)
mounts = appendRHRepoMount(defaultMountStart, mounts)
mounts = appendCATrustMount(mounts)
return mounts
// appendBuildVolumeMounts appends the Build Volume Mounts to the Transient Mounts Map
func appendBuildVolumeMounts(mountsMap *TransientMounts) error {
build := &buildapiv1.Build{}

if err := buildutil.GetBuildFromEnv(build); err != nil {
return err
}

var buildVolumes []buildapiv1.BuildVolume
switch {
case build.Spec.Strategy.Type == buildapiv1.SourceBuildStrategyType:
buildVolumes = append(buildVolumes, build.Spec.Strategy.SourceStrategy.Volumes...)
case build.Spec.Strategy.Type == buildapiv1.DockerBuildStrategyType:
buildVolumes = append(buildVolumes, build.Spec.Strategy.DockerStrategy.Volumes...)
}

for _, bv := range buildVolumes {
t := true
var sourcePath string
switch bv.Source.Type {

case buildapiv1.BuildVolumeSourceTypeSecret:
sourcePath = PathForBuildVolume(bv.Source.Secret.SecretName)
case buildapiv1.BuildVolumeSourceTypeConfigMap:
sourcePath = PathForBuildVolume(bv.Source.ConfigMap.Name)
}

for _, bvm := range bv.Mounts {

if err := mountsMap.append(TransientMount{
Destination: bvm.DestinationPath,
Source: sourcePath,
Options: TransientMountOptions{
ReadOnly: &t,
},
}); err != nil {
return err
}
}

}

return nil
}

func appendRHRepoMount(pathStart string, mounts []string) []string {
func appendRHRepoMount(pathStart string, mountsMap *TransientMounts) error {
path := filepath.Join(pathStart, repoFile)
st, err := os.Stat(path)
if err != nil {
// since the presence of the repo file is not a given, we won't log this a V(0)
log.V(4).Infof("Failed to stat %s, falling back to the Red Hat yum repository configuration in the build's base image. Error: %v", path, err)
return mounts
return nil
}
if !st.Mode().IsRegular() {
// if the file is there, but an unexpected type, then always have log show up via V(0)
log.V(0).Infof("Falling back to the Red Hat yum repository configuration in the build's base image: %s secrets location %s is a directory.", repoFile, path)
return mounts
return nil
}

// Add a bind of repo file, to pass along anything that the runtime mounted from the node
log.V(0).Infof("Adding transient rw bind mount for %s", path)
tmpDir, err := ioutil.TempDir("/tmp", repoFile+"-copy")
if err != nil {
log.V(0).Infof("Falling back to the Red Hat yum repository configuration in the base image: failed to create tmpdir for %s secret: %v", repoFile, err)
return mounts
return nil
}
fs := s2ifs.NewFileSystem()
err = fs.Copy(path, filepath.Join(tmpDir, repoFile), map[string]string{})
if err != nil {
log.V(0).Infof("Falling back to the Red Hat yum repository configuration in the base image: failed to copy %s secret: %v", repoFile, err)
return mounts
}
mounts = append(mounts, fmt.Sprintf("%s:/run/secrets/%s:rw,nodev,noexec,nosuid", filepath.Join(tmpDir, repoFile), repoFile))
return mounts
return nil
}
return mountsMap.append(TransientMount{
Source: filepath.Join(tmpDir, repoFile),
Destination: filepath.Join("/run/secrets", repoFile),
Options: TransientMountOptions{
NoDev: true,
NoExec: true,
NoSuid: true,
},
})
}

func coreAppendSecretLinksToDirs(pathStart, pathEnd string, mounts []string) []string {
func coreAppendSecretLinksToDirs(pathStart, pathEnd string, mountsMap *TransientMounts) error {
path := filepath.Join(pathStart, pathEnd)
st, err := os.Stat(path)
if err != nil {
// since the presence of dir secret is not a given, we won't log this a V(0)
log.V(4).Infof("Red Hat subscription content will not be available in this build: failed to stat directory %s: %v", path, err)
return mounts
return nil
}
if !st.IsDir() && (st.Mode()&os.ModeSymlink == 0) {
// if the file is there, but an unexpected type, then always have log show up via V(0)
log.V(0).Infof("Red Hat subscription content will not be available in this build: %s is not a directory", path)
return mounts
return nil
}

// Add a bind of dir secret, to pass along anything that the runtime mounted from the node
log.V(0).Infof("Adding transient rw bind mount for %s", path)
tmpDir, err := ioutil.TempDir("/tmp", pathEnd+"-copy")
if err != nil {
log.V(0).Infof("Red Hat subscription content will not be available in this build: failed to create tmpdir for %s secrets: %v", pathEnd, err)
return mounts
return nil
}
fs := s2ifs.NewFileSystem()
err = fs.CopyContents(path, tmpDir, map[string]string{})
if err != nil {
log.V(0).Infof("Red Hat subscription content will not be available in this build: failed to copy %s secrets: %v", pathEnd, err)
return mounts
return nil
}
mounts = append(mounts, fmt.Sprintf("%s:/run/secrets/%s:rw,nodev,noexec,nosuid", tmpDir, pathEnd))
return mounts

return mountsMap.append(TransientMount{
Destination: filepath.Join("/run/secrets", pathEnd),
Source: tmpDir,
Options: TransientMountOptions{
NoDev: true,
NoExec: true,
NoSuid: true,
},
})
}

func appendETCPKIMount(pathStart string, mounts []string) []string {
return coreAppendSecretLinksToDirs(pathStart, etcPkiEntitle, mounts)
func appendETCPKIMount(pathStart string, mountsMap *TransientMounts) error {
return coreAppendSecretLinksToDirs(pathStart, etcPkiEntitle, mountsMap)

}

func appendRHSMMount(pathStart string, mounts []string) []string {
return coreAppendSecretLinksToDirs(pathStart, subMgrCertDir, mounts)
func appendRHSMMount(pathStart string, mountsMap *TransientMounts) error {
return coreAppendSecretLinksToDirs(pathStart, subMgrCertDir, mountsMap)
}

func appendCATrustMount(mounts []string) []string {
func appendCATrustMount(mountsMap *TransientMounts) error {
mountCAEnv, exists := os.LookupEnv("BUILD_MOUNT_ETC_PKI_CATRUST")
if !exists {
return mounts
return nil
}

mountCA, err := strconv.ParseBool(mountCAEnv)
if err != nil {
log.V(0).Infof("custom PKI trust bundle will not be available in this build: failed to parse BUILD_MOUNT_ETC_PKI_CATRUST: %v", err)
return mounts
return nil
}
if !mountCA {
return mounts
return nil
}

st, err := os.Stat("/etc/pki/ca-trust")
if err != nil {
log.V(0).Infof("custom PKI trust bundle will not be available in this build: failed to stat /etc/pki/ca-trust: %v", err)
return mounts
return nil
}
if !st.IsDir() {
log.V(0).Infof("custom PKI trust bundle will not be available in this build: /etc/pki/ca-trust is not a directory")
return mounts
return nil
}

log.V(0).Infof("Adding transient ro bind mount for /etc/pki/ca-trust")
mounts = append(mounts, "/etc/pki/ca-trust:/etc/pki/ca-trust:ro")
return mounts
t := true
return mountsMap.append(TransientMount{
Destination: "/etc/pki/ca-trust",
Source: "/etc/pki/ca-trust",
Options: TransientMountOptions{
ReadOnly: &t,
},
})
}

func tagDaemonlessImage(sc types.SystemContext, store storage.Store, buildTag, pushTag string) error {
Expand Down