Skip to content

Commit

Permalink
Added 2 optional attributes to account and subaccount resources: (#388)
Browse files Browse the repository at this point in the history
* enable_http2_for_new_sites - enable HTTP/2 support for traffic between end-users (visitors) and Imperva for newly created SSL sites.
* enable_http2_to_origin_for_new_sites - enable HTTP/2 support for traffic between Imperva and origin server for newly created SSL sites.

Co-authored-by: adi.shlomo <[email protected]>
  • Loading branch information
adishlomo and adiEdriShlomo authored Jan 30, 2024
1 parent 03ff8fa commit 378791b
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 35 deletions.
10 changes: 6 additions & 4 deletions incapsula/client_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ type AccountStatusResponse struct {
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
} `json:"logins"`
SupportLevel string `json:"support_level"`
SupportAllTLSVersions bool `json:"supprt_all_tls_versions"`
WildcardSANForNewSites string `json:"wildcard_san_for_new_sites"`
NakedDomainSANForNewWWWSites bool `json:"naked_domain_san_for_new_www_sites"`
SupportLevel string `json:"support_level"`
SupportAllTLSVersions bool `json:"supprt_all_tls_versions"`
WildcardSANForNewSites string `json:"wildcard_san_for_new_sites"`
NakedDomainSANForNewWWWSites bool `json:"naked_domain_san_for_new_www_sites"`
EnableHttp2ForNewSites bool `json:"enable_http2_for_new_sites"`
EnableHttp2ToOriginForNewSites bool `json:"enable_http2_to_origin_for_new_sites"`
} `json:"account"`
ParentID int `json:"parent_id"`
Email string `json:"email"`
Expand Down
59 changes: 59 additions & 0 deletions incapsula/http2_updater.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package incapsula

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"log"
)

func updateHttp2Properties(client *Client, d *schema.ResourceData) error {
enableHttp2ForNewSiteChanged := d.HasChange("enable_http2_for_new_sites") && d.Get("enable_http2_for_new_sites") != ""
enableHttp2ToOriginForNewSitesChanged := d.HasChange("enable_http2_to_origin_for_new_sites") && d.Get("enable_http2_to_origin_for_new_sites") != ""

log.Printf("[INFO] adi enable_http2_for_new_sites %v %v %v %v\n", d.HasChange("enable_http2_for_new_sites"), d.Get("enable_http2_for_new_sites"),
d.HasChange("enable_http2_to_origin_for_new_sites"), d.Get("enable_http2_to_origin_for_new_sites"))

if !enableHttp2ForNewSiteChanged && !enableHttp2ToOriginForNewSitesChanged {
return nil
}

if d.Get("enable_http2_for_new_sites").(string) == "false" && d.Get("enable_http2_to_origin_for_new_sites").(string) == "true" {
log.Printf("[ERROR] Could not update Incapsula account param enable_http2_for_new_sites with value (%s) and enable_http2_to_origin_for_new_sites with value (%s) for account_id: %s",
d.Get("enable_http2_for_new_sites"), d.Get("enable_http2_to_origin_for_new_sites"), d.Id())
return fmt.Errorf("[ERROR] invalid values for enable_http2_for_new_sites and enable_http2_to_origin_for_new_sites")
}

updateParamsList := getParamsToUpdateInOrder(enableHttp2ForNewSiteChanged, enableHttp2ToOriginForNewSitesChanged, d)

return updateParams(client, d, updateParamsList)
}

