diff --git a/aws/table_aws_securityhub_finding.go b/aws/table_aws_securityhub_finding.go index 4b2f31622..8eed314e3 100644 --- a/aws/table_aws_securityhub_finding.go +++ b/aws/table_aws_securityhub_finding.go @@ -3,6 +3,7 @@ package aws import ( "context" "strings" + "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/securityhub" @@ -45,6 +46,8 @@ func tableAwsSecurityHubFinding(_ context.Context) *plugin.Table { {Name: "verification_state", Require: plugin.Optional, Operators: []string{"=", "<>"}}, {Name: "workflow_status", Require: plugin.Optional, Operators: []string{"=", "<>"}}, {Name: "source_account_id", Require: plugin.Optional, Operators: []string{"=", "<>"}}, + {Name: "created_at", Require: plugin.Optional, Operators: []string{"=", ">=", ">", "<=", "<"}}, + {Name: "updated_at", Require: plugin.Optional, Operators: []string{"=", ">=", ">", "<=", "<"}}, }, IgnoreConfig: &plugin.IgnoreConfig{ ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"InvalidAccessException"}), @@ -406,9 +409,60 @@ func getSecurityHubFinding(ctx context.Context, d *plugin.QueryData, _ *plugin.H func buildListFindingsParam(quals plugin.KeyColumnQualMap) *types.AwsSecurityFindingFilters { securityFindingsFilter := &types.AwsSecurityFindingFilters{} strFilter := types.StringFilter{} + dateFilter := types.DateFilter{} + timeFormat := "2006-01-02T15:04:05Z" strColumns := []string{"company_name", "compliance_status", "generator_id", "product_arn", "product_name", "record_state", "title", "verification_state", "workflow_state", "workflow_status", "source_account_id"} + timeColumns := []string{"created_at", "updated_at"} + + for _, t := range timeColumns { + if quals[t] == nil { + continue + } + for _, q := range quals[t].Quals { + value := q.Value.GetTimestampValue().AsTime().Format(timeFormat) + if value == "" { + continue + } + + switch q.Operator { + case "=", ">=", ">": + dateFilter.Start = &value + dateFilter.End = aws.String(time.Now().Format(timeFormat)) + case "<", "<=": + dateFilter.End = &value + st, err := time.Parse(timeFormat, value) + if err != nil { + panic("failed to parsing provided value " + value + " for " + t) + } + if t == "updated_at" { + // Default to past 90 days. + // https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings.html + dateFilter.Start = aws.String(st.AddDate(0, 0, -90).Format(timeFormat)) + } else { + // For the query "select * from aws_securityhub_finding where created_at <= current_timestamp - interval '31d'", we are setting the end time based on the query parameter. + // The query doesn't explicitly mention a start date for the creation time. + // AWS retains Security Hub findings updated within the last 90 days, regardless of when they were created. + // There is no strict limit for the creation start time, but we have set it to the date when AWS introduced SecurityHub. The API will return an error if we will not set the Start anf End time all together. + findingIntroduceTime := "2018-11-27T00:00:00Z" + t, err := time.Parse(timeFormat, findingIntroduceTime) + if err != nil { + panic("failed to parse the introduced securityhub findings time") + } + dateFilter.Start = aws.String(t.Format(timeFormat)) + } + + } + } + switch t { + case "created_at": + securityFindingsFilter.CreatedAt = []types.DateFilter{dateFilter} + case "updated_at": + securityFindingsFilter.UpdatedAt = []types.DateFilter{dateFilter} + } + } + for _, s := range strColumns { if quals[s] == nil { continue diff --git a/docs/tables/aws_securityhub_finding.md b/docs/tables/aws_securityhub_finding.md index 1e43f3741..747890ac3 100644 --- a/docs/tables/aws_securityhub_finding.md +++ b/docs/tables/aws_securityhub_finding.md @@ -163,7 +163,7 @@ from aws_securityhub_finding where severity ->> 'Original' = 'CRITICAL' -and +and created_at >= now() - interval '10' day; ``` @@ -177,7 +177,7 @@ from aws_securityhub_finding where json_extract(severity, '$.Original') = 'CRITICAL' -and +and created_at >= datetime('now', '-10 day'); ``` @@ -192,7 +192,7 @@ select criticality from aws_securityhub_finding -order by +order by criticality desc nulls last; ``` @@ -204,7 +204,7 @@ select criticality from aws_securityhub_finding -order by +order by case when criticality is null then 1 else 0 end, criticality desc; ``` @@ -220,7 +220,7 @@ select company_name from aws_securityhub_finding -where +where company_name = 'Turbot'; ``` @@ -233,7 +233,7 @@ select company_name from aws_securityhub_finding -where +where company_name = 'Turbot'; ``` @@ -276,7 +276,7 @@ select workflow_status from aws_securityhub_finding -where +where workflow_status = 'NOTIFIED'; ``` @@ -289,7 +289,7 @@ select workflow_status from aws_securityhub_finding -where +where workflow_status = 'NOTIFIED'; ``` @@ -310,7 +310,7 @@ select network ->> 'SourcePort' as network_source_port from aws_securityhub_finding -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -328,7 +328,7 @@ select json_extract(network, '$.SourcePort') as network_source_port from aws_securityhub_finding -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -352,7 +352,7 @@ select patch_summary ->> 'RebootOption' as reboot_option from aws_securityhub_finding -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -373,7 +373,7 @@ select json_extract(patch_summary, '$.RebootOption') as reboot_option from aws_securityhub_finding -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -396,7 +396,7 @@ select from aws_securityhub_finding, jsonb_array_elements(vulnerabilities) as v -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -416,7 +416,7 @@ select from aws_securityhub_finding, json_each(vulnerabilities) as v -where +where title = 'EC2 instance involved in SSH brute force attacks.'; ``` @@ -496,30 +496,30 @@ order by Explore which findings are associated with the CIS AWS foundations benchmark in your AWS Security Hub. This can assist in identifying potential security risks or non-compliance issues for your company. ```sql+postgres - select + select title, id, company_name, created_at, criticality, confidence -from +from aws_securityhub_finding -where +where standards_control_arn like '%cis-aws-foundations-benchmark%'; ``` ```sql+sqlite -select +select title, id, company_name, created_at, criticality, confidence -from +from aws_securityhub_finding -where +where standards_control_arn like '%cis-aws-foundations-benchmark%'; ``` @@ -527,34 +527,34 @@ where Identify instances where specific security findings are associated with a particular standard control. This is beneficial in understanding the security posture of your organization by analyzing the criticality and confidence of the findings. ```sql+postgres - select + select f.title, f.id, f.company_name, f.created_at, f.criticality, f.confidence -from +from aws_securityhub_finding as f, aws_securityhub_standards_control as c -where +where c.arn = f.standards_control_arn and c.control_id = 'Config.1'; ``` ```sql+sqlite -select +select f.title, f.id, f.company_name, f.created_at, f.criticality, f.confidence -from +from aws_securityhub_finding as f, aws_securityhub_standards_control as c -where +where c.arn = f.standards_control_arn and c.control_id = 'Config.1'; @@ -709,4 +709,68 @@ group by source_account_id order by source_account_id; +``` + +### Retrieve findings updated within a specific time range +This query retrieves AWS Security Hub findings that were updated within a specified time interval. It provides details such as the ID, company name, the first time the finding was observed, the last update time, criticality, and verification state. + +```sql+postgres +select + id, + company_name, + first_observed_at, + updated_at, + criticality, + verification_state +from + aws_securityhub_finding +where + updated_at between '2023-06-26T13:00:21+05:30' and '2024-07-04T14:45:00+05:30'; +``` + +```sql+sqlite +select + id, + company_name, + first_observed_at, + updated_at, + criticality, + verification_state +from + aws_securityhub_finding +where + updated_at between '2023-06-26T13:00:21+05:30' and '2024-07-04T14:45:00+05:30'; +``` + +### List findings that are created in the last month +This query is useful for retrieving security findings from AWS Security Hub that were created within the last 30 days. It allows you to filter and monitor findings based on their creation date, helping identify recent security issues, assess compliance status, and track product-specific incidents. This can be particularly valuable for auditing, incident response, or compliance reporting, ensuring you're working with the most recent data. + +```sql+postgres +select + id, + company_name, + created_at, + confidence, + compliance_status, + product_name, + product_arn +from + aws_securityhub_finding +where + created_at >= now() - interval '30d'; +``` + +```sql+sqlite +select + id, + company_name, + created_at, + confidence, + compliance_status, + product_name, + product_arn +from + aws_securityhub_finding +where + created_at >= datetime('now', '-30 days'); ``` \ No newline at end of file