Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Libbeat] Security - fetch IMDSv2 token for add_cloud_metadata suppor… #28285

Merged
merged 6 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Remove deprecated/undocumented IncludeCreatorMetadata setting from kubernetes metadata config options {pull}28006[28006]
- Remove deprecated fields from kubernetes module {pull}28046[28046]
- Remove deprecated config option aws_partition. {pull}28120[28120]
- Enable IMDSv2 support for `add_cloud_metadata` processor on AWS. {issue}22101[22101] {pull}28285[28285]
- Update kubernetes.namespace from keyword to group field and add name, labels, annotations, uuid as its fields {pull}27917[27917]

*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"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the empty space

"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
},
}