-
Notifications
You must be signed in to change notification settings - Fork 9.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12684 from gazoakley/new_sechub_resources
- Loading branch information
Showing
8 changed files
with
321 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-resource | ||
aws_securityhub_invite_accepter | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/securityhub" | ||
"github.com/hashicorp/aws-sdk-go-base/tfawserr" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func resourceAwsSecurityHubInviteAccepter() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsSecurityHubInviteAccepterCreate, | ||
Read: resourceAwsSecurityHubInviteAccepterRead, | ||
Delete: resourceAwsSecurityHubInviteAccepterDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"master_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"invitation_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsSecurityHubInviteAccepterCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).securityhubconn | ||
log.Print("[DEBUG] Accepting Security Hub invitation") | ||
|
||
invitationId, err := resourceAwsSecurityHubInviteAccepterGetInvitationId(conn, d.Get("master_id").(string)) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = conn.AcceptInvitation(&securityhub.AcceptInvitationInput{ | ||
InvitationId: aws.String(invitationId), | ||
MasterId: aws.String(d.Get("master_id").(string)), | ||
}) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error accepting Security Hub invitation: %w", err) | ||
} | ||
|
||
d.SetId(meta.(*AWSClient).accountid) | ||
|
||
return resourceAwsSecurityHubInviteAccepterRead(d, meta) | ||
} | ||
|
||
func resourceAwsSecurityHubInviteAccepterGetInvitationId(conn *securityhub.SecurityHub, masterId string) (string, error) { | ||
log.Printf("[DEBUG] Getting InvitationId for MasterId %s", masterId) | ||
|
||
resp, err := conn.ListInvitations(&securityhub.ListInvitationsInput{}) | ||
|
||
if err != nil { | ||
return "", fmt.Errorf("error listing Security Hub invitations: %w", err) | ||
} | ||
|
||
for _, invitation := range resp.Invitations { | ||
log.Printf("[DEBUG] Invitation: %s", invitation) | ||
if *invitation.AccountId == masterId { | ||
return *invitation.InvitationId, nil | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("Cannot find InvitationId for MasterId %s", masterId) | ||
} | ||
|
||
func resourceAwsSecurityHubInviteAccepterRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).securityhubconn | ||
log.Print("[DEBUG] Reading Security Hub master account") | ||
|
||
resp, err := conn.GetMasterAccount(&securityhub.GetMasterAccountInput{}) | ||
if tfawserr.ErrCodeEquals(err, securityhub.ErrCodeResourceNotFoundException) { | ||
log.Print("[WARN] Security Hub master account not found, removing from state") | ||
d.SetId("") | ||
return nil | ||
} | ||
if err != nil { | ||
return fmt.Errorf("error retrieving Security Hub master account: %w", err) | ||
} | ||
|
||
master := resp.Master | ||
|
||
if master == nil { | ||
log.Print("[WARN] Security Hub master account not found, removing from state") | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
d.Set("invitation_id", master.InvitationId) | ||
d.Set("master_id", master.AccountId) | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsSecurityHubInviteAccepterDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).securityhubconn | ||
log.Print("[DEBUG] Disassociating from Security Hub master account") | ||
|
||
_, err := conn.DisassociateFromMasterAccount(&securityhub.DisassociateFromMasterAccountInput{}) | ||
|
||
if tfawserr.ErrMessageContains(err, "BadRequestException", "The request is rejected because the current account is not associated to a master account") { | ||
return nil | ||
} | ||
if err != nil { | ||
return fmt.Errorf("error disassociating from Security Hub master account: %w", err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/securityhub" | ||
"github.com/hashicorp/aws-sdk-go-base/tfawserr" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform" | ||
) | ||
|
||
func testAccAWSSecurityHubInviteAccepter_basic(t *testing.T) { | ||
var providers []*schema.Provider | ||
resourceName := "aws_securityhub_invite_accepter.test" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { | ||
testAccPreCheck(t) | ||
testAccAlternateAccountPreCheck(t) | ||
}, | ||
ProviderFactories: testAccProviderFactoriesAlternate(&providers), | ||
CheckDestroy: testAccCheckAWSSecurityHubInviteAccepterDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSSecurityHubInviteAccepterConfig_basic(), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSSecurityHubInviteAccepterExists(resourceName), | ||
), | ||
}, | ||
{ | ||
Config: testAccAWSSecurityHubInviteAccepterConfig_basic(), | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSSecurityHubInviteAccepterExists(resourceName string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
_, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).securityhubconn | ||
|
||
resp, err := conn.GetMasterAccount(&securityhub.GetMasterAccountInput{}) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error retrieving Security Hub master account: %w", err) | ||
} | ||
|
||
if resp == nil || resp.Master == nil || aws.StringValue(resp.Master.AccountId) == "" { | ||
return fmt.Errorf("Security Hub master account not found for: %s", resourceName) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSSecurityHubInviteAccepterDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).securityhubconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_securityhub_invite_accepter" { | ||
continue | ||
} | ||
|
||
resp, err := conn.GetMasterAccount(&securityhub.GetMasterAccountInput{}) | ||
if tfawserr.ErrCodeEquals(err, securityhub.ErrCodeResourceNotFoundException) { | ||
continue | ||
} | ||
// If Security Hub is not enabled, the API returns "BadRequestException" | ||
if tfawserr.ErrCodeEquals(err, "BadRequestException") { | ||
continue | ||
} | ||
if err != nil { | ||
return fmt.Errorf("error retrieving Security Hub master account: %w", err) | ||
} | ||
|
||
if resp == nil || resp.Master == nil || aws.StringValue(resp.Master.AccountId) == "" { | ||
continue | ||
} | ||
|
||
return fmt.Errorf("Security Hub master account still configured: %s", aws.StringValue(resp.Master.AccountId)) | ||
} | ||
return nil | ||
} | ||
|
||
func testAccAWSSecurityHubInviteAccepterConfig_basic() string { | ||
return composeConfig( | ||
testAccAlternateAccountProviderConfig(), ` | ||
resource "aws_securityhub_invite_accepter" "test" { | ||
master_id = aws_securityhub_member.source.master_id | ||
depends_on = [aws_securityhub_account.test] | ||
} | ||
resource "aws_securityhub_member" "source" { | ||
provider = awsalternate | ||
account_id = data.aws_caller_identity.test.account_id | ||
email = "[email protected]" | ||
invite = true | ||
depends_on = [aws_securityhub_account.source] | ||
} | ||
resource "aws_securityhub_account" "test" {} | ||
resource "aws_securityhub_account" "source" { | ||
provider = awsalternate | ||
} | ||
data "aws_caller_identity" "test" {} | ||
`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
subcategory: "Security Hub" | ||
layout: "aws" | ||
page_title: "AWS: aws_securityhub_invite_accepter" | ||
description: |- | ||
Accepts a Security Hub invitation. | ||
--- | ||
|
||
# aws_securityhub_invite_accepter | ||
|
||
-> **Note:** AWS accounts can only be associated with a single Security Hub master account. Destroying this resource will disassociate the member account from the master account. | ||
|
||
Accepts a Security Hub invitation. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "aws_securityhub_account" "example" {} | ||
resource "aws_securityhub_member" "example" { | ||
account_id = "123456789012" | ||
email = "[email protected]" | ||
invite = true | ||
} | ||
resource "aws_securityhub_account" "invitee" { | ||
provider = "aws.invitee" | ||
} | ||
resource "aws_securityhub_invite_accepter" "invitee" { | ||
provider = "aws.invitee" | ||
depends_on = [aws_securityhub_account.accepter] | ||
master_id = aws_securityhub_member.example.master_id | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `master_id` - (Required) The account ID of the master Security Hub account whose invitation you're accepting. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported in addition to the arguments listed above: | ||
|
||
* `invitation_id` - The ID of the invitation. | ||
|
||
## Import | ||
|
||
Security Hub invite acceptance can be imported using the account ID, e.g. | ||
|
||
``` | ||
$ terraform import aws_securityhub_invite_acceptor.example 123456789012 | ||
``` |