Move get{Bind,Tmpfs,Secret,SSH}Mount to run_common.go
Signed-off-by: Doug Rabson <dfr@rabson.org>
This commit is contained in:
		
							parent
							
								
									0832ea2f35
								
							
						
					
					
						commit
						57a73847e4
					
				
							
								
								
									
										265
									
								
								run_common.go
								
								
								
								
							
							
						
						
									
										265
									
								
								run_common.go
								
								
								
								
							|  | @ -26,6 +26,8 @@ import ( | |||
| 	"github.com/containers/buildah/bind" | ||||
| 	"github.com/containers/buildah/copier" | ||||
| 	"github.com/containers/buildah/define" | ||||
| 	"github.com/containers/buildah/internal" | ||||
| 	internalParse "github.com/containers/buildah/internal/parse" | ||||
| 	"github.com/containers/buildah/pkg/sshagent" | ||||
| 	"github.com/containers/buildah/util" | ||||
| 	"github.com/containers/common/libnetwork/etchosts" | ||||
|  | @ -34,6 +36,7 @@ import ( | |||
| 	nettypes "github.com/containers/common/libnetwork/types" | ||||
| 	"github.com/containers/common/pkg/config" | ||||
| 	"github.com/containers/common/pkg/subscriptions" | ||||
| 	imagetypes "github.com/containers/image/v5/types" | ||||
| 	"github.com/containers/storage" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	"github.com/containers/storage/pkg/ioutils" | ||||
|  | @ -1523,3 +1526,265 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap | |||
| 	} | ||||
| 	return finalMounts, artifacts, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getBindMount(tokens []string, context *imagetypes.SystemContext, contextDir string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	if contextDir == "" { | ||||
| 		return nil, "", errors.New("Context Directory for current run invocation is not configured") | ||||
| 	} | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, image, err := internalParse.GetBindMount(context, tokens, contextDir, b.store, b.MountLabel, stageMountPoints) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	return &volumes[0], image, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getTmpfsMount(tokens []string, idMaps IDMaps) (*spec.Mount, error) { | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, err := internalParse.GetTmpfsMount(tokens) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &volumes[0], nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secret, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	errInvalidSyntax := errors.New("secret should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 	if len(tokens) == 0 { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 0400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, "", errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	// Default location for secretis is /run/secrets/id
 | ||||
| 	if target == "" { | ||||
| 		target = "/run/secrets/" + id | ||||
| 	} | ||||
| 
 | ||||
| 	secr, ok := secrets[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, "", fmt.Errorf("secret required but no secret with id %s found", id) | ||||
| 		} | ||||
| 		return nil, "", nil | ||||
| 	} | ||||
| 	var data []byte | ||||
| 	var envFile string | ||||
| 	var ctrFileOnHost string | ||||
| 
 | ||||
| 	switch secr.SourceType { | ||||
| 	case "env": | ||||
| 		data = []byte(os.Getenv(secr.Source)) | ||||
| 		tmpFile, err := ioutil.TempFile("/dev/shm", "buildah*") | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		envFile = tmpFile.Name() | ||||
| 		ctrFileOnHost = tmpFile.Name() | ||||
| 	case "file": | ||||
| 		containerWorkingDir, err := b.store.ContainerDirectory(b.ContainerID) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		data, err = ioutil.ReadFile(secr.Source) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		ctrFileOnHost = filepath.Join(containerWorkingDir, "secrets", id) | ||||
| 	default: | ||||
| 		return nil, "", errors.New("invalid source secret type") | ||||
| 	} | ||||
| 
 | ||||
| 	// Copy secrets to container working dir (or tmp dir if it's an env), since we need to chmod,
 | ||||
| 	// chown and relabel it for the container user and we don't want to mess with the original file
 | ||||
| 	if err := os.MkdirAll(filepath.Dir(ctrFileOnHost), 0755); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := ioutil.WriteFile(ctrFileOnHost, data, 0644); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(ctrFileOnHost, b.MountLabel, false); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(idMaps.uidmap, idMaps.gidmap, uid, gid) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Lchown(ctrFileOnHost, int(hostUID), int(hostGID)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Chmod(ctrFileOnHost, os.FileMode(mode)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "bind", | ||||
| 		Source:      ctrFileOnHost, | ||||
| 		Options:     []string{"bind", "rprivate", "ro"}, | ||||
| 	} | ||||
| 	return &newMount, envFile, nil | ||||
| } | ||||
| 
 | ||||
| // getSSHMount parses the --mount type=ssh flag in the Containerfile, checks if there's an ssh source provided, and creates and starts an ssh-agent to be forwarded into the container
 | ||||
| func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string]*sshagent.Source, idMaps IDMaps) (*spec.Mount, *sshagent.AgentServer, error) { | ||||
| 	errInvalidSyntax := errors.New("ssh should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 
 | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		if len(kv) < 2 { | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		id = "default" | ||||
| 	} | ||||
| 	// Default location for secretis is /run/buildkit/ssh_agent.{i}
 | ||||
| 	if target == "" { | ||||
| 		target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", count) | ||||
| 	} | ||||
| 
 | ||||
| 	sshsource, ok := sshsources[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, nil, fmt.Errorf("ssh required but no ssh with id %s found", id) | ||||
| 		} | ||||
| 		return nil, nil, nil | ||||
| 	} | ||||
| 	// Create new agent from keys or socket
 | ||||
| 	fwdAgent, err := sshagent.NewAgentServer(sshsource) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	// Start ssh server, and get the host sock we're mounting in the container
 | ||||
| 	hostSock, err := fwdAgent.Serve(b.ProcessLabel) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(filepath.Dir(hostSock), b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := label.Relabel(hostSock, b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(idMaps.uidmap, idMaps.gidmap, uid, gid) | ||||
| 	if err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Lchown(hostSock, int(hostUID), int(hostGID)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Chmod(hostSock, os.FileMode(mode)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "bind", | ||||
| 		Source:      hostSock, | ||||
| 		Options:     []string{"bind", "rprivate", "ro"}, | ||||
| 	} | ||||
| 	return &newMount, fwdAgent, nil | ||||
| } | ||||
|  |  | |||
							
								
								
									
										267
									
								
								run_freebsd.go
								
								
								
								
							
							
						
						
									
										267
									
								
								run_freebsd.go
								
								
								
								
							|  | @ -9,7 +9,6 @@ import ( | |||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | @ -19,11 +18,9 @@ import ( | |||
| 	"github.com/containers/buildah/copier" | ||||
| 	"github.com/containers/buildah/define" | ||||
| 	"github.com/containers/buildah/internal" | ||||
| 	internalParse "github.com/containers/buildah/internal/parse" | ||||
| 	internalUtil "github.com/containers/buildah/internal/util" | ||||
| 	"github.com/containers/buildah/pkg/jail" | ||||
| 	"github.com/containers/buildah/pkg/overlay" | ||||
| 	"github.com/containers/buildah/pkg/sshagent" | ||||
| 	"github.com/containers/buildah/util" | ||||
| 	"github.com/containers/common/libnetwork/resolvconf" | ||||
| 	nettypes "github.com/containers/common/libnetwork/types" | ||||
|  | @ -37,7 +34,6 @@ import ( | |||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	spec "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/opencontainers/runtime-tools/generate" | ||||
| 	"github.com/opencontainers/selinux/go-selinux/label" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | @ -320,269 +316,6 @@ func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]int | |||
| 	return nil, nil, errors.New("cache mounts not supported on freebsd") | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secret, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	errInvalidSyntax := errors.New("secret should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 	if len(tokens) == 0 { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 0400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, "", errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	// Default location for secretis is /run/secrets/id
 | ||||
| 	if target == "" { | ||||
| 		target = "/run/secrets/" + id | ||||
| 	} | ||||
| 
 | ||||
| 	secr, ok := secrets[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, "", errors.Errorf("secret required but no secret with id %s found", id) | ||||
| 		} | ||||
| 		return nil, "", nil | ||||
| 	} | ||||
| 	var data []byte | ||||
| 	var envFile string | ||||
| 	var ctrFileOnHost string | ||||
| 
 | ||||
| 	switch secr.SourceType { | ||||
| 	case "env": | ||||
| 		data = []byte(os.Getenv(secr.Source)) | ||||
| 		tmpFile, err := ioutil.TempFile("/var/tmp", "buildah*") | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		envFile = tmpFile.Name() | ||||
| 		ctrFileOnHost = tmpFile.Name() | ||||
| 	case "file": | ||||
| 		containerWorkingDir, err := b.store.ContainerDirectory(b.ContainerID) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		data, err = ioutil.ReadFile(secr.Source) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		ctrFileOnHost = filepath.Join(containerWorkingDir, "secrets", id) | ||||
| 	default: | ||||
| 		return nil, "", errors.New("invalid source secret type") | ||||
| 	} | ||||
| 
 | ||||
| 	// Copy secrets to container working dir (or tmp dir if it's an env), since we need to chmod,
 | ||||
| 	// chown and relabel it for the container user and we don't want to mess with the original file
 | ||||
| 	if err := os.MkdirAll(filepath.Dir(ctrFileOnHost), 0755); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := ioutil.WriteFile(ctrFileOnHost, data, 0644); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(ctrFileOnHost, b.MountLabel, false); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(nil, nil, uid, gid) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Lchown(ctrFileOnHost, int(hostUID), int(hostGID)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Chmod(ctrFileOnHost, os.FileMode(mode)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "nullfs", | ||||
| 		Source:      ctrFileOnHost, | ||||
| 		Options:     []string{"ro"}, | ||||
| 	} | ||||
| 	return &newMount, envFile, nil | ||||
| } | ||||
| 
 | ||||
| // getSSHMount parses the --mount type=ssh flag in the Containerfile, checks if there's an ssh source provided, and creates and starts an ssh-agent to be forwarded into the container
 | ||||
| func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string]*sshagent.Source, idMaps IDMaps) (*spec.Mount, *sshagent.AgentServer, error) { | ||||
| 	errInvalidSyntax := errors.New("ssh should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 
 | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		if len(kv) < 2 { | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		id = "default" | ||||
| 	} | ||||
| 	// Default location for secretis is /run/buildkit/ssh_agent.{i}
 | ||||
| 	if target == "" { | ||||
| 		target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", count) | ||||
| 	} | ||||
| 
 | ||||
| 	sshsource, ok := sshsources[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, nil, errors.Errorf("ssh required but no ssh with id %s found", id) | ||||
| 		} | ||||
| 		return nil, nil, nil | ||||
| 	} | ||||
| 	// Create new agent from keys or socket
 | ||||
| 	fwdAgent, err := sshagent.NewAgentServer(sshsource) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	// Start ssh server, and get the host sock we're mounting in the container
 | ||||
| 	hostSock, err := fwdAgent.Serve(b.ProcessLabel) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(filepath.Dir(hostSock), b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := label.Relabel(hostSock, b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(nil, nil, uid, gid) | ||||
| 	if err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Lchown(hostSock, int(hostUID), int(hostGID)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Chmod(hostSock, os.FileMode(mode)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "nullfs", | ||||
| 		Source:      hostSock, | ||||
| 		Options:     []string{"ro"}, | ||||
| 	} | ||||
| 	return &newMount, fwdAgent, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getBindMount(tokens []string, context *imagetypes.SystemContext, contextDir string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	if contextDir == "" { | ||||
| 		return nil, "", errors.New("Context Directory for current run invocation is not configured") | ||||
| 	} | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, image, err := internalParse.GetBindMount(context, tokens, contextDir, b.store, b.MountLabel, stageMountPoints) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	return &volumes[0], image, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getTmpfsMount(tokens []string, idMaps IDMaps) (*spec.Mount, error) { | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, err := internalParse.GetTmpfsMount(tokens) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &volumes[0], nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) cleanupTempVolumes() { | ||||
| 	for tempVolume, val := range b.TempVolumes { | ||||
| 		if val { | ||||
|  |  | |||
							
								
								
									
										263
									
								
								run_linux.go
								
								
								
								
							
							
						
						
									
										263
									
								
								run_linux.go
								
								
								
								
							|  | @ -25,7 +25,6 @@ import ( | |||
| 	internalUtil "github.com/containers/buildah/internal/util" | ||||
| 	"github.com/containers/buildah/pkg/overlay" | ||||
| 	"github.com/containers/buildah/pkg/parse" | ||||
| 	"github.com/containers/buildah/pkg/sshagent" | ||||
| 	"github.com/containers/buildah/util" | ||||
| 	"github.com/containers/common/libnetwork/resolvconf" | ||||
| 	nettypes "github.com/containers/common/libnetwork/types" | ||||
|  | @ -1176,37 +1175,6 @@ func checkIdsGreaterThan5(ids []spec.LinuxIDMapping) bool { | |||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getBindMount(tokens []string, context *imagetypes.SystemContext, contextDir string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	if contextDir == "" { | ||||
| 		return nil, "", errors.New("Context Directory for current run invocation is not configured") | ||||
| 	} | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, image, err := internalParse.GetBindMount(context, tokens, contextDir, b.store, b.MountLabel, stageMountPoints) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, image, err | ||||
| 	} | ||||
| 	return &volumes[0], image, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getTmpfsMount(tokens []string, idMaps IDMaps) (*spec.Mount, error) { | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, err := internalParse.GetTmpfsMount(tokens) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	optionMounts = append(optionMounts, mount) | ||||
| 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &volumes[0], nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, []string, error) { | ||||
| 	var optionMounts []specs.Mount | ||||
| 	mount, lockedTargets, err := internalParse.GetCacheMount(tokens, b.store, b.MountLabel, stageMountPoints) | ||||
|  | @ -1221,237 +1189,6 @@ func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]int | |||
| 	return &volumes[0], lockedTargets, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secret, idMaps IDMaps) (*spec.Mount, string, error) { | ||||
| 	errInvalidSyntax := errors.New("secret should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 	if len(tokens) == 0 { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 0400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, "", errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, "", errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		return nil, "", errInvalidSyntax | ||||
| 	} | ||||
| 	// Default location for secretis is /run/secrets/id
 | ||||
| 	if target == "" { | ||||
| 		target = "/run/secrets/" + id | ||||
| 	} | ||||
| 
 | ||||
| 	secr, ok := secrets[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, "", fmt.Errorf("secret required but no secret with id %s found", id) | ||||
| 		} | ||||
| 		return nil, "", nil | ||||
| 	} | ||||
| 	var data []byte | ||||
| 	var envFile string | ||||
| 	var ctrFileOnHost string | ||||
| 
 | ||||
| 	switch secr.SourceType { | ||||
| 	case "env": | ||||
| 		data = []byte(os.Getenv(secr.Source)) | ||||
| 		tmpFile, err := ioutil.TempFile("/dev/shm", "buildah*") | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		envFile = tmpFile.Name() | ||||
| 		ctrFileOnHost = tmpFile.Name() | ||||
| 	case "file": | ||||
| 		containerWorkingDir, err := b.store.ContainerDirectory(b.ContainerID) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		data, err = ioutil.ReadFile(secr.Source) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		ctrFileOnHost = filepath.Join(containerWorkingDir, "secrets", id) | ||||
| 	default: | ||||
| 		return nil, "", errors.New("invalid source secret type") | ||||
| 	} | ||||
| 
 | ||||
| 	// Copy secrets to container working dir (or tmp dir if it's an env), since we need to chmod,
 | ||||
| 	// chown and relabel it for the container user and we don't want to mess with the original file
 | ||||
| 	if err := os.MkdirAll(filepath.Dir(ctrFileOnHost), 0755); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := ioutil.WriteFile(ctrFileOnHost, data, 0644); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(ctrFileOnHost, b.MountLabel, false); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(idMaps.uidmap, idMaps.gidmap, uid, gid) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Lchown(ctrFileOnHost, int(hostUID), int(hostGID)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := os.Chmod(ctrFileOnHost, os.FileMode(mode)); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "bind", | ||||
| 		Source:      ctrFileOnHost, | ||||
| 		Options:     []string{"bind", "rprivate", "ro"}, | ||||
| 	} | ||||
| 	return &newMount, envFile, nil | ||||
| } | ||||
| 
 | ||||
| // getSSHMount parses the --mount type=ssh flag in the Containerfile, checks if there's an ssh source provided, and creates and starts an ssh-agent to be forwarded into the container
 | ||||
| func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string]*sshagent.Source, idMaps IDMaps) (*spec.Mount, *sshagent.AgentServer, error) { | ||||
| 	errInvalidSyntax := errors.New("ssh should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint") | ||||
| 
 | ||||
| 	var err error | ||||
| 	var id, target string | ||||
| 	var required bool | ||||
| 	var uid, gid uint32 | ||||
| 	var mode uint32 = 400 | ||||
| 	for _, val := range tokens { | ||||
| 		kv := strings.SplitN(val, "=", 2) | ||||
| 		if len(kv) < 2 { | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 		switch kv[0] { | ||||
| 		case "id": | ||||
| 			id = kv[1] | ||||
| 		case "target", "dst", "destination": | ||||
| 			target = kv[1] | ||||
| 		case "required": | ||||
| 			required, err = strconv.ParseBool(kv[1]) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 		case "mode": | ||||
| 			mode64, err := strconv.ParseUint(kv[1], 8, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			mode = uint32(mode64) | ||||
| 		case "uid": | ||||
| 			uid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			uid = uint32(uid64) | ||||
| 		case "gid": | ||||
| 			gid64, err := strconv.ParseUint(kv[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, errInvalidSyntax | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		default: | ||||
| 			return nil, nil, errInvalidSyntax | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if id == "" { | ||||
| 		id = "default" | ||||
| 	} | ||||
| 	// Default location for secretis is /run/buildkit/ssh_agent.{i}
 | ||||
| 	if target == "" { | ||||
| 		target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", count) | ||||
| 	} | ||||
| 
 | ||||
| 	sshsource, ok := sshsources[id] | ||||
| 	if !ok { | ||||
| 		if required { | ||||
| 			return nil, nil, fmt.Errorf("ssh required but no ssh with id %s found", id) | ||||
| 		} | ||||
| 		return nil, nil, nil | ||||
| 	} | ||||
| 	// Create new agent from keys or socket
 | ||||
| 	fwdAgent, err := sshagent.NewAgentServer(sshsource) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	// Start ssh server, and get the host sock we're mounting in the container
 | ||||
| 	hostSock, err := fwdAgent.Serve(b.ProcessLabel) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := label.Relabel(filepath.Dir(hostSock), b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := label.Relabel(hostSock, b.MountLabel, false); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	hostUID, hostGID, err := util.GetHostIDs(idMaps.uidmap, idMaps.gidmap, uid, gid) | ||||
| 	if err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Lchown(hostSock, int(hostUID), int(hostGID)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if err := os.Chmod(hostSock, os.FileMode(mode)); err != nil { | ||||
| 		if shutdownErr := fwdAgent.Shutdown(); shutdownErr != nil { | ||||
| 			b.Logger.Errorf("error shutting down agent: %v", shutdownErr) | ||||
| 		} | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	newMount := specs.Mount{ | ||||
| 		Destination: target, | ||||
| 		Type:        "bind", | ||||
| 		Source:      hostSock, | ||||
| 		Options:     []string{"bind", "rprivate", "ro"}, | ||||
| 	} | ||||
| 	return &newMount, fwdAgent, nil | ||||
| } | ||||
| 
 | ||||
| // cleanupRunMounts cleans up run mounts so they only appear in this run.
 | ||||
| func (b *Builder) cleanupRunMounts(context *imagetypes.SystemContext, mountpoint string, artifacts *runMountArtifacts) error { | ||||
| 	for _, agent := range artifacts.Agents { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue