support external id in STS Assume Role calls (#18901)

This commit is contained in:
Benjamin Edwards
2024-05-21 13:19:35 -04:00
committed by GitHub
parent b01132d0c6
commit 677835e2c3
23 changed files with 221 additions and 25 deletions
+1
View File
@@ -0,0 +1 @@
Add support for ExternalId in STS Assume Role APIs
+3
View File
@@ -352,6 +352,7 @@ the way that the Fleet server works.
AccessKeyID: config.Firehose.AccessKeyID,
SecretAccessKey: config.Firehose.SecretAccessKey,
StsAssumeRoleArn: config.Firehose.StsAssumeRoleArn,
StsExternalID: config.Firehose.StsExternalID,
},
Kinesis: logging.KinesisConfig{
Region: config.Kinesis.Region,
@@ -359,12 +360,14 @@ the way that the Fleet server works.
AccessKeyID: config.Kinesis.AccessKeyID,
SecretAccessKey: config.Kinesis.SecretAccessKey,
StsAssumeRoleArn: config.Kinesis.StsAssumeRoleArn,
StsExternalID: config.Kinesis.StsExternalID,
},
Lambda: logging.LambdaConfig{
Region: config.Lambda.Region,
AccessKeyID: config.Lambda.AccessKeyID,
SecretAccessKey: config.Lambda.SecretAccessKey,
StsAssumeRoleArn: config.Lambda.StsAssumeRoleArn,
StsExternalID: config.Lambda.StsExternalID,
},
PubSub: logging.PubSubConfig{
Project: config.PubSub.Project,
@@ -1430,7 +1430,7 @@ AWS secret access key to use for Firehose authentication.
firehose:
secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```
Optional unique identifier that can be used by the principal assuming the role to assert its identity.
##### firehose_sts_assume_role_arn
This flag only has effect if one of the following is true:
@@ -1447,6 +1447,23 @@ AWS STS role ARN to use for Firehose authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/firehose-role
```
##### firehose_sts_external_id
This flag only has effect if one of the following is true:
- `osquery_result_log_plugin` or `osquery_status_log_plugin` are set to `firehose`.
- `activity_audit_log_plugin` is set to `firehose` and `activity_enable_audit_log` is set to `true`.
AWS STS External ID to use for Firehose authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: none
- Environment variable: `FLEET_FIREHOSE_STS_EXTERNAL_ID`
- Config file format:
```yaml
firehose:
sts_external_id: your_unique_id
```
##### firehose_status_stream
This flag only has effect if `osquery_status_log_plugin` is set to `firehose`.
@@ -1519,6 +1536,7 @@ firehose:
access_key_id: AKIAIOSFODNN7EXAMPLE
secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
sts_assume_role_arn: arn:aws:iam::1234567890:role/firehose-role
sts_external_id: your_unique_id
status_stream: osquery_status
result_stream: osquery_result
```
@@ -1594,6 +1612,23 @@ AWS STS role ARN to use for Kinesis authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/kinesis-role
```
##### kinesis_sts_external_id
This flag only has effect if one of the following is true:
- `osquery_result_log_plugin` or `osquery_status_log_plugin` are set to `kinesis`.
- `activity_audit_log_plugin` is set to `kinesis` and `activity_enable_audit_log` is set to `true`.
AWS STS External ID to use for Kinesis authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: none
- Environment variable: `FLEET_KINESIS_STS_EXTERNAL_ID`
- Config file format:
```yaml
kinesis:
sts_external_id: your_unique_id
```
##### kinesis_status_stream
This flag only has effect if `osquery_status_log_plugin` is set to `kinesis`.
@@ -1665,6 +1700,7 @@ kinesis:
access_key_id: AKIAIOSFODNN7EXAMPLE
secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
sts_assume_role_arn: arn:aws:iam::1234567890:role/firehose-role
sts_external_id: your_unique_id
status_stream: osquery_status
result_stream: osquery_result
```
@@ -1740,6 +1776,23 @@ AWS STS role ARN to use for Lambda authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/lambda-role
```
##### lambda_sts_external_id
This flag only has effect if one of the following is true:
- `osquery_result_log_plugin` or `osquery_status_log_plugin` are set to `lambda`.
- `activity_audit_log_plugin` is set to `lambda` and `activity_enable_audit_log` is set to `true`.
AWS STS External ID to use for Lambda authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: none
- Environment variable: `FLEET_LAMBDA_STS_EXTERNAL_ID`
- Config file format:
```yaml
lambda:
sts_external_id: your_unique_id
```
##### lambda_status_function
This flag only has effect if `osquery_status_log_plugin` is set to `lambda`.
@@ -1907,9 +1960,7 @@ pubsub:
project: my-gcp-project
result_topic: osquery_result
status_topic: osquery_status
sts_assume_role_arn: arn:aws:iam::1234567890:role/firehose-role
status_function: statusFunction
result_function: resultFunction
add_attributes: true
```
#### Kafka REST Proxy logging
@@ -2102,6 +2153,22 @@ AWS STS role ARN to use for SES authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/ses-role
```
##### ses_sts_external_id
This flag only has effect if `email.backend` or `FLEET_EMAIL_BACKEND` is set to `ses`.
AWS STS External ID to use for SES authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: none
- Environment variable: `FLEET_SES_STS_EXTERNAL_ID`
- Config file format:
```yaml
ses:
sts_external_id: your_unique_id
```
##### ses_source_arn
This flag only has effect if `email.backend` or `FLEET_EMAIL_BACKEND` is set to `ses`. This configuration **is
@@ -2187,6 +2254,19 @@ AWS STS role ARN to use for S3 authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/some-s3-role
```
##### s3_sts_external_id
AWS STS External ID to use for S3 authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: none
- Environment variable: `FLEET_S3_STS_EXTERNAL_ID`
- Config file format:
```yaml
s3:
sts_external_id: your_unique_id
```
##### s3_endpoint_url
AWS S3 Endpoint URL. Override when using a different S3 compatible object storage backend (such as Minio),
@@ -2622,6 +2702,20 @@ This is the AWS STS role ARN for S3 authentication.
sts_assume_role_arn: arn:aws:iam::1234567890:role/some-s3-role
```
##### packaging_s3_sts_external_id
AWS STS External ID to use for S3 authentication. This is typically used in
conjunction with an STS role ARN to ensure that only the intended AWS account can assume the role.
- Default value: ""
- Environment variable: `FLEET_PACKAGING_S3_STS_EXTERNAL_ID`
- Config file format:
```yaml
packaging:
s3:
sts_external_id: your_unique_id
```
##### packaging_s3_endpoint_url
This is the AWS S3 Endpoint URL. Override when using a different S3 compatible object storage backend (such as Minio)
+20
View File
@@ -243,6 +243,7 @@ type FirehoseConfig struct {
AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"`
StsAssumeRoleArn string `yaml:"sts_assume_role_arn"`
StsExternalID string `yaml:"sts_external_id"`
StatusStream string `yaml:"status_stream"`
ResultStream string `yaml:"result_stream"`
AuditStream string `yaml:"audit_stream"`
@@ -255,6 +256,7 @@ type KinesisConfig struct {
AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"`
StsAssumeRoleArn string `yaml:"sts_assume_role_arn"`
StsExternalID string `yaml:"sts_external_id"`
StatusStream string `yaml:"status_stream"`
ResultStream string `yaml:"result_stream"`
AuditStream string `yaml:"audit_stream"`
@@ -267,6 +269,7 @@ type SESConfig struct {
AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"`
StsAssumeRoleArn string `yaml:"sts_assume_role_arn"`
StsExternalID string `yaml:"sts_external_id"`
SourceArn string `yaml:"source_arn"`
}
@@ -280,6 +283,7 @@ type LambdaConfig struct {
AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"`
StsAssumeRoleArn string `yaml:"sts_assume_role_arn"`
StsExternalID string `yaml:"sts_external_id"`
StatusFunction string `yaml:"status_function"`
ResultFunction string `yaml:"result_function"`
AuditFunction string `yaml:"audit_function"`
@@ -294,6 +298,7 @@ type S3Config struct {
AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"`
StsAssumeRoleArn string `yaml:"sts_assume_role_arn"`
StsExternalID string `yaml:"sts_external_id"`
DisableSSL bool `yaml:"disable_ssl"`
ForceS3PathStyle bool `yaml:"force_s3_path_style"`
}
@@ -948,6 +953,7 @@ func (man Manager) addConfigs() {
man.addConfigString("ses.access_key_id", "", "Access Key ID for AWS authentication")
man.addConfigString("ses.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("ses.sts_assume_role_arn", "", "ARN of role to assume for AWS")
man.addConfigString("ses.sts_external_id", "", "Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigString("ses.source_arn", "", "ARN of the identity that is associated with the sending authorization policy that permits you to send for the email address specified in the Source parameter")
// Firehose
@@ -958,6 +964,8 @@ func (man Manager) addConfigs() {
man.addConfigString("firehose.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("firehose.sts_assume_role_arn", "",
"ARN of role to assume for AWS")
man.addConfigString("firehose.sts_external_id", "",
"Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigString("firehose.status_stream", "",
"Firehose stream name for status logs")
man.addConfigString("firehose.result_stream", "",
@@ -973,6 +981,8 @@ func (man Manager) addConfigs() {
man.addConfigString("kinesis.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("kinesis.sts_assume_role_arn", "",
"ARN of role to assume for AWS")
man.addConfigString("kinesis.sts_external_id", "",
"Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigString("kinesis.status_stream", "",
"Kinesis stream name for status logs")
man.addConfigString("kinesis.result_stream", "",
@@ -986,6 +996,8 @@ func (man Manager) addConfigs() {
man.addConfigString("lambda.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("lambda.sts_assume_role_arn", "",
"ARN of role to assume for AWS")
man.addConfigString("lambda.sts_external_id", "",
"Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigString("lambda.status_function", "",
"Lambda function name for status logs")
man.addConfigString("lambda.result_function", "",
@@ -1001,6 +1013,7 @@ func (man Manager) addConfigs() {
man.addConfigString("s3.access_key_id", "", "Access Key ID for AWS authentication")
man.addConfigString("s3.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("s3.sts_assume_role_arn", "", "ARN of role to assume for AWS")
man.addConfigString("s3.sts_external_id", "", "Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigBool("s3.disable_ssl", false, "Disable SSL (typically for local testing)")
man.addConfigBool("s3.force_s3_path_style", false, "Set this to true to force path-style addressing, i.e., `http://s3.amazonaws.com/BUCKET/KEY`")
@@ -1088,6 +1101,7 @@ func (man Manager) addConfigs() {
man.addConfigString("packaging.s3.access_key_id", "", "Access Key ID for AWS authentication")
man.addConfigString("packaging.s3.secret_access_key", "", "Secret Access Key for AWS authentication")
man.addConfigString("packaging.s3.sts_assume_role_arn", "", "ARN of role to assume for AWS")
man.addConfigString("packaging.s3.sts_external_id", "", "Optional unique identifier that can be used by the principal assuming the role to assert its identity.")
man.addConfigBool("packaging.s3.disable_ssl", false, "Disable SSL (typically for local testing)")
man.addConfigBool("packaging.s3.force_s3_path_style", false, "Set this to true to force path-style addressing, i.e., `http://s3.amazonaws.com/BUCKET/KEY`")
@@ -1253,6 +1267,7 @@ func (man Manager) LoadConfig() FleetConfig {
AccessKeyID: man.getConfigString("firehose.access_key_id"),
SecretAccessKey: man.getConfigString("firehose.secret_access_key"),
StsAssumeRoleArn: man.getConfigString("firehose.sts_assume_role_arn"),
StsExternalID: man.getConfigString("firehose.sts_external_id"),
StatusStream: man.getConfigString("firehose.status_stream"),
ResultStream: man.getConfigString("firehose.result_stream"),
AuditStream: man.getConfigString("firehose.audit_stream"),
@@ -1266,6 +1281,7 @@ func (man Manager) LoadConfig() FleetConfig {
ResultStream: man.getConfigString("kinesis.result_stream"),
AuditStream: man.getConfigString("kinesis.audit_stream"),
StsAssumeRoleArn: man.getConfigString("kinesis.sts_assume_role_arn"),
StsExternalID: man.getConfigString("kinesis.sts_external_id"),
},
Lambda: LambdaConfig{
Region: man.getConfigString("lambda.region"),
@@ -1275,6 +1291,7 @@ func (man Manager) LoadConfig() FleetConfig {
ResultFunction: man.getConfigString("lambda.result_function"),
AuditFunction: man.getConfigString("lambda.audit_function"),
StsAssumeRoleArn: man.getConfigString("lambda.sts_assume_role_arn"),
StsExternalID: man.getConfigString("lambda.sts_external_id"),
},
S3: S3Config{
Bucket: man.getConfigString("s3.bucket"),
@@ -1284,6 +1301,7 @@ func (man Manager) LoadConfig() FleetConfig {
AccessKeyID: man.getConfigString("s3.access_key_id"),
SecretAccessKey: man.getConfigString("s3.secret_access_key"),
StsAssumeRoleArn: man.getConfigString("s3.sts_assume_role_arn"),
StsExternalID: man.getConfigString("s3.sts_external_id"),
DisableSSL: man.getConfigBool("s3.disable_ssl"),
ForceS3PathStyle: man.getConfigBool("s3.force_s3_path_style"),
},
@@ -1296,6 +1314,7 @@ func (man Manager) LoadConfig() FleetConfig {
AccessKeyID: man.getConfigString("ses.access_key_id"),
SecretAccessKey: man.getConfigString("ses.secret_access_key"),
StsAssumeRoleArn: man.getConfigString("ses.sts_assume_role_arn"),
StsExternalID: man.getConfigString("ses.sts_external_id"),
SourceArn: man.getConfigString("ses.source_arn"),
},
PubSub: PubSubConfig{
@@ -1365,6 +1384,7 @@ func (man Manager) LoadConfig() FleetConfig {
AccessKeyID: man.getConfigString("packaging.s3.access_key_id"),
SecretAccessKey: man.getConfigString("packaging.s3.secret_access_key"),
StsAssumeRoleArn: man.getConfigString("packaging.s3.sts_assume_role_arn"),
StsExternalID: man.getConfigString("packaging.s3.sts_external_id"),
DisableSSL: man.getConfigBool("packaging.s3.disable_ssl"),
ForceS3PathStyle: man.getConfigBool("packaging.s3.force_s3_path_style"),
},
+5 -2
View File
@@ -49,8 +49,11 @@ func newS3store(config config.S3Config) (*s3store, error) {
// Assume role if configured
if config.StsAssumeRoleArn != "" {
stscreds.NewCredentials(sess, config.StsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, config.StsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, config.StsAssumeRoleArn, func(provider *stscreds.AssumeRoleProvider) {
if config.StsAssumeRoleArn != "" {
provider.ExternalID = &config.StsExternalID
}
})
conf.Credentials = creds
sess, err = session.NewSession(conf)
if err != nil {
+6 -2
View File
@@ -37,7 +37,7 @@ type firehoseLogWriter struct {
logger log.Logger
}
func NewFirehoseLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, stream string, logger log.Logger) (*firehoseLogWriter, error) {
func NewFirehoseLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, stsExternalID, stream string, logger log.Logger) (*firehoseLogWriter, error) {
conf := &aws.Config{
Region: &region,
Endpoint: &endpointURL, // empty string or nil will use default values
@@ -55,7 +55,11 @@ func NewFirehoseLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, str
}
if stsAssumeRoleArn != "" {
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn, func(provider *stscreds.AssumeRoleProvider) {
if stsExternalID != "" {
provider.ExternalID = &stsExternalID
}
})
conf.Credentials = creds
sess, err = session.NewSession(conf)
+6 -2
View File
@@ -39,7 +39,7 @@ type kinesisLogWriter struct {
rand *rand.Rand
}
func NewKinesisLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, stream string, logger log.Logger) (*kinesisLogWriter, error) {
func NewKinesisLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, stsExternalID, stream string, logger log.Logger) (*kinesisLogWriter, error) {
conf := &aws.Config{
Region: &region,
Endpoint: &endpointURL, // empty string or nil will use default values
@@ -57,7 +57,11 @@ func NewKinesisLogWriter(region, endpointURL, id, secret, stsAssumeRoleArn, stre
}
if stsAssumeRoleArn != "" {
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn, func(provider *stscreds.AssumeRoleProvider) {
if stsExternalID != "" {
provider.ExternalID = &stsExternalID
}
})
conf.Credentials = creds
sess, err = session.NewSession(conf)
+6 -2
View File
@@ -30,7 +30,7 @@ type lambdaLogWriter struct {
logger log.Logger
}
func NewLambdaLogWriter(region, id, secret, stsAssumeRoleArn, functionName string, logger log.Logger) (*lambdaLogWriter, error) {
func NewLambdaLogWriter(region, id, secret, stsAssumeRoleArn, stsExternalID, functionName string, logger log.Logger) (*lambdaLogWriter, error) {
conf := &aws.Config{
Region: &region,
}
@@ -47,7 +47,11 @@ func NewLambdaLogWriter(region, id, secret, stsAssumeRoleArn, functionName strin
}
if stsAssumeRoleArn != "" {
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn, func(provider *stscreds.AssumeRoleProvider) {
if stsExternalID != "" {
provider.ExternalID = &stsExternalID
}
})
conf.Credentials = creds
sess, err = session.NewSession(conf)
+6
View File
@@ -27,6 +27,7 @@ type FirehoseConfig struct {
AccessKeyID string
SecretAccessKey string
StsAssumeRoleArn string
StsExternalID string
}
type KinesisConfig struct {
@@ -37,6 +38,7 @@ type KinesisConfig struct {
AccessKeyID string
SecretAccessKey string
StsAssumeRoleArn string
StsExternalID string
}
type LambdaConfig struct {
@@ -46,6 +48,7 @@ type LambdaConfig struct {
AccessKeyID string
SecretAccessKey string
StsAssumeRoleArn string
StsExternalID string
}
type PubSubConfig struct {
@@ -104,6 +107,7 @@ func NewJSONLogger(name string, config Config, logger log.Logger) (fleet.JSONLog
config.Firehose.AccessKeyID,
config.Firehose.SecretAccessKey,
config.Firehose.StsAssumeRoleArn,
config.Firehose.StsExternalID,
config.Firehose.StreamName,
logger,
)
@@ -118,6 +122,7 @@ func NewJSONLogger(name string, config Config, logger log.Logger) (fleet.JSONLog
config.Kinesis.AccessKeyID,
config.Kinesis.SecretAccessKey,
config.Kinesis.StsAssumeRoleArn,
config.Kinesis.StsExternalID,
config.Kinesis.StreamName,
logger,
)
@@ -131,6 +136,7 @@ func NewJSONLogger(name string, config Config, logger log.Logger) (fleet.JSONLog
config.Lambda.AccessKeyID,
config.Lambda.SecretAccessKey,
config.Lambda.StsAssumeRoleArn,
config.Lambda.StsExternalID,
config.Lambda.Function,
logger,
)
+8 -1
View File
@@ -20,7 +20,14 @@ import (
func NewService(config config.FleetConfig) (fleet.MailService, error) {
switch strings.ToLower(config.Email.EmailBackend) {
case "ses":
return NewSESSender(config.SES.Region, config.SES.EndpointURL, config.SES.AccessKeyID, config.SES.SecretAccessKey, config.SES.StsAssumeRoleArn, config.SES.SourceArn)
return NewSESSender(config.SES.Region,
config.SES.EndpointURL,
config.SES.AccessKeyID,
config.SES.SecretAccessKey,
config.SES.StsAssumeRoleArn,
config.SES.StsExternalID,
config.SES.SourceArn,
)
default:
return &mailService{}, nil
}
+6 -2
View File
@@ -41,7 +41,7 @@ func (s *sesSender) SendEmail(e fleet.Email) error {
return s.sendMail(e, msg)
}
func NewSESSender(region, endpointURL, id, secret, stsAssumeRoleArn, sourceArn string) (*sesSender, error) {
func NewSESSender(region, endpointURL, id, secret, stsAssumeRoleArn, stsExternalID, sourceArn string) (*sesSender, error) {
conf := &aws.Config{
Region: &region,
Endpoint: &endpointURL, // empty string or nil will use default values
@@ -59,7 +59,11 @@ func NewSESSender(region, endpointURL, id, secret, stsAssumeRoleArn, sourceArn s
}
if stsAssumeRoleArn != "" {
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn)
creds := stscreds.NewCredentials(sess, stsAssumeRoleArn, func(provider *stscreds.AssumeRoleProvider) {
if stsExternalID != "" {
provider.ExternalID = &stsExternalID
}
})
conf.Credentials = creds
sess, err = session.NewSession(conf)
@@ -44,6 +44,7 @@ No modules.
| <a name="input_s3_bucket_name"></a> [s3\_bucket\_name](#input\_s3\_bucket\_name) | The S3 bucket for carve results to be written to | `string` | n/a | yes |
| <a name="input_s3_bucket_region"></a> [s3\_bucket\_region](#input\_s3\_bucket\_region) | The S3 bucket region | `string` | n/a | yes |
| <a name="input_s3_carve_prefix"></a> [s3\_carve\_prefix](#input\_s3\_carve\_prefix) | The S3 object prefix to use when storing carve results | `string` | `""` | no |
| <a name="input_sts_external_id"></a> [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no |
## Outputs
@@ -1,6 +1,7 @@
output "fleet_extra_environment_variables" {
value = {
FLEET_S3_STS_ASSUME_ROLE_ARN = var.iam_role_arn
FLEET_S3_STS_EXTERNAL_ID = var.sts_external_id
FLEET_S3_BUCKET = var.s3_bucket_name
FLEET_S3_REGION = var.s3_bucket_region
FLEET_S3_PREFIX = var.s3_carve_prefix
@@ -3,6 +3,12 @@ variable "iam_role_arn" {
description = "IAM Role ARN to assume into for file carving uploads to S3"
}
variable "sts_external_id" {
type = string
description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity."
default = ""
}
variable "s3_bucket_name" {
type = string
description = "The S3 bucket for carve results to be written to"
@@ -47,6 +47,7 @@ No modules.
| [aws_iam_role_policy_attachment.s3_access_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_kms_key.s3_encryption_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_s3_bucket.carve_results_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
| [aws_s3_bucket_public_access_block.carve_results](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
| [aws_s3_bucket_server_side_encryption_configuration.sse](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -59,6 +60,7 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_bucket_name"></a> [bucket\_name](#input\_bucket\_name) | The name of the osquery carve results bucket | `string` | n/a | yes |
| <a name="input_fleet_iam_role_arn"></a> [fleet\_iam\_role\_arn](#input\_fleet\_iam\_role\_arn) | The IAM role ARN of the Fleet service | `string` | n/a | yes |
| <a name="input_sts_external_id"></a> [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no |
## Outputs
@@ -90,6 +90,14 @@ data "aws_iam_policy_document" "assume_role" {
identifiers = [var.fleet_iam_role_arn]
type = "AWS"
}
dynamic "condition" {
for_each = length(var.sts_external_id) > 0 ? [1] : []
content {
test = "StringEquals"
variable = "sts:ExternalId"
values = [var.sts_external_id]
}
}
}
}
@@ -6,4 +6,10 @@ variable "bucket_name" {
variable "fleet_iam_role_arn" {
type = string
description = "The IAM role ARN of the Fleet service"
}
variable "sts_external_id" {
type = string
description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity."
default = ""
}
@@ -1,4 +1,3 @@
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
@@ -22,15 +21,17 @@ No modules.
|------|------|
| [aws_iam_policy.fleet-assume-role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy_document.fleet-assume-role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_firehose_audit_name"></a> [firehose\_audit\_name](#input\_firehose\_audit\_name) | name of the firehose delivery stream for fleet audit logs | `string` | n/a | yes |
| <a name="input_firehose_results_name"></a> [firehose\_results\_name](#input\_firehose\_results\_name) | name of the firehose delivery stream for osquery results logs | `string` | n/a | yes |
| <a name="input_firehose_status_name"></a> [firehose\_status\_name](#input\_firehose\_status\_name) | name of the firehose delivery stream for osquery status logs | `string` | n/a | yes |
| <a name="input_iam_role_arn"></a> [iam\_role\_arn](#input\_iam\_role\_arn) | IAM Role ARN to use for Firehose destination logging | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | region the target firehose delivery stream is in | `string` | n/a | yes |
| <a name="input_sts_external_id"></a> [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no |
## Outputs
@@ -38,4 +39,3 @@ No modules.
|------|-------------|
| <a name="output_fleet_extra_environment_variables"></a> [fleet\_extra\_environment\_variables](#output\_fleet\_extra\_environment\_variables) | n/a |
| <a name="output_fleet_extra_iam_policies"></a> [fleet\_extra\_iam\_policies](#output\_fleet\_extra\_iam\_policies) | n/a |
<!-- END_TF_DOCS -->
@@ -4,6 +4,7 @@ output "fleet_extra_environment_variables" {
FLEET_FIREHOSE_RESULT_STREAM = var.firehose_results_name
FLEET_FIREHOSE_AUDIT_STREAM = var.firehose_audit_name
FLEET_FIREHOSE_STS_ASSUME_ROLE_ARN = var.iam_role_arn
FLEET_FIREHOSE_STS_EXTERNAL_ID = var.sts_external_id
FLEET_FIREHOSE_REGION = var.region
FLEET_OSQUERY_STATUS_LOG_PLUGIN = "firehose"
FLEET_OSQUERY_RESULT_LOG_PLUGIN = "firehose"
@@ -22,3 +22,9 @@ variable "region" {
type = string
description = "region the target firehose delivery stream is in"
}
variable "sts_external_id" {
type = string
description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity."
default = ""
}
@@ -54,9 +54,10 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_fleet_iam_role_arn"></a> [fleet\_iam\_role\_arn](#input\_fleet\_iam\_role\_arn) | the arn of the fleet role that firehose will assume to write data to your bucket | `string` | n/a | yes |
| <a name="input_kms_key_arn"></a> [kms\_key\_arn](#input\_kms\_key\_arn) | An optional KMS key ARN for server-side encryption. If not provided and encryption is enabled, a new key will be created. | `string` | `""` | no |
| <a name="input_log_destinations"></a> [log\_destinations](#input\_log\_destinations) | A map of configurations for Firehose delivery streams. | <pre>map(object({<br> name = string<br> prefix = string<br> error_output_prefix = string<br> buffering_size = number<br> buffering_interval = number<br> compression_format = string<br> }))</pre> | <pre>{<br> "audit": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "audit/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "fleet_audit",<br> "prefix": "audit/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> },<br> "results": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "results/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "osquery_results",<br> "prefix": "results/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> },<br> "status": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "status/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "osquery_status",<br> "prefix": "status/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> }<br>}</pre> | no |
| <a name="input_log_destinations"></a> [log\_destinations](#input\_log\_destinations) | A map of configurations for Firehose delivery streams. | <pre>map(object({<br> name = string<br> prefix = string<br> error_output_prefix = string<br> buffering_size = number<br> buffering_interval = number<br> compression_format = string<br> }))</pre> | <pre>{<br> "audit": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "audit/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "fleet_audit",<br> "prefix": "audit/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> },<br> "results": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "results/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "osquery_results",<br> "prefix": "results/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> },<br> "status": {<br> "buffering_interval": 120,<br> "buffering_size": 20,<br> "compression_format": "UNCOMPRESSED",<br> "error_output_prefix": "status/error/error=!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",<br> "name": "osquery_status",<br> "prefix": "status/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"<br> }<br>}</pre> | no |
| <a name="input_osquery_logging_destination_bucket_name"></a> [osquery\_logging\_destination\_bucket\_name](#input\_osquery\_logging\_destination\_bucket\_name) | name of the bucket to store osquery results & status logs | `string` | n/a | yes |
| <a name="input_server_side_encryption_enabled"></a> [server\_side\_encryption\_enabled](#input\_server\_side\_encryption\_enabled) | A boolean flag to enable/disable server-side encryption. Defaults to true (enabled). | `bool` | `true` | no |
| <a name="input_sts_external_id"></a> [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no |
## Outputs
@@ -10,6 +10,14 @@ data "aws_iam_policy_document" "assume_role" {
identifiers = [var.fleet_iam_role_arn]
type = "AWS"
}
dynamic "condition" {
for_each = length(var.sts_external_id) > 0 ? [1] : []
content {
test = "StringEquals"
variable = "sts:ExternalId"
values = [var.sts_external_id]
}
}
}
}
@@ -8,15 +8,21 @@ variable "fleet_iam_role_arn" {
description = "The ARN of the IAM role that will be assumed to gain permissions required to write to the Kinesis Firehose delivery stream."
}
variable "sts_external_id" {
type = string
description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity."
default = ""
}
variable "log_destinations" {
description = "A map of configurations for Firehose delivery streams."
type = map(object({
name = string
prefix = string
error_output_prefix = string
buffering_size = number
buffering_interval = number
compression_format = string
name = string
prefix = string
error_output_prefix = string
buffering_size = number
buffering_interval = number
compression_format = string
}))
default = {
results = {