Skip to content

Commit 9c8b599

Browse files
amogh09Heming Han
authored and
Heming Han
committed
Add TMDS initialization functionality to ecs-agent module (aws#3660)
1 parent 57e690d commit 9c8b599

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+17082
-1
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ analyze-cover-profile-init: coverprofile-init.out
171171
./scripts/analyze-cover-profile coverprofile-init.out
172172

173173
run-integ-tests: test-registry gremlin container-health-check-image run-sudo-tests
174-
ECS_LOGLEVEL=debug ${GOTEST} -tags integration -timeout=30m ./agent/...
174+
ECS_LOGLEVEL=debug ${GOTEST} -tags integration -timeout=30m ./agent/... ./ecs-agent/...
175175

176176
run-sudo-tests:
177177
sudo -E ${GOTEST} -tags sudo -timeout=10m ./agent/...

ecs-agent/go.mod

+5
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@ go 1.19
44

55
require (
66
github.com/aws/aws-sdk-go v1.36.0
7+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
8+
github.com/didip/tollbooth v4.0.2+incompatible
79
github.com/golang/mock v1.4.1
10+
github.com/gorilla/mux v1.8.0
811
github.com/stretchr/testify v1.7.0
912
golang.org/x/tools v0.6.0
1013
)
1114

1215
require (
1316
github.com/davecgh/go-spew v1.1.1 // indirect
1417
github.com/jmespath/go-jmespath v0.4.0 // indirect
18+
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
1519
github.com/pmezard/go-difflib v1.0.0 // indirect
1620
golang.org/x/mod v0.8.0 // indirect
1721
golang.org/x/net v0.8.0 // indirect
1822
golang.org/x/sys v0.6.0 // indirect
23+
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
1924
gopkg.in/yaml.v3 v3.0.1 // indirect
2025
)

ecs-agent/go.sum

+10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
github.com/aws/aws-sdk-go v1.36.0 h1:CscTrS+szX5iu34zk2bZrChnGO/GMtUYgMK1Xzs2hYo=
22
github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
3+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
4+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
35
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
46
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
57
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/didip/tollbooth v4.0.2+incompatible h1:fVSa33JzSz0hoh2NxpwZtksAzAgd7zjmGO20HCZtF4M=
9+
github.com/didip/tollbooth v4.0.2+incompatible/go.mod h1:A9b0665CE6l1KmzpDws2++elm/CsuWBMa5Jv4WY0PEY=
610
github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
711
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
12+
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
13+
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
814
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
915
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
1016
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
1117
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
18+
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
19+
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
1220
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1321
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1422
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -33,6 +41,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3341
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3442
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3543
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
44+
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
45+
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
3646
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
3747
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
3848
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package logging
15+
16+
import (
17+
"net/http"
18+
19+
"github.com/cihub/seelog"
20+
)
21+
22+
// LoggingHandler is used to log all requests for an endpoint.
23+
type LoggingHandler struct{ h http.Handler }
24+
25+
// NewLoggingHandler creates a new LoggingHandler object.
26+
func NewLoggingHandler(handler http.Handler) LoggingHandler {
27+
return LoggingHandler{h: handler}
28+
}
29+
30+
// ServeHTTP logs the method and remote address of the request.
31+
func (lh LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
32+
seelog.Debug("Handling http request", "method", r.Method, "from", r.RemoteAddr)
33+
lh.h.ServeHTTP(w, r)
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//go:build unit
2+
// +build unit
3+
4+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
7+
// not use this file except in compliance with the License. A copy of the
8+
// License is located at
9+
//
10+
// http://aws.amazon.com/apache2.0/
11+
//
12+
// or in the "license" file accompanying this file. This file is distributed
13+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
// express or implied. See the License for the specific language governing
15+
// permissions and limitations under the License.
16+
package logging
17+
18+
import (
19+
"fmt"
20+
"net/http"
21+
"net/http/httptest"
22+
"testing"
23+
24+
"github.com/stretchr/testify/assert"
25+
"github.com/stretchr/testify/require"
26+
)
27+
28+
type underlyingHandler struct{}
29+
30+
func (h underlyingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
31+
w.WriteHeader(http.StatusOK)
32+
fmt.Fprint(w, "Hello world")
33+
}
34+
35+
// Tests that logging handler calls the underlying handler
36+
func TestLoggingHandler(t *testing.T) {
37+
loggingHandler := LoggingHandler{underlyingHandler{}}
38+
39+
req, err := http.NewRequest("GET", "/", nil)
40+
require.NoError(t, err)
41+
res := httptest.NewRecorder()
42+
43+
loggingHandler.ServeHTTP(res, req)
44+
assert.Equal(t, http.StatusOK, res.Code)
45+
assert.Equal(t, "Hello world", res.Body.String())
46+
}

ecs-agent/tmds/server.go

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
package tmds
14+
15+
import (
16+
"errors"
17+
"fmt"
18+
"net/http"
19+
"time"
20+
21+
"github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit"
22+
"github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit/request"
23+
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/logging"
24+
muxutils "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/utils/mux"
25+
26+
"github.com/didip/tollbooth"
27+
"github.com/gorilla/mux"
28+
)
29+
30+
const (
31+
// TMDS IP and port
32+
IPv4 = "127.0.0.1"
33+
Port = 51679
34+
)
35+
36+
// IPv4 address for TMDS
37+
func AddressIPv4() string {
38+
return fmt.Sprintf("%s:%d", IPv4, Port)
39+
}
40+
41+
// Configuration for TMDS
42+
type Config struct {
43+
listenAddress string // http server listen address
44+
readTimeout time.Duration // http server read timeout
45+
writeTimeout time.Duration // http server write timeout
46+
steadyStateRate float64 // steady request rate limit
47+
burstRate int // burst request rate limit
48+
router *mux.Router // router with routes configured
49+
}
50+
51+
// Function type for updating TMDS config
52+
type ConfigOpt func(*Config)
53+
54+
// Set TMDS listen address
55+
func WithListenAddress(listenAddr string) ConfigOpt {
56+
return func(c *Config) {
57+
c.listenAddress = listenAddr
58+
}
59+
}
60+
61+
// Set TMDS read timeout
62+
func WithReadTimeout(readTimeout time.Duration) ConfigOpt {
63+
return func(c *Config) {
64+
c.readTimeout = readTimeout
65+
}
66+
}
67+
68+
// Set TMDS write timeout
69+
func WithWriteTimeout(writeTimeout time.Duration) ConfigOpt {
70+
return func(c *Config) {
71+
c.writeTimeout = writeTimeout
72+
}
73+
}
74+
75+
// Set TMDS steady request rate limit
76+
func WithSteadyStateRate(steadyStateRate float64) ConfigOpt {
77+
return func(c *Config) {
78+
c.steadyStateRate = steadyStateRate
79+
}
80+
}
81+
82+
// Set TMDS burst request rate limit
83+
func WithBurstRate(burstRate int) ConfigOpt {
84+
return func(c *Config) {
85+
c.burstRate = burstRate
86+
}
87+
}
88+
89+
// Set TMDS router
90+
func WithRouter(router *mux.Router) ConfigOpt {
91+
return func(c *Config) {
92+
c.router = router
93+
}
94+
}
95+
96+
// Create a new HTTP Task Metadata Server (TMDS)
97+
func NewServer(auditLogger audit.AuditLogger, options ...ConfigOpt) (*http.Server, error) {
98+
config := new(Config)
99+
for _, opt := range options {
100+
opt(config)
101+
}
102+
103+
return setup(auditLogger, config)
104+
}
105+
106+
func setup(auditLogger audit.AuditLogger, config *Config) (*http.Server, error) {
107+
if config.router == nil {
108+
return nil, errors.New("router cannot be nil")
109+
}
110+
111+
// Define a reqeuest rate limiter
112+
limiter := tollbooth.
113+
NewLimiter(config.steadyStateRate, nil).
114+
SetOnLimitReached(limitReachedHandler(auditLogger)).
115+
SetBurst(config.burstRate)
116+
117+
// Log all requests and then pass through to muxRouter.
118+
loggingMuxRouter := mux.NewRouter()
119+
120+
// rootPath is a path for any traffic to this endpoint
121+
rootPath := "/" + muxutils.ConstructMuxVar("root", muxutils.AnythingRegEx)
122+
loggingMuxRouter.Handle(rootPath, tollbooth.LimitHandler(
123+
limiter, logging.NewLoggingHandler(config.router)))
124+
125+
// explicitly enable path cleaning
126+
loggingMuxRouter.SkipClean(false)
127+
128+
return &http.Server{
129+
Addr: config.listenAddress,
130+
Handler: loggingMuxRouter,
131+
ReadTimeout: config.readTimeout,
132+
WriteTimeout: config.writeTimeout,
133+
}, nil
134+
}
135+
136+
// LimitReachedHandler logs the throttled request in the credentials audit log
137+
func limitReachedHandler(auditLogger audit.AuditLogger) func(http.ResponseWriter, *http.Request) {
138+
return func(w http.ResponseWriter, r *http.Request) {
139+
logRequest := request.LogRequest{
140+
Request: r,
141+
}
142+
auditLogger.Log(logRequest, http.StatusTooManyRequests, "")
143+
}
144+
}

0 commit comments

Comments
 (0)