Skip to content

Commit cf49171

Browse files
committed
awsvpc: configure local routes with env var
1 parent cb1c9ff commit cf49171

File tree

5 files changed

+87
-14
lines changed

5 files changed

+87
-14
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,10 @@ configure them as something other than the defaults.
175175
| `ECS_IMAGE_MINIMUM_CLEANUP_AGE` | 30m | The minimum time interval between when an image is pulled and when it can be considered for automated image cleanup. | 1h | 1h |
176176
| `ECS_NUM_IMAGES_DELETE_PER_CYCLE` | 5 | The maximum number of images to delete in a single automated image cleanup cycle. If set to less than 1, the value is ignored. | 5 | 5 |
177177
| `ECS_INSTANCE_ATTRIBUTES` | `{"stack": "prod"}` | These attributes take effect only during initial registration. After the agent has joined an ECS cluster, use the PutAttributes API action to add additional attributes. For more information, see [Amazon ECS Container Agent Configuration](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-config.html) in the Amazon ECS Developer Guide.| `{}` | `{}` |
178-
| `ECS_ENABLE_TASK_ENI` | `false` | Whether to enable task networking for task to be launched with its own network interface | `false` | `false` |
179-
| `ECS_CNI_PLUGINS_PATH` | `/ecs/cni` | The path where the cni binary file is located | `/amazon-ecs-cni-plugins` | `/amazon-ecs-cni-plugins` |
180-
| `ECS_AWSVPC_BLOCK_IMDS` | `true` | Whether to block access to [Instance Metdata](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for Tasks started with `awsvpc` network mode | `false` | `false`|
178+
| `ECS_ENABLE_TASK_ENI` | `false` | Whether to enable task networking for task to be launched with its own network interface | `false` | Not applicable |
179+
| `ECS_CNI_PLUGINS_PATH` | `/ecs/cni` | The path where the cni binary file is located | `/amazon-ecs-cni-plugins` | Not applicable |
180+
| `ECS_AWSVPC_BLOCK_IMDS` | `true` | Whether to block access to [Instance Metdata](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for Tasks started with `awsvpc` network mode | `false` | Not applicable |
181+
| `ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES` | `["10.0.15.0/24"]` | Additional routes that cause traffic to travel by the default ENI | `[]` | Not applicable |
181182

182183
### Persistence
183184

agent/config/config.go

+12
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/aws/amazon-ecs-agent/agent/engine/dockerclient"
3030
"github.com/aws/amazon-ecs-agent/agent/utils"
3131
"github.com/cihub/seelog"
32+
cnitypes "github.com/containernetworking/cni/pkg/types"
3233
)
3334

3435
const (
@@ -343,6 +344,16 @@ func environmentConfig() (Config, error) {
343344
seelog.Debugf("Setting instance attribute %v: %v", attributeKey, attributeValue)
344345
}
345346

347+
var additionalLocalRoutes []cnitypes.IPNet
348+
additionalLocalRoutesEnv := os.Getenv("ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES")
349+
if additionalLocalRoutesEnv != "" {
350+
err := json.Unmarshal([]byte(additionalLocalRoutesEnv), &additionalLocalRoutes)
351+
if err != nil {
352+
seelog.Warnf("Invalid format for ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES, expected a json array of CIDRs: %v", err)
353+
errs = append(errs, err)
354+
}
355+
}
356+
346357
if len(errs) > 0 {
347358
err = utils.NewMultiError(errs...)
348359
} else {
@@ -381,6 +392,7 @@ func environmentConfig() (Config, error) {
381392
InstanceAttributes: instanceAttributes,
382393
CNIPluginsPath: cniPluginsPath,
383394
AWSVPCBlockInstanceMetdata: awsVPCBlockInstanceMetadata,
395+
AWSVPCAdditionalLocalRoutes: additionalLocalRoutes,
384396
}, err
385397
}
386398

agent/config/config_test.go

+62-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package config
1515

1616
import (
17+
"encoding/json"
1718
"errors"
1819
"os"
1920
"reflect"
@@ -80,53 +81,75 @@ func TestBrokenEC2MetadataEndpoint(t *testing.T) {
8081
}
8182

8283
func TestEnvironmentConfig(t *testing.T) {
84+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
85+
defer os.Unsetenv("AWS_DEFAULT_REGION")
8386
os.Setenv("ECS_CLUSTER", "myCluster")
87+
defer os.Unsetenv("ECS_CLUSTER")
8488
os.Setenv("ECS_RESERVED_PORTS_UDP", "[42,99]")
89+
defer os.Unsetenv("ECS_RESERVED_PORTS_UDP")
8590
os.Setenv("ECS_RESERVED_MEMORY", "20")
91+
defer os.Unsetenv("ECS_RESERVED_MEMORY")
8692
os.Setenv("ECS_CONTAINER_STOP_TIMEOUT", "60s")
93+
defer os.Unsetenv("ECS_CONTAINER_STOP_TIMEOUT")
8794
os.Setenv("ECS_AVAILABLE_LOGGING_DRIVERS", "[\""+string(dockerclient.SyslogDriver)+"\"]")
95+
defer os.Unsetenv("ECS_AVAILABLE_LOGGING_DRIVERS")
8896
os.Setenv("ECS_SELINUX_CAPABLE", "true")
97+
defer os.Unsetenv("ECS_SELINUX_CAPABLE")
8998
os.Setenv("ECS_APPARMOR_CAPABLE", "true")
99+
defer os.Unsetenv("ECS_APPARMOR_CAPABLE")
90100
os.Setenv("ECS_DISABLE_PRIVILEGED", "true")
101+
defer os.Unsetenv("ECS_DISABLE_PRIVILEGED")
91102
os.Setenv("ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION", "90s")
103+
defer os.Unsetenv("ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION")
92104
os.Setenv("ECS_ENABLE_TASK_IAM_ROLE", "true")
105+
defer os.Unsetenv("ECS_ENABLE_TASK_IAM_ROLE")
93106
os.Setenv("ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST", "true")
107+
defer os.Unsetenv("ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST")
94108
os.Setenv("ECS_DISABLE_IMAGE_CLEANUP", "true")
109+
defer os.Unsetenv("ECS_DISABLE_IMAGE_CLEANUP")
95110
os.Setenv("ECS_IMAGE_CLEANUP_INTERVAL", "2h")
111+
defer os.Unsetenv("ECS_IMAGE_CLEANUP_INTERVAL")
96112
os.Setenv("ECS_IMAGE_MINIMUM_CLEANUP_AGE", "30m")
113+
defer os.Unsetenv("ECS_IMAGE_MINIMUM_CLEANUP_AGE")
97114
os.Setenv("ECS_NUM_IMAGES_DELETE_PER_CYCLE", "2")
115+
defer os.Unsetenv("ECS_NUM_IMAGES_DELETE_PER_CYCLE")
98116
os.Setenv("ECS_INSTANCE_ATTRIBUTES", "{\"my_attribute\": \"testing\"}")
117+
defer os.Unsetenv("ECS_INSTANCE_ATTRIBUTES")
99118
os.Setenv("ECS_ENABLE_TASK_ENI", "true")
119+
defer os.Unsetenv("ECS_ENABLE_TASK_ENI")
120+
additionalLocalRoutesJSON := `["1.2.3.4/22","5.6.7.8/32"]`
121+
os.Setenv("ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES", additionalLocalRoutesJSON)
100122

101123
conf, err := environmentConfig()
102-
assert.Nil(t, err)
124+
assert.NoError(t, err)
103125
assert.Equal(t, "myCluster", conf.Cluster)
104126
assert.Equal(t, 2, len(conf.ReservedPortsUDP))
105127
assert.Contains(t, conf.ReservedPortsUDP, uint16(42))
106128
assert.Contains(t, conf.ReservedPortsUDP, uint16(99))
107129
assert.Equal(t, uint16(20), conf.ReservedMemory)
108-
109130
expectedDuration, _ := time.ParseDuration("60s")
110131
assert.Equal(t, expectedDuration, conf.DockerStopTimeout)
111-
112132
assert.Equal(t, []dockerclient.LoggingDriver{dockerclient.SyslogDriver}, conf.AvailableLoggingDrivers)
113-
114133
assert.True(t, conf.PrivilegedDisabled)
115134
assert.True(t, conf.SELinuxCapable, "Wrong value for SELinuxCapable")
116135
assert.True(t, conf.AppArmorCapable, "Wrong value for AppArmorCapable")
117136
assert.True(t, conf.TaskIAMRoleEnabled, "Wrong value for TaskIAMRoleEnabled")
118137
assert.True(t, conf.TaskIAMRoleEnabledForNetworkHost, "Wrong value for TaskIAMRoleEnabledForNetworkHost")
119138
assert.True(t, conf.ImageCleanupDisabled, "Wrong value for ImageCleanupDisabled")
120139
assert.True(t, conf.TaskENIEnabled, "Wrong value for TaskNetwork")
121-
122-
assert.Equal(t, (30 * time.Minute), conf.MinimumImageDeletionAge)
123-
assert.Equal(t, (2 * time.Hour), conf.ImageCleanupInterval)
140+
assert.Equal(t, 30*time.Minute, conf.MinimumImageDeletionAge)
141+
assert.Equal(t, 2*time.Hour, conf.ImageCleanupInterval)
124142
assert.Equal(t, 2, conf.NumImagesToDeletePerCycle)
125143
assert.Equal(t, "testing", conf.InstanceAttributes["my_attribute"])
126-
assert.Equal(t, (90 * time.Second), conf.TaskCleanupWaitDuration)
144+
assert.Equal(t, 90*time.Second, conf.TaskCleanupWaitDuration)
145+
serializedAdditionalLocalRoutesJSON, err := json.Marshal(conf.AWSVPCAdditionalLocalRoutes)
146+
assert.NoError(t, err, "should marshal additional local routes")
147+
assert.Equal(t, additionalLocalRoutesJSON, string(serializedAdditionalLocalRoutesJSON))
127148
}
128149

129150
func TestTrimWhitespace(t *testing.T) {
151+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
152+
defer os.Unsetenv("AWS_DEFAULT_REGION")
130153
os.Setenv("ECS_CLUSTER", "default \r")
131154
os.Setenv("ECS_ENGINE_AUTH_TYPE", "dockercfg\r")
132155

@@ -153,6 +176,8 @@ func TestTrimWhitespace(t *testing.T) {
153176
}
154177

155178
func TestConfigBoolean(t *testing.T) {
179+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
180+
defer os.Unsetenv("AWS_DEFAULT_REGION")
156181
os.Setenv("ECS_DISABLE_METRICS", "true")
157182
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
158183
if err != nil {
@@ -253,6 +278,8 @@ func TestValidFormatParseEnvVariableDuration(t *testing.T) {
253278
}
254279

255280
func TestInvalidTaskCleanupTimeout(t *testing.T) {
281+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
282+
defer os.Unsetenv("AWS_DEFAULT_REGION")
256283
os.Setenv("ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION", "1s")
257284
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
258285
if err != nil {
@@ -267,6 +294,8 @@ func TestInvalidTaskCleanupTimeout(t *testing.T) {
267294
}
268295

269296
func TestTaskCleanupTimeout(t *testing.T) {
297+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
298+
defer os.Unsetenv("AWS_DEFAULT_REGION")
270299
os.Setenv("ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION", "10m")
271300
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
272301
if err != nil {
@@ -281,6 +310,8 @@ func TestTaskCleanupTimeout(t *testing.T) {
281310
}
282311

283312
func TestInvalidReservedMemory(t *testing.T) {
313+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
314+
defer os.Unsetenv("AWS_DEFAULT_REGION")
284315
os.Setenv("ECS_RESERVED_MEMORY", "-1")
285316
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
286317
if err != nil {
@@ -295,6 +326,8 @@ func TestInvalidReservedMemory(t *testing.T) {
295326
}
296327

297328
func TestReservedMemory(t *testing.T) {
329+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
330+
defer os.Unsetenv("AWS_DEFAULT_REGION")
298331
os.Setenv("ECS_RESERVED_MEMORY", "1")
299332
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
300333
if err != nil {
@@ -309,6 +342,8 @@ func TestReservedMemory(t *testing.T) {
309342
}
310343

311344
func TestTaskIAMRoleEnabled(t *testing.T) {
345+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
346+
defer os.Unsetenv("AWS_DEFAULT_REGION")
312347
os.Setenv("ECS_ENABLE_TASK_IAM_ROLE", "true")
313348
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
314349
if err != nil {
@@ -321,6 +356,8 @@ func TestTaskIAMRoleEnabled(t *testing.T) {
321356
}
322357

323358
func TestTaskIAMRoleForHostNetworkEnabled(t *testing.T) {
359+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
360+
defer os.Unsetenv("AWS_DEFAULT_REGION")
324361
os.Setenv("ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST", "true")
325362
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
326363
if err != nil {
@@ -333,6 +370,8 @@ func TestTaskIAMRoleForHostNetworkEnabled(t *testing.T) {
333370
}
334371

335372
func TestCredentialsAuditLogFile(t *testing.T) {
373+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
374+
defer os.Unsetenv("AWS_DEFAULT_REGION")
336375
dummyLocation := "/foo/bar.log"
337376
os.Setenv("ECS_AUDIT_LOGFILE", dummyLocation)
338377
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
@@ -346,6 +385,8 @@ func TestCredentialsAuditLogFile(t *testing.T) {
346385
}
347386

348387
func TestCredentialsAuditLogDisabled(t *testing.T) {
388+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
389+
defer os.Unsetenv("AWS_DEFAULT_REGION")
349390
os.Setenv("ECS_AUDIT_LOGFILE_DISABLED", "true")
350391
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
351392
if err != nil {
@@ -358,6 +399,8 @@ func TestCredentialsAuditLogDisabled(t *testing.T) {
358399
}
359400

360401
func TestImageCleanupMinimumInterval(t *testing.T) {
402+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
403+
defer os.Unsetenv("AWS_DEFAULT_REGION")
361404
os.Setenv("ECS_IMAGE_CLEANUP_INTERVAL", "1m")
362405
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
363406
if err != nil {
@@ -370,6 +413,8 @@ func TestImageCleanupMinimumInterval(t *testing.T) {
370413
}
371414

372415
func TestImageCleanupMinimumNumImagesToDeletePerCycle(t *testing.T) {
416+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
417+
defer os.Unsetenv("AWS_DEFAULT_REGION")
373418
os.Setenv("ECS_NUM_IMAGES_DELETE_PER_CYCLE", "-1")
374419
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
375420
if err != nil {
@@ -382,9 +427,18 @@ func TestImageCleanupMinimumNumImagesToDeletePerCycle(t *testing.T) {
382427
}
383428

384429
func TestAWSVPCBlockInstanceMetadata(t *testing.T) {
430+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
431+
defer os.Unsetenv("AWS_DEFAULT_REGION")
385432
os.Setenv("ECS_AWSVPC_BLOCK_IMDS", "true")
386433
defer os.Unsetenv("ECS_AWSVPC_BLOCK_IMDS")
387434
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
388435
assert.NoError(t, err)
389436
assert.True(t, cfg.AWSVPCBlockInstanceMetdata)
390437
}
438+
439+
func TestInvalidAWSVPCAdditionalLocalRoutes(t *testing.T) {
440+
os.Setenv("ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES", `["300.300.300.300/64"]`)
441+
defer os.Unsetenv("ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES")
442+
_, err := environmentConfig()
443+
assert.Error(t, err)
444+
}

agent/config/config_unix_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import (
2929
)
3030

3131
func TestConfigDefault(t *testing.T) {
32+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
33+
defer os.Unsetenv("AWS_DEFAULT_REGION")
3234
os.Unsetenv("ECS_DISABLE_METRICS")
3335
os.Unsetenv("ECS_RESERVED_PORTS")
3436
os.Unsetenv("ECS_RESERVED_MEMORY")
@@ -49,7 +51,7 @@ func TestConfigDefault(t *testing.T) {
4951
os.Unsetenv("ECS_AWSVPC_BLOCK_IMDS")
5052

5153
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
52-
assert.Nil(t, err)
54+
assert.NoError(t, err)
5355

5456
assert.Equal(t, "unix:///var/run/docker.sock", cfg.DockerEndpoint, "Default docker endpoint set incorrectly")
5557
assert.Equal(t, "/data/", cfg.DataDir, "Default datadir set incorrectly")

agent/config/config_windows_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
)
2626

2727
func TestConfigDefault(t *testing.T) {
28+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
29+
defer os.Unsetenv("AWS_DEFAULT")
2830
os.Unsetenv("ECS_DISABLE_METRICS")
2931
os.Unsetenv("ECS_RESERVED_PORTS")
3032
os.Unsetenv("ECS_RESERVED_MEMORY")
@@ -42,7 +44,7 @@ func TestConfigDefault(t *testing.T) {
4244
os.Unsetenv("ECS_IMAGE_CLEANUP_INTERVAL")
4345

4446
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
45-
assert.Nil(t, err)
47+
assert.NoError(t, err)
4648

4749
assert.Equal(t, "npipe:////./pipe/docker_engine", cfg.DockerEndpoint, "Default docker endpoint set incorrectly")
4850
assert.Equal(t, `C:\ProgramData\Amazon\ECS\data`, cfg.DataDir, "Default datadir set incorrectly")
@@ -64,10 +66,12 @@ func TestConfigDefault(t *testing.T) {
6466
}
6567

6668
func TestConfigIAMTaskRolesReserves80(t *testing.T) {
69+
os.Setenv("AWS_DEFAULT_REGION", "foo-bar-1")
70+
defer os.Unsetenv("AWS_DEFAULT")
6771
os.Unsetenv("ECS_RESERVED_PORTS")
6872
os.Setenv("ECS_ENABLE_TASK_IAM_ROLE", "true")
6973
cfg, err := NewConfig(ec2.NewBlackholeEC2MetadataClient())
70-
assert.Nil(t, err)
74+
assert.NoError(t, err)
7175
assert.Equal(t, []uint16{
7276
DockerReservedPort,
7377
DockerReservedSSLPort,

0 commit comments

Comments
 (0)