Skip to content

Commit 86decbd

Browse files
author
Andrea Spacca
authored
[Libbeat] Security - fetch IMDSv2 token for add_cloud_metadata suppor… (#28285)
* [Libbeat] Security - fetch IMDSv2 token for add_cloud_metadata support on aws
1 parent e454c2b commit 86decbd

2 files changed

Lines changed: 85 additions & 2 deletions

File tree

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
2323
- Remove deprecated/undocumented IncludeCreatorMetadata setting from kubernetes metadata config options {pull}28006[28006]
2424
- Remove deprecated fields from kubernetes module {pull}28046[28046]
2525
- Remove deprecated config option aws_partition. {pull}28120[28120]
26+
- Enable IMDSv2 support for `add_cloud_metadata` processor on AWS. {issue}22101[22101] {pull}28285[28285]
2627
- Update kubernetes.namespace from keyword to group field and add name, labels, annotations, uuid as its fields {pull}27917[27917]
2728

2829
*Auditbeat*

libbeat/processors/add_cloud_metadata/provider_aws_ec2.go

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,88 @@
1818
package add_cloud_metadata
1919

2020
import (
21+
"fmt"
22+
"io"
23+
"io/ioutil"
24+
"net"
25+
"net/http"
26+
27+
"github.com/elastic/beats/v7/libbeat/logp"
28+
2129
"github.com/elastic/beats/v7/libbeat/common"
2230
s "github.com/elastic/beats/v7/libbeat/common/schema"
2331
c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface"
32+
"github.com/elastic/beats/v7/libbeat/common/transport/tlscommon"
2433
)
2534

26-
const ec2InstanceIdentityURI = "/2014-02-25/dynamic/instance-identity/document"
35+
const (
36+
ec2InstanceIdentityURI = "/2014-02-25/dynamic/instance-identity/document"
37+
ec2InstanceIMDSv2TokenValueHeader = "X-aws-ec2-metadata-token"
38+
ec2InstanceIMDSv2TokenTTLHeader = "X-aws-ec2-metadata-token-ttl-seconds"
39+
ec2InstanceIMDSv2TokenTTLValue = "21600"
40+
ec2InstanceIMDSv2TokenURI = "/latest/api/token"
41+
)
42+
43+
// fetches IMDSv2 token, returns empty one on errors
44+
func getIMDSv2Token(c *common.Config) string {
45+
logger := logp.NewLogger("add_cloud_metadata")
46+
47+
config := defaultConfig()
48+
if err := c.Unpack(&config); err != nil {
49+
logger.Warnf("error when load config for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
50+
return ""
51+
}
52+
53+
tlsConfig, err := tlscommon.LoadTLSConfig(config.TLS)
54+
if err != nil {
55+
logger.Warnf("error when load TLS config for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
56+
return ""
57+
}
58+
59+
client := http.Client{
60+
Timeout: config.Timeout,
61+
Transport: &http.Transport{
62+
DisableKeepAlives: true,
63+
DialContext: (&net.Dialer{
64+
Timeout: config.Timeout,
65+
KeepAlive: 0,
66+
}).DialContext,
67+
TLSClientConfig: tlsConfig.ToConfig(),
68+
},
69+
}
70+
71+
tokenReq, err := http.NewRequest("PUT", fmt.Sprintf("http://%s%s", metadataHost, ec2InstanceIMDSv2TokenURI), nil)
72+
if err != nil {
73+
logger.Warnf("error when make token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
74+
return ""
75+
}
76+
77+
tokenReq.Header.Add(ec2InstanceIMDSv2TokenTTLHeader, ec2InstanceIMDSv2TokenTTLValue)
78+
rsp, err := client.Do(tokenReq)
79+
defer func(body io.ReadCloser) {
80+
if body != nil {
81+
body.Close()
82+
}
83+
}(rsp.Body)
84+
85+
if err != nil {
86+
logger.Warnf("error when read token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
87+
return ""
88+
}
89+
90+
if rsp.StatusCode != http.StatusOK {
91+
logger.Warnf("error when check request status for getting IMDSv2 token: http request status %d. No token in the metadata request will be used.", rsp.StatusCode)
92+
return ""
93+
}
94+
95+
all, err := ioutil.ReadAll(rsp.Body)
96+
if err != nil {
97+
logger.Warnf("error when reading token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
98+
return ""
99+
}
100+
101+
return string(all)
102+
}
27103

28104
// AWS EC2 Metadata Service
29105
var ec2MetadataFetcher = provider{
@@ -48,7 +124,13 @@ var ec2MetadataFetcher = provider{
48124
return common.MapStr{"cloud": out}
49125
}
50126

51-
fetcher, err := newMetadataFetcher(config, "aws", nil, metadataHost, ec2Schema, ec2InstanceIdentityURI)
127+
headers := make(map[string]string, 1)
128+
token := getIMDSv2Token(config)
129+
if len(token) > 0 {
130+
headers[ec2InstanceIMDSv2TokenValueHeader] = token
131+
}
132+
133+
fetcher, err := newMetadataFetcher(config, "aws", headers, metadataHost, ec2Schema, ec2InstanceIdentityURI)
52134
return fetcher, err
53135
},
54136
}

0 commit comments

Comments
 (0)