github.com/apptainer/singularity@v3.1.1+incompatible/cmd/internal/cli/action_flags.go (about)

     1  // Copyright (c) 2018, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package cli
     7  
     8  import (
     9  	"log"
    10  	"os"
    11  
    12  	"github.com/spf13/pflag"
    13  	"github.com/sylabs/singularity/internal/pkg/util/user"
    14  )
    15  
    16  // actionflags.go contains flag variables for action-like commands to draw from
    17  var (
    18  	AppName         string
    19  	BindPaths       []string
    20  	HomePath        string
    21  	OverlayPath     []string
    22  	ScratchPath     []string
    23  	WorkdirPath     string
    24  	PwdPath         string
    25  	ShellPath       string
    26  	Hostname        string
    27  	Network         string
    28  	NetworkArgs     []string
    29  	DNS             string
    30  	Security        []string
    31  	CgroupsPath     string
    32  	ContainLibsPath []string
    33  
    34  	IsBoot          bool
    35  	IsFakeroot      bool
    36  	IsCleanEnv      bool
    37  	IsContained     bool
    38  	IsContainAll    bool
    39  	IsWritable      bool
    40  	IsWritableTmpfs bool
    41  	Nvidia          bool
    42  	NoHome          bool
    43  	NoInit          bool
    44  	NoNvidia        bool
    45  
    46  	NetNamespace  bool
    47  	UtsNamespace  bool
    48  	UserNamespace bool
    49  	PidNamespace  bool
    50  	IpcNamespace  bool
    51  
    52  	AllowSUID bool
    53  	KeepPrivs bool
    54  	NoPrivs   bool
    55  	AddCaps   string
    56  	DropCaps  string
    57  )
    58  
    59  var actionFlags = pflag.NewFlagSet("ActionFlags", pflag.ExitOnError)
    60  
    61  func getHomeDir() string {
    62  	user, err := user.GetPwUID(uint32(os.Getuid()))
    63  	if err != nil {
    64  		log.Fatal(err)
    65  		return ""
    66  	}
    67  
    68  	return user.Dir
    69  }
    70  
    71  func init() {
    72  	initPathVars()
    73  	initBoolVars()
    74  	initNamespaceVars()
    75  	initPrivilegeVars()
    76  }
    77  
    78  // initPathVars initializes flags that take a string argument
    79  func initPathVars() {
    80  	// --app
    81  	actionFlags.StringVar(&AppName, "app", "", "set an application to run inside a container")
    82  	actionFlags.SetAnnotation("app", "envkey", []string{"APP", "APPNAME"})
    83  
    84  	// -B|--bind
    85  	actionFlags.StringSliceVarP(&BindPaths, "bind", "B", []string{}, "a user-bind path specification.  spec has the format src[:dest[:opts]], where src and dest are outside and inside paths.  If dest is not given, it is set equal to src.  Mount options ('opts') may be specified as 'ro' (read-only) or 'rw' (read/write, which is the default). Multiple bind paths can be given by a comma separated list.")
    86  	actionFlags.SetAnnotation("bind", "argtag", []string{"<spec>"})
    87  	actionFlags.SetAnnotation("bind", "envkey", []string{"BIND", "BINDPATH"})
    88  
    89  	// -H|--home
    90  	actionFlags.StringVarP(&HomePath, "home", "H", getHomeDir(), "a home directory specification.  spec can either be a src path or src:dest pair.  src is the source path of the home directory outside the container and dest overrides the home directory within the container.")
    91  	actionFlags.SetAnnotation("home", "argtag", []string{"<spec>"})
    92  	actionFlags.SetAnnotation("home", "envkey", []string{"HOME"})
    93  
    94  	// -o|--overlay
    95  	actionFlags.StringSliceVarP(&OverlayPath, "overlay", "o", []string{}, "use an overlayFS image for persistent data storage or as read-only layer of container")
    96  	actionFlags.SetAnnotation("overlay", "argtag", []string{"<path>"})
    97  	actionFlags.SetAnnotation("overlay", "envkey", []string{"OVERLAY", "OVERLAYIMAGE"})
    98  
    99  	// -S|--scratch
   100  	actionFlags.StringSliceVarP(&ScratchPath, "scratch", "S", []string{}, "include a scratch directory within the container that is linked to a temporary dir (use -W to force location)")
   101  	actionFlags.SetAnnotation("scratch", "argtag", []string{"<path>"})
   102  	actionFlags.SetAnnotation("scratch", "envkey", []string{"SCRATCH", "SCRATCHDIR"})
   103  
   104  	// -W|--workdir
   105  	actionFlags.StringVarP(&WorkdirPath, "workdir", "W", "", "working directory to be used for /tmp, /var/tmp and $HOME (if -c/--contain was also used)")
   106  	actionFlags.SetAnnotation("workdir", "argtag", []string{"<path>"})
   107  	actionFlags.SetAnnotation("workdir", "envkey", []string{"WORKDIR"})
   108  
   109  	// -s|--shell
   110  	actionFlags.StringVarP(&ShellPath, "shell", "s", "", "path to program to use for interactive shell")
   111  	actionFlags.SetAnnotation("shell", "argtag", []string{"<path>"})
   112  	actionFlags.SetAnnotation("shell", "envkey", []string{"SHELL"})
   113  
   114  	// --pwd
   115  	actionFlags.StringVar(&PwdPath, "pwd", "", "initial working directory for payload process inside the container")
   116  	actionFlags.SetAnnotation("pwd", "argtag", []string{"<path>"})
   117  	actionFlags.SetAnnotation("pwd", "envkey", []string{"PWD", "TARGET_PWD"})
   118  
   119  	// --hostname
   120  	actionFlags.StringVar(&Hostname, "hostname", "", "set container hostname")
   121  	actionFlags.SetAnnotation("hostname", "argtag", []string{"<name>"})
   122  	actionFlags.SetAnnotation("hostname", "envkey", []string{"HOSTNAME"})
   123  
   124  	// --network
   125  	actionFlags.StringVar(&Network, "network", "bridge", "specify desired network type separated by commas, each network will bring up a dedicated interface inside container")
   126  	actionFlags.SetAnnotation("network", "argtag", []string{"<name>"})
   127  	actionFlags.SetAnnotation("network", "envkey", []string{"NETWORK"})
   128  
   129  	// --network-args
   130  	actionFlags.StringSliceVar(&NetworkArgs, "network-args", []string{}, "specify network arguments to pass to CNI plugins")
   131  	actionFlags.SetAnnotation("network-args", "argtag", []string{"<name>"})
   132  	actionFlags.SetAnnotation("network-args", "envkey", []string{"NETWORK_ARGS"})
   133  
   134  	// --dns
   135  	actionFlags.StringVar(&DNS, "dns", "", "list of DNS server separated by commas to add in resolv.conf")
   136  	actionFlags.SetAnnotation("dns", "envkey", []string{"DNS"})
   137  
   138  	// --security
   139  	actionFlags.StringSliceVar(&Security, "security", []string{}, "enable security features (SELinux, Apparmor, Seccomp)")
   140  	actionFlags.SetAnnotation("security", "argtag", []string{""})
   141  	actionFlags.SetAnnotation("security", "envkey", []string{"SECURITY"})
   142  
   143  	// --apply-cgroups
   144  	actionFlags.StringVar(&CgroupsPath, "apply-cgroups", "", "apply cgroups from file for container processes (root only)")
   145  	actionFlags.SetAnnotation("apply-cgroups", "argtag", []string{"<path>"})
   146  	actionFlags.SetAnnotation("apply-cgroups", "envkey", []string{"APPLY_CGROUPS"})
   147  
   148  	// hidden flag to handle SINGULARITY_CONTAINLIBS environment variable
   149  	actionFlags.StringSliceVar(&ContainLibsPath, "containlibs", []string{}, "")
   150  	actionFlags.Lookup("containlibs").Hidden = true
   151  	actionFlags.SetAnnotation("containlibs", "envkey", []string{"CONTAINLIBS"})
   152  
   153  	// hidden flags to handle docker credentials
   154  	actionFlags.StringVar(&dockerUsername, "docker-username", "", "specify a username for docker authentication")
   155  	actionFlags.Lookup("docker-username").Hidden = true
   156  	actionFlags.SetAnnotation("docker-username", "envkey", []string{"DOCKER_USERNAME"})
   157  
   158  	actionFlags.StringVar(&dockerPassword, "docker-password", "", "specify a password for docker authentication")
   159  	actionFlags.Lookup("docker-password").Hidden = true
   160  	actionFlags.SetAnnotation("docker-password", "envkey", []string{"DOCKER_PASSWORD"})
   161  
   162  	// hidden flag to handle SINGULARITY_TMPDIR environment variable
   163  	actionFlags.StringVar(&tmpDir, "tmpdir", "", "specify a temporary directory to use for build")
   164  	actionFlags.Lookup("tmpdir").Hidden = true
   165  	actionFlags.SetAnnotation("tmpdir", "envkey", []string{"TMPDIR"})
   166  }
   167  
   168  // initBoolVars initializes flags that take a boolean argument
   169  func initBoolVars() {
   170  	// --boot
   171  	actionFlags.BoolVar(&IsBoot, "boot", false, "execute /sbin/init to boot container (root only)")
   172  	actionFlags.SetAnnotation("boot", "envkey", []string{"BOOT"})
   173  
   174  	// -f|--fakeroot
   175  	actionFlags.BoolVarP(&IsFakeroot, "fakeroot", "f", false, "run container in new user namespace as uid 0 (experimental)")
   176  	actionFlags.Lookup("fakeroot").Hidden = true
   177  	actionFlags.SetAnnotation("fakeroot", "envkey", []string{"FAKEROOT"})
   178  
   179  	// -e|--cleanenv
   180  	actionFlags.BoolVarP(&IsCleanEnv, "cleanenv", "e", false, "clean environment before running container")
   181  	actionFlags.SetAnnotation("cleanenv", "envkey", []string{"CLEANENV"})
   182  
   183  	// -c|--contain
   184  	actionFlags.BoolVarP(&IsContained, "contain", "c", false, "use minimal /dev and empty other directories (e.g. /tmp and $HOME) instead of sharing filesystems from your host")
   185  	actionFlags.SetAnnotation("contain", "envkey", []string{"CONTAIN"})
   186  
   187  	// -C|--containall
   188  	actionFlags.BoolVarP(&IsContainAll, "containall", "C", false, "contain not only file systems, but also PID, IPC, and environment")
   189  	actionFlags.SetAnnotation("containall", "envkey", []string{"CONTAINALL"})
   190  
   191  	// --nv
   192  	actionFlags.BoolVar(&Nvidia, "nv", false, "enable experimental Nvidia support")
   193  	actionFlags.SetAnnotation("nv", "envkey", []string{"NV"})
   194  
   195  	// -w|--writable
   196  	actionFlags.BoolVarP(&IsWritable, "writable", "w", false, "by default all Singularity containers are available as read only. This option makes the file system accessible as read/write.")
   197  	actionFlags.SetAnnotation("writable", "envkey", []string{"WRITABLE"})
   198  
   199  	// --writable-tmpfs
   200  	actionFlags.BoolVar(&IsWritableTmpfs, "writable-tmpfs", false, "makes the file system accessible as read-write with non persistent data (with overlay support only)")
   201  	actionFlags.SetAnnotation("writable-tmpfs", "envkey", []string{"WRITABLE_TMPFS"})
   202  
   203  	// --no-home
   204  	actionFlags.BoolVar(&NoHome, "no-home", false, "do NOT mount users home directory if home is not the current working directory")
   205  	actionFlags.SetAnnotation("no-home", "envkey", []string{"NO_HOME"})
   206  
   207  	// --no-init
   208  	actionFlags.BoolVar(&NoInit, "no-init", false, "do NOT start shim process with --pid")
   209  	actionFlags.SetAnnotation("no-init", "envkey", []string{"NO_INIT", "NOSHIMINIT"})
   210  
   211  	// --nohttps
   212  	actionFlags.BoolVar(&noHTTPS, "nohttps", false, "do NOT use HTTPS, for communicating with local docker registry")
   213  	actionFlags.SetAnnotation("nohttps", "envkey", []string{"NOHTTPS"})
   214  
   215  	// --docker-login
   216  	actionFlags.BoolVar(&dockerLogin, "docker-login", false, "interactive prompt for docker authentication")
   217  	actionFlags.SetAnnotation("docker-login", "envkey", []string{"DOCKER_LOGIN"})
   218  
   219  	// hidden flag to disable nvidia bindings when 'always use nv = yes'
   220  	actionFlags.BoolVar(&NoNvidia, "no-nv", false, "")
   221  	actionFlags.Lookup("no-nv").Hidden = true
   222  	actionFlags.SetAnnotation("no-nv", "envkey", []string{"NV_OFF", "NO_NV"})
   223  
   224  }
   225  
   226  // initNamespaceVars initializes flags that take toggle namespace support
   227  func initNamespaceVars() {
   228  	// -p|--pid
   229  	actionFlags.BoolVarP(&PidNamespace, "pid", "p", false, "run container in a new PID namespace")
   230  	actionFlags.SetAnnotation("pid", "envkey", []string{"PID", "UNSHARE_PID"})
   231  
   232  	// -i|--ipc
   233  	actionFlags.BoolVarP(&IpcNamespace, "ipc", "i", false, "run container in a new IPC namespace")
   234  	actionFlags.SetAnnotation("ipc", "envkey", []string{"IPC", "UNSHARE_IPC"})
   235  
   236  	// -n|--net
   237  	actionFlags.BoolVarP(&NetNamespace, "net", "n", false, "run container in a new network namespace (sets up a bridge network interface by default)")
   238  	actionFlags.SetAnnotation("net", "envkey", []string{"NET", "UNSHARE_NET"})
   239  
   240  	// --uts
   241  	actionFlags.BoolVar(&UtsNamespace, "uts", false, "run container in a new UTS namespace")
   242  	actionFlags.SetAnnotation("uts", "envkey", []string{"UTS", "UNSHARE_UTS"})
   243  
   244  	// -u|--userns
   245  	actionFlags.BoolVarP(&UserNamespace, "userns", "u", false, "run container in a new user namespace, allowing Singularity to run completely unprivileged on recent kernels. This disables some features of Singularity, for example it only works with sandbox images.")
   246  	actionFlags.SetAnnotation("userns", "envkey", []string{"USERNS", "UNSHARE_USERNS"})
   247  }
   248  
   249  // initPrivilegeVars initializes flags that manipulate privileges
   250  func initPrivilegeVars() {
   251  	// --keep-privs
   252  	actionFlags.BoolVar(&KeepPrivs, "keep-privs", false, "let root user keep privileges in container (root only)")
   253  	actionFlags.SetAnnotation("keep-privs", "envkey", []string{"KEEP_PRIVS"})
   254  
   255  	// --no-privs
   256  	actionFlags.BoolVar(&NoPrivs, "no-privs", false, "drop all privileges from root user in container")
   257  	actionFlags.SetAnnotation("no-privs", "envkey", []string{"NO_PRIVS"})
   258  
   259  	// --add-caps
   260  	actionFlags.StringVar(&AddCaps, "add-caps", "", "a comma separated capability list to add")
   261  	actionFlags.SetAnnotation("add-caps", "envkey", []string{"ADD_CAPS"})
   262  
   263  	// --drop-caps
   264  	actionFlags.StringVar(&DropCaps, "drop-caps", "", "a comma separated capability list to drop")
   265  	actionFlags.SetAnnotation("drop-caps", "envkey", []string{"DROP_CAPS"})
   266  
   267  	// --allow-setuid
   268  	actionFlags.BoolVar(&AllowSUID, "allow-setuid", false, "allow setuid binaries in container (root only)")
   269  	actionFlags.SetAnnotation("allow-setuid", "envkey", []string{"ALLOW_SETUID"})
   270  }