File: clean.go

package info (click to toggle)
singularity-container 4.0.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 21,672 kB
  • sloc: asm: 3,857; sh: 2,125; ansic: 1,677; awk: 414; makefile: 110; python: 99
file content (144 lines) | stat: -rw-r--r-- 4,397 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package env

import (
	"strings"

	"github.com/sylabs/singularity/v4/internal/pkg/runtime/engine/config/oci/generate"
	"github.com/sylabs/singularity/v4/pkg/sylog"
)

const (
	// DefaultPath defines default value for PATH environment variable.
	DefaultPath = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
	// SingularityPrefix defines the environment variable prefix SINGULARITY_.
	SingularityPrefix = "SINGULARITY_"
	// SingularityEnvPrefix defines the environment variable prefix SINGULARITYENV_.
	SingularityEnvPrefix = "SINGULARITYENV_"
)

// AlwaysPassKeys lists environment variables that are always passed from the host
// into the container.
var AlwaysPassKeys = map[string]struct{}{
	"TERM":        {},
	"http_proxy":  {},
	"HTTP_PROXY":  {},
	"https_proxy": {},
	"HTTPS_PROXY": {},
	"no_proxy":    {},
	"NO_PROXY":    {},
	"all_proxy":   {},
	"ALL_PROXY":   {},
	"ftp_proxy":   {},
	"FTP_PROXY":   {},
}

// AlwaysOmitKeys lists environment variables that are never passed from the host
// into the container, with a boolean to indicate whether the key can be overridden
// by a user-specificed SINGULARITYENV_ / --env / --env-file value.
var AlwaysOmitKeys = map[string]bool{
	"HOME":                false,
	"PATH":                false,
	"SINGULARITY_SHELL":   false,
	"SINGULARITY_APPNAME": false,
	"LD_LIBRARY_PATH":     true,
}

// SetContainerEnv cleans environment variables before running the container.
func SetContainerEnv(g *generate.Generator, hostEnvs []string, cleanEnv bool, homeDest string) map[string]string {
	singEnvKeys := make(map[string]string)

	// allow override with SINGULARITYENV_LANG
	if cleanEnv {
		g.AddProcessEnv("LANG", "C")
	}

	for _, env := range hostEnvs {
		e := strings.SplitN(env, "=", 2)
		if len(e) != 2 {
			sylog.Verbosef("Can't process environment variable %s", env)
			continue
		}
		if strings.HasPrefix(e[0], SingularityPrefix) {
			sylog.Verbosef("Not forwarding %s environment variable", e[0])
			continue
		} else if strings.HasPrefix(e[0], SingularityEnvPrefix) {
			key := e[0][len(SingularityEnvPrefix):]
			switch key {
			case "PREPEND_PATH":
				singEnvKeys["SING_USER_DEFINED_PREPEND_PATH"] = e[1]
			case "APPEND_PATH":
				singEnvKeys["SING_USER_DEFINED_APPEND_PATH"] = e[1]
			case "PATH":
				singEnvKeys["SING_USER_DEFINED_PATH"] = e[1]
			default:
				if key == "" {
					continue
				}
				if permitted, ok := AlwaysOmitKeys[key]; ok && !permitted {
					sylog.Warningf("Overriding %s environment variable with %s is not permitted", key, e[0])
					continue
				}
				sylog.Verbosef("Forwarding %s as %s environment variable", e[0], key)
				singEnvKeys[key] = e[1]
				g.RemoveProcessEnv(key)
			}
		} else {
			// SINGULARITYENV_ prefixed environment variables will take
			// precedence over the non prefixed variables
			if _, ok := singEnvKeys[e[0]]; ok {
				sylog.Verbosef("Skipping %[1]s environment variable, overridden by %[2]s%[1]s", e[0], SingularityEnvPrefix)
			} else if AddHostEnv(e[0], cleanEnv) {
				// transpose host env variables into config
				sylog.Debugf("Forwarding %s environment variable", e[0])
				g.AddProcessEnv(e[0], e[1])
			}
		}
	}

	sylog.Verbosef("Setting HOME=%s", homeDest)
	sylog.Verbosef("Setting PATH=%s", DefaultPath)
	g.AddProcessEnv("HOME", homeDest)
	g.AddProcessEnv("PATH", DefaultPath)

	return singEnvKeys
}

// AddHostEnv processes given key and returns if the environment
// variable should be added to the container or not.
func AddHostEnv(key string, cleanEnv bool) bool {
	if _, ok := AlwaysPassKeys[key]; ok {
		return true
	}
	if _, ok := AlwaysOmitKeys[key]; ok || cleanEnv {
		return false
	}
	return true
}

// HostEnvMap returns a map of host env vars to pass into the container.
func HostEnvMap(hostEnvs []string, cleanEnv bool) map[string]string {
	hostEnv := map[string]string{}

	for _, envVar := range hostEnvs {
		if strings.HasPrefix(envVar, SingularityEnvPrefix) {
			continue
		}
		parts := strings.SplitN(envVar, "=", 2)
		if len(parts) < 2 {
			continue
		}

		if !AddHostEnv(parts[0], cleanEnv) {
			continue
		}

		hostEnv[parts[0]] = parts[1]
	}

	return hostEnv
}