Skip to content

Commit fe12a53

Browse files
Ben Howardopenshift-merge-robot
Ben Howard
authored andcommitted
entrypoint: be overly pendantic about envVars
To address concerns about potential debug trama, all envVars for command execution are now put to a []string. This ensures that some random Go routine won't change a variable. Signed-off-by: Ben Howard <[email protected]>
1 parent d90836d commit fe12a53

File tree

9 files changed

+85
-60
lines changed

9 files changed

+85
-60
lines changed

entrypoint/cmd/build.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ func runOCP(c *cobra.Command, args []string) {
4343
log.Info("Jobspec will apply to templated commands.")
4444
}
4545

46+
entryEnvVars = append(entryEnvVars, b.EnvVars...)
47+
4648
b.Exec(func(v []string) error {
4749
return runScripts(c, v)
4850
})

entrypoint/cmd/entry.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"io/ioutil"
1212
"os"
13+
"os/exec"
1314
"path/filepath"
1415
"text/template"
1516

@@ -33,6 +34,9 @@ var (
3334
spec rhjobspec.JobSpec
3435
specFile string
3536

37+
// entryEnvars are set for command execution
38+
entryEnvVars []string
39+
3640
// shellCmd is the default command to execute commands.
3741
shellCmd = []string{"/bin/bash", "-x"}
3842

@@ -79,6 +83,8 @@ func init() {
7983
}
8084
}
8185

