diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 652211eb..4c0d7c50 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.21 + go-version: 1.22 - name: Import GPG key id: import_gpg uses: crazy-max/ghaction-import-gpg@v5.0.0 diff --git a/Dockerfile b/Dockerfile index ed431985..083d5116 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM hashicorp/terraform:1.7.5 as terraform +FROM hashicorp/terraform:1.9.0 as terraform -FROM golang:1.21.5-alpine3.17 AS build +FROM golang:1.22.5-alpine3.20 AS build WORKDIR /go/src/cyral COPY main.go go.mod go.sum ./ COPY client/ client/ @@ -12,7 +12,7 @@ RUN gofmt -w . \ && GOOS=darwin GOARCH=amd64 go build -o out/darwin_amd64/terraform-provider-cyral . \ && GOOS=linux GOARCH=amd64 go build -o out/linux_amd64/terraform-provider-cyral . -FROM alpine:3.20.0 as output +FROM alpine:3.20.1 as output ARG VERSION RUN mkdir -p /root/.terraform.d/plugins/local/terraform/cyral/${VERSION:?You must set the VERSION build argument} COPY --from=build /go/src/cyral/out/ /root/.terraform.d/plugins/local/terraform/cyral/${VERSION} diff --git a/cyral/internal/policy/constants.go b/cyral/internal/deprecated/policy/constants.go similarity index 100% rename from cyral/internal/policy/constants.go rename to cyral/internal/deprecated/policy/constants.go diff --git a/cyral/internal/policy/model.go b/cyral/internal/deprecated/policy/model.go similarity index 100% rename from cyral/internal/policy/model.go rename to cyral/internal/deprecated/policy/model.go diff --git a/cyral/internal/policy/resource.go b/cyral/internal/deprecated/policy/resource.go similarity index 98% rename from cyral/internal/policy/resource.go rename to cyral/internal/deprecated/policy/resource.go index 19421d9d..03367405 100644 --- a/cyral/internal/policy/resource.go +++ b/cyral/internal/deprecated/policy/resource.go @@ -27,6 +27,7 @@ var resourceContextHandler = core.DefaultContextHandler{ func resourceSchema() *schema.Resource { return &schema.Resource{ + DeprecationMessage: "For control planes `>= v4.15`, please use resource `cyral_policy_v2` instead.", Description: "Manages [policies](https://cyral.com/docs/reference/policy). See also: " + "[Policy Rule](./policy_rule.md). For more information, see the " + "[Policy Guide](https://cyral.com/docs/policy/overview).", diff --git a/cyral/internal/policy/resource_test.go b/cyral/internal/deprecated/policy/resource_test.go similarity index 97% rename from cyral/internal/policy/resource_test.go rename to cyral/internal/deprecated/policy/resource_test.go index b0f7bc11..c72981c8 100644 --- a/cyral/internal/policy/resource_test.go +++ b/cyral/internal/deprecated/policy/resource_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy" + "github.com/cyralinc/terraform-provider-cyral/cyral/internal/deprecated/policy" "github.com/cyralinc/terraform-provider-cyral/cyral/provider" "github.com/cyralinc/terraform-provider-cyral/cyral/utils" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" diff --git a/cyral/internal/policy/schema_loader.go b/cyral/internal/deprecated/policy/schema_loader.go similarity index 100% rename from cyral/internal/policy/schema_loader.go rename to cyral/internal/deprecated/policy/schema_loader.go diff --git a/cyral/internal/policy/v2/constants.go b/cyral/internal/policy/v2/constants.go new file mode 100644 index 00000000..538c8ef3 --- /dev/null +++ b/cyral/internal/policy/v2/constants.go @@ -0,0 +1,22 @@ +package policyv2 + +const ( + resourceName = "cyral_policy_v2" + dataSourceName = resourceName + apiPathLocal = "v2/policies/local" + apiPathGlobal = "v2/policies/global" + apiPathApproval = "v2/policies/approval" +) + +func getAPIPath(policyType string) string { + switch policyType { + case "POLICY_TYPE_LOCAL", "local": + return apiPathLocal + case "POLICY_TYPE_GLOBAL", "global": + return apiPathGlobal + case "POLICY_TYPE_APPROVAL", "approval": + return apiPathApproval + default: + return "" + } +} diff --git a/cyral/internal/policy/v2/datasource.go b/cyral/internal/policy/v2/datasource.go new file mode 100644 index 00000000..025eac36 --- /dev/null +++ b/cyral/internal/policy/v2/datasource.go @@ -0,0 +1,111 @@ +package policyv2 + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/cyralinc/terraform-provider-cyral/cyral/client" + "github.com/cyralinc/terraform-provider-cyral/cyral/core" + "github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" +) + +var dsContextHandler = core.DefaultContextHandler{ + ResourceName: dataSourceName, + ResourceType: resourcetype.DataSource, + SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &PolicyV2{} }, + ReadUpdateDeleteURLFactory: func(d *schema.ResourceData, c *client.Client) string { + return fmt.Sprintf("https://%s/%s/%s", c.ControlPlane, getAPIPath(d.Get("type").(string)), d.Get("id").(string)) + }, +} + +func dataSourceSchema() *schema.Resource { + return &schema.Resource{ + Description: "This data source provides information about a policy.", + ReadContext: dsContextHandler.ReadContext(), + Schema: map[string]*schema.Schema{ + "id": { + Description: "Identifier for the policy, unique within the policy type.", + Type: schema.TypeString, + Required: true, + }, + "type": { + Description: "Type of the policy, one of [`local`, `global`]", + Type: schema.TypeString, + Required: true, + }, + "name": { + Description: "Name of the policy.", + Type: schema.TypeString, + Computed: true, + }, + "description": { + Description: "Description of the policy.", + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Description: "Indicates if the policy is enabled.", + Type: schema.TypeBool, + Computed: true, + }, + "tags": { + Description: "Tags associated with the policy for categorization.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "scope": { + Description: "Scope of the policy. If empty or omitted, all repositories are in scope.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repo_ids": { + Description: "List of repository IDs that are in scope.", + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + }, + }, + }, + "valid_from": { + Description: "Time when the policy comes into effect. If omitted, the policy is in effect immediately.", + Type: schema.TypeString, + Computed: true, + }, + "valid_until": { + Description: "Time after which the policy is no longer in effect. If omitted, the policy is in effect indefinitely.", + Type: schema.TypeString, + Computed: true, + }, + "document": { + Description: "The actual policy document in JSON format. It must conform to the schema for the policy type.", + Type: schema.TypeString, + Computed: true, + }, + "last_updated": { + Description: "Information about when and by whom the policy was last updated.", + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "created": { + Description: "Information about when and by whom the policy was created.", + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "enforced": { + Description: "Indicates if the policy is enforced. If not enforced, no action is taken based on the policy, but alerts are triggered for violations.", + Type: schema.TypeBool, + Computed: true, + }, + }, + } +} diff --git a/cyral/internal/policy/v2/model.go b/cyral/internal/policy/v2/model.go new file mode 100644 index 00000000..f62ac39d --- /dev/null +++ b/cyral/internal/policy/v2/model.go @@ -0,0 +1,140 @@ +package policyv2 + +import ( + "fmt" + + "github.com/cyralinc/terraform-provider-cyral/cyral/utils" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// ChangeInfo represents information about changes to the policy +type ChangeInfo struct { + Actor string `json:"actor,omitempty"` + ActorType string `json:"actorType,omitempty"` + Timestamp string `json:"timestamp,omitempty"` +} + +// ToMap converts ChangeInfo to a map +func (c ChangeInfo) ToMap() map[string]interface{} { + return map[string]interface{}{ + "actor": c.Actor, + "actor_type": c.ActorType, + "timestamp": c.Timestamp, + } +} + +// PolicyV2 represents the top-level policy structure +type PolicyV2 struct { + Policy Policy `json:"policy,omitempty"` +} + +type Scope struct { + RepoIds []string `json:"repoIds,omitempty"` +} + +// ToMap converts Scope to a list of maps +func (s *Scope) ToMap() []map[string]interface{} { + return []map[string]interface{}{ + { + "repo_ids": s.RepoIds, + }, + } +} + +// Policy represents the policy details +type Policy struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Scope *Scope `json:"scope,omitempty"` + Tags []string `json:"tags,omitempty"` + ValidFrom string `json:"validFrom,omitempty"` + ValidUntil string `json:"validUntil,omitempty"` + Document string `json:"document,omitempty"` + LastUpdated ChangeInfo `json:"lastUpdated,omitempty"` + Created ChangeInfo `json:"created,omitempty"` + Enforced bool `json:"enforced,omitempty"` + Type string `json:"type,omitempty"` +} + +// WriteToSchema writes the policy data to the schema +func (r PolicyV2) WriteToSchema(d *schema.ResourceData) error { + if err := d.Set("id", r.Policy.ID); err != nil { + return fmt.Errorf("error setting 'id' field: %w", err) + } + if err := d.Set("name", r.Policy.Name); err != nil { + return fmt.Errorf("error setting 'name' field: %w", err) + } + if err := d.Set("description", r.Policy.Description); err != nil { + return fmt.Errorf("error setting 'description' field: %w", err) + } + if err := d.Set("enabled", r.Policy.Enabled); err != nil { + return fmt.Errorf("error setting 'enabled' field: %w", err) + } + if err := d.Set("tags", r.Policy.Tags); err != nil { + return fmt.Errorf("error setting 'tags' field: %w", err) + } + if err := d.Set("valid_from", r.Policy.ValidFrom); err != nil { + return fmt.Errorf("error setting 'valid_from' field: %w", err) + } + if err := d.Set("valid_until", r.Policy.ValidUntil); err != nil { + return fmt.Errorf("error setting 'valid_until' field: %w", err) + } + if err := d.Set("document", r.Policy.Document); err != nil { + return fmt.Errorf("error setting 'document' field: %w", err) + } + + // Use the ToMap method to set the last_updated and created fields + if err := d.Set("last_updated", r.Policy.LastUpdated.ToMap()); err != nil { + return fmt.Errorf("error setting 'last_updated' field: %w", err) + } + if err := d.Set("created", r.Policy.Created.ToMap()); err != nil { + return fmt.Errorf("error setting 'created' field: %w", err) + } + if err := d.Set("enforced", r.Policy.Enforced); err != nil { + return fmt.Errorf("error setting 'enforced' field: %w", err) + } + if r.Policy.Type != "" { + if err := d.Set("type", r.Policy.Type); err != nil { + return fmt.Errorf("error setting 'type' field: %w", err) + } + } + if r.Policy.Scope != nil { + if err := d.Set("scope", r.Policy.Scope.ToMap()); err != nil { + return fmt.Errorf("error setting 'scope' field: %w", err) + } + } + d.SetId(r.Policy.ID) + return nil +} + +// ReadFromSchema reads the policy data from the schema +func (r *PolicyV2) ReadFromSchema(d *schema.ResourceData) error { + r.Policy.ID = d.Get("id").(string) + r.Policy.Name = d.Get("name").(string) + r.Policy.Description = d.Get("description").(string) + r.Policy.Enabled = d.Get("enabled").(bool) + r.Policy.Tags = utils.ConvertFromInterfaceList[string](d.Get("tags").([]interface{})) + r.Policy.ValidFrom = d.Get("valid_from").(string) + r.Policy.ValidUntil = d.Get("valid_until").(string) + r.Policy.Document = d.Get("document").(string) + r.Policy.Enforced = d.Get("enforced").(bool) + r.Policy.Type = d.Get("type").(string) + if v, ok := d.GetOk("scope"); ok { + r.Policy.Scope = scopeFromInterface(v.([]interface{})) + } + return nil +} + +// scopeFromInterface converts the map to a Scope struct +func scopeFromInterface(s []interface{}) *Scope { + if len(s) == 0 || s[0] == nil { + return nil + } + m := s[0].(map[string]interface{}) + scope := Scope{ + RepoIds: utils.ConvertFromInterfaceList[string](m["repo_ids"].([]interface{})), + } + return &scope +} diff --git a/cyral/internal/policy/v2/resource.go b/cyral/internal/policy/v2/resource.go new file mode 100644 index 00000000..8c049717 --- /dev/null +++ b/cyral/internal/policy/v2/resource.go @@ -0,0 +1,144 @@ +package policyv2 + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/cyralinc/terraform-provider-cyral/cyral/client" + "github.com/cyralinc/terraform-provider-cyral/cyral/core" + "github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" + "github.com/cyralinc/terraform-provider-cyral/cyral/utils" +) + +var resourceContextHandler = core.DefaultContextHandler{ + ResourceName: resourceName, + ResourceType: resourcetype.Resource, + SchemaReaderFactory: func() core.SchemaReader { return &PolicyV2{} }, + SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &PolicyV2{} }, + BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string { + return fmt.Sprintf("https://%s/%s", c.ControlPlane, getAPIPath(d.Get("type").(string))) + }, + ReadUpdateDeleteURLFactory: func(d *schema.ResourceData, c *client.Client) string { + return fmt.Sprintf("https://%s/%s/%s", + c.ControlPlane, + getAPIPath(d.Get("type").(string)), + d.Get("id").(string), + ) + }, +} + +func PolicyTypes() []string { + return []string{"POLICY_TYPE_GLOBAL", "global", "POLICY_TYPE_LOCAL", "local", "POLICY_TYPE_APPROVAL", "approval"} +} + +func resourceSchema() *schema.Resource { + return &schema.Resource{ + Description: "This resource allows management of various types of policies in the Cyral platform. Policies can be used to define access controls, data governance rules to ensure compliance and security within your database environment.", + CreateContext: resourceContextHandler.CreateContext(), + ReadContext: resourceContextHandler.ReadContext(), + UpdateContext: resourceContextHandler.UpdateContext(), + DeleteContext: resourceContextHandler.DeleteContext(), + Importer: &schema.ResourceImporter{ + StateContext: importPolicyV2StateContext, + }, + Schema: map[string]*schema.Schema{ + "id": { + Description: "Identifier for the policy, unique within the policy type.", + Type: schema.TypeString, + Computed: true, + }, + "name": { + Description: "Name of the policy.", + Type: schema.TypeString, + Required: true, + }, + "description": { + Description: "Description of the policy.", + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Description: "Indicates if the policy is enabled.", + Type: schema.TypeBool, + Optional: true, + }, + "scope": { + Description: "Scope of the policy. If empty or omitted, all repositories are in scope.", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repo_ids": { + Description: "List of repository IDs that are in scope.", + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + }, + }, + }, + "tags": { + Description: "Tags associated with the policy to categorize it.", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "valid_from": { + Description: "Time when the policy comes into effect. If omitted, the policy is in effect immediately.", + Type: schema.TypeString, + Optional: true, + }, + "valid_until": { + Description: "Time after which the policy is no longer in effect. If omitted, the policy is in effect indefinitely.", + Type: schema.TypeString, + Optional: true, + }, + "document": { + Description: "The actual policy document in JSON format. It must conform to the schema for the policy type.", + Type: schema.TypeString, + Required: true, + }, + "last_updated": { + Description: "Information about when and by whom the policy was last updated.", + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "created": { + Description: "Information about when and by whom the policy was created.", + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "enforced": { + Description: "Indicates if the policy is enforced. If not enforced, no action is taken based on the policy, but alerts are triggered for violations.", + Type: schema.TypeBool, + Optional: true, + }, + "type": { + Description: "Type of the policy, one of [`local`, `global`]", + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(append(PolicyTypes(), ""), false), + }, + }, + } +} +func importPolicyV2StateContext(_ context.Context, d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + ids, err := utils.UnMarshalComposedID(d.Id(), "/", 2) + if err != nil { + return nil, err + } + policyType := ids[0] + policyID := ids[1] + _ = d.Set("type", policyType) + d.SetId(policyID) + return []*schema.ResourceData{d}, nil +} diff --git a/cyral/internal/policy/v2/resource_test.go b/cyral/internal/policy/v2/resource_test.go new file mode 100644 index 00000000..9c002f0b --- /dev/null +++ b/cyral/internal/policy/v2/resource_test.go @@ -0,0 +1,110 @@ +package policyv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/cyralinc/terraform-provider-cyral/cyral/provider" + "github.com/cyralinc/terraform-provider-cyral/cyral/utils" +) + +func initialPolicyConfig() map[string]interface{} { + document := `{"governedData":{"locations":["gym_db.users"]},"readRules":[{"conditions":[{"attribute":"identity.userGroups","operator":"contains","value":"USERS"}],"constraints":{"datasetRewrite":"SELECT * FROM ${dataset} WHERE email = '${identity.endUserEmail}'"}},{"conditions":[],"constraints":{}}]}` + + return map[string]interface{}{ + "name": "policy1", + "description": "Local policies for users table access", + "enabled": true, + "tags": []string{"tag1", "tag2"}, + "scope": map[string][]string{"repoIds": {"repo1", "repo2"}}, + "valid_from": "2023-01-01T00:00:00Z", + "valid_until": "2034-01-01T00:00:00Z", + "document": document, + "enforced": true, + "type": "POLICY_TYPE_LOCAL", + } +} + +func updatedPolicyConfig() map[string]interface{} { + return map[string]interface{}{ + "name": "policy2", + "description": "Updated local policies for users table access", + "enabled": false, + "tags": []string{"tag3"}, + "scope": map[string][]string{"repoIds": {"repo3"}}, + "valid_from": "2023-06-01T00:00:00Z", + "valid_until": "2035-06-01T00:00:00Z", + "document": `{"governedData":{"locations":["gym_db.users"]},"readRules":[{"conditions":[{"attribute":"identity.userGroups","operator":"contains","value":"ADMINS"}],"constraints":{"datasetRewrite":"SELECT * FROM ${dataset} WHERE email = '${identity.endUserEmail}'"}},{"conditions":[],"constraints":{}}]}`, + "enforced": false, + "type": "POLICY_TYPE_LOCAL", + } +} +func minimalPolicyConfig() map[string]interface{} { + return map[string]interface{}{ + "name": "policy2", + "document": `{"governedData":{"locations":["gym_db.users"]},"readRules":[{"conditions":[{"attribute":"identity.userGroups","operator":"contains","value":"ADMINS"}],"constraints":{"datasetRewrite":"SELECT * FROM ${dataset} WHERE email = '${identity.endUserEmail}'"}},{"conditions":[],"constraints":{}}]}`, + "type": "local", + } +} + +func TestAccPolicyV2Resource(t *testing.T) { + testInitialConfig, testInitialFunc := setupPolicyTest("main_test", initialPolicyConfig()) + testUpdatedConfig, testUpdatedFunc := setupPolicyTest("main_test", updatedPolicyConfig()) + resource.Test(t, resource.TestCase{ + ProviderFactories: provider.ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testInitialConfig, + Check: testInitialFunc, + }, + { + Config: testUpdatedConfig, + Check: testUpdatedFunc, + }, + }, + }) +} + +func TestAccMinimalPolicyV2Resource(t *testing.T) { + testMinimalConfig, testMinimalFunc := setupMinimalPolicyTest("main_test", minimalPolicyConfig()) + resource.Test(t, resource.TestCase{ + ProviderFactories: provider.ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testMinimalConfig, + Check: testMinimalFunc, + }, + }, + }) +} + +func setupPolicyTest(resName string, policy map[string]interface{}) (string, resource.TestCheckFunc) { + config := utils.FormatPolicyIntoConfig(resName, policy) + resourceFullName := fmt.Sprintf("cyral_policy_v2.%s", resName) + + testFunction := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceFullName, "name", policy["name"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "description", policy["description"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "enabled", fmt.Sprintf("%v", policy["enabled"])), + resource.TestCheckResourceAttr(resourceFullName, "valid_from", policy["valid_from"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "valid_until", policy["valid_until"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "document", policy["document"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "type", policy["type"].(string)), + ) + + return config, testFunction +} +func setupMinimalPolicyTest(resName string, policy map[string]interface{}) (string, resource.TestCheckFunc) { + config := utils.FormatPolicyIntoConfig(resName, policy) + resourceFullName := fmt.Sprintf("cyral_policy_v2.%s", resName) + + testFunction := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceFullName, "name", policy["name"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "document", policy["document"].(string)), + resource.TestCheckResourceAttr(resourceFullName, "type", policy["type"].(string)), + ) + + return config, testFunction +} diff --git a/cyral/internal/policy/v2/schema_loader.go b/cyral/internal/policy/v2/schema_loader.go new file mode 100644 index 00000000..e4aecccd --- /dev/null +++ b/cyral/internal/policy/v2/schema_loader.go @@ -0,0 +1,31 @@ +package policyv2 + +import "github.com/cyralinc/terraform-provider-cyral/cyral/core" + +type packageSchema struct { +} + +func (p *packageSchema) Name() string { + return "policyv2" +} + +func (p *packageSchema) Schemas() []*core.SchemaDescriptor { + return []*core.SchemaDescriptor{ + + { + Name: dataSourceName, + Type: core.DataSourceSchemaType, + Schema: dataSourceSchema, + }, + + { + Name: resourceName, + Type: core.ResourceSchemaType, + Schema: resourceSchema, + }, + } +} + +func PackageSchema() core.PackageSchema { + return &packageSchema{} +} diff --git a/cyral/internal/sweep/sweep_test.go b/cyral/internal/sweep/sweep_test.go index 4aaee5d6..bc0704c6 100644 --- a/cyral/internal/sweep/sweep_test.go +++ b/cyral/internal/sweep/sweep_test.go @@ -9,7 +9,7 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/client" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/deprecated" - "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy" + deprecated_policy "github.com/cyralinc/terraform-provider-cyral/cyral/internal/deprecated/policy" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/role" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar" @@ -151,7 +151,7 @@ func sweepPolicy(_ string) error { if err != nil { return err } - policies, err := policy.ListPolicies(c) + policies, err := deprecated_policy.ListPolicies(c) if err != nil { return err } diff --git a/cyral/provider/schema_loader.go b/cyral/provider/schema_loader.go index b474fe1f..94cae88a 100644 --- a/cyral/provider/schema_loader.go +++ b/cyral/provider/schema_loader.go @@ -3,6 +3,7 @@ package provider import ( "github.com/cyralinc/terraform-provider-cyral/cyral/core" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/datalabel" + deprecated_policy "github.com/cyralinc/terraform-provider-cyral/cyral/internal/deprecated/policy" integration_awsiam "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/awsiam" integration_mfa_duo "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/confextension/mfaduo" integration_pager_duty "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/confextension/pagerduty" @@ -13,8 +14,8 @@ import ( integration_slack "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/slack" integration_teams "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/teams" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/permission" - "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy" policy_rule "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy/rule" + policyv2 "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy/v2" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/regopolicy" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository" repository_accessgateway "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository/accessgateway" @@ -42,6 +43,7 @@ import ( func packagesSchemas() []core.PackageSchema { v := []core.PackageSchema{ datalabel.PackageSchema(), + deprecated_policy.PackageSchema(), integration_awsiam.PackageSchema(), integration_hcvault.PackageSchema(), integration_idp_saml.PackageSchema(), @@ -52,9 +54,9 @@ func packagesSchemas() []core.PackageSchema { integration_slack.PackageSchema(), integration_teams.PackageSchema(), permission.PackageSchema(), - policy.PackageSchema(), policy_rule.PackageSchema(), regopolicy.PackageSchema(), + policyv2.PackageSchema(), repository.PackageSchema(), repository_accessgateway.PackageSchema(), repository_accessrules.PackageSchema(), diff --git a/cyral/utils/testutils.go b/cyral/utils/testutils.go index bd183198..a7142ebc 100644 --- a/cyral/utils/testutils.go +++ b/cyral/utils/testutils.go @@ -266,3 +266,100 @@ func FormatDatadogIntegrationDataIntoConfig(name, apiKey string) string { api_key = "%s" }`, name, apiKey) } + +// FormatPolicyIntoConfig formats a policy map into a Terraform configuration string. +// +// resName is the resource name to be used in the Terraform configuration. +// policy is a map containing the policy data. +func FormatPolicyIntoConfig(resName string, policy map[string]interface{}) string { + var config strings.Builder + + config.WriteString(fmt.Sprintf(` +resource "cyral_policy_v2" "%s" { +`, resName)) + + if name, ok := policy["name"]; ok { + config.WriteString(fmt.Sprintf(" name = \"%s\"\n", name)) + } + if description, ok := policy["description"]; ok { + config.WriteString(fmt.Sprintf(" description = \"%s\"\n", description)) + } + if enabled, ok := policy["enabled"]; ok { + config.WriteString(fmt.Sprintf(" enabled = %v\n", enabled)) + } + if tags, ok := policy["tags"]; ok { + config.WriteString(fmt.Sprintf(" tags = %s\n", formatTags(tags))) + } + if scope, ok := policy["scope"]; ok { + config.WriteString(fmt.Sprintf(" scope %s\n", formatScope(scope))) + } + if validFrom, ok := policy["valid_from"]; ok { + config.WriteString(fmt.Sprintf(" valid_from = \"%s\"\n", validFrom)) + } + if validUntil, ok := policy["valid_until"]; ok { + config.WriteString(fmt.Sprintf(" valid_until = \"%s\"\n", validUntil)) + } + if document, ok := policy["document"]; ok { + escapedDocument := strings.ReplaceAll(document.(string), "${", "$${") + config.WriteString(fmt.Sprintf(" document = chomp(\n< 0 { + formattedTags.WriteString(", ") + } + formattedTags.WriteString(fmt.Sprintf(`"%s"`, tag)) + } + formattedTags.WriteString("]") + + return formattedTags.String() +} diff --git a/docker-compose.yaml b/docker-compose.yaml index f62f02d5..5db6bfaf 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,8 +1,6 @@ -version: "3" - services: app: - image: golang:1.21 + image: golang:1.22 container_name: terraform_provider_cyral environment: - GOFLAGS=-buildvcs=false diff --git a/docs/data-sources/policy_v2.md b/docs/data-sources/policy_v2.md new file mode 100644 index 00000000..f0efe89f --- /dev/null +++ b/docs/data-sources/policy_v2.md @@ -0,0 +1,42 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "cyral_policy_v2 Data Source - terraform-provider-cyral" +subcategory: "" +description: |- + This data source provides information about a policy. +--- + +# cyral_policy_v2 (Data Source) + +This data source provides information about a policy. + + + +## Schema + +### Required + +- `id` (String) Identifier for the policy, unique within the policy type. +- `type` (String) Type of the policy, one of [`local`, `global`] + +### Read-Only + +- `created` (Map of String) Information about when and by whom the policy was created. +- `description` (String) Description of the policy. +- `document` (String) The actual policy document in JSON format. It must conform to the schema for the policy type. +- `enabled` (Boolean) Indicates if the policy is enabled. +- `enforced` (Boolean) Indicates if the policy is enforced. If not enforced, no action is taken based on the policy, but alerts are triggered for violations. +- `last_updated` (Map of String) Information about when and by whom the policy was last updated. +- `name` (String) Name of the policy. +- `scope` (List of Object) Scope of the policy. If empty or omitted, all repositories are in scope. (see [below for nested schema](#nestedatt--scope)) +- `tags` (List of String) Tags associated with the policy for categorization. +- `valid_from` (String) Time when the policy comes into effect. If omitted, the policy is in effect immediately. +- `valid_until` (String) Time after which the policy is no longer in effect. If omitted, the policy is in effect indefinitely. + + + +### Nested Schema for `scope` + +Read-Only: + +- `repo_ids` (List of String) diff --git a/docs/resources/policy.md b/docs/resources/policy.md index c1d075a5..faac5209 100644 --- a/docs/resources/policy.md +++ b/docs/resources/policy.md @@ -3,12 +3,12 @@ page_title: "cyral_policy Resource - terraform-provider-cyral" subcategory: "" description: |- - Manages policies https://cyral.com/docs/reference/policy. See also: Policy Rule ./policy_rule.md. For more information, see the Policy Guide https://cyral.com/docs/policy/overview. + ~> DEPRECATED For control planes >= v4.15, please use resource cyral_policy_v2 instead. --- # cyral_policy (Resource) -Manages [policies](https://cyral.com/docs/reference/policy). See also: [Policy Rule](./policy_rule.md). For more information, see the [Policy Guide](https://cyral.com/docs/policy/overview). +~> **DEPRECATED** For control planes `>= v4.15`, please use resource `cyral_policy_v2` instead. ## Example Usage diff --git a/docs/resources/policy_v2.md b/docs/resources/policy_v2.md new file mode 100644 index 00000000..89906521 --- /dev/null +++ b/docs/resources/policy_v2.md @@ -0,0 +1,124 @@ +# cyral_policy_v2 (Resource) + +This resource allows management of various types of policies in the Cyral platform. Policies can be used to define access controls, data governance rules to ensure compliance and security within your database environment. + +-> Import ID syntax is `{policy_type}/{policy_id}`, where `{policy_type}` is one of [local, global] `{policy_id}` is the ID of the policy in the Cyral Control Plane. + +## Example Usage + +```terraform +resource "cyral_repository" "myrepo" { + type = "mongodb" + name = "myrepo" + + repo_node { + name = "node-1" + host = "mongodb.cyral.com" + port = 27017 + } + + mongodb_settings { + server_type = "standalone" + } +} + +resource "cyral_policy_v2" "local_policy_example" { + name = "local_policy" + description = "Local policy to allow gym users to read their own data" + enabled = true + tags = ["gym", "local"] + scope { + repo_ids = [cyral_repository.myrepo.id] + } + document = jsonencode({ + governedData = { + locations = ["gym_db.users"] + } + readRules = [ + { + conditions = [ + { + attribute = "identity.userGroups" + operator = "contains" + value = "users" + } + ] + constraints = { + datasetRewrite = "SELECT * FROM $${dataset} WHERE email = '$${identity.endUserEmail}'" + } + } + ] + }) + enforced = true + type = "local" +} + +resource "cyral_policy_v2" "global_policy_example" { + name = "global_policy" + description = "Global policy for finance users with row limit for PII data" + enabled = true + tags = ["finance", "global"] + scope { + repo_ids = [cyral_repository.myrepo.id] + } + document = jsonencode({ + governedData = { + tags = ["PII"] + } + readRules = [ + { + conditions = [ + { + attribute = "identity.userGroups" + operator = "contains" + value = "finance" + } + ] + constraints = { + maxRows = 5 + } + }, + { + conditions = [] + constraints = {} + } + ] + }) + enforced = true + type = "global" +} +``` + + + +## Schema + +### Required + +- `document` (String) The actual policy document in JSON format. It must conform to the schema for the policy type. +- `name` (String) Name of the policy. +- `type` (String) Type of the policy, one of [`local`, `global`] + +### Optional + +- `description` (String) Description of the policy. +- `enabled` (Boolean) Indicates if the policy is enabled. +- `enforced` (Boolean) Indicates if the policy is enforced. If not enforced, no action is taken based on the policy, but alerts are triggered for violations. +- `scope` (Block List) Scope of the policy. If empty or omitted, all repositories are in scope. (see [below for nested schema](#nestedblock--scope)) +- `tags` (List of String) Tags associated with the policy to categorize it. +- `valid_from` (String) Time when the policy comes into effect. If omitted, the policy is in effect immediately. +- `valid_until` (String) Time after which the policy is no longer in effect. If omitted, the policy is in effect indefinitely. + +### Read-Only + +- `created` (Map of String) Information about when and by whom the policy was created. +- `id` (String) Identifier for the policy, unique within the policy type. +- `last_updated` (Map of String) Information about when and by whom the policy was last updated. + + + +### Nested Schema for `scope` + +Optional: + +- `repo_ids` (List of String) List of repository IDs that are in scope. diff --git a/examples/resources/cyral_policy_v2/resource.tf b/examples/resources/cyral_policy_v2/resource.tf new file mode 100644 index 00000000..fab59f87 --- /dev/null +++ b/examples/resources/cyral_policy_v2/resource.tf @@ -0,0 +1,80 @@ +resource "cyral_repository" "myrepo" { + type = "mongodb" + name = "myrepo" + + repo_node { + name = "node-1" + host = "mongodb.cyral.com" + port = 27017 + } + + mongodb_settings { + server_type = "standalone" + } +} + +resource "cyral_policy_v2" "local_policy_example" { + name = "local_policy" + description = "Local policy to allow gym users to read their own data" + enabled = true + tags = ["gym", "local"] + scope { + repo_ids = [cyral_repository.myrepo.id] + } + document = jsonencode({ + governedData = { + locations = ["gym_db.users"] + } + readRules = [ + { + conditions = [ + { + attribute = "identity.userGroups" + operator = "contains" + value = "users" + } + ] + constraints = { + datasetRewrite = "SELECT * FROM $${dataset} WHERE email = '$${identity.endUserEmail}'" + } + } + ] + }) + enforced = true + type = "local" +} + +resource "cyral_policy_v2" "global_policy_example" { + name = "global_policy" + description = "Global policy for finance users with row limit for PII data" + enabled = true + tags = ["finance", "global"] + scope { + repo_ids = [cyral_repository.myrepo.id] + } + document = jsonencode({ + governedData = { + tags = ["PII"] + } + readRules = [ + { + conditions = [ + { + attribute = "identity.userGroups" + operator = "contains" + value = "finance" + } + ] + constraints = { + maxRows = 5 + } + }, + { + conditions = [] + constraints = {} + } + ] + }) + enforced = true + type = "global" +} diff --git a/go.mod b/go.mod index 0bc81531..33bae0d7 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/cyralinc/terraform-provider-cyral -go 1.21 +go 1.22 require ( - github.com/aws/aws-sdk-go v1.48.11 + github.com/aws/aws-sdk-go v1.54.13 github.com/google/uuid v1.6.0 github.com/hashicorp/terraform-plugin-docs v0.18.0 github.com/hashicorp/terraform-plugin-log v0.9.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 github.com/stretchr/testify v1.9.0 - golang.org/x/exp v0.0.0-20231127185646-65229373498e + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 golang.org/x/oauth2 v0.21.0 ) @@ -18,32 +18,32 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/ProtonMail/go-crypto v1.1.0-alpha.0 // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.3.9 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.16.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/hashicorp/cli v1.1.6 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.6.3 // indirect - github.com/hashicorp/hcl/v2 v2.19.1 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/hc-install v0.7.0 // indirect + github.com/hashicorp/hcl/v2 v2.21.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.20.0 // indirect - github.com/hashicorp/terraform-json v0.21.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.22.0 // indirect + github.com/hashicorp/terraform-exec v0.21.0 // indirect + github.com/hashicorp/terraform-json v0.22.1 // indirect + github.com/hashicorp/terraform-plugin-go v0.23.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -68,16 +68,18 @@ require ( github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/yuin/goldmark v1.6.0 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect - github.com/zclconf/go-cty v1.14.2 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.22.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect - google.golang.org/grpc v1.61.1 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d6ab6229..097f7f87 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v1.1.0-alpha.0 h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE9N5vPhgY2I+j0= -github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton h1:0RXAi0EJFs81j+MMsqvHNuAUGWzeVfCO9LnHAfoQ8NA= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= @@ -19,14 +19,14 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.48.11 h1:9YbiSbaF/jWi+qLRl+J5dEhr2mcbDYHmKg2V7RBcD5M= -github.com/aws/aws-sdk-go v1.48.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.54.13 h1:zpCuiG+/mFdDY/klKJvmSioAZWk45F4rLGq0JWVAAzk= +github.com/aws/aws-sdk-go v1.54.13/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= +github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -35,16 +35,16 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -52,8 +52,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -73,36 +73,36 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.6.3 h1:yE/r1yJvWbtrJ0STwScgEnCanb0U9v7zp0Gbkmcoxqs= -github.com/hashicorp/hc-install v0.6.3/go.mod h1:KamGdbodYzlufbWh4r9NRo8y6GLHWZP2GBtdnms1Ln0= -github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= -github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= +github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= +github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14= +github.com/hashicorp/hcl/v2 v2.21.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo= -github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= -github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= -github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= +github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= +github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= +github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= github.com/hashicorp/terraform-plugin-docs v0.18.0 h1:2bINhzXc+yDeAcafurshCrIjtdu1XHn9zZ3ISuEhgpk= github.com/hashicorp/terraform-plugin-docs v0.18.0/go.mod h1:iIUfaJpdUmpi+rI42Kgq+63jAjI8aZVTyxp3Bvk9Hg8= -github.com/hashicorp/terraform-plugin-go v0.22.0 h1:1OS1Jk5mO0f5hrziWJGXXIxBrMe2j/B8E+DVGw43Xmc= -github.com/hashicorp/terraform-plugin-go v0.22.0/go.mod h1:mPULV91VKss7sik6KFEcEu7HuTogMLLO/EvWCuFkRVE= +github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= +github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg= github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= @@ -129,8 +129,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -166,13 +164,13 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= @@ -197,30 +195,34 @@ github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= -github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI= -github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= -golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -234,8 +236,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -245,26 +247,26 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= -google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/templates/resources/policy_v2.md.tmpl b/templates/resources/policy_v2.md.tmpl new file mode 100644 index 00000000..52470c58 --- /dev/null +++ b/templates/resources/policy_v2.md.tmpl @@ -0,0 +1,11 @@ +# {{ .Name | trimspace }} ({{ .Type | trimspace }}) + +{{ .Description | trimspace }} + +-> Import ID syntax is `{policy_type}/{policy_id}`, where `{policy_type}` is one of [local, global] `{policy_id}` is the ID of the policy in the Cyral Control Plane. + +## Example Usage + +{{ tffile "examples/resources/cyral_policy_v2/resource.tf" }} + +{{ .SchemaMarkdown | trimspace }}