func getParamsToUpdateInOrder(enableHttp2ForNewSiteChanged bool, enableHttp2ToOriginForNewSitesChanged bool, d *schema.ResourceData) []string {

updateParamsList := make([]string, 0)
if enableHttp2ForNewSiteChanged && !enableHttp2ToOriginForNewSitesChanged {
updateParamsList = append(updateParamsList, "enable_http2_for_new_sites")
} else if !enableHttp2ForNewSiteChanged && enableHttp2ToOriginForNewSitesChanged {
updateParamsList = append(updateParamsList, "enable_http2_to_origin_for_new_sites")
} else if d.Get("enable_http2_to_origin_for_new_sites").(string) == "true" { // if the origin is true, then the client must be set first
updateParamsList = append(updateParamsList, "enable_http2_for_new_sites", "enable_http2_to_origin_for_new_sites")
} else {
updateParamsList = append(updateParamsList, "enable_http2_to_origin_for_new_sites", "enable_http2_for_new_sites")
}
return updateParamsList
}

func updateParams(client *Client, d *schema.ResourceData, updateParams []string) error {
for i := 0; i < len(updateParams); i++ {
param := updateParams[i]
if d.HasChange(param) && d.Get(param) != "" {
log.Printf("[INFO] Updating Incapsula account param (%s) with value (%s) for account_id: %s\n", param, d.Get(param), d.Id())
_, err := client.UpdateAccount(d.Id(), param, d.Get(param).(string))
if err != nil {
log.Printf("[ERROR] Could not update Incapsula account param (%s) with value (%t) for account_id: %s %s\n", param, d.Get(param).(bool), d.Id(), err)
return err
}
}
}
return nil
}
20 changes: 16 additions & 4 deletions incapsula/resource_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,18 @@ func resourceAccount() *schema.Resource {
Optional: true,
Computed: true,
},

"enable_http2_for_new_sites": {
Description: "Enable HTTP/2 for traffic between end-users (visitors) and Imperva for newly created SSL sites. Options are `true` and `false`. Defaults to `true`",
Type: schema.TypeString,
Default: "true",
Optional: true,
},
"enable_http2_to_origin_for_new_sites": {
Description: "Enable HTTP/2 support for traffic between Imperva and your origin server for newly created SSL sites. This option can only be 'true' once 'enable_http2_for_new_sites' is enabled for newly created sites. Options are `true` and `false`. Defaults to `false`",
Type: schema.TypeString,
Default: "false",
Optional: true,
},
// Computed Attributes
"support_level": {
Description: "Account support level",
Expand Down Expand Up @@ -201,15 +212,16 @@ func resourceAccountRead(d *schema.ResourceData, m interface{}) error {
d.Set("plan_id", accountStatusResponse.Account.PlanID)
d.Set("plan_name", accountStatusResponse.Account.PlanName)
d.Set("trial_end_date", accountStatusResponse.Account.TrialEndDate)
d.Set("account_id", accountStatusResponse.Account.AccountID)
d.Set("ref_id", accountStatusResponse.Account.RefID)
d.Set("user_name", accountStatusResponse.Account.UserName)
d.Set("account_name", accountStatusResponse.Account.AccountName)
d.Set("support_level", accountStatusResponse.Account.SupportLevel)
d.Set("support_all_tls_versions", accountStatusResponse.Account.SupportAllTLSVersions)
d.Set("support_all_tls_versions", strconv.FormatBool(accountStatusResponse.Account.SupportAllTLSVersions))
d.Set("wildcard_san_for_new_sites", accountStatusResponse.Account.WildcardSANForNewSites)
d.Set("naked_domain_san_for_new_www_sites", strconv.FormatBool(accountStatusResponse.Account.NakedDomainSANForNewWWWSites))
d.Set("consent_required", accountStatusResponse.ConsentRequired)
d.Set("enable_http2_for_new_sites", strconv.FormatBool(accountStatusResponse.Account.EnableHttp2ForNewSites))
d.Set("enable_http2_to_origin_for_new_sites", strconv.FormatBool(accountStatusResponse.Account.EnableHttp2ToOriginForNewSites))

// Get the performance settings for the site
defaultAccountDataStorageRegion, err := client.GetAccountDataStorageRegion(d.Id())
Expand Down Expand Up @@ -307,7 +319,7 @@ func updateAdditionalAccountProperties(client *Client, d *schema.ResourceData) e
}
}

