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

DEVPROD-8409: support host auth using env vars #8680

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion agent/globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const (
AWSSessionToken = "AWS_SESSION_TOKEN"
// AWSRoleExpiration is the expansion name for the expiration of a temporary AWS access key.
AWSRoleExpiration = "AWS_ROLE_EXPIRATION"
// HostSecret is the environment variable within the agent that is unique to its running host.
// HostSecret is the expansion name within the agent that is the host's unique secret.
HostSecret = "HOST_SECRET"
)

Expand Down
1 change: 1 addition & 0 deletions cloud/docker_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ func (c *dockerClientImpl) CreateContainer(ctx context.Context, parentHost, cont
// Build Evergreen agent command.
agentCmdParts = containerHost.AgentCommand(c.evergreenSettings, pathToExecutable)
containerHost.DockerOptions.Command = strings.Join(agentCmdParts, "\n")
containerHost.DockerOptions.EnvironmentVars = append(containerHost.DockerOptions.EnvironmentVars, containerHost.AgentEnvSlice()...)
}

// Populate container settings with command and new image.
Expand Down
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var (

// Agent version to control agent rollover. The format is the calendar date
// (YYYY-MM-DD).
AgentVersion = "2025-01-23"
AgentVersion = "2025-01-29"
)

const (
Expand Down
3 changes: 3 additions & 0 deletions globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ const (
AgentMonitorTag = "agent-monitor"
HostFetchTag = "host-fetch"

HostIDEnvVar = "HOST_ID"
HostSecretEnvVar = "HOST_SECRET"

DegradedLoggingPercent = 10

SetupScriptName = "setup.sh"
Expand Down
27 changes: 25 additions & 2 deletions model/host/hostutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,9 @@ func (h *Host) AgentCommand(settings *evergreen.Settings, executablePath string)
"agent",
fmt.Sprintf("--api_server=%s", settings.Api.URL),
"--mode=host",
// TODO (DEVPROD-8409): delete the host ID and secret from the CLI args
// once the agent monitor and agent on all static/dynamic hosts have
// rolled over to newer versions.
fmt.Sprintf("--host_id=%s", h.Id),
fmt.Sprintf("--host_secret=%s", h.Secret),
fmt.Sprintf("--provider=%s", h.Distro.Provider),
Expand All @@ -1029,6 +1032,25 @@ func (h *Host) AgentCommand(settings *evergreen.Settings, executablePath string)
}
}

// AgentEnv returns the environment variables required to start the agent.
func (h *Host) AgentEnv() map[string]string {
return map[string]string{
evergreen.HostIDEnvVar: h.Id,
evergreen.HostSecretEnvVar: h.Secret,
}
}

// AgentEnvSlice is the same as AgentEnv but returns the environment variables
// as a slice of key=value strings.
func (h *Host) AgentEnvSlice() []string {
env := h.AgentEnv()
var envSlice []string
for k, v := range env {
envSlice = append(envSlice, fmt.Sprintf("%s=%s", k, v))
}
return envSlice
}

// AgentMonitorOptions assembles the input to a Jasper request to start the
// agent monitor.
func (h *Host) AgentMonitorOptions(settings *evergreen.Settings) *options.Create {
Expand All @@ -1048,8 +1070,9 @@ func (h *Host) AgentMonitorOptions(settings *evergreen.Settings) *options.Create
)

return &options.Create{
Args: args,
Tags: []string{evergreen.AgentMonitorTag},
Args: args,
Environment: h.AgentEnv(),
Tags: []string{evergreen.AgentMonitorTag},
}
}

