Skip to content

Commit

Permalink
Merge pull request #13 from imperva/petal/support-synctype-param
Browse files Browse the repository at this point in the history
Support sync_type parameter
  • Loading branch information
mattJsonar authored Sep 9, 2024
2 parents 58121e3 + 98dc8a1 commit 7c88628
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 17 deletions.
4 changes: 2 additions & 2 deletions dsfhub/client_cloud_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Client) CreateCloudAccount(cloudAccount ResourceWrapper) (*ResourceWrap
return nil, fmt.Errorf("failed to JSON marshal CloudAccount: %s\n", err)
}

resp, err := c.MakeCall(http.MethodPost, endpointCloudAccounts, cloudAccountJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPost, endpointCloudAccounts, cloudAccountJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error adding CloudAccount of serverType: %s and gatewayID: %s | err: %s\n", cloudAccount.Data.ServerType, cloudAccount.Data.GatewayID, err)
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func (c *Client) UpdateCloudAccount(cloudAccountId string, cloudAccountIdData Re
}

reqURL := fmt.Sprintf(endpointCloudAccounts+"/%s", url.PathEscape(cloudAccountId))
resp, err := c.MakeCall(http.MethodPut, reqURL, cloudAccountJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPut, reqURL, cloudAccountJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error updating CloudAccount with cloudAccountId: %s | err: %s\n", cloudAccountId, err)
}
Expand Down
4 changes: 2 additions & 2 deletions dsfhub/client_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Client) CreateDSFDataSource(dsfDataSource ResourceWrapper) (*ResourceWr
return nil, fmt.Errorf("failed to JSON marshal dsfDataSource: %s", err)
}

resp, err := c.MakeCall(http.MethodPost, endpointDsfDataSource, dsfDataSourceJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPost, endpointDsfDataSource, dsfDataSourceJSON, c.config.Params)
if err != nil {
log.Printf("[INFO] err.Error(): %s\n", err.Error())
return nil, fmt.Errorf("error adding DSFDataSource for serverType: %s and gatewayId: %s | err: %s", dsfDataSource.Data.ServerType, dsfDataSource.Data.GatewayID, err)
Expand Down Expand Up @@ -120,7 +120,7 @@ func (c *Client) UpdateDSFDataSource(dataSourceId string, dsfDataSourceData Reso
}

reqURL := fmt.Sprintf(endpointDsfDataSource+"/%s", url.PathEscape(dataSourceId))
resp, err := c.MakeCall(http.MethodPut, reqURL, dsfDataSourceJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPut, reqURL, dsfDataSourceJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error updating DSFDataSource for dataSourceId: %s | err: %s", dataSourceId, err)
}
Expand Down
4 changes: 2 additions & 2 deletions dsfhub/client_log_aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (c *Client) CreateLogAggregator(logAggregator ResourceWrapper) (*ResourceWr
return nil, fmt.Errorf("failed to JSON marshal LogAggregator: %s\n", err)
}

resp, err := c.MakeCall(http.MethodPost, endpointLogAggregators, logAggregatorJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPost, endpointLogAggregators, logAggregatorJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error adding LogAggregator of serverType: %s and gatewayID: %s | err: %s\n", logAggregator.Data.ServerType, logAggregator.Data.GatewayID, err)
}
Expand Down Expand Up @@ -115,7 +115,7 @@ func (c *Client) UpdateLogAggregator(logAggregatorId string, logAggregatorData R
}

reqURL := fmt.Sprintf(endpointLogAggregators+"/%s", url.PathEscape(logAggregatorId))
resp, err := c.MakeCall(http.MethodPut, reqURL, logAggregatorJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPut, reqURL, logAggregatorJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error updating LogAggregator with logAggregatorId: %s | err: %s\n", logAggregatorId, err)
}
Expand Down
4 changes: 2 additions & 2 deletions dsfhub/client_secret_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Client) CreateSecretManager(secretManager ResourceWrapper) (*ResourceWr
return nil, fmt.Errorf("failed to JSON marshal SecreManager: %s\n", err)
}

resp, err := c.MakeCall(http.MethodPost, endpointSecretManagers, secretManagerJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPost, endpointSecretManagers, secretManagerJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error adding SecretManager of serverType: %s and gatewayID: %s | err: %s\n", secretManager.Data.ServerType, secretManager.Data.GatewayID, err)
}
Expand Down Expand Up @@ -116,7 +116,7 @@ func (c *Client) UpdateSecretManager(secretManagerId string, secretManager Resou
}

