From af118c71c317e8ddd2a4e204530e40126ff78166 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 2 Sep 2019 18:08:47 +0200 Subject: [PATCH 01/61] Added a partially copied, partially corrected resource file --- aws/resource_aws_guardduty_filter.go | 215 +++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 aws/resource_aws_guardduty_filter.go diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go new file mode 100644 index 00000000000..d750f4eacc2 --- /dev/null +++ b/aws/resource_aws_guardduty_filter.go @@ -0,0 +1,215 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/guardduty" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsGuardDutyFilter() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsGuardDutyFilterCreate, + Read: resourceAwsGuardDutyFilterRead, + Update: resourceAwsGuardDutyFilterUpdate, + Delete: resourceAwsGuardDutyFilterDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "account_id": { // idk, do we need it + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAwsAccountId, + }, + "detector_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "tags": { + Type: schema.TypeTags, // probably wrong type + Optional: true, + }, + "findingCriteria": { + Type: schema.TypeString, // need to implement a new type + Required: true, + }, + "action": { + Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE + Optional: true, + }, + "invite": { + Type: schema.TypeInteger, + Optional: true, + }, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(60 * time.Second), + Update: schema.DefaultTimeout(60 * time.Second), + }, + } +} + +func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + accountID := d.Get("account_id").(string) + detectorID := d.Get("detector_id").(string) + + input := guardduty.CreateMembersInput{ + AccountDetails: []*guardduty.AccountDetail{{ + AccountId: aws.String(accountID), + Email: aws.String(d.Get("email").(string)), + }}, + DetectorId: aws.String(detectorID), + } + + log.Printf("[DEBUG] Creating GuardDuty Member: %s", input) + _, err := conn.CreateMembers(&input) + if err != nil { + return fmt.Errorf("Creating GuardDuty Member failed: %s", err.Error()) + } + + d.SetId(fmt.Sprintf("%s:%s", detectorID, accountID)) + + if !d.Get("invite").(bool) { + return resourceAwsGuardDutyFilterRead(d, meta) + } + + imi := &guardduty.InviteMembersInput{ + DetectorId: aws.String(detectorID), + AccountIds: []*string{aws.String(accountID)}, + DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), + Message: aws.String(d.Get("invitation_message").(string)), + } + + log.Printf("[INFO] Inviting GuardDuty Member: %s", input) + _, err = conn.InviteMembers(imi) + if err != nil { + return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) + } + + err = inviteGuardDutyMemberWaiter(accountID, detectorID, d.Timeout(schema.TimeoutUpdate), conn) + if err != nil { + return fmt.Errorf("error waiting for GuardDuty Member %q invite: %s", d.Id(), err) + } + + return resourceAwsGuardDutyFilterRead(d, meta) +} + +func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + filterName := d.Get("filterName") + + input := guardduty.GetFilterInput{ + DetectorId: aws.String(d.Id()), + FilterName: aws.String(filterName), + } + + log.Printf("[DEBUG] Reading GuardDuty Filter: %s", input) + filter, err := conn.GetFilter(&input) + + if err != nil { + if isAWSErr(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { + log.Printf("[WARN] GuardDuty detector %q not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", filterName, err.Error()) + } + + d.Set("account_id", filter.Action) + d.Set("account_id", filter.Description) + d.Set("account_id", filter.Name) + d.Set("account_id", filter.Rank) + d.Set("detector_id", d.Id()) + + d.Set("account_id", filter.FindingCriteria) + + // FindingCriteria.Criterion + // Eq + // Gt + // Gte + // Lt + // Lte + // Neq + + return nil +} + +func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + + accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) + if err != nil { + return err + } + + if d.HasChange("invite") { + if d.Get("invite").(bool) { + input := &guardduty.InviteMembersInput{ + DetectorId: aws.String(detectorID), + AccountIds: []*string{aws.String(accountID)}, + DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), + Message: aws.String(d.Get("invitation_message").(string)), + } + + log.Printf("[INFO] Inviting GuardDuty Member: %s", input) + output, err := conn.InviteMembers(input) + if err != nil { + return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) + } + + // {"unprocessedAccounts":[{"result":"The request is rejected because the current account has already invited or is already the GuardDuty master of the given member account ID.","accountId":"067819342479"}]} + if len(output.UnprocessedAccounts) > 0 { + return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), aws.StringValue(output.UnprocessedAccounts[0].Result)) + } + } else { + input := &guardduty.DisassociateMembersInput{ + AccountIds: []*string{aws.String(accountID)}, + DetectorId: aws.String(detectorID), + } + log.Printf("[INFO] Disassociating GuardDuty Member: %s", input) + _, err := conn.DisassociateMembers(input) + if err != nil { + return fmt.Errorf("error disassociating GuardDuty Member %q: %s", d.Id(), err) + } + } + } + + return resourceAwsGuardDutyFilterRead(d, meta) +} + +func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + + accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) + if err != nil { + return err + } + + input := guardduty.DeleteMembersInput{ + AccountIds: []*string{aws.String(accountID)}, + DetectorId: aws.String(detectorID), + } + + log.Printf("[DEBUG] Delete GuardDuty Member: %s", input) + _, err = conn.DeleteMembers(&input) + if err != nil { + return fmt.Errorf("Deleting GuardDuty Member '%s' failed: %s", d.Id(), err.Error()) + } + return nil +} From 70d99dd718cea659feced43675caa910869583ce Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 3 Sep 2019 12:48:39 +0200 Subject: [PATCH 02/61] Fixed or workarounded syntax errors --- aws/provider.go | 1 + aws/resource_aws_guardduty_filter.go | 231 ++++++++++++++------------- 2 files changed, 120 insertions(+), 112 deletions(-) diff --git a/aws/provider.go b/aws/provider.go index 96834ce7345..4d2ec38e1d9 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -623,6 +623,7 @@ func Provider() terraform.ResourceProvider { "aws_glue_trigger": resourceAwsGlueTrigger(), "aws_glue_workflow": resourceAwsGlueWorkflow(), "aws_guardduty_detector": resourceAwsGuardDutyDetector(), + "aws_guardduty_filter": resourceAwsGuardDutyFilter(), "aws_guardduty_invite_accepter": resourceAwsGuardDutyInviteAccepter(), "aws_guardduty_ipset": resourceAwsGuardDutyIpset(), "aws_guardduty_member": resourceAwsGuardDutyMember(), diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index d750f4eacc2..bd92ab9c50b 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -12,21 +12,21 @@ import ( func resourceAwsGuardDutyFilter() *schema.Resource { return &schema.Resource{ - Create: resourceAwsGuardDutyFilterCreate, - Read: resourceAwsGuardDutyFilterRead, - Update: resourceAwsGuardDutyFilterUpdate, + // Create: resourceAwsGuardDutyFilterCreate, + Read: resourceAwsGuardDutyFilterRead, + // Update: resourceAwsGuardDutyFilterUpdate, Delete: resourceAwsGuardDutyFilterDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, + // Importer: &schema.ResourceImporter{ + // State: schema.ImportStatePassthrough, + // }, Schema: map[string]*schema.Schema{ - "account_id": { // idk, do we need it - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateAwsAccountId, - }, + // "account_id": { // idk, do we need it + // Type: schema.TypeString, + // Required: true, + // ForceNew: true, + // ValidateFunc: validateAwsAccountId, + // }, "detector_id": { Type: schema.TypeString, Required: true, @@ -35,26 +35,31 @@ func resourceAwsGuardDutyFilter() *schema.Resource { "name": { Type: schema.TypeString, Required: true, + ForceNew: true, // perhaps remove here and below, when Update is back }, "description": { Type: schema.TypeString, Optional: true, + ForceNew: true, // perhaps remove here and below, when Update is back }, - "tags": { - Type: schema.TypeTags, // probably wrong type - Optional: true, - }, - "findingCriteria": { - Type: schema.TypeString, // need to implement a new type - Required: true, - }, + // "tags": { // Must be added back + // Type: schema.TypeTags, // probably wrong type + // Optional: true, + // }, + // "findingCriteria": { + // Type: schema.TypeString, // need to implement a new type + // Optional: true, // change to required + // ForceNew: true, // perhaps remove here and below, when Update is back + // }, "action": { Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE Optional: true, + ForceNew: true, // perhaps remove here and below, when Update is back }, - "invite": { - Type: schema.TypeInteger, + "rank": { + Type: schema.TypeInt, Optional: true, + ForceNew: true, // perhaps remove here and below, when Update is back }, }, Timeouts: &schema.ResourceTimeout{ @@ -64,58 +69,59 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } -func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).guarddutyconn - accountID := d.Get("account_id").(string) - detectorID := d.Get("detector_id").(string) - - input := guardduty.CreateMembersInput{ - AccountDetails: []*guardduty.AccountDetail{{ - AccountId: aws.String(accountID), - Email: aws.String(d.Get("email").(string)), - }}, - DetectorId: aws.String(detectorID), - } - - log.Printf("[DEBUG] Creating GuardDuty Member: %s", input) - _, err := conn.CreateMembers(&input) - if err != nil { - return fmt.Errorf("Creating GuardDuty Member failed: %s", err.Error()) - } - - d.SetId(fmt.Sprintf("%s:%s", detectorID, accountID)) - - if !d.Get("invite").(bool) { - return resourceAwsGuardDutyFilterRead(d, meta) - } - - imi := &guardduty.InviteMembersInput{ - DetectorId: aws.String(detectorID), - AccountIds: []*string{aws.String(accountID)}, - DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), - Message: aws.String(d.Get("invitation_message").(string)), - } - - log.Printf("[INFO] Inviting GuardDuty Member: %s", input) - _, err = conn.InviteMembers(imi) - if err != nil { - return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) - } - - err = inviteGuardDutyMemberWaiter(accountID, detectorID, d.Timeout(schema.TimeoutUpdate), conn) - if err != nil { - return fmt.Errorf("error waiting for GuardDuty Member %q invite: %s", d.Id(), err) - } - - return resourceAwsGuardDutyFilterRead(d, meta) -} +// func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { +// conn := meta.(*AWSClient).guarddutyconn +// accountID := d.Get("account_id").(string) +// detectorID := d.Get("detector_id").(string) +// +// input := guardduty.CreateMembersInput{ +// AccountDetails: []*guardduty.AccountDetail{{ +// AccountId: aws.String(accountID), +// Email: aws.String(d.Get("email").(string)), +// }}, +// DetectorId: aws.String(detectorID), +// } +// +// log.Printf("[DEBUG] Creating GuardDuty Member: %s", input) +// _, err := conn.CreateMembers(&input) +// if err != nil { +// return fmt.Errorf("Creating GuardDuty Member failed: %s", err.Error()) +// } +// +// d.SetId(fmt.Sprintf("%s:%s", detectorID, accountID)) +// +// if !d.Get("invite").(bool) { +// return resourceAwsGuardDutyFilterRead(d, meta) +// } +// +// imi := &guardduty.InviteMembersInput{ +// DetectorId: aws.String(detectorID), +// AccountIds: []*string{aws.String(accountID)}, +// DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), +// Message: aws.String(d.Get("invitation_message").(string)), +// } +// +// log.Printf("[INFO] Inviting GuardDuty Member: %s", input) +// _, err = conn.InviteMembers(imi) +// if err != nil { +// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) +// } +// +// err = inviteGuardDutyMemberWaiter(accountID, detectorID, d.Timeout(schema.TimeoutUpdate), conn) +// if err != nil { +// return fmt.Errorf("error waiting for GuardDuty Member %q invite: %s", d.Id(), err) +// } +// +// return resourceAwsGuardDutyFilterRead(d, meta) +// } func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn - filterName := d.Get("filterName") + detectorId := d.Get("detectorId").(string) + filterName := d.Get("filterName").(string) input := guardduty.GetFilterInput{ - DetectorId: aws.String(d.Id()), + DetectorId: aws.String(detectorId), FilterName: aws.String(filterName), } @@ -137,7 +143,8 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.Set("account_id", filter.Rank) d.Set("detector_id", d.Id()) - d.Set("account_id", filter.FindingCriteria) + // need to find a way how to fill it interface{} + // d.Set("account_id", filter.FindingCriteria) // FindingCriteria.Criterion // Eq @@ -150,48 +157,48 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return nil } -func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).guarddutyconn - - accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) - if err != nil { - return err - } - - if d.HasChange("invite") { - if d.Get("invite").(bool) { - input := &guardduty.InviteMembersInput{ - DetectorId: aws.String(detectorID), - AccountIds: []*string{aws.String(accountID)}, - DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), - Message: aws.String(d.Get("invitation_message").(string)), - } - - log.Printf("[INFO] Inviting GuardDuty Member: %s", input) - output, err := conn.InviteMembers(input) - if err != nil { - return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) - } - - // {"unprocessedAccounts":[{"result":"The request is rejected because the current account has already invited or is already the GuardDuty master of the given member account ID.","accountId":"067819342479"}]} - if len(output.UnprocessedAccounts) > 0 { - return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), aws.StringValue(output.UnprocessedAccounts[0].Result)) - } - } else { - input := &guardduty.DisassociateMembersInput{ - AccountIds: []*string{aws.String(accountID)}, - DetectorId: aws.String(detectorID), - } - log.Printf("[INFO] Disassociating GuardDuty Member: %s", input) - _, err := conn.DisassociateMembers(input) - if err != nil { - return fmt.Errorf("error disassociating GuardDuty Member %q: %s", d.Id(), err) - } - } - } - - return resourceAwsGuardDutyFilterRead(d, meta) -} +// func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { +// conn := meta.(*AWSClient).guarddutyconn +// +// accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) +// if err != nil { +// return err +// } +// +// if d.HasChange("invite") { +// if d.Get("invite").(bool) { +// input := &guardduty.InviteMembersInput{ +// DetectorId: aws.String(detectorID), +// AccountIds: []*string{aws.String(accountID)}, +// DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), +// Message: aws.String(d.Get("invitation_message").(string)), +// } +// +// log.Printf("[INFO] Inviting GuardDuty Member: %s", input) +// output, err := conn.InviteMembers(input) +// if err != nil { +// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) +// } +// +// // {"unprocessedAccounts":[{"result":"The request is rejected because the current account has already invited or is already the GuardDuty master of the given member account ID.","accountId":"067819342479"}]} +// if len(output.UnprocessedAccounts) > 0 { +// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), aws.StringValue(output.UnprocessedAccounts[0].Result)) +// } +// } else { +// input := &guardduty.DisassociateMembersInput{ +// AccountIds: []*string{aws.String(accountID)}, +// DetectorId: aws.String(detectorID), +// } +// log.Printf("[INFO] Disassociating GuardDuty Member: %s", input) +// _, err := conn.DisassociateMembers(input) +// if err != nil { +// return fmt.Errorf("error disassociating GuardDuty Member %q: %s", d.Id(), err) +// } +// } +// } +// +// return resourceAwsGuardDutyFilterRead(d, meta) +// } func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn From 622fe203f167cf1e7235106610dc069abdd6101a Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 3 Sep 2019 15:07:48 +0200 Subject: [PATCH 03/61] Made Create action uncommented and not crashing --- aws/resource_aws_guardduty_filter.go | 68 +++++++++------------------- 1 file changed, 21 insertions(+), 47 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index bd92ab9c50b..1d59ce14039 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -12,8 +12,8 @@ import ( func resourceAwsGuardDutyFilter() *schema.Resource { return &schema.Resource{ - // Create: resourceAwsGuardDutyFilterCreate, - Read: resourceAwsGuardDutyFilterRead, + Create: resourceAwsGuardDutyFilterCreate, + Read: resourceAwsGuardDutyFilterRead, // Update: resourceAwsGuardDutyFilterUpdate, Delete: resourceAwsGuardDutyFilterDelete, @@ -69,51 +69,25 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } -// func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { -// conn := meta.(*AWSClient).guarddutyconn -// accountID := d.Get("account_id").(string) -// detectorID := d.Get("detector_id").(string) -// -// input := guardduty.CreateMembersInput{ -// AccountDetails: []*guardduty.AccountDetail{{ -// AccountId: aws.String(accountID), -// Email: aws.String(d.Get("email").(string)), -// }}, -// DetectorId: aws.String(detectorID), -// } -// -// log.Printf("[DEBUG] Creating GuardDuty Member: %s", input) -// _, err := conn.CreateMembers(&input) -// if err != nil { -// return fmt.Errorf("Creating GuardDuty Member failed: %s", err.Error()) -// } -// -// d.SetId(fmt.Sprintf("%s:%s", detectorID, accountID)) -// -// if !d.Get("invite").(bool) { -// return resourceAwsGuardDutyFilterRead(d, meta) -// } -// -// imi := &guardduty.InviteMembersInput{ -// DetectorId: aws.String(detectorID), -// AccountIds: []*string{aws.String(accountID)}, -// DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), -// Message: aws.String(d.Get("invitation_message").(string)), -// } -// -// log.Printf("[INFO] Inviting GuardDuty Member: %s", input) -// _, err = conn.InviteMembers(imi) -// if err != nil { -// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) -// } -// -// err = inviteGuardDutyMemberWaiter(accountID, detectorID, d.Timeout(schema.TimeoutUpdate), conn) -// if err != nil { -// return fmt.Errorf("error waiting for GuardDuty Member %q invite: %s", d.Id(), err) -// } -// -// return resourceAwsGuardDutyFilterRead(d, meta) -// } +func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + + input := guardduty.CreateFilterInput{ + Name: aws.String(d.Get("name").(string)), + Description: aws.String(d.Get("description").(string)), + Action: aws.String(d.Get("action").(string)), + Rank: aws.Int64(int64(d.Get("rank").(int))), + } + + log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) + output, err := conn.CreateFilter(&input) + if err != nil { + return fmt.Errorf("Creating GuardDuty Filter failed: %s", err.Error()) + } + d.SetId(*output.Name) + + return resourceAwsGuardDutyFilterRead(d, meta) +} func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn From 8852d147ccdf2abe1411ce67514cd38c70f4178f Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 4 Sep 2019 18:49:26 +0200 Subject: [PATCH 04/61] Made Create action to make its way to the API request --- aws/resource_aws_guardduty_filter.go | 112 ++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 1d59ce14039..83c2de4acd0 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -20,7 +20,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { // Importer: &schema.ResourceImporter{ // State: schema.ImportStatePassthrough, // }, - Schema: map[string]*schema.Schema{ + Schema: map[string]*schema.Schema{ // TODO: add validations // "account_id": { // idk, do we need it // Type: schema.TypeString, // Required: true, @@ -46,11 +46,58 @@ func resourceAwsGuardDutyFilter() *schema.Resource { // Type: schema.TypeTags, // probably wrong type // Optional: true, // }, - // "findingCriteria": { - // Type: schema.TypeString, // need to implement a new type - // Optional: true, // change to required - // ForceNew: true, // perhaps remove here and below, when Update is back - // }, + "finding_criteria": { + Type: schema.TypeList, // Probably need to use FindingCriteria type + MaxItems: 1, + Required: true, // change to required + ForceNew: true, // perhaps remove here and below, when Update is back + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "criterion": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "condition": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "greater_than": { + Type: schema.TypeInt, + Optional: true, + }, + "greater_than_or_equal": { + Type: schema.TypeInt, + Optional: true, + }, + "less_than": { + Type: schema.TypeInt, + Optional: true, + }, + "less_than_or_equal": { + Type: schema.TypeInt, + Optional: true, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, "action": { Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE Optional: true, @@ -73,12 +120,54 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) conn := meta.(*AWSClient).guarddutyconn input := guardduty.CreateFilterInput{ + DetectorId: aws.String(d.Get("detector_id").(string)), Name: aws.String(d.Get("name").(string)), Description: aws.String(d.Get("description").(string)), - Action: aws.String(d.Get("action").(string)), Rank: aws.Int64(int64(d.Get("rank").(int))), } + // building FindingCriteria + findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) + criterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) + condition := criterion["condition"].(*schema.Set).List()[0].(map[string]interface{}) + + interfaceForEquals := condition["equals"].([]interface{}) + + equals := make([]string, len(interfaceForEquals)) + for i, v := range interfaceForEquals { + new[i] = string(v.(string)) + } + + interfaceForNotEquals := condition["equals"].([]interface{}) + + notEquals := make([]string, len(interfaceForNotEquals)) + for i, v := range interfaceForNotEquals { + new[i] = string(v.(string)) + } + + input.FindingCriteria = &guardduty.FindingCriteria{ + Criterion: map[string]*guardduty.Condition{ // with star or without, that't the question! + "condition": &guardduty.Condition{ + Equals: aws.StringSlice(equals), + GreaterThan: aws.Int64(int64(condition["greater_than"].(int))), + GreaterThanOrEqual: aws.Int64(int64(condition["greater_than_or_equal"].(int))), + LessThan: aws.Int64(int64(condition["less_than"].(int))), + LessThanOrEqual: aws.Int64(int64(condition["less_than_or_equal"].(int))), + NotEquals: aws.StringSlice(notEquals), //aws.StringSlice([]string(condition["equals"].([]interface{}))), + }, + }, + } + log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) + + // Setting the default value for `action` + action := "NOOP" + + if len(d.Get("action").(string)) > 0 { + action = d.Get("action").(string) + } + + input.Action = aws.String(action) + log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) output, err := conn.CreateFilter(&input) if err != nil { @@ -111,11 +200,10 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", filterName, err.Error()) } - d.Set("account_id", filter.Action) - d.Set("account_id", filter.Description) - d.Set("account_id", filter.Name) - d.Set("account_id", filter.Rank) - d.Set("detector_id", d.Id()) + d.Set("action", filter.Action) + d.Set("description", filter.Description) + d.Set("rank", filter.Rank) + d.Set("name", d.Id()) // need to find a way how to fill it interface{} // d.Set("account_id", filter.FindingCriteria) From 6f7535a6f70799abf039229af79dea8909f93c35 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 11 Sep 2019 15:10:17 +0200 Subject: [PATCH 05/61] Added tags field for creation --- aws/resource_aws_guardduty_filter.go | 30 ++++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 83c2de4acd0..d4f96dcfe93 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -42,14 +42,11 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Optional: true, ForceNew: true, // perhaps remove here and below, when Update is back }, - // "tags": { // Must be added back - // Type: schema.TypeTags, // probably wrong type - // Optional: true, - // }, + "tags": tagsSchemaForceNew(), "finding_criteria": { - Type: schema.TypeList, // Probably need to use FindingCriteria type + Type: schema.TypeList, MaxItems: 1, - Required: true, // change to required + Required: true, ForceNew: true, // perhaps remove here and below, when Update is back Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -126,7 +123,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) Rank: aws.Int64(int64(d.Get("rank").(int))), } - // building FindingCriteria + // building `FindingCriteria` findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) criterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) condition := criterion["condition"].(*schema.Set).List()[0].(map[string]interface{}) @@ -135,25 +132,36 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) equals := make([]string, len(interfaceForEquals)) for i, v := range interfaceForEquals { - new[i] = string(v.(string)) + equals[i] = string(v.(string)) // Maybe aws.string? } interfaceForNotEquals := condition["equals"].([]interface{}) notEquals := make([]string, len(interfaceForNotEquals)) for i, v := range interfaceForNotEquals { - new[i] = string(v.(string)) + notEquals[i] = string(v.(string)) + } + + if len(d.Get("tags")) > 0 { + tagsInterface := d.Get("tags").(map[string]interface{}) + + tags := make(map[string]*string, len(tagsInterface)) + for i, v := range tagsInterface { + tags[i] = aws.String(v.(string)) + } + + input.Tags = tags } input.FindingCriteria = &guardduty.FindingCriteria{ - Criterion: map[string]*guardduty.Condition{ // with star or without, that't the question! + Criterion: map[string]*guardduty.Condition{ "condition": &guardduty.Condition{ Equals: aws.StringSlice(equals), GreaterThan: aws.Int64(int64(condition["greater_than"].(int))), GreaterThanOrEqual: aws.Int64(int64(condition["greater_than_or_equal"].(int))), LessThan: aws.Int64(int64(condition["less_than"].(int))), LessThanOrEqual: aws.Int64(int64(condition["less_than_or_equal"].(int))), - NotEquals: aws.StringSlice(notEquals), //aws.StringSlice([]string(condition["equals"].([]interface{}))), + NotEquals: aws.StringSlice(notEquals), }, }, } From 17e3fb404e366e02fb2502d9cd4bb610f82c9814 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 11 Sep 2019 15:18:35 +0200 Subject: [PATCH 06/61] Fixed tags assignment --- aws/resource_aws_guardduty_filter.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index d4f96dcfe93..57dbf3758cb 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -142,9 +142,8 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) notEquals[i] = string(v.(string)) } - if len(d.Get("tags")) > 0 { - tagsInterface := d.Get("tags").(map[string]interface{}) - + tagsInterface := d.Get("tags").(map[string]interface{}) + if len(tagsInterface) > 0 { tags := make(map[string]*string, len(tagsInterface)) for i, v := range tagsInterface { tags[i] = aws.String(v.(string)) From 7f22a945eed156b53da4d5b18cd02ab24018fe7d Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 11 Sep 2019 17:06:30 +0200 Subject: [PATCH 07/61] Made create request work for region only condition --- aws/resource_aws_guardduty_filter.go | 122 +++++++++++++++++++++------ 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 57dbf3758cb..68307407a52 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -55,7 +55,77 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "condition": &schema.Schema{ + "account_id": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "confidence": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "greater_than": { + Type: schema.TypeInt, + Optional: true, + }, + "greater_than_or_equal": { + Type: schema.TypeInt, + Optional: true, + }, + "less_than": { + Type: schema.TypeInt, + Optional: true, + }, + "less_than_or_equal": { + Type: schema.TypeInt, + Optional: true, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "id": &schema.Schema{ Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ @@ -102,7 +172,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { }, "rank": { Type: schema.TypeInt, - Optional: true, + Required: true, ForceNew: true, // perhaps remove here and below, when Update is back }, }, @@ -126,7 +196,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) // building `FindingCriteria` findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) criterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) - condition := criterion["condition"].(*schema.Set).List()[0].(map[string]interface{}) + condition := criterion["region"].(*schema.Set).List()[0].(map[string]interface{}) interfaceForEquals := condition["equals"].([]interface{}) @@ -135,7 +205,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) equals[i] = string(v.(string)) // Maybe aws.string? } - interfaceForNotEquals := condition["equals"].([]interface{}) + interfaceForNotEquals := condition["not_equals"].([]interface{}) notEquals := make([]string, len(interfaceForNotEquals)) for i, v := range interfaceForNotEquals { @@ -152,15 +222,23 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) input.Tags = tags } + //input.FindingCriteria = &guardduty.FindingCriteria{ + // Criterion: map[string]*guardduty.Condition{ + // "condition": &guardduty.Condition{ + // Equals: aws.StringSlice(equals), + // GreaterThan: aws.Int64(int64(condition["greater_than"].(int))), + // GreaterThanOrEqual: aws.Int64(int64(condition["greater_than_or_equal"].(int))), + // LessThan: aws.Int64(int64(condition["less_than"].(int))), + // LessThanOrEqual: aws.Int64(int64(condition["less_than_or_equal"].(int))), + // NotEquals: aws.StringSlice(notEquals), + // }, + // }, + //} + // Currently it works only for region, must be expanded to all other resources input.FindingCriteria = &guardduty.FindingCriteria{ Criterion: map[string]*guardduty.Condition{ - "condition": &guardduty.Condition{ - Equals: aws.StringSlice(equals), - GreaterThan: aws.Int64(int64(condition["greater_than"].(int))), - GreaterThanOrEqual: aws.Int64(int64(condition["greater_than_or_equal"].(int))), - LessThan: aws.Int64(int64(condition["less_than"].(int))), - LessThanOrEqual: aws.Int64(int64(condition["less_than_or_equal"].(int))), - NotEquals: aws.StringSlice(notEquals), + "region": &guardduty.Condition{ + Equals: aws.StringSlice(equals), }, }, } @@ -180,6 +258,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) if err != nil { return fmt.Errorf("Creating GuardDuty Filter failed: %s", err.Error()) } + d.SetId(*output.Name) return resourceAwsGuardDutyFilterRead(d, meta) @@ -187,12 +266,12 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn - detectorId := d.Get("detectorId").(string) - filterName := d.Get("filterName").(string) + detectorId := d.Get("detector_id").(string) + name := d.Get("name").(string) input := guardduty.GetFilterInput{ DetectorId: aws.String(detectorId), - FilterName: aws.String(filterName), + FilterName: aws.String(name), } log.Printf("[DEBUG] Reading GuardDuty Filter: %s", input) @@ -204,25 +283,14 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.SetId("") return nil } - return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", filterName, err.Error()) + return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) } - d.Set("action", filter.Action) + d.Set("action", filter.Action) // Make sure I really want to set all these attrs d.Set("description", filter.Description) d.Set("rank", filter.Rank) d.Set("name", d.Id()) - // need to find a way how to fill it interface{} - // d.Set("account_id", filter.FindingCriteria) - - // FindingCriteria.Criterion - // Eq - // Gt - // Gte - // Lt - // Lte - // Neq - return nil } From fc29555a83db25e5081e4538573572c8806fbf68 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 11 Sep 2019 17:52:09 +0200 Subject: [PATCH 08/61] Implemented DELETE action for filters --- aws/resource_aws_guardduty_filter.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 68307407a52..dc6612d27d4 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -340,20 +340,19 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn - accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) - if err != nil { - return err - } + detectorId := d.Get("detector_id").(string) + name := d.Get("name").(string) - input := guardduty.DeleteMembersInput{ - AccountIds: []*string{aws.String(accountID)}, - DetectorId: aws.String(detectorID), + input := guardduty.DeleteFilterInput{ + FilterName: aws.String(name), + DetectorId: aws.String(detectorId), } - log.Printf("[DEBUG] Delete GuardDuty Member: %s", input) - _, err = conn.DeleteMembers(&input) + log.Printf("[DEBUG] Delete GuardDuty Filter: %s", input) + + _, err := conn.DeleteFilter(&input) if err != nil { - return fmt.Errorf("Deleting GuardDuty Member '%s' failed: %s", d.Id(), err.Error()) + return fmt.Errorf("Deleting GuardDuty Filter '%s' failed: %s", d.Id(), err.Error()) } return nil } From 031b0f115076c3de3d5753691bf20871acd11484 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Thu, 12 Sep 2019 17:27:35 +0200 Subject: [PATCH 09/61] Filled in finding criteria --- aws/resource_aws_guardduty_filter.go | 796 ++++++++++++++++++++++++++- 1 file changed, 790 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index dc6612d27d4..7eeca6bb23d 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -21,12 +21,6 @@ func resourceAwsGuardDutyFilter() *schema.Resource { // State: schema.ImportStatePassthrough, // }, Schema: map[string]*schema.Schema{ // TODO: add validations - // "account_id": { // idk, do we need it - // Type: schema.TypeString, - // Required: true, - // ForceNew: true, - // ValidateFunc: validateAwsAccountId, - // }, "detector_id": { Type: schema.TypeString, Required: true, @@ -159,6 +153,796 @@ func resourceAwsGuardDutyFilter() *schema.Resource { }, }, }, + "resource.accessKeyDetails.accessKeyId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.accessKeyDetails.principalId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.accessKeyDetails.userName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.accessKeyDetails.userType": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.iamInstanceProfile.id": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.imageId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.instanceId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.ipv6Addresses": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.publicDnsName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.publicIp": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.securityGroups.groupId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.securityGroups.groupName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.subnetId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.networkInterfaces.vpcId": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.tags.key": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.instanceDetails.tags.value": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "resource.resourceType": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.actionType": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.api": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.callerType": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.remoteIpDetails.city.cityName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.remoteIpDetails.country.countryName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.remoteIpDetails.organization.asn": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.awsApiCallAction.serviceName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.dnsRequestAction.domain": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.blocked": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.connectionDirection": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.localPortDetails.port": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.protocol": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remoteIpDetails.city.cityName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remoteIpDetails.country.countryName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remoteIpDetails.organization.asn": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.action.networkConnectionAction.remotePortDetails.port": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.additionalInfo.threatListName": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "service.archived": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeBool, + Optional: true, + }, + "not_equals": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + "service.resourceRole": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "severity": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "type": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "updatedAt": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + }, + }, + }, }, }, }, From e912469c552c9f5fc844ff67e2b3410df7ca3be7 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 14 Oct 2019 09:44:37 +0200 Subject: [PATCH 10/61] Extracted buildFindingCriteria --- aws/resource_aws_guardduty_filter.go | 116 +++++++++++++++++++++------ 1 file changed, 92 insertions(+), 24 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 7eeca6bb23d..605d6589914 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -967,6 +967,96 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } +func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.FindingCriteria { + criteriaMap := map[string][]string{ + "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, + "resource.instanceDetails.imageId": {"equals", "not_equals"}, + "resource.instanceDetails.instanceId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, + "resource.instanceDetails.tags.key": {"equals", "not_equals"}, + "resource.instanceDetails.tags.value": {"equals", "not_equals"}, + "resource.resourceType": {"equals", "not_equals"}, + "service.action.actionType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.api": {"equals", "not_equals"}, + "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, + "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, + "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, + "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, + "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, + "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, + "service.additionalInfo.threatListName": {"equals", "not_equals"}, + "service.archived": {"equals", "not_equals"}, + "service.resourceRole": {"equals", "not_equals"}, + "severity": {"equals", "not_equals"}, + "type": {"equals", "not_equals"}, + "updatedAt": {"equals", "not_equals"}, + } + + inputFindingCriterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) + resultedFindingCriterion := map[string]*guardduty.Condition{} + + for criterion, conditions := range criteriaMap { + condition := inputFindingCriterion[criterion].(*schema.Set).List()[0].(map[string]interface{}) + + + interfaceForEquals := condition["equals"].([]interface{}) + + equals := make([]string, len(interfaceForEquals)) + for i, v := range interfaceForEquals { + equals[i] = string(v.(string)) + } + + resultedFindingCriterion[criterion] := &guardduty.Condition{ + Equals: aws.StringSlice(equals), + }, + + interfaceForNotEquals := condition["not_equals"].([]interface{}) + + notEquals := make([]string, len(interfaceForNotEquals)) + for i, v := range interfaceForNotEquals { + notEquals[i] = string(v.(string)) + } + } + + + log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) + + return &guardduty.FindingCriteria{ + Criterion: map[string]*guardduty.Condition{ + "region": &guardduty.Condition{ + Equals: aws.StringSlice(equals), + }, + }, + } +} + func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn @@ -979,22 +1069,8 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) // building `FindingCriteria` findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) - criterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) - condition := criterion["region"].(*schema.Set).List()[0].(map[string]interface{}) - - interfaceForEquals := condition["equals"].([]interface{}) - - equals := make([]string, len(interfaceForEquals)) - for i, v := range interfaceForEquals { - equals[i] = string(v.(string)) // Maybe aws.string? - } - - interfaceForNotEquals := condition["not_equals"].([]interface{}) - - notEquals := make([]string, len(interfaceForNotEquals)) - for i, v := range interfaceForNotEquals { - notEquals[i] = string(v.(string)) - } + buildFindingCriteria(findingCriteria) + input.FindingCriteria = buildFindingCriteria(findingCriteria) tagsInterface := d.Get("tags").(map[string]interface{}) if len(tagsInterface) > 0 { @@ -1019,14 +1095,6 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) // }, //} // Currently it works only for region, must be expanded to all other resources - input.FindingCriteria = &guardduty.FindingCriteria{ - Criterion: map[string]*guardduty.Condition{ - "region": &guardduty.Condition{ - Equals: aws.StringSlice(equals), - }, - }, - } - log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) // Setting the default value for `action` action := "NOOP" From 7df19ebf0e88077dcb4fd9d459aac3b349a99d9d Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 14 Oct 2019 15:58:28 +0200 Subject: [PATCH 11/61] Changed the format of guard_duty_filter criterion --- aws/resource_aws_guardduty_filter.go | 1062 ++------------------------ 1 file changed, 77 insertions(+), 985 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 605d6589914..fcfa0e811cb 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -49,899 +49,21 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "account_id": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "region": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "confidence": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "greater_than": { - Type: schema.TypeInt, - Optional: true, - }, - "greater_than_or_equal": { - Type: schema.TypeInt, - Optional: true, - }, - "less_than": { - Type: schema.TypeInt, - Optional: true, - }, - "less_than_or_equal": { - Type: schema.TypeInt, - Optional: true, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "id": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "greater_than": { - Type: schema.TypeInt, - Optional: true, - }, - "greater_than_or_equal": { - Type: schema.TypeInt, - Optional: true, - }, - "less_than": { - Type: schema.TypeInt, - Optional: true, - }, - "less_than_or_equal": { - Type: schema.TypeInt, - Optional: true, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.accessKeyDetails.accessKeyId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.accessKeyDetails.principalId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.accessKeyDetails.userName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.accessKeyDetails.userType": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.iamInstanceProfile.id": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.imageId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.instanceId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.ipv6Addresses": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.publicDnsName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, + "field": { + Type: schema.TypeString, + Required: true, + // ValidateFunc: validation.StringInSlice([]string{ + // "region" + // }, false), }, - "resource.instanceDetails.networkInterfaces.publicIp": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.securityGroups.groupId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.securityGroups.groupName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.subnetId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.networkInterfaces.vpcId": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.tags.key": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.instanceDetails.tags.value": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "resource.resourceType": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.actionType": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.api": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.callerType": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.remoteIpDetails.city.cityName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.remoteIpDetails.country.countryName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, + "condition": { + Type: schema.TypeString, + Required: true, }, - "service.action.awsApiCallAction.remoteIpDetails.organization.asn": &schema.Schema{ - Type: schema.TypeSet, + "values": { + Type: schema.TypeList, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.awsApiCallAction.serviceName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.dnsRequestAction.domain": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.blocked": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.connectionDirection": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.localPortDetails.port": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.protocol": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remoteIpDetails.city.cityName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remoteIpDetails.country.countryName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remoteIpDetails.organization.asn": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.action.networkConnectionAction.remotePortDetails.port": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.additionalInfo.threatListName": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "service.archived": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeBool, - Optional: true, - }, - "not_equals": { - Type: schema.TypeBool, - Optional: true, - }, - }, - }, - }, - "service.resourceRole": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "severity": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "type": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "updatedAt": &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeInt}, - }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeInt}, - }, - }, - }, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, @@ -967,94 +89,78 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } +//noinspection GoMissingReturn func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.FindingCriteria { - criteriaMap := map[string][]string{ - "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "account_id": {"equals", "not_equals"}, - "region": {"equals", "not_equals"}, - "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - "resource.accessKeyDetails.userType": {"equals", "not_equals"}, - "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, - "resource.instanceDetails.imageId": {"equals", "not_equals"}, - "resource.instanceDetails.instanceId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, - "resource.instanceDetails.tags.key": {"equals", "not_equals"}, - "resource.instanceDetails.tags.value": {"equals", "not_equals"}, - "resource.resourceType": {"equals", "not_equals"}, - "service.action.actionType": {"equals", "not_equals"}, - "service.action.awsApiCallAction.api": {"equals", "not_equals"}, - "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, - "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, - "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, - "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, - "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, - "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, - "service.additionalInfo.threatListName": {"equals", "not_equals"}, - "service.archived": {"equals", "not_equals"}, - "service.resourceRole": {"equals", "not_equals"}, - "severity": {"equals", "not_equals"}, - "type": {"equals", "not_equals"}, - "updatedAt": {"equals", "not_equals"}, - } - - inputFindingCriterion := findingCriteria["criterion"].(*schema.Set).List()[0].(map[string]interface{}) - resultedFindingCriterion := map[string]*guardduty.Condition{} - - for criterion, conditions := range criteriaMap { - condition := inputFindingCriterion[criterion].(*schema.Set).List()[0].(map[string]interface{}) - - - interfaceForEquals := condition["equals"].([]interface{}) - - equals := make([]string, len(interfaceForEquals)) - for i, v := range interfaceForEquals { - equals[i] = string(v.(string)) + // criteriaMap := map[string][]string{ + // "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + // "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + // "account_id": {"equals", "not_equals"}, + // "region": {"equals", "not_equals"}, + // "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + // "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + // "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + // "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + // "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, + // "resource.instanceDetails.imageId": {"equals", "not_equals"}, + // "resource.instanceDetails.instanceId": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, + // "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, + // "resource.instanceDetails.tags.key": {"equals", "not_equals"}, + // "resource.instanceDetails.tags.value": {"equals", "not_equals"}, + // "resource.resourceType": {"equals", "not_equals"}, + // "service.action.actionType": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.api": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + // "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, + // "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + // "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, + // "service.additionalInfo.threatListName": {"equals", "not_equals"}, + // "service.archived": {"equals", "not_equals"}, + // "service.resourceRole": {"equals", "not_equals"}, + // "severity": {"equals", "not_equals"}, + // "type": {"equals", "not_equals"}, + // "updatedAt": {"equals", "not_equals"}, + // } + // + inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() //[0].(map[string]interface{}) + criteria := map[string]*guardduty.Condition{} + for _, criterion := range inputFindingCriteria { + typedCriterion := criterion.(map[string]interface{}) + log.Printf("[DEBUG!!!!!!!!!!] Criterion info: %#v", criterion) + + values := make([]string, len(typedCriterion["values"].([]interface{}))) + for i, v := range typedCriterion["values"].([]interface{}) { + values[i] = string(v.(string)) } - resultedFindingCriterion[criterion] := &guardduty.Condition{ - Equals: aws.StringSlice(equals), - }, - - interfaceForNotEquals := condition["not_equals"].([]interface{}) - - notEquals := make([]string, len(interfaceForNotEquals)) - for i, v := range interfaceForNotEquals { - notEquals[i] = string(v.(string)) + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + Equals: aws.StringSlice(values), } } - - log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) + log.Printf("[DEBUG] Creating FindingCriteria's criteria map: %#v", criteria) - return &guardduty.FindingCriteria{ - Criterion: map[string]*guardduty.Condition{ - "region": &guardduty.Condition{ - Equals: aws.StringSlice(equals), - }, - }, - } + return &guardduty.FindingCriteria{Criterion: criteria} } func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { @@ -1082,20 +188,6 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) input.Tags = tags } - //input.FindingCriteria = &guardduty.FindingCriteria{ - // Criterion: map[string]*guardduty.Condition{ - // "condition": &guardduty.Condition{ - // Equals: aws.StringSlice(equals), - // GreaterThan: aws.Int64(int64(condition["greater_than"].(int))), - // GreaterThanOrEqual: aws.Int64(int64(condition["greater_than_or_equal"].(int))), - // LessThan: aws.Int64(int64(condition["less_than"].(int))), - // LessThanOrEqual: aws.Int64(int64(condition["less_than_or_equal"].(int))), - // NotEquals: aws.StringSlice(notEquals), - // }, - // }, - //} - // Currently it works only for region, must be expanded to all other resources - // Setting the default value for `action` action := "NOOP" From fb5db6ffc0f73171cd1791830f7842ecab22358d Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 14 Oct 2019 19:35:29 +0200 Subject: [PATCH 12/61] Made different sort of conditions work --- aws/resource_aws_guardduty_filter.go | 55 ++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index fcfa0e811cb..653a2f6719f 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strconv" "time" "github.com/aws/aws-sdk-go/aws" @@ -89,7 +90,6 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } -//noinspection GoMissingReturn func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.FindingCriteria { // criteriaMap := map[string][]string{ // "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, @@ -148,14 +148,33 @@ func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.Fin typedCriterion := criterion.(map[string]interface{}) log.Printf("[DEBUG!!!!!!!!!!] Criterion info: %#v", criterion) - values := make([]string, len(typedCriterion["values"].([]interface{}))) - for i, v := range typedCriterion["values"].([]interface{}) { - values[i] = string(v.(string)) + switch typedCriterion["condition"].(string) { + case "equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + Equals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), + } + case "greater_than": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "greater_than_or_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "less_than": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "less_than_or_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "not_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + NotEquals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), + } } - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - Equals: aws.StringSlice(values), - } } log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) log.Printf("[DEBUG] Creating FindingCriteria's criteria map: %#v", criteria) @@ -163,6 +182,28 @@ func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.Fin return &guardduty.FindingCriteria{Criterion: criteria} } +func conditionValueToStrings(untypedValues []interface{}) []string { + values := make([]string, len(untypedValues)) + for i, v := range untypedValues { + values[i] = string(v.(string)) + } + return values +} + +func conditionValueToInt(untypedValues []interface{}) interface{} { + if len(untypedValues) != 1 { + return fmt.Errorf("Exactly one value must be given for conditions like less_ or greater_than. Instead given: %v", untypedValues) + } + + untypedValue := untypedValues[0] + typedValue, err := strconv.ParseInt(untypedValue.(string), 10, 64) + if err != nil { + return fmt.Errorf("Parsing condition value failed: %s", err.Error()) + } + + return typedValue +} + func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn From c8b32848eda1f2c6ee55777fc91e4262c076b968 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 22 Oct 2019 14:34:22 +0200 Subject: [PATCH 13/61] Added the update action for the guardduty filter --- aws/resource_aws_guardduty_filter.go | 79 ++++++++++++---------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 653a2f6719f..70b120c26e4 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -25,24 +25,20 @@ func resourceAwsGuardDutyFilter() *schema.Resource { "detector_id": { Type: schema.TypeString, Required: true, - ForceNew: true, }, "name": { Type: schema.TypeString, Required: true, - ForceNew: true, // perhaps remove here and below, when Update is back }, "description": { Type: schema.TypeString, Optional: true, - ForceNew: true, // perhaps remove here and below, when Update is back }, "tags": tagsSchemaForceNew(), "finding_criteria": { Type: schema.TypeList, MaxItems: 1, Required: true, - ForceNew: true, // perhaps remove here and below, when Update is back Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "criterion": &schema.Schema{ @@ -279,48 +275,39 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return nil } -// func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { -// conn := meta.(*AWSClient).guarddutyconn -// -// accountID, detectorID, err := decodeGuardDutyMemberID(d.Id()) -// if err != nil { -// return err -// } -// -// if d.HasChange("invite") { -// if d.Get("invite").(bool) { -// input := &guardduty.InviteMembersInput{ -// DetectorId: aws.String(detectorID), -// AccountIds: []*string{aws.String(accountID)}, -// DisableEmailNotification: aws.Bool(d.Get("disable_email_notification").(bool)), -// Message: aws.String(d.Get("invitation_message").(string)), -// } -// -// log.Printf("[INFO] Inviting GuardDuty Member: %s", input) -// output, err := conn.InviteMembers(input) -// if err != nil { -// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), err) -// } -// -// // {"unprocessedAccounts":[{"result":"The request is rejected because the current account has already invited or is already the GuardDuty master of the given member account ID.","accountId":"067819342479"}]} -// if len(output.UnprocessedAccounts) > 0 { -// return fmt.Errorf("error inviting GuardDuty Member %q: %s", d.Id(), aws.StringValue(output.UnprocessedAccounts[0].Result)) -// } -// } else { -// input := &guardduty.DisassociateMembersInput{ -// AccountIds: []*string{aws.String(accountID)}, -// DetectorId: aws.String(detectorID), -// } -// log.Printf("[INFO] Disassociating GuardDuty Member: %s", input) -// _, err := conn.DisassociateMembers(input) -// if err != nil { -// return fmt.Errorf("error disassociating GuardDuty Member %q: %s", d.Id(), err) -// } -// } -// } -// -// return resourceAwsGuardDutyFilterRead(d, meta) -// } +func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).guarddutyconn + + input := guardduty.UpdateFilterInput{ + DetectorId: aws.String(d.Get("detector_id").(string)), + FilterName: aws.String(d.Get("name").(string)), + Description: aws.String(d.Get("description").(string)), + Rank: aws.Int64(int64(d.Get("rank").(int))), + } + + // building `FindingCriteria` + findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) + buildFindingCriteria(findingCriteria) + input.FindingCriteria = buildFindingCriteria(findingCriteria) + + // Setting the default value for `action` + action := "NOOP" + + if len(d.Get("action").(string)) > 0 { + action = d.Get("action").(string) + } + + input.Action = aws.String(action) + + log.Printf("[DEBUG] Updating GuardDuty Filter: %s", input) + + output, err := conn.UpdateFilter(&input) + if err != nil { + return fmt.Errorf("Updating GuardDuty Filter with ID %s failed: %s", d.Id(), err.Error()) + } + + return resourceAwsGuardDutyFilterRead(d, meta) +} func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn From 4dfc52c82884c8fc3fe523c79d3895daa89501f6 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 23 Oct 2019 08:22:34 +0200 Subject: [PATCH 14/61] Cleaned up the action default and unveiled the update action --- aws/resource_aws_guardduty_filter.go | 34 ++++++++-------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 70b120c26e4..207ecab7d7c 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -15,7 +15,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { return &schema.Resource{ Create: resourceAwsGuardDutyFilterCreate, Read: resourceAwsGuardDutyFilterRead, - // Update: resourceAwsGuardDutyFilterUpdate, + Update: resourceAwsGuardDutyFilterUpdate, Delete: resourceAwsGuardDutyFilterDelete, // Importer: &schema.ResourceImporter{ @@ -25,10 +25,12 @@ func resourceAwsGuardDutyFilter() *schema.Resource { "detector_id": { Type: schema.TypeString, Required: true, + ForceNew: true, }, "name": { Type: schema.TypeString, Required: true, + ForceNew: true, }, "description": { Type: schema.TypeString, @@ -70,13 +72,11 @@ func resourceAwsGuardDutyFilter() *schema.Resource { }, "action": { Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE - Optional: true, - ForceNew: true, // perhaps remove here and below, when Update is back + Required: true, }, "rank": { Type: schema.TypeInt, Required: true, - ForceNew: true, // perhaps remove here and below, when Update is back }, }, Timeouts: &schema.ResourceTimeout{ @@ -204,9 +204,10 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) conn := meta.(*AWSClient).guarddutyconn input := guardduty.CreateFilterInput{ + Action: aws.String(d.Get("action").(string)), + Description: aws.String(d.Get("description").(string)), DetectorId: aws.String(d.Get("detector_id").(string)), Name: aws.String(d.Get("name").(string)), - Description: aws.String(d.Get("description").(string)), Rank: aws.Int64(int64(d.Get("rank").(int))), } @@ -225,15 +226,6 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) input.Tags = tags } - // Setting the default value for `action` - action := "NOOP" - - if len(d.Get("action").(string)) > 0 { - action = d.Get("action").(string) - } - - input.Action = aws.String(action) - log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) output, err := conn.CreateFilter(&input) if err != nil { @@ -279,9 +271,10 @@ func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) conn := meta.(*AWSClient).guarddutyconn input := guardduty.UpdateFilterInput{ + Action: aws.String(d.Get("action").(string)), + Description: aws.String(d.Get("description").(string)), DetectorId: aws.String(d.Get("detector_id").(string)), FilterName: aws.String(d.Get("name").(string)), - Description: aws.String(d.Get("description").(string)), Rank: aws.Int64(int64(d.Get("rank").(int))), } @@ -290,18 +283,9 @@ func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) buildFindingCriteria(findingCriteria) input.FindingCriteria = buildFindingCriteria(findingCriteria) - // Setting the default value for `action` - action := "NOOP" - - if len(d.Get("action").(string)) > 0 { - action = d.Get("action").(string) - } - - input.Action = aws.String(action) - log.Printf("[DEBUG] Updating GuardDuty Filter: %s", input) - output, err := conn.UpdateFilter(&input) + _, err := conn.UpdateFilter(&input) if err != nil { return fmt.Errorf("Updating GuardDuty Filter with ID %s failed: %s", d.Id(), err.Error()) } From f990e1e3906af3de0c00b9936b934d9a2612a4b1 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 23 Oct 2019 10:30:41 +0200 Subject: [PATCH 15/61] Added validations for generic cases --- aws/resource_aws_guardduty_filter.go | 133 ++++++++++++++++----------- 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 207ecab7d7c..33b46d61a84 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/guardduty" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" ) func resourceAwsGuardDutyFilter() *schema.Resource { @@ -49,15 +50,21 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "field": { - Type: schema.TypeString, - Required: true, - // ValidateFunc: validation.StringInSlice([]string{ - // "region" - // }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(criteriaFields(), false), }, "condition": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "equals", + "not_equals", + "greater_than", + "greater_than_or_equal", + "less_than", + "less_than_or_equal", + }, false), }, "values": { Type: schema.TypeList, @@ -73,6 +80,10 @@ func resourceAwsGuardDutyFilter() *schema.Resource { "action": { Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "NOOP", + "ARCHIVE", + }, false), }, "rank": { Type: schema.TypeInt, @@ -86,58 +97,68 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } +func criteriaFields() []string { + criteria := make([]string, 0, len(criteriaMap())) + for criterion := range criteriaMap() { + criteria = append(criteria, criterion) + } + return criteria +} + +func criteriaMap() map[string][]string { + return map[string][]string{ + "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, + "resource.instanceDetails.imageId": {"equals", "not_equals"}, + "resource.instanceDetails.instanceId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, + "resource.instanceDetails.tags.key": {"equals", "not_equals"}, + "resource.instanceDetails.tags.value": {"equals", "not_equals"}, + "resource.resourceType": {"equals", "not_equals"}, + "service.action.actionType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.api": {"equals", "not_equals"}, + "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, + "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, + "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, + "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, + "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, + "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, + "service.additionalInfo.threatListName": {"equals", "not_equals"}, + "service.archived": {"equals", "not_equals"}, + "service.resourceRole": {"equals", "not_equals"}, + "severity": {"equals", "not_equals"}, + "type": {"equals", "not_equals"}, + "updatedAt": {"equals", "not_equals"}, + } +} + func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.FindingCriteria { - // criteriaMap := map[string][]string{ - // "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - // "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - // "account_id": {"equals", "not_equals"}, - // "region": {"equals", "not_equals"}, - // "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - // "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - // "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - // "resource.accessKeyDetails.userType": {"equals", "not_equals"}, - // "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, - // "resource.instanceDetails.imageId": {"equals", "not_equals"}, - // "resource.instanceDetails.instanceId": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, - // "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, - // "resource.instanceDetails.tags.key": {"equals", "not_equals"}, - // "resource.instanceDetails.tags.value": {"equals", "not_equals"}, - // "resource.resourceType": {"equals", "not_equals"}, - // "service.action.actionType": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.api": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - // "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, - // "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - // "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, - // "service.additionalInfo.threatListName": {"equals", "not_equals"}, - // "service.archived": {"equals", "not_equals"}, - // "service.resourceRole": {"equals", "not_equals"}, - // "severity": {"equals", "not_equals"}, - // "type": {"equals", "not_equals"}, - // "updatedAt": {"equals", "not_equals"}, - // } - // inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() //[0].(map[string]interface{}) criteria := map[string]*guardduty.Condition{} for _, criterion := range inputFindingCriteria { From 2fa228fc4ad85d92899b6416a88ce51d572c0a8a Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 23 Oct 2019 18:00:34 +0200 Subject: [PATCH 16/61] Implemented on-the-flight validation for the conditions --- aws/resource_aws_guardduty_filter.go | 43 ++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 33b46d61a84..847a4150e95 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -22,7 +22,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { // Importer: &schema.ResourceImporter{ // State: schema.ImportStatePassthrough, // }, - Schema: map[string]*schema.Schema{ // TODO: add validations + Schema: map[string]*schema.Schema{ "detector_id": { Type: schema.TypeString, Required: true, @@ -158,13 +158,29 @@ func criteriaMap() map[string][]string { } } -func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.FindingCriteria { - inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() //[0].(map[string]interface{}) +func conditionAllowedForCriterion(criterion map[string]interface{}) bool { + availableConditions := criteriaMap()[criterion["field"].(string)] + conditionToCheck := criterion["condition"].(string) + + for _, availableCondition := range availableConditions { + if availableCondition == conditionToCheck { + return true + } + } + return false +} + +func buildFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.FindingCriteria, error) { + inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() criteria := map[string]*guardduty.Condition{} for _, criterion := range inputFindingCriteria { typedCriterion := criterion.(map[string]interface{}) log.Printf("[DEBUG!!!!!!!!!!] Criterion info: %#v", criterion) + if !conditionAllowedForCriterion(typedCriterion) { + return nil, fmt.Errorf("The condition is not supported for the given field. Supported conditions are: %v", criteriaMap()[typedCriterion["field"].(string)]) + } + switch typedCriterion["condition"].(string) { case "equals": criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ @@ -196,7 +212,7 @@ func buildFindingCriteria(findingCriteria map[string]interface{}) *guardduty.Fin log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) log.Printf("[DEBUG] Creating FindingCriteria's criteria map: %#v", criteria) - return &guardduty.FindingCriteria{Criterion: criteria} + return &guardduty.FindingCriteria{Criterion: criteria}, nil } func conditionValueToStrings(untypedValues []interface{}) []string { @@ -234,8 +250,12 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) // building `FindingCriteria` findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) - buildFindingCriteria(findingCriteria) - input.FindingCriteria = buildFindingCriteria(findingCriteria) + + var err error + input.FindingCriteria, err = buildFindingCriteria(findingCriteria) + if err != nil { + return err + } tagsInterface := d.Get("tags").(map[string]interface{}) if len(tagsInterface) > 0 { @@ -301,12 +321,17 @@ func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) // building `FindingCriteria` findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) - buildFindingCriteria(findingCriteria) - input.FindingCriteria = buildFindingCriteria(findingCriteria) + + var err error + input.FindingCriteria, err = buildFindingCriteria(findingCriteria) + + if err != nil { + return err + } log.Printf("[DEBUG] Updating GuardDuty Filter: %s", input) - _, err := conn.UpdateFilter(&input) + _, err = conn.UpdateFilter(&input) if err != nil { return fmt.Errorf("Updating GuardDuty Filter with ID %s failed: %s", d.Id(), err.Error()) } From bdba53cb250e208ed02144057ae75d17f3c8329c Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 23 Oct 2019 18:18:12 +0200 Subject: [PATCH 17/61] Cleaned up comments --- aws/resource_aws_guardduty_filter.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 847a4150e95..752e04c7f99 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -78,7 +78,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { }, }, "action": { - Type: schema.TypeString, // should have a new type or a validation for NOOP/ARCHIVE + Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ "NOOP", @@ -175,7 +175,6 @@ func buildFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.Fi criteria := map[string]*guardduty.Condition{} for _, criterion := range inputFindingCriteria { typedCriterion := criterion.(map[string]interface{}) - log.Printf("[DEBUG!!!!!!!!!!] Criterion info: %#v", criterion) if !conditionAllowedForCriterion(typedCriterion) { return nil, fmt.Errorf("The condition is not supported for the given field. Supported conditions are: %v", criteriaMap()[typedCriterion["field"].(string)]) @@ -210,7 +209,6 @@ func buildFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.Fi } log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) - log.Printf("[DEBUG] Creating FindingCriteria's criteria map: %#v", criteria) return &guardduty.FindingCriteria{Criterion: criteria}, nil } @@ -300,10 +298,12 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) } - d.Set("action", filter.Action) // Make sure I really want to set all these attrs + d.Set("action", filter.Action) d.Set("description", filter.Description) - d.Set("rank", filter.Rank) + d.Set("finding_criteria", filter.FindingCriteria) d.Set("name", d.Id()) + d.Set("rank", filter.Rank) + d.Set("tags", filter.Tags) return nil } From fd81374c80dd10cd05bcf10972cf52869a8d01ab Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Thu, 24 Oct 2019 12:04:59 +0200 Subject: [PATCH 18/61] Made Id of GD filter to be a compounded one --- aws/resource_aws_guardduty_filter.go | 31 ++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 752e04c7f99..6cb985b514a 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -271,15 +272,35 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Creating GuardDuty Filter failed: %s", err.Error()) } - d.SetId(*output.Name) + d.SetId(strings.Join([]string{d.Get("detector_id").(string), *output.Name}, "_")) return resourceAwsGuardDutyFilterRead(d, meta) } +func parseImportedId(importedId string) (string, string, error) { + parts := strings.SplitN(importedId, "_", 2) + if len(parts) < 2 { + return "", "", fmt.Errorf("Error Importing aws_guardduty_filter record: '%s' Please make sure the record ID is in the form detectorId_name.", importedId) + } + return parts[0], parts[1], nil +} + func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { + var detectorId, name string + var err error + + if _, ok := d.GetOk("detector_id"); !ok { + // If there is no "detector_id" passed, then it's an import. + detectorId, name, err = parseImportedId(d.Id()) + if err != nil { + return err + } + } else { + detectorId = d.Get("detector_id").(string) + name = d.Get("name").(string) + } + conn := meta.(*AWSClient).guarddutyconn - detectorId := d.Get("detector_id").(string) - name := d.Get("name").(string) input := guardduty.GetFilterInput{ DetectorId: aws.String(detectorId), @@ -301,9 +322,11 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.Set("action", filter.Action) d.Set("description", filter.Description) d.Set("finding_criteria", filter.FindingCriteria) - d.Set("name", d.Id()) + d.Set("name", filter.Name) + d.Set("detector_id", detectorId) d.Set("rank", filter.Rank) d.Set("tags", filter.Tags) + d.SetId(strings.Join([]string{detectorId, name}, "_")) return nil } From 34c86302cda7a7ed2c5d7f1501fe82404ab9ff2c Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Thu, 24 Oct 2019 12:07:00 +0200 Subject: [PATCH 19/61] Moved a function --- aws/resource_aws_guardduty_filter.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 6cb985b514a..ce39fd6eb76 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -277,14 +277,6 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) return resourceAwsGuardDutyFilterRead(d, meta) } -func parseImportedId(importedId string) (string, string, error) { - parts := strings.SplitN(importedId, "_", 2) - if len(parts) < 2 { - return "", "", fmt.Errorf("Error Importing aws_guardduty_filter record: '%s' Please make sure the record ID is in the form detectorId_name.", importedId) - } - return parts[0], parts[1], nil -} - func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) error { var detectorId, name string var err error @@ -381,3 +373,11 @@ func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) } return nil } + +func parseImportedId(importedId string) (string, string, error) { + parts := strings.SplitN(importedId, "_", 2) + if len(parts) < 2 { + return "", "", fmt.Errorf("Error Importing aws_guardduty_filter record: '%s' Please make sure the record ID is in the form detectorId_name.", importedId) + } + return parts[0], parts[1], nil +} From 08b50a88638bdf1aea782f39da845cf1d034ac90 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 09:24:49 +0100 Subject: [PATCH 20/61] Added import function without the findingCriteria --- aws/resource_aws_guardduty_filter.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index ce39fd6eb76..d40ad317043 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -20,9 +20,9 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Update: resourceAwsGuardDutyFilterUpdate, Delete: resourceAwsGuardDutyFilterDelete, - // Importer: &schema.ResourceImporter{ - // State: schema.ImportStatePassthrough, - // }, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "detector_id": { Type: schema.TypeString, @@ -171,7 +171,7 @@ func conditionAllowedForCriterion(criterion map[string]interface{}) bool { return false } -func buildFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.FindingCriteria, error) { +func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.FindingCriteria, error) { inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() criteria := map[string]*guardduty.Condition{} for _, criterion := range inputFindingCriteria { @@ -251,7 +251,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) var err error - input.FindingCriteria, err = buildFindingCriteria(findingCriteria) + input.FindingCriteria, err = serializeFindingCriteria(findingCriteria) if err != nil { return err } @@ -311,9 +311,12 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) } + // Setting the findingCriteria on import currently is not yet implemented. + // It shall be manually "flattened" or deserialized. As an example + // `resource_aws_appautoscaling_policy` can be taken. + // d.Set("finding_criteria", filter.Action) d.Set("action", filter.Action) d.Set("description", filter.Description) - d.Set("finding_criteria", filter.FindingCriteria) d.Set("name", filter.Name) d.Set("detector_id", detectorId) d.Set("rank", filter.Rank) @@ -338,7 +341,7 @@ func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) findingCriteria := d.Get("finding_criteria").([]interface{})[0].(map[string]interface{}) var err error - input.FindingCriteria, err = buildFindingCriteria(findingCriteria) + input.FindingCriteria, err = serializeFindingCriteria(findingCriteria) if err != nil { return err From db2daeba9b3b7b3d9e2f7922baa326552be6af23 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 10:14:45 +0100 Subject: [PATCH 21/61] Gofmt fixes --- aws/resource_aws_guardduty_filter.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index d40ad317043..a8340e7f079 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -108,14 +108,14 @@ func criteriaFields() []string { func criteriaMap() map[string][]string { return map[string][]string{ - "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "account_id": {"equals", "not_equals"}, - "region": {"equals", "not_equals"}, - "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, "resource.instanceDetails.imageId": {"equals", "not_equals"}, "resource.instanceDetails.instanceId": {"equals", "not_equals"}, @@ -217,7 +217,7 @@ func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guarddut func conditionValueToStrings(untypedValues []interface{}) []string { values := make([]string, len(untypedValues)) for i, v := range untypedValues { - values[i] = string(v.(string)) + values[i] = v.(string) } return values } From bc4ac655aed2c77622fef3869471b6caac895c4b Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 10:42:35 +0100 Subject: [PATCH 22/61] Gofmt with -s fixes --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index a8340e7f079..fd4763566c0 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -45,7 +45,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "criterion": &schema.Schema{ + "criterion": { Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ From c241f375c273540b2f850158af192fd05f3aa795 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 12:18:00 +0100 Subject: [PATCH 23/61] Implemented a mock of flattening of the finding criteria --- aws/resource_aws_guardduty_filter.go | 43 +++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index fd4763566c0..24f0656d20f 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -311,10 +311,7 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) } - // Setting the findingCriteria on import currently is not yet implemented. - // It shall be manually "flattened" or deserialized. As an example - // `resource_aws_appautoscaling_policy` can be taken. - // d.Set("finding_criteria", filter.Action) + d.Set("finding_criteria", flattenFindingCriteria()) //filter.FindingCriteria)) d.Set("action", filter.Action) d.Set("description", filter.Description) d.Set("name", filter.Name) @@ -326,6 +323,44 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return nil } +func criterionResource() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field": { + Type: schema.TypeString, + Required: true, + }, + "condition": { + Type: schema.TypeString, + Required: true, + }, + "values": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func flattenFindingCriteria() []interface{} { //findingCriteriaRemote filter.FindingCriteria) []interface{} { + var result []interface{} + var flatCriteria []interface{} + criteria := make(map[string]*schema.Set) + + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = "region" + flatCriterion["condition"] = "equals" + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"] = append(flatCriterion["values"].([]interface{}), "eu-west-1") + + flatCriteria = append(flatCriteria, flatCriterion) + + criteria["criterion"] = schema.NewSet(schema.HashResource(criterionResource()), flatCriteria) + result = append(result, criteria) + return result +} + func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn From d4b07c243fb353b836459730ca84fa7e9a8af417 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 17:29:24 +0100 Subject: [PATCH 24/61] Fixed map with possible conditions --- aws/resource_aws_guardduty_filter.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 24f0656d20f..4be9ac10641 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -108,14 +108,14 @@ func criteriaFields() []string { func criteriaMap() map[string][]string { return map[string][]string{ - "confidence": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "id": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - "account_id": {"equals", "not_equals"}, - "region": {"equals", "not_equals"}, - "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "confidence": {"equals", "not_equals"}, + "id": {"equals", "not_equals"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, "resource.instanceDetails.imageId": {"equals", "not_equals"}, "resource.instanceDetails.instanceId": {"equals", "not_equals"}, @@ -155,7 +155,7 @@ func criteriaMap() map[string][]string { "service.resourceRole": {"equals", "not_equals"}, "severity": {"equals", "not_equals"}, "type": {"equals", "not_equals"}, - "updatedAt": {"equals", "not_equals"}, + "updatedAt": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, } } From d6e6608c153423a9f0f6de887b2eb0f9d8669fc7 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 17:29:46 +0100 Subject: [PATCH 25/61] Made import work also for Finding Criteria --- aws/resource_aws_guardduty_filter.go | 70 ++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 4be9ac10641..1d27069882d 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -311,7 +311,11 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) } - d.Set("finding_criteria", flattenFindingCriteria()) //filter.FindingCriteria)) + err = d.Set("finding_criteria", flattenFindingCriteria(filter.FindingCriteria)) + if err != nil { + return fmt.Errorf("Setting GuardDuty Filter FindingCriteria failed: %s", err.Error()) + } + d.Set("action", filter.Action) d.Set("description", filter.Description) d.Set("name", filter.Name) @@ -343,18 +347,66 @@ func criterionResource() *schema.Resource { } } -func flattenFindingCriteria() []interface{} { //findingCriteriaRemote filter.FindingCriteria) []interface{} { +func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) []interface{} { var result []interface{} var flatCriteria []interface{} - criteria := make(map[string]*schema.Set) - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = "region" - flatCriterion["condition"] = "equals" - flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"] = append(flatCriterion["values"].([]interface{}), "eu-west-1") + for field, conditions := range findingCriteriaRemote.Criterion { + if len(conditions.Equals) > 0 { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "equals" + flatCriterion["values"] = make([]interface{}, len(conditions.Equals)) + for i, value := range conditions.Equals { + flatCriterion["values"].([]interface{})[i] = string(*value) + } + flatCriteria = append(flatCriteria, flatCriterion) + } + if len(conditions.NotEquals) > 0 { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "not_equals" + flatCriterion["values"] = make([]interface{}, len(conditions.NotEquals)) + for i, value := range conditions.NotEquals { + flatCriterion["values"].([]interface{})[i] = string(*value) + } + flatCriteria = append(flatCriteria, flatCriterion) + } + if conditions.GreaterThan != nil { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "greater_than" + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.GreaterThan, 10) + flatCriteria = append(flatCriteria, flatCriterion) + } + if conditions.GreaterThanOrEqual != nil { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "greater_than_or_equal" + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.GreaterThanOrEqual, 10) + flatCriteria = append(flatCriteria, flatCriterion) + } + if conditions.LessThan != nil { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "less_than" + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.LessThan, 10) + flatCriteria = append(flatCriteria, flatCriterion) + } + if conditions.LessThanOrEqual != nil { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = "less_than_or_equal" + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.LessThanOrEqual, 10) + flatCriteria = append(flatCriteria, flatCriterion) + } + } - flatCriteria = append(flatCriteria, flatCriterion) + criteria := make(map[string]*schema.Set) criteria["criterion"] = schema.NewSet(schema.HashResource(criterionResource()), flatCriteria) result = append(result, criteria) From 73a737e29f5020b8c722942c8ef67d9b8ff6f056 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 17:42:49 +0100 Subject: [PATCH 26/61] Dryed up the flattening functions --- aws/resource_aws_guardduty_filter.go | 158 ++++++++++++--------------- 1 file changed, 72 insertions(+), 86 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 1d27069882d..bfd2df178b3 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -327,92 +327,6 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er return nil } -func criterionResource() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "field": { - Type: schema.TypeString, - Required: true, - }, - "condition": { - Type: schema.TypeString, - Required: true, - }, - "values": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - } -} - -func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) []interface{} { - var result []interface{} - var flatCriteria []interface{} - - for field, conditions := range findingCriteriaRemote.Criterion { - if len(conditions.Equals) > 0 { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "equals" - flatCriterion["values"] = make([]interface{}, len(conditions.Equals)) - for i, value := range conditions.Equals { - flatCriterion["values"].([]interface{})[i] = string(*value) - } - flatCriteria = append(flatCriteria, flatCriterion) - } - if len(conditions.NotEquals) > 0 { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "not_equals" - flatCriterion["values"] = make([]interface{}, len(conditions.NotEquals)) - for i, value := range conditions.NotEquals { - flatCriterion["values"].([]interface{})[i] = string(*value) - } - flatCriteria = append(flatCriteria, flatCriterion) - } - if conditions.GreaterThan != nil { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "greater_than" - flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.GreaterThan, 10) - flatCriteria = append(flatCriteria, flatCriterion) - } - if conditions.GreaterThanOrEqual != nil { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "greater_than_or_equal" - flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.GreaterThanOrEqual, 10) - flatCriteria = append(flatCriteria, flatCriterion) - } - if conditions.LessThan != nil { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "less_than" - flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.LessThan, 10) - flatCriteria = append(flatCriteria, flatCriterion) - } - if conditions.LessThanOrEqual != nil { - flatCriterion := make(map[string]interface{}) - flatCriterion["field"] = field - flatCriterion["condition"] = "less_than_or_equal" - flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditions.LessThanOrEqual, 10) - flatCriteria = append(flatCriteria, flatCriterion) - } - } - - criteria := make(map[string]*schema.Set) - - criteria["criterion"] = schema.NewSet(schema.HashResource(criterionResource()), flatCriteria) - result = append(result, criteria) - return result -} - func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn @@ -471,3 +385,75 @@ func parseImportedId(importedId string) (string, string, error) { } return parts[0], parts[1], nil } + +func criterionResource() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field": { + Type: schema.TypeString, + Required: true, + }, + "condition": { + Type: schema.TypeString, + Required: true, + }, + "values": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) []interface{} { + var result []interface{} + var flatCriteria []interface{} + + for field, conditions := range findingCriteriaRemote.Criterion { + if len(conditions.Equals) > 0 { + flatCriteria = append(flatCriteria, flattenStringCondition(field, "equals", conditions.Equals)) + } + if len(conditions.NotEquals) > 0 { + flatCriteria = append(flatCriteria, flattenStringCondition(field, "not_equals", conditions.NotEquals)) + } + if conditions.GreaterThan != nil { + flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", conditions.GreaterThan)) + } + if conditions.GreaterThanOrEqual != nil { + flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", conditions.GreaterThanOrEqual)) + } + if conditions.LessThan != nil { + flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than", conditions.LessThan)) + } + if conditions.LessThanOrEqual != nil { + flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than_or_equal", conditions.LessThanOrEqual)) + } + } + + criteria := make(map[string]*schema.Set) + + criteria["criterion"] = schema.NewSet(schema.HashResource(criterionResource()), flatCriteria) + result = append(result, criteria) + return result +} + +func flattenIntCondition(field string, conditionName string, conditionValue *int64) map[string]interface{} { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = conditionName + flatCriterion["values"] = make([]interface{}, 1) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditionValue, 10) + return flatCriterion +} + +func flattenStringCondition(field string, conditionName string, conditionValues []*string) map[string]interface{} { + flatCriterion := make(map[string]interface{}) + flatCriterion["field"] = field + flatCriterion["condition"] = conditionName + flatCriterion["values"] = make([]interface{}, len(conditionValues)) + for i, value := range conditionValues { + flatCriterion["values"].([]interface{})[i] = string(*value) + } + return flatCriterion +} From 74326983cf2d80d88b16950967c08a39cd070ce7 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 17:46:19 +0100 Subject: [PATCH 27/61] Just moved things around --- aws/resource_aws_guardduty_filter.go | 276 +++++++++++++-------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index bfd2df178b3..63e6537abbd 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -98,144 +98,6 @@ func resourceAwsGuardDutyFilter() *schema.Resource { } } -func criteriaFields() []string { - criteria := make([]string, 0, len(criteriaMap())) - for criterion := range criteriaMap() { - criteria = append(criteria, criterion) - } - return criteria -} - -func criteriaMap() map[string][]string { - return map[string][]string{ - "confidence": {"equals", "not_equals"}, - "id": {"equals", "not_equals"}, - "account_id": {"equals", "not_equals"}, - "region": {"equals", "not_equals"}, - "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - "resource.accessKeyDetails.userType": {"equals", "not_equals"}, - "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, - "resource.instanceDetails.imageId": {"equals", "not_equals"}, - "resource.instanceDetails.instanceId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, - "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, - "resource.instanceDetails.tags.key": {"equals", "not_equals"}, - "resource.instanceDetails.tags.value": {"equals", "not_equals"}, - "resource.resourceType": {"equals", "not_equals"}, - "service.action.actionType": {"equals", "not_equals"}, - "service.action.awsApiCallAction.api": {"equals", "not_equals"}, - "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, - "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, - "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, - "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, - "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, - "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, - "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, - "service.additionalInfo.threatListName": {"equals", "not_equals"}, - "service.archived": {"equals", "not_equals"}, - "service.resourceRole": {"equals", "not_equals"}, - "severity": {"equals", "not_equals"}, - "type": {"equals", "not_equals"}, - "updatedAt": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, - } -} - -func conditionAllowedForCriterion(criterion map[string]interface{}) bool { - availableConditions := criteriaMap()[criterion["field"].(string)] - conditionToCheck := criterion["condition"].(string) - - for _, availableCondition := range availableConditions { - if availableCondition == conditionToCheck { - return true - } - } - return false -} - -func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.FindingCriteria, error) { - inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() - criteria := map[string]*guardduty.Condition{} - for _, criterion := range inputFindingCriteria { - typedCriterion := criterion.(map[string]interface{}) - - if !conditionAllowedForCriterion(typedCriterion) { - return nil, fmt.Errorf("The condition is not supported for the given field. Supported conditions are: %v", criteriaMap()[typedCriterion["field"].(string)]) - } - - switch typedCriterion["condition"].(string) { - case "equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - Equals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), - } - case "greater_than": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), - } - case "greater_than_or_equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), - } - case "less_than": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), - } - case "less_than_or_equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), - } - case "not_equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - NotEquals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), - } - } - - } - log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) - - return &guardduty.FindingCriteria{Criterion: criteria}, nil -} - -func conditionValueToStrings(untypedValues []interface{}) []string { - values := make([]string, len(untypedValues)) - for i, v := range untypedValues { - values[i] = v.(string) - } - return values -} - -func conditionValueToInt(untypedValues []interface{}) interface{} { - if len(untypedValues) != 1 { - return fmt.Errorf("Exactly one value must be given for conditions like less_ or greater_than. Instead given: %v", untypedValues) - } - - untypedValue := untypedValues[0] - typedValue, err := strconv.ParseInt(untypedValue.(string), 10, 64) - if err != nil { - return fmt.Errorf("Parsing condition value failed: %s", err.Error()) - } - - return typedValue -} - func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).guarddutyconn @@ -378,6 +240,144 @@ func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) return nil } +func criteriaFields() []string { + criteria := make([]string, 0, len(criteriaMap())) + for criterion := range criteriaMap() { + criteria = append(criteria, criterion) + } + return criteria +} + +func criteriaMap() map[string][]string { + return map[string][]string{ + "confidence": {"equals", "not_equals"}, + "id": {"equals", "not_equals"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, + "resource.instanceDetails.imageId": {"equals", "not_equals"}, + "resource.instanceDetails.instanceId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.ipv6Addresses": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.privateIpAddresses.privateIpAddress": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicDnsName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.publicIp": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.securityGroups.groupName": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.subnetId": {"equals", "not_equals"}, + "resource.instanceDetails.networkInterfaces.vpcId": {"equals", "not_equals"}, + "resource.instanceDetails.tags.key": {"equals", "not_equals"}, + "resource.instanceDetails.tags.value": {"equals", "not_equals"}, + "resource.resourceType": {"equals", "not_equals"}, + "service.action.actionType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.api": {"equals", "not_equals"}, + "service.action.awsApiCallAction.callerType": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.awsApiCallAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.awsApiCallAction.serviceName": {"equals", "not_equals"}, + "service.action.dnsRequestAction.domain": {"equals", "not_equals"}, + "service.action.networkConnectionAction.blocked": {"equals", "not_equals"}, + "service.action.networkConnectionAction.connectionDirection": {"equals", "not_equals"}, + "service.action.networkConnectionAction.localPortDetails.port": {"equals", "not_equals"}, + "service.action.networkConnectionAction.protocol": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.city.cityName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.country.countryName": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asn": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remoteIpDetails.organization.asnOrg": {"equals", "not_equals"}, + "service.action.networkConnectionAction.remotePortDetails.port": {"equals", "not_equals"}, + "service.additionalInfo.threatListName": {"equals", "not_equals"}, + "service.archived": {"equals", "not_equals"}, + "service.resourceRole": {"equals", "not_equals"}, + "severity": {"equals", "not_equals"}, + "type": {"equals", "not_equals"}, + "updatedAt": {"equals", "not_equals", "greater_than", "greater_than_or_equal", "less_than", "less_than_or_equal"}, + } +} + +func conditionAllowedForCriterion(criterion map[string]interface{}) bool { + availableConditions := criteriaMap()[criterion["field"].(string)] + conditionToCheck := criterion["condition"].(string) + + for _, availableCondition := range availableConditions { + if availableCondition == conditionToCheck { + return true + } + } + return false +} + +func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guardduty.FindingCriteria, error) { + inputFindingCriteria := findingCriteria["criterion"].(*schema.Set).List() + criteria := map[string]*guardduty.Condition{} + for _, criterion := range inputFindingCriteria { + typedCriterion := criterion.(map[string]interface{}) + + if !conditionAllowedForCriterion(typedCriterion) { + return nil, fmt.Errorf("The condition is not supported for the given field. Supported conditions are: %v", criteriaMap()[typedCriterion["field"].(string)]) + } + + switch typedCriterion["condition"].(string) { + case "equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + Equals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), + } + case "greater_than": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "greater_than_or_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "less_than": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "less_than_or_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + case "not_equals": + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + NotEquals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), + } + } + + } + log.Printf("[DEBUG] Creating FindingCriteria map: %#v", findingCriteria) + + return &guardduty.FindingCriteria{Criterion: criteria}, nil +} + +func conditionValueToStrings(untypedValues []interface{}) []string { + values := make([]string, len(untypedValues)) + for i, v := range untypedValues { + values[i] = v.(string) + } + return values +} + +func conditionValueToInt(untypedValues []interface{}) interface{} { + if len(untypedValues) != 1 { + return fmt.Errorf("Exactly one value must be given for conditions like less_ or greater_than. Instead given: %v", untypedValues) + } + + untypedValue := untypedValues[0] + typedValue, err := strconv.ParseInt(untypedValue.(string), 10, 64) + if err != nil { + return fmt.Errorf("Parsing condition value failed: %s", err.Error()) + } + + return typedValue +} + func parseImportedId(importedId string) (string, string, error) { parts := strings.SplitN(importedId, "_", 2) if len(parts) < 2 { From 2821f8788d32663aec2a340fdea76cff95a06f66 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 18:06:44 +0100 Subject: [PATCH 28/61] Fixed create/update case where one field can contain more than one condition --- aws/resource_aws_guardduty_filter.go | 56 ++++++++++++++++++---------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 63e6537abbd..d1f3b1cbbe4 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -250,14 +250,14 @@ func criteriaFields() []string { func criteriaMap() map[string][]string { return map[string][]string{ - "confidence": {"equals", "not_equals"}, - "id": {"equals", "not_equals"}, - "account_id": {"equals", "not_equals"}, - "region": {"equals", "not_equals"}, - "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, - "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, - "resource.accessKeyDetails.userName": {"equals", "not_equals"}, - "resource.accessKeyDetails.userType": {"equals", "not_equals"}, + "confidence": {"equals", "not_equals"}, + "id": {"equals", "not_equals"}, + "account_id": {"equals", "not_equals"}, + "region": {"equals", "not_equals"}, + "resource.accessKeyDetails.accessKeyId": {"equals", "not_equals"}, + "resource.accessKeyDetails.principalId": {"equals", "not_equals"}, + "resource.accessKeyDetails.userName": {"equals", "not_equals"}, + "resource.accessKeyDetails.userType": {"equals", "not_equals"}, "resource.instanceDetails.iamInstanceProfile.id": {"equals", "not_equals"}, "resource.instanceDetails.imageId": {"equals", "not_equals"}, "resource.instanceDetails.instanceId": {"equals", "not_equals"}, @@ -329,20 +329,38 @@ func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guarddut Equals: aws.StringSlice(conditionValueToStrings(typedCriterion["values"].([]interface{}))), } case "greater_than": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + // Here and below we need this complex condition because for one field we may have + // a combination of these filters. + if criteria[typedCriterion["field"].(string)] == nil { + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + } else { + criteria[typedCriterion["field"].(string)].GreaterThan = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) } - case "greater_than_or_equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + case "greater_than_or_equal": + if criteria[typedCriterion["field"].(string)] == nil { + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + } else { + criteria[typedCriterion["field"].(string)].GreaterThanOrEqual = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) } case "less_than": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + if criteria[typedCriterion["field"].(string)] == nil { + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + } else { + criteria[typedCriterion["field"].(string)].LessThan = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) } - case "less_than_or_equals": - criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + case "less_than_or_equal": + if criteria[typedCriterion["field"].(string)] == nil { + criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ + LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + } + } else { + criteria[typedCriterion["field"].(string)].LessThanOrEqual = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) } case "not_equals": criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ @@ -418,7 +436,7 @@ func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) [] flatCriteria = append(flatCriteria, flattenStringCondition(field, "not_equals", conditions.NotEquals)) } if conditions.GreaterThan != nil { - flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", conditions.GreaterThan)) + flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than", conditions.GreaterThan)) } if conditions.GreaterThanOrEqual != nil { flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", conditions.GreaterThanOrEqual)) From de0c9b54c0c896a7162ba94bb7688152e3801632 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Mon, 28 Oct 2019 20:33:29 +0100 Subject: [PATCH 29/61] Implemented a better error output --- aws/resource_aws_guardduty_filter.go | 40 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index d1f3b1cbbe4..9dcedbae438 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -331,36 +331,52 @@ func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guarddut case "greater_than": // Here and below we need this complex condition because for one field we may have // a combination of these filters. + value, err := conditionValueToInt(typedCriterion["values"].([]interface{})) + if err != nil { + return nil, fmt.Errorf("Value seems to be not an integer: %v", typedCriterion["values"].([]interface{})[0]) + } if criteria[typedCriterion["field"].(string)] == nil { criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + GreaterThan: aws.Int64(value.(int64)), } } else { - criteria[typedCriterion["field"].(string)].GreaterThan = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) + criteria[typedCriterion["field"].(string)].GreaterThan = aws.Int64(value.(int64)) } case "greater_than_or_equal": + value, err := conditionValueToInt(typedCriterion["values"].([]interface{})) + if err != nil { + return nil, fmt.Errorf("Value seems to be not an integer: %v", typedCriterion["values"].([]interface{})[0]) + } if criteria[typedCriterion["field"].(string)] == nil { criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - GreaterThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + GreaterThanOrEqual: aws.Int64(value.(int64)), } } else { - criteria[typedCriterion["field"].(string)].GreaterThanOrEqual = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) + criteria[typedCriterion["field"].(string)].GreaterThanOrEqual = aws.Int64(value.(int64)) } case "less_than": + value, err := conditionValueToInt(typedCriterion["values"].([]interface{})) + if err != nil { + return nil, fmt.Errorf("Value seems to be not an integer: %v", typedCriterion["values"].([]interface{})[0]) + } if criteria[typedCriterion["field"].(string)] == nil { criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThan: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + LessThan: aws.Int64(value.(int64)), } } else { - criteria[typedCriterion["field"].(string)].LessThan = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) + criteria[typedCriterion["field"].(string)].LessThan = aws.Int64(value.(int64)) } case "less_than_or_equal": + value, err := conditionValueToInt(typedCriterion["values"].([]interface{})) + if err != nil { + return nil, fmt.Errorf("Value seems to be not an integer: %v", typedCriterion["values"].([]interface{})[0]) + } if criteria[typedCriterion["field"].(string)] == nil { criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ - LessThanOrEqual: aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)), + LessThanOrEqual: aws.Int64(value.(int64)), } } else { - criteria[typedCriterion["field"].(string)].LessThanOrEqual = aws.Int64(conditionValueToInt(typedCriterion["values"].([]interface{})).(int64)) + criteria[typedCriterion["field"].(string)].LessThanOrEqual = aws.Int64(value.(int64)) } case "not_equals": criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ @@ -382,18 +398,18 @@ func conditionValueToStrings(untypedValues []interface{}) []string { return values } -func conditionValueToInt(untypedValues []interface{}) interface{} { +func conditionValueToInt(untypedValues []interface{}) (interface{}, error) { if len(untypedValues) != 1 { - return fmt.Errorf("Exactly one value must be given for conditions like less_ or greater_than. Instead given: %v", untypedValues) + return nil, fmt.Errorf("Exactly one value must be given for conditions like less_ or greater_than. Instead given: %v", untypedValues) } untypedValue := untypedValues[0] typedValue, err := strconv.ParseInt(untypedValue.(string), 10, 64) if err != nil { - return fmt.Errorf("Parsing condition value failed: %s", err.Error()) + return nil, fmt.Errorf("Parsing condition value failed: %s", err.Error()) } - return typedValue + return typedValue, nil } func parseImportedId(importedId string) (string, string, error) { From 4d109214b951f9a33e94c4deec9e993c6d957710 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 29 Oct 2019 14:38:41 +0100 Subject: [PATCH 30/61] Added tests for GuardDuty filter --- aws/resource_aws_guardduty_filter_test.go | 170 ++++++++++++++++++++++ aws/resource_aws_guardduty_test.go | 4 + 2 files changed, 174 insertions(+) create mode 100644 aws/resource_aws_guardduty_filter_test.go diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go new file mode 100644 index 00000000000..1df545d115f --- /dev/null +++ b/aws/resource_aws_guardduty_filter_test.go @@ -0,0 +1,170 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/guardduty" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func testAccAwsGuardDutyFilter_basic(t *testing.T) { + resourceName := "aws_guardduty_filter.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsGuardDutyFilterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGuardDutyFilterConfig_to_fail_1, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsGuardDutyFilterDoesNotExist(resourceName), + ), + }, + { + Config: testAccGuardDutyFilterConfig_to_fail_2, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsGuardDutyFilterDoesNotExist(resourceName), + ), + }, + { + Config: testAccGuardDutyFilterConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsGuardDutyFilterExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), + resource.TestCheckResourceAttr(resourceName, "detector_id", "123456271278c0df5e089123480d8765"), + ), + }, + { + Config: testAccGuardDutyFilterConfig_full, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsGuardDutyFilterExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), + resource.TestCheckResourceAttr(resourceName, "detector_id", "123456271278c0df5e089123480d8765"), + // add more fields to test! + ), + }, + }, + }) +} + +func testAccAwsGuardDutyFilter_import(t *testing.T) { + resourceName := "aws_guardduty_filter.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsGuardDutyFilterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGuardDutyFilterConfig_basic, + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckAwsGuardDutyFilterDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).guarddutyconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_guardduty_filter" { + continue + } + + input := &guardduty.GetFilterInput{ + FilterName: aws.String(rs.Primary.Attributes["filter_name"]), + DetectorId: aws.String(rs.Primary.Attributes["detector_id"]), + } + + _, err := conn.GetFilter(input) + if err != nil { + if isAWSErr(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { + return nil + } + return err + } + + return fmt.Errorf("Expected GuardDuty Filter to be destroyed, %s found", rs.Primary.Attributes["filter_name"]) + } + + return nil +} + +func testAccCheckAwsGuardDutyFilterExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + return nil + } +} + +func testAccCheckAwsGuardDutyFilterDoesNotExist(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[name] + if !ok { + return nil + } + + return fmt.Errorf("Not found: %s", name) + } +} + +const testAccGuardDutyFilterConfig_to_fail_1 = ` +resource "aws_guardduty_filter" "test" {}` + +const testAccGuardDutyFilterConfig_to_fail_2 = ` +resource "aws_guardduty_filter" "test" { + detector_id = "123456271278c0df5e089123480d8765" + }` + +const testAccGuardDutyFilterConfig_basic = ` +resource "aws_guardduty_filter" "test" { + detector_id = "123456271278c0df5e089123480d8765" + name = "test-filter" +}` + +const testAccGuardDutyFilterConfig_full = ` +resource "aws_guardduty_filter" "test" { + detector_id = "123456271278c0df5e089123480d8765" + name = "test-filter" + action = "ARCHIVE" + rank = 2 + + finding_criteria { + criterion { + field = "region" + values = ["eu-west-1"] + condition = "equals" + } + + criterion { + field = "service.additionalInfo.threatListName" + values = ["some-threat", "another-threat"] + condition = "not_equals" + } + + criterion { + field = "updatedAt" + values = ["1570744740000"] + condition = "less_than" + } + + criterion { + field = "updatedAt" + values = ["1570744240000"] + condition = "greater_than" + } + } +}` diff --git a/aws/resource_aws_guardduty_test.go b/aws/resource_aws_guardduty_test.go index 8b9f12e4d9c..31327dd2e2f 100644 --- a/aws/resource_aws_guardduty_test.go +++ b/aws/resource_aws_guardduty_test.go @@ -13,6 +13,10 @@ func TestAccAWSGuardDuty(t *testing.T) { "datasource_basic": testAccAWSGuarddutyDetectorDataSource_basic, "datasource_id": testAccAWSGuarddutyDetectorDataSource_Id, }, + "Filter": { + "basic": testAccAwsGuardDutyFilter_basic, + "import": testAccAwsGuardDutyFilter_import, + }, "InviteAccepter": { "basic": testAccAwsGuardDutyInviteAccepter_basic, }, From 124db85660f3ca52e4c7a742499ebc492267f6ec Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 29 Oct 2019 19:55:09 +0100 Subject: [PATCH 31/61] Improved tests --- aws/resource_aws_guardduty_filter_test.go | 54 ++++++++++------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 1df545d115f..f20c1f6782e 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "strings" "testing" "github.com/aws/aws-sdk-go/aws" @@ -31,20 +32,13 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { ), }, { - Config: testAccGuardDutyFilterConfig_basic, + Config: testAccGuardDutyFilterConfig_full(), Check: resource.ComposeTestCheckFunc( testAccCheckAwsGuardDutyFilterExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "detector_id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), - resource.TestCheckResourceAttr(resourceName, "detector_id", "123456271278c0df5e089123480d8765"), - ), - }, - { - Config: testAccGuardDutyFilterConfig_full, - Check: resource.ComposeTestCheckFunc( - testAccCheckAwsGuardDutyFilterExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), - resource.TestCheckResourceAttr(resourceName, "detector_id", "123456271278c0df5e089123480d8765"), - // add more fields to test! + resource.TestCheckResourceAttr(resourceName, "action", "Archive"), + resource.TestCheckResourceAttr(resourceName, "rank", "2"), ), }, }, @@ -60,7 +54,7 @@ func testAccAwsGuardDutyFilter_import(t *testing.T) { CheckDestroy: testAccCheckAwsGuardDutyFilterDestroy, Steps: []resource.TestStep{ { - Config: testAccGuardDutyFilterConfig_basic, + Config: testAccGuardDutyFilterConfig_full(), }, { @@ -80,9 +74,11 @@ func testAccCheckAwsGuardDutyFilterDestroy(s *terraform.State) error { continue } + parts := strings.SplitN(rs.Primary.ID, "_", 2) + input := &guardduty.GetFilterInput{ - FilterName: aws.String(rs.Primary.Attributes["filter_name"]), - DetectorId: aws.String(rs.Primary.Attributes["detector_id"]), + DetectorId: aws.String(parts[0]), + FilterName: aws.String(parts[1]), } _, err := conn.GetFilter(input) @@ -121,24 +117,13 @@ func testAccCheckAwsGuardDutyFilterDoesNotExist(name string) resource.TestCheckF } } -const testAccGuardDutyFilterConfig_to_fail_1 = ` -resource "aws_guardduty_filter" "test" {}` - -const testAccGuardDutyFilterConfig_to_fail_2 = ` -resource "aws_guardduty_filter" "test" { - detector_id = "123456271278c0df5e089123480d8765" - }` - -const testAccGuardDutyFilterConfig_basic = ` -resource "aws_guardduty_filter" "test" { - detector_id = "123456271278c0df5e089123480d8765" - name = "test-filter" -}` +func testAccGuardDutyFilterConfig_full() string { + return fmt.Sprintf(` +%[1]s -const testAccGuardDutyFilterConfig_full = ` resource "aws_guardduty_filter" "test" { - detector_id = "123456271278c0df5e089123480d8765" - name = "test-filter" + detector_id = "${aws_guardduty_detector.test.id}" + name = "test-filter" action = "ARCHIVE" rank = 2 @@ -167,4 +152,13 @@ resource "aws_guardduty_filter" "test" { condition = "greater_than" } } +}`, testAccGuardDutyDetectorConfig_basic3) +} + +const testAccGuardDutyFilterConfig_to_fail_1 = ` +resource "aws_guardduty_filter" "test" {}` + +const testAccGuardDutyFilterConfig_to_fail_2 = ` +resource "aws_guardduty_filter" "test" { + detector_id = "123456271278c0df5e089123480d8765" }` From f08993c4cbd1a45b2a26ced8bbfca7c8b7734dfa Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 29 Oct 2019 20:05:12 +0100 Subject: [PATCH 32/61] Added the documentation --- aws/resource_aws_guardduty_filter_test.go | 2 +- website/aws.erb | 3 + website/docs/r/guardduty_filter.html.markdown | 75 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 website/docs/r/guardduty_filter.html.markdown diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index f20c1f6782e..0fc5da8c455 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -37,7 +37,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { testAccCheckAwsGuardDutyFilterExists(resourceName), resource.TestCheckResourceAttrSet(resourceName, "detector_id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), - resource.TestCheckResourceAttr(resourceName, "action", "Archive"), + resource.TestCheckResourceAttr(resourceName, "action", "ARCHIVE"), resource.TestCheckResourceAttr(resourceName, "rank", "2"), ), }, diff --git a/website/aws.erb b/website/aws.erb index 008f986c920..f69b61b4040 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -1835,6 +1835,9 @@
  • aws_guardduty_detector
  • +
  • + aws_guardduty_filter +
  • aws_guardduty_invite_accepter
  • diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown new file mode 100644 index 00000000000..6a2cfbb0383 --- /dev/null +++ b/website/docs/r/guardduty_filter.html.markdown @@ -0,0 +1,75 @@ +--- +layout: "aws" +page_title: "AWS: aws_guardduty_filter" +sidebar_current: "docs-aws-resource-guardduty-filter" +description: |- + Provides a resource to manage a GuardDuty filter +--- + +# Resource: aws_guardduty_filter + +Provides a resource to manage a GuardDuty filter. + +## Example Usage + +```hcl +resource "aws_guardduty_filter" "MyFilter" { + name = "MyFilter" + action = "ARCHIVE" + description = "Some description" + detector_id = "123456271278c0df5e089123480d8765" + rank = 1 + + finding_criteria { + criterion { + field = "region" + values = ["eu-west-1"] + condition = "equals" + } + + criterion { + field = "service.additionalInfo.threatListName" + values = ["some-threat"] + condition = "not_equals" + } + + criterion { + field = "updatedAt" + values = ["1570744740000"] + condition = "less_than" + } + + criterion { + field = "updatedAt" + values = ["1570744240000"] + condition = "greater_than" + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `detector_id` - (Required) ID of a GuardDuty detector, attached to your account. +* `name` - (Required) The name of your filter. +* `description` - (Optional) Description of the filter. +* `rank` - (Required) Specifies the position of the filter in the list of current filters. Also specifies the order in which this filter is applied to the findings. +* `action` - (Required) Specifies the action that is to be applied to the findings that match the filter. Can be one of (ARCHIVE|NOOP). +* `tags` (Optional) - The tags that you want to add to the Filter resource. A tag consists of a key and a value. +* `finding_criteria` (Required) - Represents the criteria to be used in the filter for querying findings. A list, consists of `criterion` structures, each having required `condition`, `field` and `values` fields. See the example for the structure and see the [AWS Documentation](https://docs.aws.amazon.com/guardduty/latest/ug/create-filter.html) for the list of available fields for the `field` attribute. + +## Attributes Reference + +In addition to all arguments above, the following attribute is exported: + +* `id` - A compound field, consisting of the ID of the GuardDuty detector and the name of the filter. + +## Import + +GuardDuty filters can be imported using the detector ID and filter's name separated by underscore, e.g. + +``` +$ terraform import aws_guardduty_filter.MyFilter 00b00fd5aecc0ab60a708659477e9617_MyFilter +``` From 88a5e3aa2d17fdb5e9849d2c72f1d7af5305d1db Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 29 Oct 2019 20:41:50 +0100 Subject: [PATCH 33/61] Tiny stylefix --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 9dcedbae438..f92759201cd 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -487,7 +487,7 @@ func flattenStringCondition(field string, conditionName string, conditionValues flatCriterion["condition"] = conditionName flatCriterion["values"] = make([]interface{}, len(conditionValues)) for i, value := range conditionValues { - flatCriterion["values"].([]interface{})[i] = string(*value) + flatCriterion["values"].([]interface{})[i] = *value } return flatCriterion } From 5678e3f41b764204b439fdb1bcf73e109cae7ace Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Wed, 30 Oct 2019 14:48:25 +0100 Subject: [PATCH 34/61] Updated the resource to work with the new provider version --- aws/resource_aws_guardduty_filter.go | 8 +++--- aws/resource_aws_guardduty_filter_test.go | 31 +++-------------------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index f92759201cd..56ece2324e0 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -9,8 +9,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/guardduty" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) func resourceAwsGuardDutyFilter() *schema.Resource { @@ -38,7 +38,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "tags": tagsSchemaForceNew(), + "tags": tagsSchema(), "finding_criteria": { Type: schema.TypeList, MaxItems: 1, @@ -131,7 +131,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) output, err := conn.CreateFilter(&input) if err != nil { - return fmt.Errorf("Creating GuardDuty Filter failed: %s", err.Error()) + return fmt.Errorf("Creating GuardDuty Filter %s failed: %s", input, err.Error()) } d.SetId(strings.Join([]string{d.Get("detector_id").(string), *output.Name}, "_")) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 0fc5da8c455..fdd43005b1f 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -7,8 +7,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/guardduty" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" ) func testAccAwsGuardDutyFilter_basic(t *testing.T) { @@ -19,18 +19,6 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAwsGuardDutyFilterDestroy, Steps: []resource.TestStep{ - { - Config: testAccGuardDutyFilterConfig_to_fail_1, - Check: resource.ComposeTestCheckFunc( - testAccCheckAwsGuardDutyFilterDoesNotExist(resourceName), - ), - }, - { - Config: testAccGuardDutyFilterConfig_to_fail_2, - Check: resource.ComposeTestCheckFunc( - testAccCheckAwsGuardDutyFilterDoesNotExist(resourceName), - ), - }, { Config: testAccGuardDutyFilterConfig_full(), Check: resource.ComposeTestCheckFunc( @@ -38,7 +26,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "detector_id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "ARCHIVE"), - resource.TestCheckResourceAttr(resourceName, "rank", "2"), + resource.TestCheckResourceAttr(resourceName, "rank", "1"), ), }, }, @@ -106,17 +94,6 @@ func testAccCheckAwsGuardDutyFilterExists(name string) resource.TestCheckFunc { } } -func testAccCheckAwsGuardDutyFilterDoesNotExist(name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - _, ok := s.RootModule().Resources[name] - if !ok { - return nil - } - - return fmt.Errorf("Not found: %s", name) - } -} - func testAccGuardDutyFilterConfig_full() string { return fmt.Sprintf(` %[1]s @@ -125,7 +102,7 @@ resource "aws_guardduty_filter" "test" { detector_id = "${aws_guardduty_detector.test.id}" name = "test-filter" action = "ARCHIVE" - rank = 2 + rank = 1 finding_criteria { criterion { From 9b3fdb4b1309776416e3094c514d768f5a677432 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Thu, 31 Oct 2019 19:53:28 +0100 Subject: [PATCH 35/61] Removed obsolete tests cases --- aws/resource_aws_guardduty_filter_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index fdd43005b1f..172d56467ef 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -131,11 +131,3 @@ resource "aws_guardduty_filter" "test" { } }`, testAccGuardDutyDetectorConfig_basic3) } - -const testAccGuardDutyFilterConfig_to_fail_1 = ` -resource "aws_guardduty_filter" "test" {}` - -const testAccGuardDutyFilterConfig_to_fail_2 = ` -resource "aws_guardduty_filter" "test" { - detector_id = "123456271278c0df5e089123480d8765" -}` From a33fa1ebd40417bb4c4c8a26a08946aaf0019d02 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:28:56 +0900 Subject: [PATCH 36/61] Add the subcategory "GuardDuty" https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381009352 --- website/docs/r/guardduty_filter.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown index 6a2cfbb0383..cd1ec0775be 100644 --- a/website/docs/r/guardduty_filter.html.markdown +++ b/website/docs/r/guardduty_filter.html.markdown @@ -1,5 +1,6 @@ --- layout: "aws" +subcategory: "GuardDuty" page_title: "AWS: aws_guardduty_filter" sidebar_current: "docs-aws-resource-guardduty-filter" description: |- From 88da7202976560e9cd57e267becc3ab23a78e013 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:33:14 +0900 Subject: [PATCH 37/61] Add a validator for a minimum length of 3, maximum length of 64 https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381009972 --- aws/resource_aws_guardduty_filter.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 56ece2324e0..2da7f08de2b 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -30,9 +30,10 @@ func resourceAwsGuardDutyFilter() *schema.Resource { ForceNew: true, }, "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 64), }, "description": { Type: schema.TypeString, From a6c803c46e16f998891e3b613cd6393cb36e9024 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:34:28 +0900 Subject: [PATCH 38/61] Add a validator for a maximum length of 512 https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381010064 --- aws/resource_aws_guardduty_filter.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 2da7f08de2b..d053d682b80 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -36,8 +36,9 @@ func resourceAwsGuardDutyFilter() *schema.Resource { ValidateFunc: validation.StringLenBetween(3, 64), }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 512), }, "tags": tagsSchema(), "finding_criteria": { From 771b217545e83f7adacd3adbdb64bfc0b629fc37 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:50:25 +0900 Subject: [PATCH 39/61] Use keyvaluetags package https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381014152 --- aws/resource_aws_guardduty_filter.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index d053d682b80..b5b7adac06f 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/guardduty" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsGuardDutyFilter() *schema.Resource { @@ -120,15 +121,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) return err } - tagsInterface := d.Get("tags").(map[string]interface{}) - if len(tagsInterface) > 0 { - tags := make(map[string]*string, len(tagsInterface)) - for i, v := range tagsInterface { - tags[i] = aws.String(v.(string)) - } - - input.Tags = tags - } + input.Tags = keyvaluetags.New(d.Get("tags").(map[string]interface{})).GuarddutyTags() log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) output, err := conn.CreateFilter(&input) From f08db2388936023fa4ec0e90bd025d63b79ab23f Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:51:41 +0900 Subject: [PATCH 40/61] Update the fmt.Errorf calls to return the error object itself using the %w directive https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381015289 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index b5b7adac06f..b78ef3cf2c3 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -170,7 +170,7 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er err = d.Set("finding_criteria", flattenFindingCriteria(filter.FindingCriteria)) if err != nil { - return fmt.Errorf("Setting GuardDuty Filter FindingCriteria failed: %s", err.Error()) + return fmt.Errorf("Setting GuardDuty Filter FindingCriteria failed: %w", err) } d.Set("action", filter.Action) From 3c15febb5df4e76bab513cdc81b802ca1b673a57 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 08:52:37 +0900 Subject: [PATCH 41/61] Rephrase an error message https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381016058 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index b78ef3cf2c3..1883f430e85 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -340,7 +340,7 @@ func serializeFindingCriteria(findingCriteria map[string]interface{}) (*guarddut case "greater_than_or_equal": value, err := conditionValueToInt(typedCriterion["values"].([]interface{})) if err != nil { - return nil, fmt.Errorf("Value seems to be not an integer: %v", typedCriterion["values"].([]interface{})[0]) + return nil, fmt.Errorf("Value must be an integer: %v", typedCriterion["values"].([]interface{})[0]) } if criteria[typedCriterion["field"].(string)] == nil { criteria[typedCriterion["field"].(string)] = &guardduty.Condition{ From 647492a96cf895c63a44164179ea7650ddb560c0 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 09:02:38 +0900 Subject: [PATCH 42/61] Add test to cover updating values https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381017067 --- aws/resource_aws_guardduty_filter_test.go | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 172d56467ef..cb87864c3d0 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -29,6 +29,16 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "rank", "1"), ), }, + { + Config: testAccGuardDutyFilterConfigNoop_full(), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsGuardDutyFilterExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "detector_id"), + resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), + resource.TestCheckResourceAttr(resourceName, "action", "NOOP"), + resource.TestCheckResourceAttr(resourceName, "rank", "1"), + ), + }, }, }) } @@ -131,3 +141,41 @@ resource "aws_guardduty_filter" "test" { } }`, testAccGuardDutyDetectorConfig_basic3) } + +func testAccGuardDutyFilterConfigNoop_full() string { + return fmt.Sprintf(` +%[1]s + +resource "aws_guardduty_filter" "test" { + detector_id = "${aws_guardduty_detector.test.id}" + name = "test-filter" + action = "NOOP" + rank = 1 + + finding_criteria { + criterion { + field = "region" + values = ["eu-west-1"] + condition = "equals" + } + + criterion { + field = "service.additionalInfo.threatListName" + values = ["some-threat", "another-threat"] + condition = "not_equals" + } + + criterion { + field = "updatedAt" + values = ["1570744740000"] + condition = "less_than" + } + + criterion { + field = "updatedAt" + values = ["1570744240000"] + condition = "greater_than" + } + } +}`, testAccGuardDutyDetectorConfig_basic3) +} From 958a39ffc49a023767d17187cb588518adc1b5d2 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 09:11:14 +0900 Subject: [PATCH 43/61] Use resource.TestCheckResourceAttrPair to verify that the correct value is set https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381018081 --- aws/resource_aws_guardduty_filter_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index cb87864c3d0..f87deede5f7 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -23,7 +23,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { Config: testAccGuardDutyFilterConfig_full(), Check: resource.ComposeTestCheckFunc( testAccCheckAwsGuardDutyFilterExists(resourceName), - resource.TestCheckResourceAttrSet(resourceName, "detector_id"), + resource.TestCheckResourceAttrPair(resourceName, "detector_id", "aws_guardduty_detector.test", "id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "ARCHIVE"), resource.TestCheckResourceAttr(resourceName, "rank", "1"), @@ -33,7 +33,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { Config: testAccGuardDutyFilterConfigNoop_full(), Check: resource.ComposeTestCheckFunc( testAccCheckAwsGuardDutyFilterExists(resourceName), - resource.TestCheckResourceAttrSet(resourceName, "detector_id"), + resource.TestCheckResourceAttrPair(resourceName, "detector_id", "aws_guardduty_detector.test", "id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "NOOP"), resource.TestCheckResourceAttr(resourceName, "rank", "1"), From e8792bffe35aa968bf4964c55d860ae83b7690cf Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 30 Jun 2020 09:20:45 +0900 Subject: [PATCH 44/61] Add test for finding_criteria https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r381018570 --- aws/resource_aws_guardduty_filter_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index f87deede5f7..14558a39c00 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -27,6 +27,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "ARCHIVE"), resource.TestCheckResourceAttr(resourceName, "rank", "1"), + resource.TestCheckResourceAttrSet(resourceName, "finding_criteria"), ), }, { @@ -37,6 +38,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "NOOP"), resource.TestCheckResourceAttr(resourceName, "rank", "1"), + resource.TestCheckResourceAttrSet(resourceName, "finding_criteria"), ), }, }, From a2885f267e25453ebaf9303458b62239ee8c4d45 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 7 Jul 2020 09:54:19 +0200 Subject: [PATCH 45/61] Fix a lint error AWSR002 https://github.com/terraform-providers/terraform-provider-aws/pull/10676/checks?check_run_id=842275982 https://github.com/terraform-providers/terraform-provider-aws/blob/master/awsproviderlint/passes/AWSR002/README.md ``` AWSR002: missing (keyvaluetags.KeyValueTags).IgnoreConfig() ``` By @suzuki-shunsuke --- aws/resource_aws_guardduty_filter.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 1883f430e85..8640a8342db 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -178,7 +178,8 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.Set("name", filter.Name) d.Set("detector_id", detectorId) d.Set("rank", filter.Rank) - d.Set("tags", filter.Tags) + ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig + d.Set("tags", keyvaluetags.GuarddutyKeyValueTags(filter.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()) d.SetId(strings.Join([]string{detectorId, name}, "_")) return nil From 7da9ed35cc544ce3e46b7fa77628f839538557f6 Mon Sep 17 00:00:00 2001 From: Kirill Zonov Date: Tue, 7 Jul 2020 09:55:25 +0200 Subject: [PATCH 46/61] Remove deprecated 'sidebar_current' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/terraform-providers/terraform-provider-aws/pull/10676/checks?check_run_id=842278427 * bflad/tfproviderdocs#23 * https://github.com/hashicorp/terraform-website#yaml-frontmatter > sidebar_current (deprecated) — No longer used for anything. > Omit this from new pages, and feel free to remove it from existing ones. By @suzuki-shunsuke --- website/docs/r/guardduty_filter.html.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown index cd1ec0775be..41bdd6248a3 100644 --- a/website/docs/r/guardduty_filter.html.markdown +++ b/website/docs/r/guardduty_filter.html.markdown @@ -2,7 +2,6 @@ layout: "aws" subcategory: "GuardDuty" page_title: "AWS: aws_guardduty_filter" -sidebar_current: "docs-aws-resource-guardduty-filter" description: |- Provides a resource to manage a GuardDuty filter --- From d48e8ce2d5e80a3467890765c34afaeb8b4eefe2 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 11 Aug 2020 10:18:00 -0700 Subject: [PATCH 47/61] Update aws/resource_aws_guardduty_filter.go --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 8640a8342db..c10def9dcef 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -165,7 +165,7 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.SetId("") return nil } - return fmt.Errorf("Reading GuardDuty Filter '%s' failed: %s", name, err.Error()) + return fmt.Errorf("error reading GuardDuty Filter '%s': %w", name, err) } err = d.Set("finding_criteria", flattenFindingCriteria(filter.FindingCriteria)) From b0c158ea39b0e7cdcc6eac3166788540b9a44d88 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 11:34:56 +0900 Subject: [PATCH 48/61] Remove the timeout setting https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455330897 > We only provide custom timeout values when there's a need to allow very long timeouts, such as 45 minutes or longer --- aws/resource_aws_guardduty_filter.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index c10def9dcef..5bb23c31f82 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -5,7 +5,6 @@ import ( "log" "strconv" "strings" - "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/guardduty" @@ -94,10 +93,6 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Required: true, }, }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(60 * time.Second), - Update: schema.DefaultTimeout(60 * time.Second), - }, } } From 0199cf6631d88a2d599d8d6f2661cdbbc931f2c1 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 11:37:27 +0900 Subject: [PATCH 49/61] Fix the error handling https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455332746 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 5bb23c31f82..ac2cc1a9976 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -121,7 +121,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Creating GuardDuty Filter: %s", input) output, err := conn.CreateFilter(&input) if err != nil { - return fmt.Errorf("Creating GuardDuty Filter %s failed: %s", input, err.Error()) + return fmt.Errorf("error creating GuardDuty Filter: %w", err) } d.SetId(strings.Join([]string{d.Get("detector_id").(string), *output.Name}, "_")) From 07490bfd6640111a6f0fd0b448a43f9c0f7fc3a2 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 11:38:12 +0900 Subject: [PATCH 50/61] Fix the error handling https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455337847 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index ac2cc1a9976..f2cad551ca6 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -205,7 +205,7 @@ func resourceAwsGuardDutyFilterUpdate(d *schema.ResourceData, meta interface{}) _, err = conn.UpdateFilter(&input) if err != nil { - return fmt.Errorf("Updating GuardDuty Filter with ID %s failed: %s", d.Id(), err.Error()) + return fmt.Errorf("error updating GuardDuty Filter %s: %w", d.Id(), err) } return resourceAwsGuardDutyFilterRead(d, meta) From c4df914e59160a9d1bf677e4c51d6a7b29b03329 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 11:38:59 +0900 Subject: [PATCH 51/61] Fix the error handling https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455338466 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index f2cad551ca6..0a8c91c4dc5 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -226,7 +226,7 @@ func resourceAwsGuardDutyFilterDelete(d *schema.ResourceData, meta interface{}) _, err := conn.DeleteFilter(&input) if err != nil { - return fmt.Errorf("Deleting GuardDuty Filter '%s' failed: %s", d.Id(), err.Error()) + return fmt.Errorf("error deleting GuardDuty Filter %s: %w", d.Id(), err) } return nil } From cab69c1c1df98c7454ed9d3559bd29104bf0c66a Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 15:58:28 +0900 Subject: [PATCH 52/61] Replace strings to constants defined in the AWS SDK --- aws/resource_aws_guardduty_filter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 0a8c91c4dc5..48f89268ff6 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -84,8 +84,8 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - "NOOP", - "ARCHIVE", + guardduty.FilterActionNoop, + guardduty.FilterActionArchive, }, false), }, "rank": { From 045fb7748a924f103b1b7a07ff853553d3a84c07 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Thu, 16 Jul 2020 16:02:29 +0900 Subject: [PATCH 53/61] Fix the style in document https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455432998 --- website/docs/r/guardduty_filter.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown index 41bdd6248a3..c245255fd49 100644 --- a/website/docs/r/guardduty_filter.html.markdown +++ b/website/docs/r/guardduty_filter.html.markdown @@ -56,7 +56,7 @@ The following arguments are supported: * `name` - (Required) The name of your filter. * `description` - (Optional) Description of the filter. * `rank` - (Required) Specifies the position of the filter in the list of current filters. Also specifies the order in which this filter is applied to the findings. -* `action` - (Required) Specifies the action that is to be applied to the findings that match the filter. Can be one of (ARCHIVE|NOOP). +* `action` - (Required) Specifies the action that is to be applied to the findings that match the filter. Can be one of `ARCHIVE` or `NOOP`. * `tags` (Optional) - The tags that you want to add to the Filter resource. A tag consists of a key and a value. * `finding_criteria` (Required) - Represents the criteria to be used in the filter for querying findings. A list, consists of `criterion` structures, each having required `condition`, `field` and `values` fields. See the example for the structure and see the [AWS Documentation](https://docs.aws.amazon.com/guardduty/latest/ug/create-filter.html) for the list of available fields for the `field` attribute. From 9094964843c2bd06423595c8053bf18454319b58 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Fri, 17 Jul 2020 11:28:16 +0900 Subject: [PATCH 54/61] Simplify flattenFindingCriteria --- aws/resource_aws_guardduty_filter.go | 31 +++++----------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 48f89268ff6..00dd507c25c 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -411,28 +411,7 @@ func parseImportedId(importedId string) (string, string, error) { return parts[0], parts[1], nil } -func criterionResource() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "field": { - Type: schema.TypeString, - Required: true, - }, - "condition": { - Type: schema.TypeString, - Required: true, - }, - "values": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - } -} - func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) []interface{} { - var result []interface{} var flatCriteria []interface{} for field, conditions := range findingCriteriaRemote.Criterion { @@ -456,11 +435,11 @@ func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) [] } } - criteria := make(map[string]*schema.Set) - - criteria["criterion"] = schema.NewSet(schema.HashResource(criterionResource()), flatCriteria) - result = append(result, criteria) - return result + return []interface{}{ + map[string][]interface{}{ + "criterion": flatCriteria, + }, + } } func flattenIntCondition(field string, conditionName string, conditionValue *int64) map[string]interface{} { From 5db310e6fd57d4f293f904f999bf6d0cddb4ef73 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Fri, 17 Jul 2020 11:36:24 +0900 Subject: [PATCH 55/61] Change pointer https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455441224 https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455442023 --- aws/resource_aws_guardduty_filter.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 00dd507c25c..0c604b66ed9 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -416,22 +416,22 @@ func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) [] for field, conditions := range findingCriteriaRemote.Criterion { if len(conditions.Equals) > 0 { - flatCriteria = append(flatCriteria, flattenStringCondition(field, "equals", conditions.Equals)) + flatCriteria = append(flatCriteria, flattenStringCondition(field, "equals", aws.StringValueSlice(conditions.Equals))) } if len(conditions.NotEquals) > 0 { - flatCriteria = append(flatCriteria, flattenStringCondition(field, "not_equals", conditions.NotEquals)) + flatCriteria = append(flatCriteria, flattenStringCondition(field, "not_equals", aws.StringValueSlice(conditions.NotEquals))) } if conditions.GreaterThan != nil { - flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than", conditions.GreaterThan)) + flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than", *conditions.GreaterThan)) } if conditions.GreaterThanOrEqual != nil { - flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", conditions.GreaterThanOrEqual)) + flatCriteria = append(flatCriteria, flattenIntCondition(field, "greater_than_or_equal", *conditions.GreaterThanOrEqual)) } if conditions.LessThan != nil { - flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than", conditions.LessThan)) + flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than", *conditions.LessThan)) } if conditions.LessThanOrEqual != nil { - flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than_or_equal", conditions.LessThanOrEqual)) + flatCriteria = append(flatCriteria, flattenIntCondition(field, "less_than_or_equal", *conditions.LessThanOrEqual)) } } @@ -442,22 +442,22 @@ func flattenFindingCriteria(findingCriteriaRemote *guardduty.FindingCriteria) [] } } -func flattenIntCondition(field string, conditionName string, conditionValue *int64) map[string]interface{} { +func flattenIntCondition(field string, conditionName string, conditionValue int64) map[string]interface{} { flatCriterion := make(map[string]interface{}) flatCriterion["field"] = field flatCriterion["condition"] = conditionName flatCriterion["values"] = make([]interface{}, 1) - flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(*conditionValue, 10) + flatCriterion["values"].([]interface{})[0] = strconv.FormatInt(conditionValue, 10) return flatCriterion } -func flattenStringCondition(field string, conditionName string, conditionValues []*string) map[string]interface{} { +func flattenStringCondition(field string, conditionName string, conditionValues []string) map[string]interface{} { flatCriterion := make(map[string]interface{}) flatCriterion["field"] = field flatCriterion["condition"] = conditionName flatCriterion["values"] = make([]interface{}, len(conditionValues)) for i, value := range conditionValues { - flatCriterion["values"].([]interface{})[i] = *value + flatCriterion["values"].([]interface{})[i] = value } return flatCriterion } From fbcd71a54eb317f627f92d3df3d3557f1eb8e9d4 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Fri, 17 Jul 2020 11:38:46 +0900 Subject: [PATCH 56/61] Check for too many parts as well https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455355425 --- aws/resource_aws_guardduty_filter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 0c604b66ed9..4fb6b4bdaf7 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -404,8 +404,8 @@ func conditionValueToInt(untypedValues []interface{}) (interface{}, error) { } func parseImportedId(importedId string) (string, string, error) { - parts := strings.SplitN(importedId, "_", 2) - if len(parts) < 2 { + parts := strings.Split(importedId, "_") + if len(parts) != 2 { return "", "", fmt.Errorf("Error Importing aws_guardduty_filter record: '%s' Please make sure the record ID is in the form detectorId_name.", importedId) } return parts[0], parts[1], nil From a120a04f7a536581f97c9a1322d5e8898fdca11d Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Fri, 17 Jul 2020 11:44:54 +0900 Subject: [PATCH 57/61] Make test data simple and move the resource under test to the top of the configuration https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455388494 --- aws/resource_aws_guardduty_filter_test.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 14558a39c00..060c4ff0e1f 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -107,9 +107,7 @@ func testAccCheckAwsGuardDutyFilterExists(name string) resource.TestCheckFunc { } func testAccGuardDutyFilterConfig_full() string { - return fmt.Sprintf(` -%[1]s - + return ` resource "aws_guardduty_filter" "test" { detector_id = "${aws_guardduty_detector.test.id}" name = "test-filter" @@ -141,13 +139,15 @@ resource "aws_guardduty_filter" "test" { condition = "greater_than" } } -}`, testAccGuardDutyDetectorConfig_basic3) } -func testAccGuardDutyFilterConfigNoop_full() string { - return fmt.Sprintf(` -%[1]s +resource "aws_guardduty_detector" "test" { + enable = true +}` +} +func testAccGuardDutyFilterConfigNoop_full() string { + return ` resource "aws_guardduty_filter" "test" { detector_id = "${aws_guardduty_detector.test.id}" name = "test-filter" @@ -179,5 +179,9 @@ resource "aws_guardduty_filter" "test" { condition = "greater_than" } } -}`, testAccGuardDutyDetectorConfig_basic3) +} + +resource "aws_guardduty_detector" "test" { + enable = true +}` } From 672d35f1a227810b3403638832648d5851d1078e Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Sun, 19 Jul 2020 17:34:11 +0900 Subject: [PATCH 58/61] Use parseImportedId https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455431694 --- aws/resource_aws_guardduty_filter_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 060c4ff0e1f..37a5c5ad126 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -2,7 +2,6 @@ package aws import ( "fmt" - "strings" "testing" "github.com/aws/aws-sdk-go/aws" @@ -74,14 +73,17 @@ func testAccCheckAwsGuardDutyFilterDestroy(s *terraform.State) error { continue } - parts := strings.SplitN(rs.Primary.ID, "_", 2) + detectorID, filterName, err := parseImportedId(rs.Primary.ID) + if err != nil { + return err + } input := &guardduty.GetFilterInput{ - DetectorId: aws.String(parts[0]), - FilterName: aws.String(parts[1]), + DetectorId: aws.String(detectorID), + FilterName: aws.String(filterName), } - _, err := conn.GetFilter(input) + _, err = conn.GetFilter(input) if err != nil { if isAWSErr(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { return nil From 88ea72dbccbda9660d9f0eddb356a6f5a5e74f70 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Sun, 19 Jul 2020 17:43:21 +0900 Subject: [PATCH 59/61] Define the function to create the GuardDuty Filter's ID https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455430998 --- aws/resource_aws_guardduty_filter.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 4fb6b4bdaf7..66d548fd351 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -124,7 +124,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error creating GuardDuty Filter: %w", err) } - d.SetId(strings.Join([]string{d.Get("detector_id").(string), *output.Name}, "_")) + d.SetId(joinGuardDutyFilterID(d.Get("detector_id").(string), *output.Name)) return resourceAwsGuardDutyFilterRead(d, meta) } @@ -175,7 +175,7 @@ func resourceAwsGuardDutyFilterRead(d *schema.ResourceData, meta interface{}) er d.Set("rank", filter.Rank) ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig d.Set("tags", keyvaluetags.GuarddutyKeyValueTags(filter.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()) - d.SetId(strings.Join([]string{detectorId, name}, "_")) + d.SetId(joinGuardDutyFilterID(detectorId, name)) return nil } @@ -403,6 +403,10 @@ func conditionValueToInt(untypedValues []interface{}) (interface{}, error) { return typedValue, nil } +func joinGuardDutyFilterID(detectorID, filterName string) string { + return detectorID + "_" + filterName +} + func parseImportedId(importedId string) (string, string, error) { parts := strings.Split(importedId, "_") if len(parts) != 2 { From 87638fe40476e712b38e822c6d314b3f7ef354ee Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Sun, 19 Jul 2020 17:46:03 +0900 Subject: [PATCH 60/61] Use aws.StringValue instead of direct pointer manupulation https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455430267 --- aws/resource_aws_guardduty_filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 66d548fd351..eccbbf74298 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -124,7 +124,7 @@ func resourceAwsGuardDutyFilterCreate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error creating GuardDuty Filter: %w", err) } - d.SetId(joinGuardDutyFilterID(d.Get("detector_id").(string), *output.Name)) + d.SetId(joinGuardDutyFilterID(d.Get("detector_id").(string), aws.StringValue(output.Name))) return resourceAwsGuardDutyFilterRead(d, meta) } From e313e2beb8862c229b97765d489c0b2804b51ba2 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Tue, 21 Jul 2020 19:49:50 +0900 Subject: [PATCH 61/61] Add a variable detectorResourceName https://github.com/terraform-providers/terraform-provider-aws/pull/10676#discussion_r455407077 --- aws/resource_aws_guardduty_filter_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter_test.go b/aws/resource_aws_guardduty_filter_test.go index 37a5c5ad126..e3b738bd6ac 100644 --- a/aws/resource_aws_guardduty_filter_test.go +++ b/aws/resource_aws_guardduty_filter_test.go @@ -12,6 +12,7 @@ import ( func testAccAwsGuardDutyFilter_basic(t *testing.T) { resourceName := "aws_guardduty_filter.test" + detectorResourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -22,7 +23,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { Config: testAccGuardDutyFilterConfig_full(), Check: resource.ComposeTestCheckFunc( testAccCheckAwsGuardDutyFilterExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "detector_id", "aws_guardduty_detector.test", "id"), + resource.TestCheckResourceAttrPair(resourceName, "detector_id", detectorResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "ARCHIVE"), resource.TestCheckResourceAttr(resourceName, "rank", "1"), @@ -33,7 +34,7 @@ func testAccAwsGuardDutyFilter_basic(t *testing.T) { Config: testAccGuardDutyFilterConfigNoop_full(), Check: resource.ComposeTestCheckFunc( testAccCheckAwsGuardDutyFilterExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "detector_id", "aws_guardduty_detector.test", "id"), + resource.TestCheckResourceAttrPair(resourceName, "detector_id", detectorResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "name", "test-filter"), resource.TestCheckResourceAttr(resourceName, "action", "NOOP"), resource.TestCheckResourceAttr(resourceName, "rank", "1"),