Expand Down
20 changes: 16 additions & 4 deletions operations/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ func Agent() cli.Command {
},
Flags: []cli.Flag{
cli.StringFlag{
Name: agentHostIDFlagName,
Usage: "the ID of the host the agent is running on (applies only to host mode)",
Name: agentHostIDFlagName,
Usage: "the ID of the host the agent is running on (applies only to host mode)",
EnvVar: evergreen.HostIDEnvVar,
},
cli.StringFlag{
Name: agentHostSecretFlagName,
Usage: "secret for the current host (applies only to host mode)",
Name: agentHostSecretFlagName,
Usage: "secret for the current host (applies only to host mode)",
EnvVar: evergreen.HostSecretEnvVar,
},
cli.StringFlag{
Name: podIDFlagName,
Expand Down Expand Up @@ -159,6 +161,16 @@ func Agent() cli.Command {
SendTaskLogsToGlobalSender: c.Bool(sendTaskLogsToGlobalSenderFlagName),
}

// Once the agent has retrieved the host ID and secret, unset those
// env vars to prevent them from being inherited by task
// subprocesses (e.g. shell.exec).
if err := os.Unsetenv(evergreen.HostIDEnvVar); err != nil {
return errors.Wrapf(err, "unsetting %s env var", evergreen.HostIDEnvVar)
}
if err := os.Unsetenv(evergreen.HostSecretEnvVar); err != nil {
return errors.Wrapf(err, "unsetting %s env var", evergreen.HostSecretEnvVar)
}

if err := os.MkdirAll(opts.WorkingDirectory, 0777); err != nil {
return errors.Wrapf(err, "creating working directory '%s'", opts.WorkingDirectory)
}
Expand Down
30 changes: 23 additions & 7 deletions operations/service_deploy_smoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func startLocalEvergreen() cli.Command {
return errors.Wrap(err, "getting working directory")
}
binary := filepath.Join(wd, "clients", runtime.GOOS+"_"+runtime.GOARCH, "evergreen")
if err := smokeRunBinary(exit, "web.service", wd, binary, "service", "web", "--db", "evergreen_local", "--testing-env"); err != nil {
if err := smokeRunBinary(exit, "web.service", wd, nil, binary, "service", "web", "--db", "evergreen_local", "--testing-env"); err != nil {
return errors.Wrap(err, "running web service")
}
<-exit
Expand Down Expand Up @@ -142,7 +142,7 @@ func smokeStartEvergreen() cli.Command {
exit := make(chan error, 3)

if startWeb {
if err := smokeRunBinary(exit, "web.service", wd, binary, "service", "web", "--testing-env", "--conf", confPath); err != nil {
if err := smokeRunBinary(exit, "web.service", wd, nil, binary, "service", "web", "--testing-env", "--conf", confPath); err != nil {
return errors.Wrap(err, "running web service")
}
}
Expand All @@ -153,13 +153,26 @@ func smokeStartEvergreen() cli.Command {
return errors.Wrap(err, "starting mock Cedar service")
}

var envVars []string
switch mode {
case string(globals.HostMode):
envVars = []string{
fmt.Sprintf("HOST_ID=%s", execModeID),
fmt.Sprintf("HOST_SECRET=%s", execModeSecret),
}
case string(globals.PodMode):
envVars = []string{
fmt.Sprintf("POD_ID=%s", execModeID),
fmt.Sprintf("POD_SECRET=%s", execModeSecret),
}
}

err := smokeRunBinary(exit, "agent",
wd,
envVars,
binary,
"agent",
fmt.Sprintf("--mode=%s", mode),
fmt.Sprintf("--%s_id=%s", mode, execModeID),
fmt.Sprintf("--%s_secret=%s", mode, execModeSecret),
"--api_server", apiServerURL,
"--log_output", string(globals.LogOutputFile),
"--log_prefix", "smoke.agent",
Expand Down Expand Up @@ -208,11 +221,13 @@ func smokeStartEvergreen() cli.Command {
exit,
"agent.monitor",
wd,
[]string{
fmt.Sprintf("HOST_ID=%s", execModeID),
fmt.Sprintf("HOST_SECRET=%s", execModeSecret),
},
binary,
"agent",
fmt.Sprintf("--mode=%s", globals.HostMode),
"--host_id", execModeID,
"--host_secret", execModeSecret,
"--api_server", apiServerURL,
"--log_output", string(globals.LogOutputFile),
"--global_task_logs",
Expand All @@ -239,9 +254,10 @@ func smokeStartEvergreen() cli.Command {
}
}

func smokeRunBinary(exit chan error, name, wd, bin string, cmdParts ...string) error {
func smokeRunBinary(exit chan error, name string, wd string, envVars []string, bin string, cmdParts ...string) error {
cmd := exec.Command(bin, cmdParts...)
cmd.Env = append(os.Environ(), fmt.Sprintf("EVGHOME=%s", wd))
cmd.Env = append(cmd.Env, envVars...)
cmdSender := send.NewWriterSender(send.MakeNative())
cmdSender.SetName(name)
cmd.Stdout = cmdSender
Expand Down
3 changes: 2 additions & 1 deletion units/provisioning_agent_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ func (j *agentDeployJob) startAgentOnRemote(ctx context.Context, settings *everg
ctx, cancel := context.WithTimeout(ctx, startAgentTimeout)
defer cancel()

startAgentCmd := fmt.Sprintf("nohup %s > /tmp/start 2>&1 &", remoteCmd)
agentEnvVars := strings.Join(j.host.AgentEnvSlice(), " ")
startAgentCmd := fmt.Sprintf("%s nohup %s > /tmp/start 2>&1 &", agentEnvVars, remoteCmd)
logs, err := j.host.RunSSHCommand(ctx, startAgentCmd)
if err != nil {
return logs, errors.Wrapf(err, "starting agent on host '%s'", j.host.Id)
Expand Down
Loading