86+
entryEnvVars = os.Environ()
87+
8288
log.SetOutput(os.Stdout)
8389
log.SetLevel(log.DebugLevel)
8490
newPath := fmt.Sprintf("%s:%s", cosaDir, os.Getenv("PATH"))
@@ -132,7 +138,10 @@ func runScripts(c *cobra.Command, args []string) error {
132138
log.Infof("Executing %d script(s)", len(rendered))
133139
for i, v := range rendered {
134140
log.WithFields(log.Fields{"script": i}).Info("Startig script")
135-
rc, err := ee.RunCmds(append(shellCmd, v.Name()))
141+
cArgs := append(shellCmd, v.Name())
142+
cmd := exec.Command(cArgs[0], cArgs[1:]...)
143+
cmd.Env = entryEnvVars
144+
rc, err := ee.RunCmds(cmd)
136145
if rc != 0 {
137146
return fmt.Errorf("Script exited with return code %d", rc)
138147
}
@@ -162,7 +171,9 @@ func runSingle(c *cobra.Command, args []string) {
162171
}
163172

164173
log.Infof("Executing commands: %v", args)
165-
rc, err := ee.RunCmds(args)
174+
cmd := exec.Command(args[0], args[1:]...)
175+
cmd.Env = entryEnvVars
176+
rc, err := ee.RunCmds(cmd)
166177
if rc != 0 || err != nil {
167178
log.WithFields(log.Fields{
168179
"return code": rc,

entrypoint/exec/run.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,22 @@ package exec
22

33
import (
44
"context"
5-
"os"
5+
"errors"
66
"os/exec"
77
"sync"
88
)
99

1010
// RunCmds runs args as a command and ensures that each
11-
func RunCmds(args []string) (int, error) {
12-
if len(args) <= 1 {
13-
os.Exit(0)
11+
func RunCmds(cmd *exec.Cmd) (int, error) {
12+
if cmd == nil {
13+
return 1, errors.New("No command to execute")
1414
}
15-
1615
ctx, cancel := context.WithCancel(context.Background())
1716
var wg sync.WaitGroup
1817
wg.Add(1)
1918
go RemoveZombies(ctx, &wg)
2019

2120
var rc int
22-
cmd := exec.Command(args[0], args[1:]...)
2321
err := Run(cmd)
2422
if err != nil {
2523
rc = 1

entrypoint/ocp/build_secrets.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
// copySecret is a hack. OpenShift presents secrets with 0400.
1919
// Since syscall.SetUid is blocked, we need to use sudo read the file.
20-
func copySecret(inDir, name, from string) error {
20+
func copySecret(inDir, name, from string, ret *[]string) error {
2121
sDir := filepath.Join(inDir, "secrets", name)
2222
if err := os.MkdirAll(sDir, 0755); err != nil {
2323
return err
@@ -53,8 +53,7 @@ func copySecret(inDir, name, from string) error {
5353
return fmt.Errorf("%s envVar should be in format 'K=V', not %s", e, ev)
5454
}
5555
if v[1] == baseName {
56-
os.Setenv(v[0], to)
57-
log.Debugf("Set envVar: %s=%s", v[0], to)
56+
*ret = append(*ret, fmt.Sprintf("%s=%s", v[0], to))
5857
}
5958
}
6059

@@ -65,13 +64,14 @@ func copySecret(inDir, name, from string) error {
6564
// able to read them. Secrets on 3.x clusters are mapped to 0400 and owned by root.
6665
// To allow the non-privilaged build user access, they need to be copied before
6766
// /usr/lib/coreos-assembler sudo's to the builder user.
68-
func buildSecretsSetup(contextDir string) error {
67+
func buildSecretsSetup(contextDir string) ([]string, error) {
68+
var ret []string
6969
if apiBuild.Spec.Source.Secrets == nil {
70-
return nil
70+
return ret, nil
7171
}
7272
secrets := apiBuild.Spec.Source.Secrets
7373
if len(secrets) == 0 {
74-
return nil
74+
return ret, nil
7575
}
7676

7777
log.Infof("Build has defined %d secrets.", len(secrets))
@@ -83,16 +83,16 @@ func buildSecretsSetup(contextDir string) error {
8383
fs, err := filepath.Glob(fmt.Sprintf("%s/%s/*/*", ocpSecretDir, s.Secret.Name))
8484
if err != nil {
8585
log.Errorf("Failed to get file listing: %v", err)
86-
return err
86+
return ret, err
8787
}
8888

8989
for _, f := range fs {
9090
log.Infof("Processing secret: %s at %s", s.Secret.Name, f)
91-
if err := copySecret(contextDir, s.Secret.Name, f); err != nil {
92-
return err
91+
if err := copySecret(contextDir, s.Secret.Name, f, &ret); err != nil {
92+
return ret, err
9393
}
9494
}
9595
}
9696

97-
return nil
97+
return ret, nil
9898
}

entrypoint/ocp/builder.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ type Builder struct {
4141
JobSpecFile string `envVar:"COSA_JOBSPEC_FILE"`
4242
CosaCmds string `envVar:"COSA_CMDS"`
4343

44+
// EnvVars is a listing of specific envVars to set
45+
EnvVars []string
46+
4447
// Internal copy of the JobSpec
4548
JobSpec *spec.JobSpec
4649
}
@@ -73,8 +76,13 @@ func NewBuilder() (*Builder, error) {
7376
if buildAPIErr != nil && buildAPIErr != ErrNoOCPBuildSpec {
7477
log.Errorf("Failed to initalized the OpenShift Build API Client: %v", buildAPIErr)
7578
return nil, buildAPIErr
79+
} else {
80+
v.EnvVars = append(
81+
os.Environ(),
82+
"COSA_SKIP_OVERLAY=skip",
83+
"FORCE_UNPRIVILEGED=1",
84+
)
7685
}
77-
7886
// Builder requires either a Build API Client or Kuberneres Cluster client.
7987
if k8sAPIErr != nil && buildAPIErr != nil {
8088
return nil, ErrInvalidOCPMode
@@ -95,15 +103,27 @@ func (o *Builder) PrepareEnv() error {
95103

96104
// Load secrets directly from the Kubernetes API that are
97105
// are "well-known" secrets.
98-
if err := kubernetesSecretsSetup(cosaSrvDir); err != nil {
106+
ks, err := kubernetesSecretsSetup(cosaSrvDir)
107+
if err != nil {
99108
log.Errorf("Failed to setup Service Account Secrets: %v", err)
109+
} else {
110+
log.Infof("Mapped %d secrets from Kubernetes", len(ks))
100111
}
101112

102113
// Read setup the secrets locally.
103-
if err := buildSecretsSetup(cosaSrvDir); err != nil {
114+
bs, err := buildSecretsSetup(cosaSrvDir)
115+
if err != nil {
104116
log.Errorf("Failed to setup OCP Build Secrets: %v", err)
117+
} else {
118+
log.Infof("Mapped %d secrets from Kubernetes", len(bs))
105119
}
106120

121+
preCount := len(o.EnvVars)
122+
o.EnvVars = append(o.EnvVars, bs...)
123+
o.EnvVars = append(o.EnvVars, ks...)
124+
addedCount := len(o.EnvVars) - preCount
125+
log.Infof("Added %d secret envVar mappings", addedCount)
126+
107127
// Extract any binary sources first. If a binary payload is delivered,
108128
// then blindly execute any script ending in .cosa.sh
109129
bin, err := extractInputBinary(cosaSrvDir)
@@ -121,7 +141,7 @@ func (o *Builder) PrepareEnv() error {
121141
// If there is no binary payload, then init COSA
122142
// With OCP its either binary _or_ source.
123143
if !bin {
124-
if err := cosaInit(); err != ErrNoSourceInput {
144+
if err := cosaInit(o.EnvVars); err != ErrNoSourceInput {
125145
return err
126146
}
127147
log.Info("No source input, relying solely on envVars...this won't end well.")

entrypoint/ocp/cosa_init.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ocp
33
import (
44
"errors"
55
"os"
6+
"os/exec"
67
"strings"
78

89
ee "github.com/coreos/entrypoint/exec"
@@ -13,7 +14,7 @@ import (
1314
// based builds first, check the API client, then check envVars. The use of envVars
1415
// in this case is *safe*; `SOURCE_{URI,REF} == apiBuild.Spec.Source.Git.{URI,REF}`. That
1516
// is, SOURCE_* envVars will always match the apiBuild.Spec.Source.Git.* values.
16-
func cosaInit() error {
17+
func cosaInit(envVars []string) error {
1718
var gitURI, gitRef string
1819
if apiBuild.Spec.Source.Git != nil {
1920
gitURI = apiBuild.Spec.Source.Git.URI
@@ -27,16 +28,18 @@ func cosaInit() error {
2728
return ErrNoSourceInput
2829
}
2930

30-
initCmd := []string{"cosa", "init"}
31+
args := []string{"init"}
3132
if gitRef != "" {
32-
initCmd = append(initCmd, "--force", "--branch", gitRef)
33+
args = append(args, "--force", "--branch", gitRef)
3334
}
34-
initCmd = append(initCmd, gitURI)
35-
log.Infof("running '%v'", strings.Join(initCmd, " "))
36-
rc, err := ee.RunCmds(initCmd)
35+
args = append(args, gitURI)
36+
log.Infof("running 'git %v'", strings.Join(args, " "))
37+
cmd := exec.Command("cosa", args...)
38+
cmd.Env = envVars
39+
rc, err := ee.RunCmds(cmd)
3740
if rc != 0 || err != nil {
3841
log.WithFields(log.Fields{
39-
"cmd": initCmd,
42+
"cmd": args,
4043
"return code": rc,
4144
"error": err,
4245
}).Error("Failed to checkout respository")

entrypoint/ocp/ocp.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ func ocpBuildClient() error {
5050
}
5151
log.Info("Host is running as an OpenShift custom strategy builder.")
5252

53-
// BuildConfigs do not use overlays. And when running in Buildconfig
54-
// mode, force running as unprivileged.
55-
os.Setenv("COSA_SKIP_OVERLAY", "skip")
56-
os.Setenv("FORCE_UNPRIVILEGED", "1")
57-
5853
// Check to make sure that we have a valid contextDir
5954
// Almost _always_ this should be in /srv for COSA.
6055
cDir := apiBuild.Spec.Source.ContextDir

entrypoint/ocp/sa_secrets.go

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ocp
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"os"
67
"path/filepath"
@@ -96,55 +97,52 @@ func getSecretMapping(s string) (*secretMap, bool) {
9697
return nil, false
9798
}
9899

99-
func (sm *secretMap) writeSecretEnvVars(d map[string][]byte) (int, error) {
100-
count := 0
100+
func (sm *secretMap) writeSecretEnvVars(d map[string][]byte, ret *[]string) error {
101101
for k, v := range d {
102102
envKey, ok := sm.envVarMap[k]
103103
if !ok {
104104
continue
105105
}
106106
log.Debugf("Set envVar %s from secret", envKey)
107-
os.Setenv(envKey, strings.TrimSuffix(string(v), "\n"))
108-
count++
107+
*ret = append(*ret, fmt.Sprintf("%s=%s", envKey, strings.TrimSuffix(string(v), "\n")))
109108
}
110-
return count, nil
109+
return nil
111110
}
112111

113-
func (sm *secretMap) writeSecretFiles(toDir, name string, d map[string][]byte) (int, error) {
112+
func (sm *secretMap) writeSecretFiles(toDir, name string, d map[string][]byte, ret *[]string) error {
114113
sDir := filepath.Join(toDir, name)
115114
if err := os.MkdirAll(sDir, 0755); err != nil {
116-
return 0, err
115+
return err
117116
}
118-
count := 0
119117
for k, v := range d {
120118
eKey, ok := sm.fileVarMap[k]
121119
if !ok {
122120
continue
123121
}
124122
f := filepath.Join(sDir, k)
125123
if err := ioutil.WriteFile(k, v, 0555); err != nil {
126-
return count, err
124+
return err
127125
}
128-
os.Setenv(eKey, f)
129-
log.Debugf("Set envVar %s to filepath %s", eKey, f)
130-
count++
126+
*ret = append(*ret, fmt.Sprintf("%s=%s", eKey, f))
131127
}
132-
return count, nil
128+
return nil
133129
}
134130

135131
// kubernetesSecretSetup looks for matching secrets in the environment matching
136132
// 'coreos-assembler.coreos.com/secret=k' and then maps the secret
137133
// automatically in. "k" must be in the "known" secrets type to be mapped
138134
// automatically.
139-
func kubernetesSecretsSetup(toDir string) error {
135+
func kubernetesSecretsSetup(toDir string) ([]string, error) {
140136
lo := metav1.ListOptions{
141137
LabelSelector: secretLabelName,
142138
Limit: 100,
143139
}
144140

141+
var ret []string
142+
145143
secrets, err := apiClient.Secrets(projectNamespace).List(lo)
146144
if err != nil {
147-
return err
145+
return ret, err
148146
}
149147
log.Infof("Found %d secrets to consider", len(secrets.Items))
150148

@@ -162,18 +160,14 @@ func kubernetesSecretsSetup(toDir string) error {
162160
}
163161
log.Infof("Known secret type for %s found, mapping automatically", v)
164162

165-
c, err := m.writeSecretEnvVars(secret.Data)
166-
if err != nil {
163+
if err := m.writeSecretEnvVars(secret.Data, &ret); err != nil {
167164
log.Errorf("Failed to set envVars for %s: %s", sName, err)
168165
}
169-
log.Infof("Set %d envVars from %s", c, sName)
170166

171-
c, err = m.writeSecretFiles(toDir, sName, secret.Data)
172-
if err != nil {
167+
if err := m.writeSecretFiles(toDir, sName, secret.Data, &ret); err != nil {
173168
log.Errorf("Failed to set files envVars for %s: %s", sName, err)
174169
}
175-
log.Infof("Set %d envVars to files from %s", c, sName)
176170
}
177171
}
178-
return nil
172+
return ret, nil
179173
}

entrypoint/spec/clone.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"io/ioutil"
66
"os"
7+
"os/exec"
78
"path/filepath"
89

910
ee "github.com/coreos/entrypoint/exec"
@@ -29,12 +30,13 @@ func cloneJobSpec(url, ref, specFile string) (*JobSpec, error) {
2930

3031
// Clone the JobSpec Repo
3132
jsD := filepath.Join(tmpd, "jobspec")
32-
gitCmd := []string{"git", "clone"}
33+
args := []string{"clone"}
3334
if ref != "" {
34-
gitCmd = append(gitCmd, "--branch", ref)
35+
args = append(args, "--branch", ref)
3536
}
36-
gitCmd = append(gitCmd, url, jsD)
37-
rc, err := ee.RunCmds(gitCmd)
37+
args = append(args, url, jsD)
38+
cmd := exec.Command("git", args...)
39+
rc, err := ee.RunCmds(cmd)
3840
if rc != 0 {
3941
if err == nil {
4042
err = errors.New("non-zero exit from command")

0 commit comments

Comments
 (0)