diff --git a/sysdig/data_source_sysdig_secure_zone.go b/sysdig/data_source_sysdig_secure_zone.go new file mode 100644 index 000000000..a39299c83 --- /dev/null +++ b/sysdig/data_source_sysdig_secure_zone.go @@ -0,0 +1,124 @@ +package sysdig + +import ( + "context" + "fmt" + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceSysdigSecureZone() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceSysdigSecureZoneRead, + + Schema: map[string]*schema.Schema{ + SchemaDescriptionKey: { + Type: schema.TypeString, + Computed: true, + }, + SchemaIsSystemKey: { + Type: schema.TypeBool, + Computed: true, + }, + SchemaAuthorKey: { + Type: schema.TypeString, + Computed: true, + }, + SchemaLastModifiedBy: { + Type: schema.TypeString, + Computed: true, + }, + SchemaLastUpdated: { + Type: schema.TypeString, + Computed: true, + }, + SchemaScopeKey: { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + SchemaIDKey: { + Type: schema.TypeInt, + Computed: true, + }, + SchemaTargetTypeKey: { + Type: schema.TypeString, + Computed: true, + }, + SchemaRulesKey: { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "id": { + Type: schema.TypeString, + Optional: true, + ExactlyOneOf: []string{"id", "name"}, + Description: "The ID of the zone to retrieve.", + }, + "name": { + Type: schema.TypeString, + Optional: true, + ExactlyOneOf: []string{"id", "name"}, + Description: "The name of the zone to retrieve.", + }, + }, + } +} + +func dataSourceSysdigSecureZoneRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + client, err := getZoneClient(m.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + var zone *v2.Zone + zoneIDRaw, hasZoneID := d.GetOk("id") + if hasZoneID { + zoneID, err := strconv.Atoi(zoneIDRaw.(string)) + if err != nil { + return diag.FromErr(fmt.Errorf("invalid zone id: %s", err)) + } + zone, err = client.GetZoneById(ctx, zoneID) + if err != nil { + return diag.FromErr(fmt.Errorf("error fetching zone by ID: %s", err)) + } + } else if nameRaw, hasName := d.GetOk("name"); hasName { + name := nameRaw.(string) + zones, err := client.GetZones(ctx, name) + if err != nil { + return diag.FromErr(fmt.Errorf("error fetching zones: %s", err)) + } + for _, z := range zones { + if z.Name == name { + zone = &z + break + } + } + if zone == nil { + return diag.FromErr(fmt.Errorf("zone with name '%s' not found", name)) + } + } else { + return diag.FromErr(fmt.Errorf("either id or name must be specified")) + } + + d.SetId(fmt.Sprintf("%d", zone.ID)) + _ = d.Set(SchemaNameKey, zone.Name) + _ = d.Set(SchemaDescriptionKey, zone.Description) + _ = d.Set(SchemaIsSystemKey, zone.IsSystem) + _ = d.Set(SchemaAuthorKey, zone.Author) + _ = d.Set(SchemaLastModifiedBy, zone.LastModifiedBy) + _ = d.Set(SchemaLastUpdated, time.UnixMilli(zone.LastUpdated).Format(time.RFC3339)) + + if err := d.Set(SchemaScopeKey, fromZoneScopesResponse(zone.Scopes)); err != nil { + return diag.FromErr(fmt.Errorf("error setting scope: %s", err)) + } + + return nil +} diff --git a/sysdig/data_source_sysdig_secure_zone_test.go b/sysdig/data_source_sysdig_secure_zone_test.go new file mode 100644 index 000000000..5409bf96d --- /dev/null +++ b/sysdig/data_source_sysdig_secure_zone_test.go @@ -0,0 +1,62 @@ +//go:build tf_acc_sysdig_secure || tf_acc_onprem_secure + +package sysdig_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/draios/terraform-provider-sysdig/sysdig" +) + +func TestAccDataSourceSysdigSecureZone(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceSysdigSecureZoneConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.sysdig_secure_zone.test", "name", "test-secure-zone"), + resource.TestCheckResourceAttrSet("data.sysdig_secure_zone.test", "description"), + resource.TestCheckResourceAttrSet("data.sysdig_secure_zone.test", "is_system"), + resource.TestCheckResourceAttrSet("data.sysdig_secure_zone.test", "author"), + resource.TestCheckResourceAttrSet("data.sysdig_secure_zone.test", "last_modified_by"), + resource.TestCheckResourceAttrSet("data.sysdig_secure_zone.test", "last_updated"), + resource.TestCheckTypeSetElemNestedAttrs( + "data.sysdig_secure_zone.test", + "scope.*", + map[string]string{ + "target_type": "aws", + "rules": "organization in (\"o1\", \"o2\") and account in (\"a1\", \"a2\")", + }, + ), + ), + }, + }, + }) +} + +func testAccDataSourceSysdigSecureZoneConfig() string { + return ` +resource "sysdig_secure_zone" "sample" { + name = "test-secure-zone" + description = "Test secure zone" + scope { + target_type = "aws" + rules = "organization in (\"o1\", \"o2\") and account in (\"a1\", \"a2\")" + } +} + +data "sysdig_secure_zone" "test" { + depends_on = ["sysdig_secure_zone.sample"] + name = "test-secure-zone" +} + ` +} diff --git a/sysdig/internal/client/v2/model.go b/sysdig/internal/client/v2/model.go index 649bc22e5..320c03c98 100644 --- a/sysdig/internal/client/v2/model.go +++ b/sysdig/internal/client/v2/model.go @@ -1225,7 +1225,7 @@ type OrganizationSecure struct { } type ZonesWrapper struct { - Zones []Zone `json:"zones"` + Zones []Zone `json:"data"` } type ZoneRequest struct { diff --git a/sysdig/internal/client/v2/zones.go b/sysdig/internal/client/v2/zones.go index c2b132c7c..52fa19955 100644 --- a/sysdig/internal/client/v2/zones.go +++ b/sysdig/internal/client/v2/zones.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" ) const ( @@ -13,15 +14,18 @@ const ( type ZoneInterface interface { Base - GetZones(ctx context.Context) ([]Zone, error) + GetZones(ctx context.Context, name string) ([]Zone, error) GetZoneById(ctx context.Context, id int) (*Zone, error) CreateZone(ctx context.Context, zone *ZoneRequest) (*Zone, error) UpdateZone(ctx context.Context, zone *ZoneRequest) (*Zone, error) DeleteZone(ctx context.Context, id int) error } -func (client *Client) GetZones(ctx context.Context) ([]Zone, error) { - response, err := client.requester.Request(ctx, http.MethodGet, client.getZonesURL(), nil) +func (client *Client) GetZones(ctx context.Context, name string) ([]Zone, error) { + zonesURL := client.getZonesURL() + zonesURL = fmt.Sprintf("%s?filter=name:%s", zonesURL, url.QueryEscape(name)) + + response, err := client.requester.Request(ctx, http.MethodGet, zonesURL, nil) if err != nil { return nil, err } diff --git a/sysdig/provider.go b/sysdig/provider.go index 4a3f4a3ff..82ca1fbf8 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -237,6 +237,7 @@ func (p *SysdigProvider) Provider() *schema.Provider { "sysdig_secure_custom_role_permissions": dataSourceSysdigSecureCustomRolePermissions(), "sysdig_secure_rule_stateful": dataSourceSysdigSecureRuleStateful(), "sysdig_secure_rule_stateful_count": dataSourceSysdigSecureRuleStatefulCount(), + "sysdig_secure_zone": dataSourceSysdigSecureZone(), "sysdig_current_user": dataSourceSysdigCurrentUser(), "sysdig_user": dataSourceSysdigUser(), diff --git a/website/docs/d/secure_zone.md b/website/docs/d/secure_zone.md new file mode 100644 index 000000000..9b8f37232 --- /dev/null +++ b/website/docs/d/secure_zone.md @@ -0,0 +1,54 @@ +--- +subcategory: "Sysdig Secure" +layout: "sysdig" +page_title: "Sysdig: sysdig_secure_zone" +description: |- + Retrieves Zone by ID. +--- + +# sysdig\_secure\_zone Data Source + +The `sysdig_secure_zone` data source allows you to retrieve information about a specific Sysdig Secure Zone. + +## Example Usage + +```hcl +resource "sysdig_secure_zone" "sample" { + name = "test-secure-zone" + description = "Test secure zone" + scope { + target_type = "aws" + rules = "organization in (\"o1\", \"o2\") and account in (\"a1\", \"a2\")" + } +} + +data "sysdig_secure_zone" "test" { + depends_on = [sysdig_secure_zone.sample] + name = sysdig_secure_zone.sample.name +} +``` + +## Argument Reference + +The following arguments are supported, it is required that one of them is provided: + +- `name` - The name of the Sysdig Secure Zone. +- `id` - The ID of the Sysdig Secure Zone. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +- `is_system` - (Computed) Whether the Zone is a system zone. +- `author` - (Computed) The zone author. +- `scope` - (Computed) The scope of the zone. +- `last_modified_by` - (Computed) By whom is last modification made. +- `last_updated` - (Computed) Timestamp of last modification of zone. + +## Import + +Zone can be imported using the ID, e.g. + +``` +$ terraform import sysdig_secure_zone.example 12345 +```