reqURL := fmt.Sprintf(endpointSecretManagers+"/%s", url.PathEscape(secretManagerId))
resp, err := c.MakeCall(http.MethodPut, reqURL, secretManagerJSON)
resp, err := c.MakeCallWithQueryParams(http.MethodPut, reqURL, secretManagerJSON, c.config.Params)
if err != nil {
return nil, fmt.Errorf("error updating SecretManager with secretManagerId: %s | err: %s\n", secretManagerId, err)
}
Expand Down
20 changes: 18 additions & 2 deletions dsfhub/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dsfhub

import (
"errors"
"slices"
"strings"
)

Expand All @@ -15,21 +16,32 @@ type Config struct {

// InsecureSSL
InsecureSSL bool

// Params including syncType
Params map[string]string
}

var missingAPITokenMessage = "DSF HUB API Token must be provided"
var missingDSFHostMessage = "DSF HUB host/API endpoint must be provided"
var validSyncTypes = []string { "SYNC_GW_BLOCKING", "SYNC_GW_NON_BLOCKING", "DO_NOT_SYNC_GW"}
var invalidSyncTypeMessage = "Invalid sync_type. Available values: " + strings.Join(validSyncTypes, ", ")

// Client configures and returns a fully initialized DSF Client
func (c *Config) Client() (interface{}, error) {
// Check DSFToken env var
// Check DSFToken
if strings.TrimSpace(c.DSFHUBToken) == "" {
return nil, errors.New(missingAPITokenMessage)
}
// Check DSFHost env var
// Check DSFHost
if strings.TrimSpace(c.DSFHUBHost) == "" {
return nil, errors.New(missingDSFHostMessage)
}
// Check sync_type param
if syncType, exists := c.Params["syncType"]; exists {
if ! IsValidSyncType(syncType) {
return nil, errors.New(invalidSyncTypeMessage)
}
}

// Create client
client := NewClient(c)
Expand All @@ -43,3 +55,7 @@ func (c *Config) Client() (interface{}, error) {

return client, nil
}

func IsValidSyncType (sync_type string) bool {
return slices.Contains(validSyncTypes, sync_type)
}
27 changes: 27 additions & 0 deletions dsfhub/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,30 @@ func TestValidDSFHUBToken(t *testing.T) {
t.Error("Client should not be nil")
}
}

func TestInvalidSyncType(t *testing.T) {
log.Printf("======================== BEGIN TEST ========================")
log.Printf("[INFO] Running test TestInvalidSyncType \n")

server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if req.URL.String() != "/dsf/api/v2/gateways" {
t.Errorf("Should have have hit /gateways endpoint. Got: %s", req.URL.String())
}
rw.Write([]byte(`{ "data": [ { "applianceId": 1, "applianceType": "DSF_HUB", "id": "a1b2c3-4d5e-6f7g-8h9i-9adf5a7d8a72-172.16.1.123", "name": "ba-dsf-4.12-hub", "hostname": "172.16.1.123", "serverType": "IMPERVA WAREHOUSE", "sonar": { "jsonarUid": "a1b2c3-4d5e-6f7g-8h9i-678910" } } ] }`))
}))
defer server.Close()


invalidSyncType := "BAD_SYNC_TYPE"
log.Printf("[INFO] Configuring client with sync_type: '%v'\n", invalidSyncType)
log.Printf("[DEBUG] Test server URL %v \n", server.URL)

config := Config{DSFHUBToken: "good", DSFHUBHost: server.URL, Params: map[string]string{"syncType": invalidSyncType}}
client, err := config.Client()
if err == nil {
t.Errorf("Should have received an error, got a client: %q", client)
}
if err.Error() != invalidSyncTypeMessage {
t.Errorf("Should have invalid sync_type message, got: %s", err)
}
}
15 changes: 15 additions & 0 deletions dsfhub/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func init() {
"insecure_ssl": "The boolean flag that instructs the provider to allow for " +
"insecure SSL API calls to the DSF Hub, or support for self-signed certificates.\n" +
"Example: 'true/false'. Can be set via TF_VAR_insecure_ssl environment variable.",

"sync_type": "Determines whether to sync asset creation/update operations with the Agentless gateways. Available values:\n" +
"SYNC_GW_BLOCKING: The operation is synchronous and blocks until all gateways have been updated. This means that, if syncing the assets to Agentless Gateways fails, the provider will throw an error and not continue. This may result in a difference between the state of which Terraform is aware and the assets that were actually imported.\n" +
"SYNC_GW_NON_BLOCKING: The operation is asynchronous and returns immediately.\n" +
"DO_NOT_SYNC_GW: The operation is synchronous and does not update the gateways.\n" +
"Default: SYNC_GW_BLOCKING",
}
}

Expand All @@ -29,6 +35,9 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa
DSFHUBToken: d.Get("dsfhub_token").(string),
DSFHUBHost: d.Get("dsfhub_host").(string),
InsecureSSL: d.Get("insecure_ssl").(bool),
Params: map[string]string{
"syncType": d.Get("sync_type").(string),
},
}

