diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index cf46e3fd..ffe95ee1 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -1,7 +1,7 @@ name: pull_request on: pull_request: - types: [push, force-push, opened, edited, synchronize, reopened] + types: [opened, edited, synchronize, reopened] jobs: pull_request: runs-on: ubuntu-latest @@ -21,9 +21,9 @@ jobs: run: git fetch --prune --unshallow - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: 1.20.5 + go-version: 1.22 - name: Run Go Mod Tidy run: go mod tidy @@ -50,6 +50,6 @@ jobs: fi - name: Static Check - uses: dominikh/staticcheck-action@v1.3.0 + uses: dominikh/staticcheck-action@v1.3.1 with: - version: "2022.1.3" + version: "latest" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8836563..1c818a8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,9 +26,9 @@ jobs: run: git fetch --prune --unshallow - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: 1.20.5 + go-version: 1.22 - name: Test run: go test ./banyan/... -v @@ -45,7 +45,7 @@ jobs: PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@v5 with: version: latest args: release --rm-dist diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 5282bcc3..3d6f8eaf 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -1,8 +1,19 @@ name: run_tests on: - push: + workflow_dispatch: branches: [ "dev" ] + inputs: + command_center_url: + description: 'Command Center URL' + required: true + default: 'https://net.banyanops.com' + type: string + secrets: + api_key: + description: 'API Key' + required: true + type: string jobs: run_tests: @@ -20,9 +31,9 @@ jobs: run: git fetch --prune --unshallow - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: 1.20.5 + go-version: 1.22 - name: Run Go Mod Tidy run: go mod tidy @@ -31,8 +42,8 @@ jobs: run: go test ./banyan/... -v env: TF_ACC: true - BANYAN_API_KEY: ${{ secrets.BANYAN_API_KEY }} - BANYAN_HOST: ${{ secrets.BANYAN_HOST }} + BANYAN_API_KEY: ${{ secrets.api_key }} + BANYAN_HOST: ${{ inputs.command_center_url }} - name: Generate Documentation run: go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-name terraform-provider-banyan --examples-dir ./examples/ @@ -47,6 +58,6 @@ jobs: fi - name: Static Check - uses: dominikh/staticcheck-action@v1.3.0 + uses: dominikh/staticcheck-action@v1.3.1 with: - version: "2022.1.3" + version: "latest" diff --git a/banyan/provider.go b/banyan/provider.go index d096b130..8e61b73e 100644 --- a/banyan/provider.go +++ b/banyan/provider.go @@ -42,6 +42,8 @@ func Provider() *schema.Provider { "banyan_api_key": resourceApiKey(), "banyan_connector": resourceConnector(), "banyan_accesstier": resourceAccessTier(), + "banyan_accesstier_group": resourceAccessTierGroup(), + "banyan_scim": resourceSCIM(), }, DataSourcesMap: map[string]*schema.Resource{ "banyan_oidc_settings": dataSourceOidcSettings(), diff --git a/banyan/resource_accesstier_group.go b/banyan/resource_accesstier_group.go new file mode 100644 index 00000000..c00b85c6 --- /dev/null +++ b/banyan/resource_accesstier_group.go @@ -0,0 +1,477 @@ +package banyan + +import ( + "context" + "encoding/json" + "reflect" + + "github.com/banyansecurity/terraform-banyan-provider/client" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstier" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstiergroup" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceAccessTierGroup() *schema.Resource { + return &schema.Resource{ + Description: "The access tier group resource allows for configuration of the access tier group API object. ", + CreateContext: resourceAccessTierGroupCreate, + ReadContext: resourceAccessTierGroupRead, + DeleteContext: resourceAccessTierGroupDelete, + UpdateContext: resourceAccessTierGroupUpdate, + Schema: AccessTierGroupSchema(), + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + } +} + +func AccessTierGroupSchema() map[string]*schema.Schema { + s := map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the access tier group in Banyan", + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: "Name of the access tier group", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Description of access tier group", + }, + "cluster": { + Type: schema.TypeString, + Required: true, + Description: "Cluster / shield name in Banyan", + }, + "dns_search_domains": { + Type: schema.TypeString, + Required: true, + Description: "", + }, + "cidrs": { + Type: schema.TypeSet, + Required: true, + Description: "CIDR range", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dns_enabled": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable DNS for service tunnels (needed to work properly with both private and public targets)", + }, + "udp_port_number": { + Type: schema.TypeInt, + Required: true, + Description: "UDP port", + }, + "keepalive": { + Type: schema.TypeInt, + Required: true, + Description: "Keepalive", + }, + "domains": { + Type: schema.TypeSet, + Required: true, + Description: "Any internal domains that can only be resolved on your internal network’s private DNS", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "shared_fqdn": { + Type: schema.TypeString, + Required: true, + Description: "Shared FQDN", + }, + "attach_access_tier_ids": { + Type: schema.TypeSet, + Optional: true, + Description: "Access tier IDs to attach to access tier group", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "detach_access_tier_ids": { + Type: schema.TypeSet, + Optional: true, + Description: "Access tier IDs to detach from access tier group", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "console_log_level": { + Type: schema.TypeString, + Optional: true, + Description: "Controls verbosity of logs to console. Must be one of \"ERR\", \"WARN\", \"INFO\", \"DEBUG\"", + ValidateFunc: validation.StringInSlice([]string{"ERR", "WARN", "INFO", "DEBUG"}, false), + }, + "file_log_level": { + Type: schema.TypeString, + Optional: true, + Description: "Controls verbosity of logs to file. Must be one of \"ERR\", \"WARN\", \"INFO\", \"DEBUG\"", + ValidateFunc: validation.StringInSlice([]string{"ERR", "WARN", "INFO", "DEBUG"}, false), + }, + "file_log": { + Type: schema.TypeBool, + Optional: true, + Description: "Whether to log to file or not", + }, + "log_num": { + Type: schema.TypeInt, + Optional: true, + Description: "For file logs: Number of files to use for log rotation", + }, + "log_size": { + Type: schema.TypeInt, + Optional: true, + Description: "For file logs: Size of each file for log rotation", + }, + "statsd_address": { + Type: schema.TypeString, + Optional: true, + Description: "Address to send statsd messages: “hostname:port” for UDP, “unix:///path/to/socket” for UDS", + }, + "events_rate_limiting": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable rate limiting of Access Event generation based on a credit-based rate control mechanism", + }, + "event_key_rate_limiting": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable rate limiting of Access Event generation based on a credit-based rate control mechanism", + }, + "forward_trust_cookie": { + Type: schema.TypeBool, + Optional: true, + Description: "Forward the Banyan trust cookie to upstream servers. This may be enabled if upstream servers wish to make use of information in the Banyan trust cookie.", + }, + "enable_hsts": { + Type: schema.TypeBool, + Optional: true, + Description: "If enabled, Banyan will send the HTTP Strict-Transport-Security response header", + }, + "infra_maximum_session_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: "Timeout in seconds infrastructure sessions connected via the access tier", + }, + "debug_http_backend_log": { + Type: schema.TypeBool, + Optional: true, + Description: "Verbose logging for HTTP backend traffic", + }, + "debug_visibility_only": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable or disable visibility mode. If on, Netagent will not do policy enforcement on inbound traffic", + }, + "debug_shield_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: "If Shield is not available, policies will be treated as if they are permissive. Zero means this is disabled.", + }, + "debug_keep_alive": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable TCP keepalive messages for TCP sockets handled by Netagent", + }, + "debug_keep_idle": { + Type: schema.TypeInt, + Optional: true, + Description: "Idle time before sending a TCP keepalive", + }, + "debug_keep_interval": { + Type: schema.TypeInt, + Optional: true, + Description: "Time between consecutive TCP keepalive messages", + }, + "debug_keep_count": { + Type: schema.TypeInt, + Optional: true, + Description: "Number of missing TCP keepalive acknowledgements before closing connection", + }, + "debug_cpu_profile": { + Type: schema.TypeString, + Optional: true, + Description: "Output file for CPU profiling; may impact performance. If empty, this is disabled", + }, + "debug_mem_profile": { + Type: schema.TypeBool, + Optional: true, + Description: "Output file for memory profiling; may impact performance. If empty, this is disabled", + }, + "debug_host_only": { + Type: schema.TypeBool, + Optional: true, + Description: "Host only mode", + }, + "debug_disable_docker": { + Type: schema.TypeBool, + Optional: true, + Description: "Disable Docker monitoring", + }, + "debug_send_zeros": { + Type: schema.TypeBool, + Optional: true, + Description: "Send all-zero data points to Shield", + }, + "debug_period": { + Type: schema.TypeInt, + Optional: true, + Description: "Interval for reporting statistics", + }, + "debug_request_level_events": { + Type: schema.TypeBool, + Optional: true, + Description: "Generate access events at the request level", + }, + "debug_address_transparency": { + Type: schema.TypeBool, + Optional: true, + Description: "Provide client address transparency", + }, + "debug_use_rsa": { + Type: schema.TypeBool, + Optional: true, + Description: "Netagent will generate RSA instead of ECDSA keys", + }, + "debug_full_server_cert_chain": { + Type: schema.TypeBool, + Optional: true, + Description: "Include non-root (intermediate) CA certs during TLS handshakes", + }, + "debug_code_flow": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable or disable OpenID Connect", + }, + "debug_inactivity_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: "HTTP inactivity timeout", + }, + "debug_client_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: "Client identification timeout", + }, + "debug_service_discovery_enable": { + Type: schema.TypeBool, + Optional: true, + Description: "Enable or disable DNS and conntrack logging", + }, + "debug_service_discovery_msg_limit": { + Type: schema.TypeInt, + Optional: true, + Description: "Message threshold for batch processing", + ValidateFunc: validation.IntInSlice([]int{100, 1000, 5000}), + }, + "debug_service_discovery_msg_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: "Timeout value for service discovery batch processing", + }, + } + return s +} + +func resourceAccessTierGroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + atg, err := c.AccessTierGroup.Create(atgFromState(d)) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(atg.ID) + + attachIDs := convertSchemaSetToStringSlice(d.Get("attach_access_tier_ids").(*schema.Set)) + if len(attachIDs) != 0 { + err = attachAccessTiers(c, d.Get("id").(string), attachIDs) + if err != nil { + return + } + } + + return +} + +func resourceAccessTierGroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + key, err := c.AccessTierGroup.Get(d.Id()) + if err != nil { + handleNotFoundError(d, err) + return + } + d.SetId(key.ID) + err = d.Set("name", key.Name) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("description", key.Description) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("cluster", key.ClusterName) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("cidrs", key.TunnelConfig.CIDRs) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("domains", key.TunnelConfig.Domains) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("dns_enabled", key.TunnelConfig.DNSEnabled) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("shared_fqdn", key.TunnelConfig.SharedFQDN) + if err != nil { + return diag.FromErr(err) + } + + var advancedSettings accesstier.AccessTierLocalConfig + err = json.Unmarshal([]byte(key.AdvancedSettings), &advancedSettings) + if err != nil { + return diag.FromErr(err) + } + + err = flattenLoggingParameters(d, advancedSettings) + if err != nil { + return diag.FromErr(err) + } + err = flattenEventParameters(d, advancedSettings) + if err != nil { + return diag.FromErr(err) + } + err = flattenWebServices(d, advancedSettings) + if err != nil { + return diag.FromErr(err) + } + err = flattenInfrastructureServiceParameters(d, advancedSettings) + if err != nil { + return diag.FromErr(err) + } + err = flattenDebuggingParameters(d, advancedSettings) + if err != nil { + return diag.FromErr(err) + } + + return +} + +func resourceAccessTierGroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + _, err := c.AccessTierGroup.Update(d.Id(), atgFromState(d)) + if err != nil { + return diag.FromErr(err) + } + + attachIDs := convertSchemaSetToStringSlice(d.Get("attach_access_tier_ids").(*schema.Set)) + if len(attachIDs) != 0 { + err = attachAccessTiers(c, d.Get("id").(string), attachIDs) + if err != nil { + return + } + } + + detachIDs := convertSchemaSetToStringSlice(d.Get("detach_access_tier_ids").(*schema.Set)) + if len(detachIDs) != 0 { + err = detachAccessTiers(c, d.Get("id").(string), detachIDs) + if err != nil { + return + } + } + + return +} + +func resourceAccessTierGroupDelete(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + err := c.AccessTierGroup.Delete(d.Id()) + if err != nil { + diagnostics = diag.FromErr(err) + return + } + d.SetId("") + return +} + +// creates an access tier group from the terraform state +func atgFromState(d *schema.ResourceData) accesstiergroup.AccessTierGroupPost { + at := accesstiergroup.AccessTierGroupPost{ + Name: d.Get("name").(string), + Description: d.Get("description").(string), + SharedFQDN: d.Get("shared_fqdn").(string), + ClusterName: d.Get("cluster").(string), + TunnelConfig: setATGTunnelConfigEndUserRequest(d), + AdvancedSettings: expandAdvancedSettings(d), + } + return at +} + +func setATGTunnelConfigEndUserRequest(d *schema.ResourceData) (expanded *accesstier.AccessTierTunnelInfoPost) { + e := accesstier.AccessTierTunnelInfoPost{ + UDPPortNumber: d.Get("udp_port_number").(int), + DNSEnabled: d.Get("dns_enabled").(bool), + CIDRs: convertSchemaSetToStringSlice(d.Get("cidrs").(*schema.Set)), + Domains: convertSchemaSetToStringSlice(d.Get("domains").(*schema.Set)), + } + if reflect.DeepEqual(e, accesstier.AccessTierTunnelInfoPost{}) { + return nil + } + return &e +} + +func attachAccessTiers(c *client.Holder, atgID string, atIDs []string) (err error) { + + attachReqBody := accesstiergroup.AccessTierList{ + AccessTierIDs: atIDs, + } + _, err = c.AccessTierGroup.AttachAccessTiers(atgID, attachReqBody) + if err != nil { + return + } + + return +} + +func detachAccessTiers(c *client.Holder, atgID string, atIDs []string) (err error) { + attachReqBody := accesstiergroup.AccessTierList{ + AccessTierIDs: atIDs, + } + _, err = c.AccessTierGroup.DetachAccessTiers(atgID, attachReqBody) + if err != nil { + return + } + + return +} + +func expandAdvancedSettings(d *schema.ResourceData) accesstier.AccessTierLocalConfig { + lc := accesstier.AccessTierLocalConfig{ + LoggingParameters: expandLogging(d), + EventParameters: expandEventParameters(d), + HostedWebServiceParameters: expandHostedWebServices(d), + InfrastructureServiceParameters: expandInfrastructureService(d), + DebuggingParameters: expandDebugging(d), + } + + return lc +} diff --git a/banyan/resource_accesstier_group_test.go b/banyan/resource_accesstier_group_test.go new file mode 100644 index 00000000..581fadbd --- /dev/null +++ b/banyan/resource_accesstier_group_test.go @@ -0,0 +1,46 @@ +package banyan + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccAccessTierGroup_basic(t *testing.T) { + + rName := fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + // Creates the access_tier_group with the given terraform configuration and asserts that the access_tier_group is created + { + Config: testAccAccessTierGroup_basic_create(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("banyan_accesstier_group.example", "name", rName), + ), + }, + }, + }) +} + +func testAccAccessTierGroup_basic_create(name string) string { + return fmt.Sprintf(` +resource "banyan_accesstier_group" "example" { + name = "%s" + description = "testing-1" + cluster = "cluster1" + dns_search_domains = "" + statsd_address = "192.168.0.1:8090" + domains = ["test-1.com"] + cidrs = ["198.169.0.1/24"] + dns_enabled = false + shared_fqdn = "testing.com" + udp_port_number = 16580 + keepalive = 30 +} +`, name) +} diff --git a/banyan/resource_api_key.go b/banyan/resource_api_key.go index 3e2917c2..a02ecd08 100644 --- a/banyan/resource_api_key.go +++ b/banyan/resource_api_key.go @@ -2,6 +2,7 @@ package banyan import ( "context" + "github.com/banyansecurity/terraform-banyan-provider/client" "github.com/banyansecurity/terraform-banyan-provider/client/apikey" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" diff --git a/banyan/resource_scim.go b/banyan/resource_scim.go new file mode 100644 index 00000000..c903f2e2 --- /dev/null +++ b/banyan/resource_scim.go @@ -0,0 +1,208 @@ +package banyan + +import ( + "context" + + "github.com/banyansecurity/terraform-banyan-provider/client" + "github.com/banyansecurity/terraform-banyan-provider/client/scim" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceSCIM() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceSCIMCreate, + ReadContext: resourceSCIMRead, + UpdateContext: resourceSCIMUpdate, + DeleteContext: resourceSCIMDelete, + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the access tier group in Banyan", + ForceNew: true, + }, + "is_enabled": { + Type: schema.TypeBool, + Optional: true, + Description: "Is scim enabled for an org", + }, + "base_url": { + Type: schema.TypeString, + Description: "base url of idp ", + Optional: true, + }, + "token": { + Type: schema.TypeString, + Description: "token is to communicate with idp", + Sensitive: true, + Optional: true, + ForceNew: true, + }, + "token_info": { + Type: schema.TypeSet, + MaxItems: 2, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uuid": { + Type: schema.TypeString, + Description: "uuid of token", + Optional: true, + }, + "created_at": { + Type: schema.TypeInt, + Description: "time of token creation", + Optional: true, + }, + }, + }, + }, + }, + } +} + +func resourceSCIMCreate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + + id, err := uuid.GenerateUUID() + if err != nil { + return + } + + isEnabled := d.Get("is_enabled").(bool) + + post := scim.SCIMProvisionRequest{ + IsEnabled: isEnabled, + } + + err = c.SCIM.ProvisionSCIM(post) + if err != nil { + return diag.FromErr(err) + } + + if !isEnabled { + d.SetId(id) + return + } + + key, err := c.SCIM.Create() + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("token", key.Data.Token) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("is_enabled", isEnabled) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("base_url", key.Data.BaseURL) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(id) + + return +} + +func resourceSCIMUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + post := scim.SCIMProvisionRequest{ + IsEnabled: d.Get("is_enabled").(bool), + } + + err := c.SCIM.Update(post, expandTokenInfo(d)) + if err != nil { + return diag.FromErr(err) + } + + return +} + +func resourceSCIMRead(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + key, err := c.SCIM.Get() + if err != nil { + handleNotFoundError(d, err) + return + } + + d.SetId(d.Get("id").(string)) + + err = d.Set("is_enabled", d.Get("is_enabled").(bool)) + if err != nil { + return diag.FromErr(err) + } + + err = d.Set("base_url", key.BaseURL) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("token_info", flattenTokenInfo(key.Tokens)) + if err != nil { + return diag.FromErr(err) + } + + return +} + +func resourceSCIMDelete(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { + c := m.(*client.Holder) + err := c.SCIM.Delete(expandTokenInfo(d)) + if err != nil { + diagnostics = diag.FromErr(err) + return + } + + d.SetId("") + + return +} + +func flattenTokenInfo(tokenInfos []scim.TokenInfo) (flattened []interface{}) { + if len(tokenInfos) == 0 { + return + } + + for _, tokenInfo := range tokenInfos { + tl := make(map[string]interface{}) + if tokenInfo.UUID != "" { + tl["uuid"] = tokenInfo.UUID + } + tl["created_at"] = tokenInfo.CreatedAt + + if len(tl) != 0 { + flattened = append(flattened, tl) + } + } + return +} + +func expandTokenInfo(d *schema.ResourceData) (tokeninfos []scim.TokenInfo) { + v, ok := d.GetOk("token_info") + if !ok { + return nil + } + tokens := v.(*schema.Set).List() + for _, t := range tokens { + + uuid := t.(map[string]interface{})["uuid"].(string) + createdAt := t.(map[string]interface{})["created_at"].(int) + + token := scim.TokenInfo{ + UUID: uuid, + CreatedAt: int64(createdAt), + } + + tokeninfos = append(tokeninfos, token) + } + + return +} diff --git a/banyan/resource_service_tunnel.go b/banyan/resource_service_tunnel.go index 8e6f3f0d..ccc1d6f6 100644 --- a/banyan/resource_service_tunnel.go +++ b/banyan/resource_service_tunnel.go @@ -138,6 +138,16 @@ func TunnelSchema() (s map[string]*schema.Schema) { Type: schema.TypeString, }, }, + "access_tier_group": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the access_tier group which the service tunnel should be associated with", + }, + "lock_autorun": { + Type: schema.TypeBool, + Optional: true, + Description: "Lock autorun for the service, if set true service tunnel will be always autorun. end user cannot set it off", + }, } return } @@ -158,7 +168,8 @@ func TunFromState(d *schema.ResourceData) (tun servicetunnel.Info) { Icon: &icon, DescriptionLink: &descriptionLink, }, - Autorun: expandAutorun(d), + Autorun: expandAutorun(d), + LockAutoRun: expandLockAutorun(d), }, Spec: expandServiceTunnelSpec(d), } @@ -288,14 +299,22 @@ func expandServiceTunnelSpec(d *schema.ResourceData) (expanded servicetunnel.Spe exclApplications := convertSchemaSetToStringSlice(d.Get("applications_exclude").(*schema.Set)) var peers []servicetunnel.PeerAccessTier - - // if access_tiers not set => global-edge, use ["*"] + accessTierGroup := d.Get("access_tier_group").(string) + // if access_tiers not set and access tier group is empty => global-edge, use ["*"] if len(ats) == 0 { - peers = append(peers, servicetunnel.PeerAccessTier{ + peer := servicetunnel.PeerAccessTier{ Cluster: d.Get("cluster").(string), AccessTiers: []string{"*"}, Connectors: conns, - }) + } + + if accessTierGroup != "" { + peer.AccessTiers = nil + peer.Connectors = nil + peer.AccessTierGroup = accessTierGroup + } + + peers = append(peers, peer) } else { // If multiple accessTiers are set create peer foreach. for i, eachAts := range ats { @@ -423,6 +442,12 @@ func flattenServiceTunnelSpec(d *schema.ResourceData, tun servicetunnel.ServiceT } } } + + err = d.Set("access_tier_group", eachPeer.AccessTierGroup) + if err != nil { + return err + } + } err = d.Set("access_tiers", ats) if err != nil { @@ -431,3 +456,11 @@ func flattenServiceTunnelSpec(d *schema.ResourceData, tun servicetunnel.ServiceT } return } + +func expandLockAutorun(d *schema.ResourceData) bool { + lockAutorun, exists := d.GetOk("lock_autorun") + if exists { + return lockAutorun.(bool) + } + return false +} diff --git a/banyan/resource_service_tunnel_test.go b/banyan/resource_service_tunnel_test.go index 55f02e46..3dc80483 100644 --- a/banyan/resource_service_tunnel_test.go +++ b/banyan/resource_service_tunnel_test.go @@ -19,6 +19,7 @@ func TestSchemaServiceTunnel_tunnel_at(t *testing.T) { "autorun": true, "cluster": "cluster1", "access_tiers": []interface{}{"gcp-tdnovpn-v1", "gcp-tdnovpn-v2"}, + "lock_autorun": true, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_at) svc_obj := TunFromState(d) @@ -57,6 +58,7 @@ func TestSchemaServiceTunnel_tunnel_public(t *testing.T) { "public_domains_include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, "public_traffic_tunnel_via_access_tier": "gcp-tdnovpn-v2", "applications_include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, + "access_tier_group": "", } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) svc_obj := TunFromState(d) @@ -78,6 +80,7 @@ func TestSchemaServiceTunnel_tunnel_public_one_at(t *testing.T) { "public_domains_include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, "applications_include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, + "access_tier_group": "", } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) svc_obj := TunFromState(d) @@ -99,6 +102,7 @@ func TestSchemaServiceTunnel_tunnel_public_select_at_from_multiple(t *testing.T) "public_domains_include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, "applications_include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, "public_traffic_tunnel_via_access_tier": "gcp-tdnovpn-v2", + "access_tier_group": "", } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) svc_obj := TunFromState(d) @@ -291,3 +295,88 @@ func TestAccServiceTunnel_change_policy(t *testing.T) { }, }) } + +func TestSchemaServiceTunnel_with_access_tier_group(t *testing.T) { + svc_tunnel_public := map[string]interface{}{ + "name": "tunnel-domains", + "description": "describe tunnel-domains", + "cluster": "cluster1", + "access_tier_group": "atg-1", + } + d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) + svc_obj := TunFromState(d) + + json_spec := []byte(`{ + "kind": "BanyanServiceTunnel", + "api_version": "rbac.banyanops.com/v1", + "type": "origin", + "metadata": + { + "name": "tunnel-domains", + "friendly_name": "tunnel-domains", + "description": "describe tunnel-domains", + "tags": + { + "icon": "", + "description_link": "" + }, + "autorun": false, + "lock_autorun": false + }, + "spec": + { + "peer_access_tiers": + [ + { + "cluster": "cluster1", + "access_tier_group":"atg-1" + } + ] + } + }`) + var ref_obj servicetunnel.Info + _ = json.Unmarshal([]byte(json_spec), &ref_obj) + + AssertServiceTunnelEqual(t, svc_obj, ref_obj) +} + +func TestAccServiceTunnel_with_access_tier_group(t *testing.T) { + + rName := fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + // Creates the servicetunnel with the given terraform configuration and asserts that the servicetunnel is created + { + Config: fmt.Sprintf(` + + resource "banyan_policy_tunnel" "example" { + name = "%s" + description = "some tunnel policy description" + access { + roles = ["ANY"] + trust_level = "High" + } + } + + resource "banyan_service_tunnel" "example" { + name = "%s" + description = "realdescription" + access_tier_group = "new-grp-1" + policy = banyan_policy_tunnel.example.id + } + `, rName, rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("banyan_service_tunnel.example", "name", rName), + ), + }, + { + ResourceName: "banyan_service_tunnel.example", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/banyan/resource_service_web.go b/banyan/resource_service_web.go index 7bc079c6..e596854f 100644 --- a/banyan/resource_service_web.go +++ b/banyan/resource_service_web.go @@ -3,13 +3,14 @@ package banyan import ( "context" "fmt" + "log" + "strconv" + "github.com/banyansecurity/terraform-banyan-provider/client" "github.com/banyansecurity/terraform-banyan-provider/client/service" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "log" - "strconv" ) // Schema for the service resource. For more information on Banyan services, see the documentation @@ -280,6 +281,11 @@ func WebSchema() (s map[string]*schema.Schema) { }, }, }, + "access_tier_group": { + Type: schema.TypeString, + Optional: true, + Description: "access tier group which is associated with service", + }, } return } diff --git a/banyan/resource_service_web_test.go b/banyan/resource_service_web_test.go index e840f214..fbe67318 100644 --- a/banyan/resource_service_web_test.go +++ b/banyan/resource_service_web_test.go @@ -306,6 +306,7 @@ func testAccService_basic_web_create_json(name string) string { ], "host_tag_selector": [ { + "com.banyanops.hosttag.access_tier_group": "", "com.banyanops.hosttag.site_name": "us-west1" } ], @@ -405,6 +406,7 @@ func testAccService_basic_web_update_json(name string) string { ], "host_tag_selector": [ { + "com.banyanops.hosttag.access_tier_group": "", "com.banyanops.hosttag.site_name": "us-west1" } ], diff --git a/banyan/schema_helpers.go b/banyan/schema_helpers.go index 50ab3c3e..998a4c9b 100644 --- a/banyan/schema_helpers.go +++ b/banyan/schema_helpers.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/banyansecurity/terraform-banyan-provider/client" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstiergroup" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -163,6 +164,7 @@ func GetIntPtr(d *schema.ResourceData, key string) (result *int) { func buildHostTagSelector(d *schema.ResourceData) (hostTagSelector []map[string]string, err error) { conn, connOk := d.GetOk("connector") at, atOk := d.GetOk("access_tier") + atg, atgOk := d.GetOk("access_tier_group") // error if both are set if connOk && atOk { @@ -170,11 +172,21 @@ func buildHostTagSelector(d *schema.ResourceData) (hostTagSelector []map[string] return } + if (atgOk && atOk) || (connOk && atgOk) { + err = errors.New("cannot have both access_tier or connector and access tier group set") + return + } + // if connector is set, ensure access_tier is * if conn.(string) != "" { at = "*" } siteNameSelector := map[string]string{"com.banyanops.hosttag.site_name": at.(string)} + + if atg != nil { + siteNameSelector["com.banyanops.hosttag.access_tier_group"] = atg.(string) + } + hostTagSelector = append(hostTagSelector, siteNameSelector) return } @@ -207,6 +219,8 @@ func determineCluster(c *client.Holder, d *schema.ResourceData) (clusterName str _, connsOk := d.GetOk("connectors") ats, atsOk := d.GetOk("access_tiers") + atg, atgOk := d.GetOk("access_tier_group") + // error if singular and plural are used if (connOk && connsOk) || (atOk && atsOk) { err = errors.New("cannot have both access_tier and access_tiers set or both connector and connectors set") @@ -219,6 +233,11 @@ func determineCluster(c *client.Holder, d *schema.ResourceData) (clusterName str return } + if (atgOk && atOk) || (atgOk && atsOk) { + err = errors.New("cannot have both access_tier and access tier group set") + return + } + // set to global-edge if connector is set if connOk || connsOk { clusterName = "global-edge" @@ -233,6 +252,18 @@ func determineCluster(c *client.Holder, d *schema.ResourceData) (clusterName str } } + if atg != nil { + var atDetails accesstiergroup.AccessTierGroupResponse + atDetails, err = c.AccessTierGroup.GetName(atg.(string)) + if err != nil { + _ = fmt.Errorf("accesstier group %s not found", atg.(string)) + clusterName, err = getFirstCluster(c) + return + } + clusterName = atDetails.ClusterName + return + } + // otherwise determine which cluster to set based off of the access tier atDetails, err := c.AccessTier.GetName(at.(string)) if err != nil { diff --git a/banyan/specs/service_tunnel/tunnel-at.json b/banyan/specs/service_tunnel/tunnel-at.json index 8c6a63b4..6596ea7d 100644 --- a/banyan/specs/service_tunnel/tunnel-at.json +++ b/banyan/specs/service_tunnel/tunnel-at.json @@ -12,7 +12,8 @@ "icon": "", "description_link": "" }, - "autorun": true + "autorun": true, + "lock_autorun": true }, "spec": { @@ -31,7 +32,7 @@ [ "gcp-tdnovpn-v2" ] - } + } ] } -} \ No newline at end of file +} diff --git a/banyan/specs/service_tunnel/tunnel-conn.json b/banyan/specs/service_tunnel/tunnel-conn.json index 6cb63f91..a9975a29 100644 --- a/banyan/specs/service_tunnel/tunnel-conn.json +++ b/banyan/specs/service_tunnel/tunnel-conn.json @@ -12,7 +12,8 @@ "icon": "", "description_link": "" }, - "autorun": false + "autorun": false, + "lock_autorun": false }, "spec": { @@ -32,4 +33,4 @@ } ] } -} \ No newline at end of file +} diff --git a/banyan/specs/service_tunnel/tunnel-public-multiple-at.json b/banyan/specs/service_tunnel/tunnel-public-multiple-at.json index 988d658c..deb9f780 100644 --- a/banyan/specs/service_tunnel/tunnel-public-multiple-at.json +++ b/banyan/specs/service_tunnel/tunnel-public-multiple-at.json @@ -12,7 +12,8 @@ "icon": "", "description_link": "" }, - "autorun": false + "autorun": false, + "lock_autorun": false }, "spec": { @@ -62,4 +63,4 @@ } ] } -} \ No newline at end of file +} diff --git a/banyan/specs/service_tunnel/tunnel-public.json b/banyan/specs/service_tunnel/tunnel-public.json index c6ec8602..8dfea6b7 100644 --- a/banyan/specs/service_tunnel/tunnel-public.json +++ b/banyan/specs/service_tunnel/tunnel-public.json @@ -12,7 +12,8 @@ "icon": "", "description_link": "" }, - "autorun": false + "autorun": false, + "lock_autorun": false }, "spec": { @@ -58,4 +59,4 @@ } ] } -} \ No newline at end of file +} diff --git a/banyan/specs/service_web/web-at.json b/banyan/specs/service_web/web-at.json index e4a89fef..f20e16dc 100644 --- a/banyan/specs/service_web/web-at.json +++ b/banyan/specs/service_web/web-at.json @@ -30,6 +30,7 @@ ], "host_tag_selector": [ { + "com.banyanops.hosttag.access_tier_group": "", "com.banyanops.hosttag.site_name": "gcp-wg" } ], diff --git a/banyan/specs/service_web/web-certs.json b/banyan/specs/service_web/web-certs.json index 3cdfbd0f..b3756174 100644 --- a/banyan/specs/service_web/web-certs.json +++ b/banyan/specs/service_web/web-certs.json @@ -30,6 +30,7 @@ ], "host_tag_selector": [ { + "com.banyanops.hosttag.access_tier_group": "", "com.banyanops.hosttag.site_name": "*" } ], diff --git a/banyan/specs/service_web/web-conn.json b/banyan/specs/service_web/web-conn.json index 7d6e48a4..bbb96cd7 100644 --- a/banyan/specs/service_web/web-conn.json +++ b/banyan/specs/service_web/web-conn.json @@ -30,6 +30,7 @@ ], "host_tag_selector": [ { + "com.banyanops.hosttag.access_tier_group": "", "com.banyanops.hosttag.site_name": "*" } ], diff --git a/client/accesstiergroup/accesstiergroup.go b/client/accesstiergroup/accesstiergroup.go new file mode 100644 index 00000000..60de77c3 --- /dev/null +++ b/client/accesstiergroup/accesstiergroup.go @@ -0,0 +1,75 @@ +package accesstiergroup + +import ( + "github.com/banyansecurity/terraform-banyan-provider/client/accesstier" +) + +type AccessTierGroupInfo struct { + ID string `json:"id"` + Name string `json:"name"` + OrgID string `json:"org_id"` + Description string `json:"description"` + TunnelConfigID string `json:"tunnel_config_id"` + AdvancedSettings string `json:"advanced_settings"` + ClusterName string `json:"cluster_name"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` +} + +type AccessTierGroupPost struct { + ID string `json:"id"` + Name string `json:"name"` + OrgID string `json:"org_id"` + Description string `json:"description"` + SharedFQDN string `json:"shared_fqdn"` + TunnelConfig *accesstier.AccessTierTunnelInfoPost `json:"tunnel_enduser"` + AdvancedSettings accesstier.AccessTierLocalConfig `json:"advanced_settings"` + ClusterName string `json:"cluster_name"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` +} + +type AccessTierGroupResponse struct { + ID string `json:"id"` + Name string `json:"name"` + OrgID string `json:"org_id"` + Description string `json:"description"` + AdvancedSettings string `json:"advanced_settings"` + AccessTierIDs []string `json:"access_tier_ids"` + ClusterName string `json:"cluster_name"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` + TunnelConfig TunnelConfigInfo `json:"tunnel_config"` +} + +type TunnelConfigInfo struct { + ID string `json:"id"` + OrgID string `json:"org_id"` + TunnelPeerType string `json:"tunnel_peer_type"` + DNSSearchDomains string `json:"dns_search_domains"` + UDPPortNumber int64 `json:"udp_port_number"` + TunnelIPAddress string `json:"tunnel_ip_address"` + WireguardPublicKey string `json:"wireguard_public_key"` + WireguardPrivateKey string `json:"wireguard_private_key,omitempty"` + DNSEnabled bool `json:"dns_enabled"` + Keepalive int64 `json:"keepalive"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` + SharedFQDN string `json:"shared_fqdn,omitempty"` + + CIDRs []string `json:"cidrs"` + Domains []string `json:"domains"` + + ClientCIDRRange string `json:"client_cidr_range"` +} + +type ATGResponse struct { + RequestId string `json:"request_id"` + ErrorCode int `json:"error_code"` + ErrorDescription string `json:"error_description"` + Data AccessTierGroupResponse `json:"data"` +} + +type AccessTierList struct { + AccessTierIDs []string `json:"access_tier_ids"` +} diff --git a/client/accesstiergroup/client.go b/client/accesstiergroup/client.go new file mode 100644 index 00000000..a71e6246 --- /dev/null +++ b/client/accesstiergroup/client.go @@ -0,0 +1,186 @@ +package accesstiergroup + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + + "github.com/banyansecurity/terraform-banyan-provider/client/restclient" +) + +const apiVersion = "api/v2" +const component = "access_tier_groups" + +type AccessTierGroup struct { + restClient *restclient.Client +} + +// NewClient returns a new client for interacting with the access tier resource +func NewClient(restClient *restclient.Client) Client { + client := AccessTierGroup{ + restClient: restClient, + } + return &client +} + +type Client interface { + Create(spec AccessTierGroupPost) (created AccessTierGroupResponse, err error) + Get(id string) (atg AccessTierGroupResponse, err error) + Delete(id string) (err error) + Update(id string, post AccessTierGroupPost) (updatedApiKey AccessTierGroupResponse, err error) + GetName(name string) (spec AccessTierGroupResponse, err error) + AttachAccessTiers(groupID string, ats AccessTierList) (attachedATs []string, err error) + DetachAccessTiers(groupID string, ats AccessTierList) (detachedATs []string, err error) +} + +func (a *AccessTierGroup) Create(atgInfo AccessTierGroupPost) (created AccessTierGroupResponse, err error) { + body, err := json.Marshal(atgInfo) + if err != nil { + return + } + resp, err := a.restClient.Create(apiVersion, component, body, "") + if err != nil { + return + } + var j ATGResponse + err = json.Unmarshal(resp, &j) + if err != nil { + return + } + created = j.Data + return +} + +func (a *AccessTierGroup) Get(id string) (atg AccessTierGroupResponse, err error) { + resp, err := a.restClient.Read(apiVersion, component, id, "") + if err != nil { + return + } + var j ATGResponse + err = json.Unmarshal(resp, &j) + if err != nil { + return + } + return j.Data, nil +} + +func (a *AccessTierGroup) Update(id string, post AccessTierGroupPost) (updatedApiKey AccessTierGroupResponse, err error) { + body, err := json.Marshal(post) + if err != nil { + return + } + resp, err := a.restClient.Update(apiVersion, component, id, body, "") + if err != nil { + return + } + err = json.Unmarshal(resp, &updatedApiKey) + return +} + +func (a *AccessTierGroup) Delete(id string) (err error) { + return a.restClient.Delete(apiVersion, component, id, "") +} + +func (a *AccessTierGroup) GetName(name string) (atg AccessTierGroupResponse, err error) { + v := url.Values{} + v.Add("access_tier_group_name", name) + resp, err := a.restClient.ReadQuery(component, v, fmt.Sprintf("%s/%s", apiVersion, component)) + if err != nil { + return + } + + type atgs struct { + AccessTierGroups []AccessTierGroupResponse `json:"access_tier_groups,omitempty"` + Count int `json:"count"` + } + + response := struct { + RequestId string `json:"request_id"` + ErrorCode int `json:"error_code"` + ErrorDescription string `json:"error_description"` + Data atgs `json:"data"` + }{} + + err = json.Unmarshal(resp, &response) + if err != nil { + return + } + + if response.Data.Count == 0 { + err = fmt.Errorf("access tier with name %s not found", name) + return + } + + for _, accessTierGroup := range response.Data.AccessTierGroups { + if accessTierGroup.Name == name { + atg = accessTierGroup + break + } + } + + if atg.Name == "" { + err = fmt.Errorf("access tier group with name %s not found in results %+v", name, response.Data.AccessTierGroups) + } + + return +} + +func (a *AccessTierGroup) AttachAccessTiers(groupID string, ats AccessTierList) (attachedATs []string, err error) { + body, err := json.Marshal(ats) + if err != nil { + return + } + attachURL := fmt.Sprintf("/%s/%s/attach", component, groupID) + resp, err := a.restClient.Create(apiVersion, attachURL, body, "") + if err != nil { + return + } + var j AccessTierList + err = json.Unmarshal(resp, &j) + if err != nil { + return + } + + attachedATs = j.AccessTierIDs + return +} + +func (a *AccessTierGroup) DetachAccessTiers(groupID string, ats AccessTierList) (detachedATs []string, err error) { + body, err := json.Marshal(ats) + if err != nil { + return + } + detachURL := fmt.Sprintf("%s/%s/%s/detach", apiVersion, component, groupID) + req, err := a.restClient.NewRequest(http.MethodDelete, detachURL, bytes.NewBuffer(body)) + if err != nil { + return + } + + HTTPClient := &http.Client{} + resp, err := HTTPClient.Do(req) + if err != nil { + return + } + + if resp.StatusCode != http.StatusOK { + err = fmt.Errorf("error occurred while detaching access tier from group") + return + } + + response, err := io.ReadAll(resp.Body) + if err != nil { + return + } + + var j AccessTierList + err = json.Unmarshal(response, &j) + if err != nil { + return + } + + detachedATs = j.AccessTierIDs + return +} diff --git a/client/accesstiergroup/client_test.go b/client/accesstiergroup/client_test.go new file mode 100644 index 00000000..9903cebf --- /dev/null +++ b/client/accesstiergroup/client_test.go @@ -0,0 +1,73 @@ +package accesstiergroup_test + +import ( + "testing" + + "github.com/banyansecurity/terraform-banyan-provider/client/accesstier" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstiergroup" + "github.com/banyansecurity/terraform-banyan-provider/client/testutil" + "github.com/stretchr/testify/assert" +) + +var want = accesstiergroup.AccessTierGroupPost{ + Name: "new-nnm-88w", + Description: "testing-1", + ClusterName: "cluster1", + AdvancedSettings: accesstier.AccessTierLocalConfig{ + LoggingParameters: &accesstier.LoggingParameters{ + StatsD: accesstier.BoolPtr(false), + StatsDAddress: accesstier.StringPtr("127.0.0.1:8125"), + }, + }, + TunnelConfig: &accesstier.AccessTierTunnelInfoPost{ + DNSSearchDomains: "", + Domains: []string{"test-1.com"}, + CIDRs: []string{"198.169.0.1/24"}, + DNSEnabled: false, + UDPPortNumber: 16578, + }, + SharedFQDN: "testing.com", +} + +func Test_Create(t *testing.T) { + + client, err := testutil.GetClientHolderForTest() + + assert.NoError(t, err, "Expected to not get an error here") + + got, err := client.AccessTierGroup.Create(want) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, got.Name, want.Name) + assert.Equal(t, got.ClusterName, want.ClusterName) + assert.Equal(t, got.TunnelConfig.SharedFQDN, want.SharedFQDN) +} + +func Test_Get(t *testing.T) { + client, err := testutil.GetClientHolderForTest() + + assert.NoError(t, err, "Expected to not get an error here") + + got, err := client.AccessTierGroup.GetName(want.Name) + + assert.NoError(t, err, "expected no error here") + assert.Equal(t, got.Name, want.Name) +} + +func Test_Delete(t *testing.T) { + client, err := testutil.GetClientHolderForTest() + + assert.NoError(t, err, "Expected to not get an error here") + + data, err := client.AccessTierGroup.Get(want.Name) + if err != nil { + t.Fatal(err) + } + + err = client.ApiKey.Delete(data.ID) + if err != nil { + t.Fatal(err) + } +} diff --git a/client/client_holder.go b/client/client_holder.go index c47d0f04..57a09d1c 100644 --- a/client/client_holder.go +++ b/client/client_holder.go @@ -1,7 +1,10 @@ package client import ( + "log" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstier" + "github.com/banyansecurity/terraform-banyan-provider/client/accesstiergroup" admin "github.com/banyansecurity/terraform-banyan-provider/client/admin" "github.com/banyansecurity/terraform-banyan-provider/client/apikey" "github.com/banyansecurity/terraform-banyan-provider/client/policy" @@ -9,10 +12,10 @@ import ( "github.com/banyansecurity/terraform-banyan-provider/client/restclient" "github.com/banyansecurity/terraform-banyan-provider/client/role" "github.com/banyansecurity/terraform-banyan-provider/client/satellite" + "github.com/banyansecurity/terraform-banyan-provider/client/scim" service "github.com/banyansecurity/terraform-banyan-provider/client/service" "github.com/banyansecurity/terraform-banyan-provider/client/servicetunnel" "github.com/banyansecurity/terraform-banyan-provider/client/shield" - "log" ) type Holder struct { @@ -27,6 +30,8 @@ type Holder struct { AccessTier accesstier.Client Shield shield.Client RestClient *restclient.Client + AccessTierGroup accesstiergroup.Client + SCIM scim.Client } // NewClientHolder returns a new client which is used to perform operations on all Banyan resources. @@ -47,6 +52,8 @@ func NewClientHolder(hostUrl string, apiKey string) (client *Holder, err error) Admin: admin.NewClient(restClient), Shield: shield.NewClient(restClient), RestClient: restClient, + AccessTierGroup: accesstiergroup.NewClient(restClient), + SCIM: scim.NewClient(restClient), } return &c, err } diff --git a/client/scim/client.go b/client/scim/client.go new file mode 100644 index 00000000..0453e010 --- /dev/null +++ b/client/scim/client.go @@ -0,0 +1,121 @@ +package scim + +import ( + "encoding/json" + "fmt" + "net/url" + + "github.com/banyansecurity/terraform-banyan-provider/client/restclient" +) + +type SCIM struct { + restClient *restclient.Client +} + +const apiVersion = "api/v2" +const scimCredentialsPath = "scim/credentials" +const scimProvisionPath = "scim/provision" +const scimTokenDeletePath = "scim/token" + +func NewClient(restClient *restclient.Client) Client { + scimClient := SCIM{ + restClient: restClient, + } + return &scimClient +} + +type Client interface { + Get() (scimCreds SCIMCredentialsResponse, err error) + Create() (scimCreds createResp, err error) + Update(post SCIMProvisionRequest, tInfo []TokenInfo) (err error) + Delete(tInfo []TokenInfo) (err error) + ProvisionSCIM(post SCIMProvisionRequest) (err error) +} + +func (k *SCIM) Get() (scimCreds SCIMCredentialsResponse, err error) { + + path := fmt.Sprintf("%s/%s", apiVersion, scimCredentialsPath) + + myUrl, err := url.Parse(path) + if err != nil { + return + } + + response, err := k.restClient.DoGet(myUrl.String()) + if err != nil { + err = fmt.Errorf("request to %s %s failed %w", response.Request.Method, response.Request.URL.String(), err) + return + } + resp, err := restclient.HandleResponse(response) + if err != nil { + return + } + + var j getResp + err = json.Unmarshal(resp, &j) + if err != nil { + return + } + return j.Data, nil +} + +func (k *SCIM) Create() (scimCreds createResp, err error) { + + //create scim credentials for org + response, err := k.restClient.Create(apiVersion, scimCredentialsPath, nil, "") + if err != nil { + return + } + + var responseData createResp + err = json.Unmarshal(response, &responseData) + scimCreds = responseData + return +} + +func (k *SCIM) Update(post SCIMProvisionRequest, tInfo []TokenInfo) (err error) { + + err = k.ProvisionSCIM(post) + if err != nil { + return + } + + if post.IsEnabled { + _, err = k.restClient.Create(apiVersion, scimCredentialsPath, nil, "") + if err != nil { + return + } + } else { + err = k.Delete(tInfo) + if err != nil { + return + } + } + + return +} + +func (k *SCIM) Delete(tInfo []TokenInfo) (err error) { + for _, t := range tInfo { + err = k.restClient.Delete(apiVersion, scimTokenDeletePath, t.UUID, "") + if err != nil { + return + } + } + return +} + +func (k *SCIM) ProvisionSCIM(post SCIMProvisionRequest) (err error) { + body, err := json.Marshal(post) + if err != nil { + return + } + + //provision scim for an org + _, err = k.restClient.Create(apiVersion, scimProvisionPath, body, "") + if err != nil { + return + } + + return +} diff --git a/client/scim/scim.go b/client/scim/scim.go new file mode 100644 index 00000000..4ddafc3f --- /dev/null +++ b/client/scim/scim.go @@ -0,0 +1,34 @@ +package scim + +type SCIMProvisionRequest struct { + IsEnabled bool `json:"is_enabled"` +} + +type SCIMCredentialsResponse struct { + BaseURL string `json:"base_url"` + Tokens []TokenInfo `json:"tokens"` +} + +type CreateSCIMCredentialsResponse struct { + BaseURL string `json:"base_url"` + Token string `json:"token"` +} + +type TokenInfo struct { + UUID string `json:"uuid"` + CreatedAt int64 `json:"created_at"` +} + +type getResp struct { + RequestID string `json:"request_id"` + ErrorCode int `json:"error_code"` + ErrorDescription string `json:"error_description"` + Data SCIMCredentialsResponse `json:"data"` +} + +type createResp struct { + RequestID string `json:"request_id"` + ErrorCode int `json:"error_code"` + ErrorDescription string `json:"error_description"` + Data CreateSCIMCredentialsResponse `json:"data"` +} diff --git a/client/servicetunnel/client.go b/client/servicetunnel/client.go index 063b6481..46910ad6 100644 --- a/client/servicetunnel/client.go +++ b/client/servicetunnel/client.go @@ -3,9 +3,10 @@ package servicetunnel import ( "encoding/json" "fmt" - "github.com/banyansecurity/terraform-banyan-provider/client/restclient" "html" "log" + + "github.com/banyansecurity/terraform-banyan-provider/client/restclient" ) const apiVersion = "api/v2" @@ -51,6 +52,8 @@ func (a *ServiceTunnel) Create(spec Info) (created ServiceTunnelInfo, err error) Name: spec.Metadata.Name, FriendlyName: spec.Metadata.FriendlyName, Description: spec.Metadata.Description, + Autorun: spec.Autorun, + LockAutoRun: spec.LockAutoRun, }, Spec: spec.Spec, }) diff --git a/client/servicetunnel/service_tunnel.go b/client/servicetunnel/service_tunnel.go index adb47935..666d160b 100644 --- a/client/servicetunnel/service_tunnel.go +++ b/client/servicetunnel/service_tunnel.go @@ -69,6 +69,7 @@ type Metadata struct { Description string `json:"description,omitempty"` Tags Tags `json:"tags"` Autorun bool `json:"autorun"` + LockAutoRun bool `json:"lock_autorun"` } // Tags represents the metadata tags @@ -92,6 +93,8 @@ type PeerAccessTier struct { PublicCIDRs *IncludeExclude `json:"public_cidrs,omitempty"` PublicDomains *IncludeExclude `json:"public_domains,omitempty"` Applications *IncludeExclude `json:"applications,omitempty"` + + AccessTierGroup string `json:"access_tier_group"` } type IncludeExclude struct { diff --git a/docs/resources/accesstier_group.md b/docs/resources/accesstier_group.md new file mode 100644 index 00000000..b1664280 --- /dev/null +++ b/docs/resources/accesstier_group.md @@ -0,0 +1,72 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "banyan_accesstier_group Resource - terraform-provider-banyan" +subcategory: "" +description: |- + The access tier group resource allows for configuration of the access tier group API object. +--- + +# banyan_accesstier_group (Resource) + +The access tier group resource allows for configuration of the access tier group API object. + + + + +## Schema + +### Required + +- `cidrs` (Set of String) CIDR range +- `cluster` (String) Cluster / shield name in Banyan +- `dns_search_domains` (String) +- `domains` (Set of String) Any internal domains that can only be resolved on your internal network’s private DNS +- `keepalive` (Number) Keepalive +- `name` (String) Name of the access tier group +- `shared_fqdn` (String) Shared FQDN +- `udp_port_number` (Number) UDP port + +### Optional + +- `attach_access_tier_ids` (Set of String) Access tier IDs to attach to access tier group +- `console_log_level` (String) Controls verbosity of logs to console. Must be one of "ERR", "WARN", "INFO", "DEBUG" +- `debug_address_transparency` (Boolean) Provide client address transparency +- `debug_client_timeout` (Number) Client identification timeout +- `debug_code_flow` (Boolean) Enable or disable OpenID Connect +- `debug_cpu_profile` (String) Output file for CPU profiling; may impact performance. If empty, this is disabled +- `debug_disable_docker` (Boolean) Disable Docker monitoring +- `debug_full_server_cert_chain` (Boolean) Include non-root (intermediate) CA certs during TLS handshakes +- `debug_host_only` (Boolean) Host only mode +- `debug_http_backend_log` (Boolean) Verbose logging for HTTP backend traffic +- `debug_inactivity_timeout` (Number) HTTP inactivity timeout +- `debug_keep_alive` (Boolean) Enable TCP keepalive messages for TCP sockets handled by Netagent +- `debug_keep_count` (Number) Number of missing TCP keepalive acknowledgements before closing connection +- `debug_keep_idle` (Number) Idle time before sending a TCP keepalive +- `debug_keep_interval` (Number) Time between consecutive TCP keepalive messages +- `debug_mem_profile` (Boolean) Output file for memory profiling; may impact performance. If empty, this is disabled +- `debug_period` (Number) Interval for reporting statistics +- `debug_request_level_events` (Boolean) Generate access events at the request level +- `debug_send_zeros` (Boolean) Send all-zero data points to Shield +- `debug_service_discovery_enable` (Boolean) Enable or disable DNS and conntrack logging +- `debug_service_discovery_msg_limit` (Number) Message threshold for batch processing +- `debug_service_discovery_msg_timeout` (Number) Timeout value for service discovery batch processing +- `debug_shield_timeout` (Number) If Shield is not available, policies will be treated as if they are permissive. Zero means this is disabled. +- `debug_use_rsa` (Boolean) Netagent will generate RSA instead of ECDSA keys +- `debug_visibility_only` (Boolean) Enable or disable visibility mode. If on, Netagent will not do policy enforcement on inbound traffic +- `description` (String) Description of access tier group +- `detach_access_tier_ids` (Set of String) Access tier IDs to detach from access tier group +- `dns_enabled` (Boolean) Enable DNS for service tunnels (needed to work properly with both private and public targets) +- `enable_hsts` (Boolean) If enabled, Banyan will send the HTTP Strict-Transport-Security response header +- `event_key_rate_limiting` (Boolean) Enable rate limiting of Access Event generation based on a credit-based rate control mechanism +- `events_rate_limiting` (Boolean) Enable rate limiting of Access Event generation based on a credit-based rate control mechanism +- `file_log` (Boolean) Whether to log to file or not +- `file_log_level` (String) Controls verbosity of logs to file. Must be one of "ERR", "WARN", "INFO", "DEBUG" +- `forward_trust_cookie` (Boolean) Forward the Banyan trust cookie to upstream servers. This may be enabled if upstream servers wish to make use of information in the Banyan trust cookie. +- `infra_maximum_session_timeout` (Number) Timeout in seconds infrastructure sessions connected via the access tier +- `log_num` (Number) For file logs: Number of files to use for log rotation +- `log_size` (Number) For file logs: Size of each file for log rotation +- `statsd_address` (String) Address to send statsd messages: “hostname:port” for UDP, “unix:///path/to/socket” for UDS + +### Read-Only + +- `id` (String) ID of the access tier group in Banyan diff --git a/docs/resources/scim.md b/docs/resources/scim.md new file mode 100644 index 00000000..a3dbbc35 --- /dev/null +++ b/docs/resources/scim.md @@ -0,0 +1,35 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "banyan_scim Resource - terraform-provider-banyan" +subcategory: "" +description: |- + +--- + +# banyan_scim (Resource) + + + + + + +## Schema + +### Optional + +- `base_url` (String) base url of idp +- `is_enabled` (Boolean) Is scim enabled for an org +- `token` (String, Sensitive) token is to communicate with idp +- `token_info` (Block Set, Max: 2) (see [below for nested schema](#nestedblock--token_info)) + +### Read-Only + +- `id` (String) ID of the access tier group in Banyan + + +### Nested Schema for `token_info` + +Optional: + +- `created_at` (Number) time of token creation +- `uuid` (String) uuid of token diff --git a/docs/resources/service_tunnel.md b/docs/resources/service_tunnel.md index a91b3c52..55e17081 100644 --- a/docs/resources/service_tunnel.md +++ b/docs/resources/service_tunnel.md @@ -127,6 +127,7 @@ In this example an access tier is configured to tunnel `10.10.0.0/16`. A service ### Optional +- `access_tier_group` (String) Name of the access_tier group which the service tunnel should be associated with - `access_tiers` (Set of String) Names of the access_tiers which the service tunnel should be associated with - `applications_exclude` (Set of String) Specifies the applications ids that should be excluded in the tunnel, ex: 633301ab-fd20-439b-b5ae-47153ec7fbf2 - `applications_include` (Set of String) Specifies the applications ids that should be included in the tunnel, ex: 905a72d3-6216-4ffc-ad18-db1593782915 @@ -135,6 +136,7 @@ In this example an access tier is configured to tunnel `10.10.0.0/16`. A service - `connectors` (Set of String) Names of the connectors which the service tunnel should be associated with - `description` (String) Description of the service tunnel - `description_link` (String) Link shown to the end user of the banyan app for this service +- `lock_autorun` (Boolean) Lock autorun for the service, if set true service tunnel will be always autorun. end user cannot set it off - `public_cidrs_exclude` (Set of String) Specifies public IP addresses in CIDR notation that should be excluded from the tunnel, ex: 8.8.12.0/24. - `public_cidrs_include` (Set of String) Specifies public IP addresses in CIDR notation that should be included in the tunnel, ex: 8.8.0.0/16. - `public_domains_exclude` (Set of String) Specifies the domains that should be that should be excluded from the tunnel, ex: zoom.us diff --git a/docs/resources/service_web.md b/docs/resources/service_web.md index 6bf4a044..4ab799ed 100644 --- a/docs/resources/service_web.md +++ b/docs/resources/service_web.md @@ -97,6 +97,7 @@ resource "banyan_service_web" "example-service" { ### Optional - `access_tier` (String) Name of the access_tier which will proxy requests to your service backend +- `access_tier_group` (String) access tier group which is associated with service - `available_in_app` (Boolean) Whether this service is available in the app for users with permission to access this service - `backend_port` (Number) The internal port where this service is hosted. Default is 443 - `backend_tls` (Boolean) Indicates whether the connection to the backend server uses TLS diff --git a/go.mod b/go.mod index d34a7992..912671f0 100644 --- a/go.mod +++ b/go.mod @@ -1,54 +1,56 @@ module github.com/banyansecurity/terraform-banyan-provider -go 1.20 +go 1.22 require ( - github.com/google/go-cmp v0.5.9 - github.com/hashicorp/terraform-plugin-docs v0.16.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0 - github.com/jinzhu/copier v0.3.5 + github.com/google/go-cmp v0.6.0 + github.com/hashicorp/go-uuid v1.0.3 + github.com/hashicorp/terraform-plugin-docs v0.18.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 + github.com/jinzhu/copier v0.4.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 ) require ( + github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // 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.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/uuid v1.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.4.10 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.5.2 // indirect - github.com/hashicorp/hcl/v2 v2.17.0 // indirect + github.com/hashicorp/hc-install v0.6.4 // indirect + github.com/hashicorp/hcl/v2 v2.20.1 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.18.1 // indirect - github.com/hashicorp/terraform-json v0.17.1 // indirect - github.com/hashicorp/terraform-plugin-go v0.16.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.1 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect - github.com/hashicorp/terraform-registry-address v0.2.1 // 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 - github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mitchellh/cli v1.1.5 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect @@ -57,23 +59,28 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/zclconf/go-cty v1.13.2 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/mod v0.11.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + github.com/yuin/goldmark v1.7.1 // indirect + github.com/yuin/goldmark-meta v1.1.0 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/tools v0.20.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e52dd24a..754b31ff 100644 --- a/go.sum +++ b/go.sum @@ -1,53 +1,67 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= +github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= -github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +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.2-proton h1:HKz85FwoXx86kVtTvFke7rgHvq/HoloSUvW5semjFWs= +github.com/ProtonMail/go-crypto v1.1.0-alpha.2-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= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +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/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +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/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= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +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/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= -github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= +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/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +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.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= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -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.2/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.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8= +github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -58,71 +72,74 @@ 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.4.10 h1:xUbmA4jC6Dq163/fWcp8P3JuHilrHHMLNRxzGQJ9hNk= -github.com/hashicorp/go-plugin v1.4.10/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0= +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-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.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0= -github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI= -github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY= -github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4= +github.com/hashicorp/hc-install v0.6.4 h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0= +github.com/hashicorp/hc-install v0.6.4/go.mod h1:05LWLy8TD842OtgcfBbOT0WMoInBMUSHjmDx10zuBIA= +github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= +github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= 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.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4= -github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980= -github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= -github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= -github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI= -github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA= -github.com/hashicorp/terraform-plugin-go v0.16.0 h1:DSOQ0rz5FUiVO4NUzMs8ln9gsPgHMTsfns7Nk+6gPuE= -github.com/hashicorp/terraform-plugin-go v0.16.0/go.mod h1:4sn8bFuDbt+2+Yztt35IbOrvZc0zyEi87gJzsTgCES8= +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-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.1 h1:iTS7WHNVrn7uhe3cojtvWWn83cm2Z6ryIUDTRO0EV7w= +github.com/hashicorp/terraform-plugin-go v0.22.1/go.mod h1:qrjnqRghvQ6KnDbB12XeZ4FluclYwptntoWCr9QaXTI= 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.27.0 h1:I8efBnjuDrgPjNF1MEypHy48VgcTIUY4X6rOFunrR3Y= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0/go.mod h1:cUEP4ly/nxlHy5HzD6YRrHydtlheGvGRJDhiWqqVik4= -github.com/hashicorp/terraform-registry-address v0.2.1 h1:QuTf6oJ1+WSflJw6WYOHhLgwUiQ0FrROpHPYFtwTYWM= -github.com/hashicorp/terraform-registry-address v0.2.1/go.mod h1:BSE9fIFzp0qWsJUUyGquo4ldV9k2n+psif6NYkBRS3Y= +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-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= github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= -github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -138,101 +155,131 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +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.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.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= +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= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= -github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= +github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +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.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-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +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= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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/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.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +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.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +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-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= +google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=