-
Notifications
You must be signed in to change notification settings - Fork 612
/
manager_init_task_linux.go
197 lines (169 loc) · 7 KB
/
manager_init_task_linux.go
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//go:build linux
// +build linux
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package execcmd
import (
"fmt"
"path/filepath"
"strings"
dockercontainer "github.com/docker/docker/api/types/container"
)
const (
ecsAgentExecDepsDir = "/managed-agents/execute-command"
// ecsAgentDepsBinDir is the directory where ECS Agent will read versions of SSM agent
ecsAgentDepsBinDir = ecsAgentExecDepsDir + "/bin"
ecsAgentDepsCertsDir = ecsAgentExecDepsDir + "/certs"
ContainerDepsDirPrefix = "/ecs-execute-command-"
SSMAgentBinName = "amazon-ssm-agent"
SSMAgentWorkerBinName = "ssm-agent-worker"
SessionWorkerBinName = "ssm-session-worker"
HostLogDir = "/var/log/ecs/exec"
ContainerLogDir = "/var/log/amazon/ssm"
ECSAgentExecLogDir = "/log/exec"
HostCertFile = "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem"
ContainerCertFileSuffix = "certs/amazon-ssm-agent.crt"
ContainerConfigFileSuffix = "configuration/" + containerConfigFileName
// ECSAgentExecConfigDir is the directory where ECS Agent will write the ExecAgent config files to
ECSAgentExecConfigDir = ecsAgentExecDepsDir + "/" + ContainerConfigDirName
// HostExecConfigDir is the dir where ExecAgents Config files will live
HostExecConfigDir = hostExecDepsDir + "/" + ContainerConfigDirName
ContainerLogConfigFile = "configuration/" + ExecAgentLogConfigFileName
)
var (
execAgentLogConfigTemplate = `<seelog type="adaptive" mininterval="2000000"
maxinterval="100000000" critmsgcount="500" minlevel="info">
<exceptions>
<exception filepattern="test*" minlevel="error"/>
</exceptions>
<outputs formatid="fmtinfo">
<console formatid="fmtinfo"/>
<rollingfile type="size"
filename="/var/log/amazon/ssm/amazon-ssm-agent.log"
maxsize="40000000" maxrolls="1"/>
<filter levels="error,critical" formatid="fmterror">
<rollingfile type="size"
filename="/var/log/amazon/ssm/errors.log"
maxsize="10000000" maxrolls="1"/>
</filter>
</outputs>
<formats>
<format id="fmterror" format="%Date %Time %LEVEL [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="fmtdebug" format="%Date %Time %LEVEL [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="fmtinfo" format="%Date %Time %LEVEL %Msg%n"/>
</formats>
</seelog>`
// TODO: [ecs-exec] seelog config needs to be implemented following a similar approach to ss, config
execAgentConfigFileNameTemplate = `amazon-ssm-agent-%s.json`
logConfigFileNameTemplate = `seelog-%s.xml`
)
var GetExecAgentLogConfigFile = getAgentLogConfigFile
func getAgentLogConfigFile() (string, error) {
hash := getExecAgentConfigHash(execAgentLogConfigTemplate)
logConfigFileName := fmt.Sprintf(logConfigFileNameTemplate, hash)
// check if config file exists already
logConfigFilePath := filepath.Join(ECSAgentExecConfigDir, logConfigFileName)
if fileExists(logConfigFilePath) && validConfigExists(logConfigFilePath, hash) {
return logConfigFileName, nil
}
// check if config file is a dir; if true, remove it
if isDir(logConfigFilePath) {
if err := removeAll(logConfigFilePath); err != nil {
return "", err
}
}
// create new seelog config file
if err := createNewExecAgentConfigFile(execAgentLogConfigTemplate, logConfigFilePath); err != nil {
return "", err
}
return logConfigFileName, nil
}
func validConfigExists(configFilePath, expectedHash string) bool {
config, err := getFileContent(configFilePath)
if err != nil {
return false
}
hash := getExecAgentConfigHash(string(config))
return strings.Compare(expectedHash, hash) == 0
}
var GetExecAgentConfigFileName = getAgentConfigFileName
func getAgentConfigFileName(sessionLimit int) (string, error) {
config := fmt.Sprintf(execAgentConfigTemplate, sessionLimit)
hash := getExecAgentConfigHash(config)
configFileName := fmt.Sprintf(execAgentConfigFileNameTemplate, hash)
// check if config file exists already
configFilePath := filepath.Join(ECSAgentExecConfigDir, configFileName)
if fileExists(configFilePath) && validConfigExists(configFilePath, hash) {
return configFileName, nil
}
// check if config file is a dir; if true, remove it
if isDir(configFilePath) {
if err := removeAll(configFilePath); err != nil {
return "", err
}
}
// config doesn't exist; create a new one
if err := createNewExecAgentConfigFile(config, configFilePath); err != nil {
return "", err
}
return configFileName, nil
}
func certsExist() bool {
return fileExists(filepath.Join(ecsAgentDepsCertsDir, "tls-ca-bundle.pem"))
}
// This function creates any necessary config directories/files and ensures that
// the ssm-agent binaries, configs, logs, and plugin is bind mounted
func addRequiredBindMounts(taskId, cn, latestBinVersionDir, uuid string, sessionWorkersLimit int, hostConfig *dockercontainer.HostConfig) error {
configFile, rErr := GetExecAgentConfigFileName(sessionWorkersLimit)
if rErr != nil {
rErr = fmt.Errorf("could not generate ExecAgent Config File: %v", rErr)
return rErr
}
logConfigFile, rErr := GetExecAgentLogConfigFile()
if rErr != nil {
rErr = fmt.Errorf("could not generate ExecAgent LogConfig file: %v", rErr)
return rErr
}
containerDepsFolder := ContainerDepsDirPrefix + uuid
if !certsExist() {
rErr = fmt.Errorf("could not find certs")
return rErr
}
// Add ssm binary mounts
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
filepath.Join(latestBinVersionDir, SSMAgentBinName),
filepath.Join(containerDepsFolder, SSMAgentBinName)))
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
filepath.Join(latestBinVersionDir, SSMAgentWorkerBinName),
filepath.Join(containerDepsFolder, SSMAgentWorkerBinName)))
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
filepath.Join(latestBinVersionDir, SessionWorkerBinName),
filepath.Join(containerDepsFolder, SessionWorkerBinName)))
// Add exec agent config file mount
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
filepath.Join(HostExecConfigDir, configFile),
filepath.Join(containerDepsFolder, ContainerConfigFileSuffix)))
// Add exec agent log config file mount
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
filepath.Join(HostExecConfigDir, logConfigFile),
filepath.Join(containerDepsFolder, ContainerLogConfigFile)))
// Append TLS cert mount
hostConfig.Binds = append(hostConfig.Binds, getReadOnlyBindMountMapping(
HostCertFile,
filepath.Join(containerDepsFolder, ContainerCertFileSuffix)))
// Add ssm log bind mount
hostConfig.Binds = append(hostConfig.Binds, getBindMountMapping(
filepath.Join(HostLogDir, taskId, cn),
ContainerLogDir))
return nil
}