return config.Client()
Expand Down Expand Up @@ -56,6 +65,12 @@ func Provider() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("INSECURE_SSL", true),
Description: descriptions["insecure_ssl"],
},
"sync_type": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("SYNC_TYPE", "SYNC_GW_BLOCKING"),
Description: descriptions["sync_type"],
},
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down
3 changes: 3 additions & 0 deletions dsfhub/resource_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ func connectDisconnectGateway(d *schema.ResourceData, dsfDataSource ResourceWrap
// if audit_pull_enabled has been changed, connect/disconnect from gateway as needed
if auditPullEnabledChanged {
if auditPullEnabled {
// allow time for asset syncs to gateways to finish
time.Sleep(wait)

// connect gateway
_, err := client.EnableAuditDSFDataSource(assetId)
if err != nil {
Expand Down
41 changes: 34 additions & 7 deletions website/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ Use the navigation to the left to read about the available resources.

The following arguments are supported:

* `dsfhub_host` - (Required) The DSF host endpoint for [DSF HUB API](https://docs.imperva.com/bundle/v4.13-sonar-user-guide/page/84552.htm) operations. Example: 'https://1.2.3.4:8443'. Can be set via `TF_VAR_dsfhub_host` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable).
* `dsfhub_token` - (Required) The [DSF API Token](https://docs.imperva.com/bundle/v4.13-sonar-user-guide/page/84555.htm) for API operations. You can retrieve this from the DSF management hub console. Can be set via `TF_VAR_dsfhub_token` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable).
* `insecure_ssl` - (Optional) The boolean flag that instructs the provider to allow for insecure SSL API calls to a DSF Hub instance to support tests against instances with self-signed certificates.

* `dsfhub_host` - (Required) The DSF host endpoint for [DSF HUB API](https://docs.imperva.com/bundle/v4.13-sonar-user-guide/page/84552.htm) operations. Example: 'https://1.2.3.4:8443'. Can be set via `DSFHUB_HOST` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable).
* `dsfhub_token` - (Required) The [DSF API Token](https://docs.imperva.com/bundle/v4.13-sonar-user-guide/page/84555.htm) for API operations. You can retrieve this from the DSF management hub console. Can be set via `DSFHUB_TOKEN` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable).
* `insecure_ssl` - (Optional) The boolean flag that instructs the provider to allow for insecure SSL API calls to a DSF Hub instance to support tests against instances with self-signed certificates. Can be set via `INSECURE_SSL` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable).
* `sync_type` - (Optional) Determines whether to sync asset creation/update operations with the Agentless gateways. Defaults to SYNC_GW_BLOCKING. Can be set via `SYNC_TYPE` shell [environment variable](https://en.wikipedia.org/wiki/Environment_variable). Available values:
- SYNC_GW_BLOCKING: The operation is synchronous and blocks until all gateways have been updated. This means that, if syncing the assets to Agentless Gateways fails, the provider will throw an error and not continue. This may result in a difference between the state of which Terraform is aware and the assets that were actually imported.
- SYNC_GW_NON_BLOCKING: The operation is asynchronous and returns immediately.
- DO_NOT_SYNC_GW: The operation is synchronous and does not update the gateways.

For example,
```hcl
# Specify path for provider
terraform {
Expand All @@ -31,13 +36,35 @@ terraform {
}
}
# Configure the DSFHUB provider
provider "dsfhub" {
dsfhub_host = "${var.dsfhub_host}" # TF_VAR_dsfhub_host env variable
dsfhub_token = "${var.dsfhub_token}" # TF_VAR_dsfhub_token env variable
dsfhub_host = "https://1.2.3.4:8443"
dsfhub_token = "a1b2c3d4-e5f6-g8h9-wxyz-123456790"
}
```

### Environment Variables
Provider arguments can be set via environment variables as noted above. For example,
```hcl
# Specify path for provider
terraform {
required_providers {
dsfhub = {
source = "imperva/dsfhub"
}
}
}
provider "dsfhub" {}
```
```bash
$ export DSFHUB_HOST="https://1.2.3.4:8443"
$ export DSFHUB_TOKEN="a1b2c3d4-e5f6-g8h9-wxyz-123456790"
$ export INSECURE_SSL=true
$ export SYNC_TYPE="SYNC_GW_NON_BLOCKING"
$ terraform plan
```

## Example Usage - dsfhub_cloud_account

The following is an example of creating a [dsfhub_cloud_account](../r/cloud_account.md) resource used in this example to connect the DSFHUB to an AWS account.
Expand Down

0 comments on commit 7c88628

Please sign in to comment.