return nil
return updateHttp2Properties(client, d)
}

func replaceAccountNameParamName(param string) string {
Expand Down
120 changes: 97 additions & 23 deletions incapsula/resource_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,33 @@ package incapsula

import (
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"testing"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

const testEmail = "example@example.com"
const testEmail = "example@imperva.com"
const accountResourceName = "incapsula_account.test-terraform-account"

func GenerateTestEmail(t *testing.T) string {
if v := os.Getenv("INCAPSULA_API_ID"); v == "" {
t.Fatal("INCAPSULA_API_ID must be set for acceptance tests")
}
return "id" + os.Getenv("INCAPSULA_API_ID") + "." + testEmail
}

func SkipIfAccountTypeIsResellerEndUser(t *testing.T) resource.ErrorCheckFunc {
return func(err error) error {
if err == nil {
return nil
}
if strings.Contains(err.Error(), "Operation not allowed") {
t.Skipf("skipping test since account type is RESELLER_END_USER. Error: %s", err.Error())
}

return err
}
}

func TestIncapsulaAccount_Basic(t *testing.T) {
email := GenerateTestEmail(t)
resource.Test(t, resource.TestCase{
ErrorCheck: SkipIfAccountTypeIsResellerEndUser(t),
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckIncapsulaAccountDestroy,
Steps: []resource.TestStep{
{
Config: testCheckIncapsulaAccountConfigBasic(GenerateTestEmail(t)),
Config: testCheckIncapsulaAccountConfigBasic(email),
Check: resource.ComposeTestCheckFunc(
testCheckIncapsulaAccountExists(accountResourceName),
resource.TestCheckResourceAttr(accountResourceName, "email", GenerateTestEmail(t)),
resource.TestCheckResourceAttr(accountResourceName, "email", email),
),
},
},
Expand All @@ -66,6 +49,40 @@ func TestIncapsulaAccount_ImportBasic(t *testing.T) {
ResourceName: "incapsula_account.test-terraform-account",
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testACCStateAccountID,
},
},
})
}

func TestIncapsulaAccount_Http2Defaults(t *testing.T) {
testIncapsulaAccountHttp2Client(t, true, false)
}

func TestIncapsulaAccount_Http2ClientAndOriginEnabled(t *testing.T) {
testIncapsulaAccountHttp2Client(t, true, true)
}

func TestIncapsulaAccount_Http2ClientAndOriginDisabled(t *testing.T) {
testIncapsulaAccountHttp2Client(t, false, false)
}

func testIncapsulaAccountHttp2Client(t *testing.T, enableHttp2ForNewSites bool, enableHttp2ToOriginForNewSites bool) {
email := GenerateTestEmail(t)
resource.Test(t, resource.TestCase{
ErrorCheck: SkipIfAccountTypeIsResellerEndUser(t),
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckIncapsulaAccountDestroy,
Steps: []resource.TestStep{
{
Config: testHttp2AccountConfig(email, enableHttp2ForNewSites, enableHttp2ToOriginForNewSites),
Check: resource.ComposeTestCheckFunc(
testCheckIncapsulaAccountExists(accountResourceName),
resource.TestCheckResourceAttr(accountResourceName, "email", email),
resource.TestCheckResourceAttr(accountResourceName, "enable_http2_for_new_sites", strconv.FormatBool(enableHttp2ForNewSites)),
resource.TestCheckResourceAttr(accountResourceName, "enable_http2_to_origin_for_new_sites", strconv.FormatBool(enableHttp2ToOriginForNewSites)),
),
},
},
})
Expand Down Expand Up @@ -127,10 +144,67 @@ func testCheckIncapsulaAccountExists(name string) resource.TestCheckFunc {
}

func testCheckIncapsulaAccountConfigBasic(email string) string {
return fmt.Sprintf(`
resource "incapsula_account" "test-terraform-account" {
email = "%s"
account_name = "testTerraform"
plan_id = "entTrial"
support_all_tls_versions = "false"
naked_domain_san_for_new_www_sites = "true"
}`,
email,
)
}

func testHttp2AccountConfig(email string, enableHttp2ForNewSites bool, enableHttp2ToOriginForNewSites bool) string {
return fmt.Sprintf(`
resource "incapsula_account" "test-terraform-account" {
email = "%s"
enable_http2_for_new_sites = "%t"
enable_http2_to_origin_for_new_sites = "%t"
account_name = "testTerraform"
plan_id = "entTrial"
support_all_tls_versions = "false"
}`,
email,
enableHttp2ForNewSites,
enableHttp2ToOriginForNewSites,
)
}

func SkipIfAccountTypeIsResellerEndUser(t *testing.T) resource.ErrorCheckFunc {
return func(err error) error {
if err == nil {
return nil
}
if strings.Contains(err.Error(), "Operation not allowed") {
t.Skipf("skipping test since account type is RESELLER_END_USER. Error: %s", err.Error())
}

return err
}
}

func GenerateTestEmail(t *testing.T) string {
if v := os.Getenv("INCAPSULA_API_ID"); v == "" {
t.Fatal("INCAPSULA_API_ID must be set for acceptance tests")
}

s3 := rand.NewSource(time.Now().UnixNano())
r3 := rand.New(s3)
generatedDomain = "id" + os.Getenv("INCAPSULA_API_ID") + strconv.Itoa(r3.Intn(1000)) + testEmail

return generatedDomain
}

func testACCStateAccountID(s *terraform.State) (string, error) {
for _, rs := range s.RootModule().Resources {
if rs.Type != "incapsula_account" {
continue
}
accountID := rs.Primary.ID

return accountID, nil
}
return "", fmt.Errorf("Error finding an Account\"")
}
24 changes: 24 additions & 0 deletions incapsula/resource_subaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ func resourceSubAccount() *schema.Resource {
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"APAC", "EU", "US", "AU"}, false),
},
"enable_http2_for_new_sites": {
Description: "Enable HTTP/2 for traffic between end-users (visitors) and Imperva for newly created SSL sites. Options are `true` and `false`. Defaults to `true`",
Type: schema.TypeString,
Default: "true",
Optional: true,
},
"enable_http2_to_origin_for_new_sites": {
Description: "Enable HTTP/2 support for traffic between Imperva and your origin server for newly created SSL sites. This option can only be 'true' once 'enable_http2_for_new_sites' is enabled for newly created sites. Options are `true` and `false`. Defaults to `false`",
Type: schema.TypeString,
Default: "false",
Optional: true,
},
},
}
}
Expand Down Expand Up @@ -96,6 +108,11 @@ func resourceSubAccountCreate(d *schema.ResourceData, m interface{}) error {
return err
}

err = updateHttp2Properties(client, d)
if err != nil {
return err
}

// There may be a timing/race condition here
// Set an arbitrary period to sleep
time.Sleep(3 * time.Second)
Expand Down Expand Up @@ -138,6 +155,8 @@ func resourceSubAccountRead(d *schema.ResourceData, m interface{}) error {
return err
}
d.Set("data_storage_region", defaultAccountDataStorageRegion.Region)
d.Set("enable_http2_for_new_sites", strconv.FormatBool(accountStatusResponse.Account.EnableHttp2ForNewSites))
d.Set("enable_http2_to_origin_for_new_sites", strconv.FormatBool(accountStatusResponse.Account.EnableHttp2ToOriginForNewSites))

log.Printf("[INFO] Finished reading Incapsula account for account ud: %d\n", accountID)

Expand Down Expand Up @@ -187,6 +206,11 @@ func resourceSubAccountUpdate(d *schema.ResourceData, m interface{}) error {
return err
}

err = updateHttp2Properties(client, d)
if err != nil {
return err
}

// Set the rest of the state from the resource read
return resourceAccountRead(d, m)
}
Loading

0 comments on commit 378791b

Please sign in to comment.