Skip to content

Commit

Permalink
[7.x](backport #28285) [Libbeat] Security - fetch IMDSv2 token for ad…
Browse files Browse the repository at this point in the history
…d_cloud_metadata suppor… (#28400)

* [Libbeat] Security - fetch IMDSv2 token for add_cloud_metadata support on aws

(cherry picked from commit 86decbd)
  • Loading branch information
mergify[bot] authored Oct 14, 2021
1 parent 4a080bf commit ab22af9
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Make error message about locked data path actionable. {pull}18667[18667]
- Fix panic with inline SSL when the certificate or key were small than 256 bytes. {pull}23820[23820]
- Skip add_kubernetes_metadata processor when kubernetes metadata are already present {pull}27689[27689]
- Enable IMDSv2 support for `add_cloud_metadata` processor on AWS. {issue}22101[22101] {pull}28285[28285]

*Auditbeat*

Expand Down
86 changes: 84 additions & 2 deletions libbeat/processors/add_cloud_metadata/provider_aws_ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,88 @@
package add_cloud_metadata

import (
"fmt"
"io"
"io/ioutil"
"net"
"net/http"

"github.com/elastic/beats/v7/libbeat/logp"

"github.com/elastic/beats/v7/libbeat/common"
s "github.com/elastic/beats/v7/libbeat/common/schema"
c "github.com/elastic/beats/v7/libbeat/common/schema/mapstriface"
"github.com/elastic/beats/v7/libbeat/common/transport/tlscommon"
)

const ec2InstanceIdentityURI = "/2014-02-25/dynamic/instance-identity/document"
const (
ec2InstanceIdentityURI = "/2014-02-25/dynamic/instance-identity/document"
ec2InstanceIMDSv2TokenValueHeader = "X-aws-ec2-metadata-token"
ec2InstanceIMDSv2TokenTTLHeader = "X-aws-ec2-metadata-token-ttl-seconds"
ec2InstanceIMDSv2TokenTTLValue = "21600"
ec2InstanceIMDSv2TokenURI = "/latest/api/token"
)

// fetches IMDSv2 token, returns empty one on errors
func getIMDSv2Token(c *common.Config) string {
logger := logp.NewLogger("add_cloud_metadata")

config := defaultConfig()
if err := c.Unpack(&config); err != nil {
logger.Warnf("error when load config for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
return ""
}

tlsConfig, err := tlscommon.LoadTLSConfig(config.TLS)
if err != nil {
logger.Warnf("error when load TLS config for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
return ""
}

client := http.Client{
Timeout: config.Timeout,
Transport: &http.Transport{
DisableKeepAlives: true,
DialContext: (&net.Dialer{
Timeout: config.Timeout,
KeepAlive: 0,
}).DialContext,
TLSClientConfig: tlsConfig.ToConfig(),
},
}

tokenReq, err := http.NewRequest("PUT", fmt.Sprintf("http://%s%s", metadataHost, ec2InstanceIMDSv2TokenURI), nil)
if err != nil {
logger.Warnf("error when make token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
return ""
}

tokenReq.Header.Add(ec2InstanceIMDSv2TokenTTLHeader, ec2InstanceIMDSv2TokenTTLValue)
rsp, err := client.Do(tokenReq)
defer func(body io.ReadCloser) {
if body != nil {
body.Close()
}
}(rsp.Body)

if err != nil {
logger.Warnf("error when read token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
return ""
}

if rsp.StatusCode != http.StatusOK {
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)
return ""
}

all, err := ioutil.ReadAll(rsp.Body)
if err != nil {
logger.Warnf("error when reading token request for getting IMDSv2 token: %s. No token in the metadata request will be used.", err)
return ""
}

return string(all)
}

// AWS EC2 Metadata Service
var ec2MetadataFetcher = provider{
Expand All @@ -48,7 +124,13 @@ var ec2MetadataFetcher = provider{
return common.MapStr{"cloud": out}
}

fetcher, err := newMetadataFetcher(config, "aws", nil, metadataHost, ec2Schema, ec2InstanceIdentityURI)
headers := make(map[string]string, 1)
token := getIMDSv2Token(config)
if len(token) > 0 {
headers[ec2InstanceIMDSv2TokenValueHeader] = token
}

fetcher, err := newMetadataFetcher(config, "aws", headers, metadataHost, ec2Schema, ec2InstanceIdentityURI)
return fetcher, err
},
}

0 comments on commit ab22af9

Please sign in to comment.