From d81221490facc329042518a7270b911ba0a826a1 Mon Sep 17 00:00:00 2001 From: Naresh Kakubal Date: Sun, 15 Sep 2024 11:43:47 -0700 Subject: [PATCH] Service tunnel configuration support (#181) * service tunnel delta implementation with api * service tunnel delta implementation with api * fix tests * add nameserver configuration * fix tests to determine defaults for access_tiers and cluster name * Documentation generated * add documentation for service tunnel resource usage * Documentation generated * add documentation for service tunnel resource usage --------- Co-authored-by: github-actions --- banyan/resource_connector_test.go | 6 +- banyan/resource_service_tunnel.go | 621 +++++++++++------- banyan/resource_service_tunnel_test.go | 174 +++-- banyan/specs/service_tunnel/tunnel-at.json | 7 - ...ic-multiple-at-multiple-configuration.json | 111 ++++ .../tunnel-public-multiple-at.json | 7 - client/dns/nameresolution.go | 6 + client/servicetunnel/client.go | 16 +- client/servicetunnel/service_tunnel.go | 35 +- docs/resources/service_tunnel.md | 144 +++- .../banyan_service_tunnel/resource.tf | 71 +- .../resource.tf | 11 +- 12 files changed, 886 insertions(+), 323 deletions(-) create mode 100644 banyan/specs/service_tunnel/tunnel-public-multiple-at-multiple-configuration.json create mode 100644 client/dns/nameresolution.go diff --git a/banyan/resource_connector_test.go b/banyan/resource_connector_test.go index 8b58aa38..cba88b91 100644 --- a/banyan/resource_connector_test.go +++ b/banyan/resource_connector_test.go @@ -76,8 +76,10 @@ func TestAccConnector_tunnel(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "realdescription" - connectors = [banyan_connector.example.name] - policy = banyan_policy_tunnel.example.id + network_settings { + connectors = [banyan_connector.example.name] + } + policy = banyan_policy_tunnel.example.id } `, rName, rName, rName, rName), Check: resource.ComposeTestCheckFunc( diff --git a/banyan/resource_service_tunnel.go b/banyan/resource_service_tunnel.go index ccc1d6f6..bf720a95 100644 --- a/banyan/resource_service_tunnel.go +++ b/banyan/resource_service_tunnel.go @@ -3,6 +3,7 @@ package banyan import ( "context" "fmt" + "github.com/banyansecurity/terraform-banyan-provider/client/dns" "strings" "github.com/banyansecurity/terraform-banyan-provider/client" @@ -54,108 +55,161 @@ func TunnelSchema() (s map[string]*schema.Schema) { Optional: true, Description: "Autorun for the service, if set true service would autorun on the app", }, - "connectors": { - Type: schema.TypeSet, - Optional: true, - Description: "Names of the connectors which the service tunnel should be associated with", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - ConflictsWith: []string{"access_tiers"}, - }, - "access_tiers": { - Type: schema.TypeSet, - Optional: true, - Description: "Names of the access_tiers which the service tunnel should be associated with", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - ConflictsWith: []string{"connectors"}, - }, - "public_cidrs_include": { - Type: schema.TypeSet, - Optional: true, - Description: "Specifies public IP addresses in CIDR notation that should be included in the tunnel, ex: 8.8.0.0/16.", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "public_cidrs_exclude": { - Type: schema.TypeSet, + "lock_autorun": { + Type: schema.TypeBool, Optional: true, - Description: "Specifies public IP addresses in CIDR notation that should be excluded from the tunnel, ex: 8.8.12.0/24.", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Description: "Lock autorun for the service, if set true service tunnel will be always autorun. end user cannot set it off", }, - "public_domains_include": { + + "network_settings": { Type: schema.TypeSet, Optional: true, - Description: "Specifies the domains that should be that should be included in the tunnel, ex: cnn.com", - Elem: &schema.Schema{ - Type: schema.TypeString, + Description: "Add a network that will be accessible via this Service Tunnel.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster": { + Type: schema.TypeString, + Optional: true, + Description: "cluster name where access-tier belongs to", + }, + "access_tiers": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "connectors": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "public_cidrs": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "include": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "exclude": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "public_domains": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "include": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "exclude": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "applications": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "include": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "exclude": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "access_tier_group": { + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "AccessTier group name", + }, + }, }, }, - "public_domains_exclude": { + "name_resolution": { Type: schema.TypeSet, Optional: true, - Description: "Specifies the domains that should be that should be excluded from the tunnel, ex: zoom.us", - Elem: &schema.Schema{ - Type: schema.TypeString, + MaxItems: 1, + Description: "Private Search Domains", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name_servers": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dns_search_domains": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, }, }, - "public_traffic_tunnel_via_access_tier": { - Type: schema.TypeString, - Optional: true, - Description: "Access Tier to be used to tunnel through public traffic", - }, "policy": { Type: schema.TypeString, Required: true, Description: "Policy ID to be attached to this service tunnel", }, - "cluster": { - Type: schema.TypeString, - Description: "(Depreciated) Sets the cluster / shield for the service", - Computed: true, - Optional: true, - Deprecated: "This attribute is now configured automatically. This attribute will be removed in a future release of the provider.", - ForceNew: true, - }, - "applications_include": { - Type: schema.TypeSet, - Optional: true, - Description: "Specifies the applications ids that should be included in the tunnel, ex: 905a72d3-6216-4ffc-ad18-db1593782915", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "applications_exclude": { - Type: schema.TypeSet, - Optional: true, - Description: "Specifies the applications ids that should be excluded in the tunnel, ex: 633301ab-fd20-439b-b5ae-47153ec7fbf2", - Elem: &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": { + "policy_enforcing": { 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", + Default: true, + Description: "Policy Enforcing / Permissive", }, } return } -func TunFromState(d *schema.ResourceData) (tun servicetunnel.Info) { +func TunFromState(d *schema.ResourceData) (tun servicetunnel.Info, err error) { icon := "" descriptionLink := "" - + spec, err := expandServiceTunnelSpec(d) + if err != nil { + return + } tun = servicetunnel.Info{ Kind: "BanyanServiceTunnel", APIVersion: "rbac.banyanops.com/v1", @@ -171,17 +225,17 @@ func TunFromState(d *schema.ResourceData) (tun servicetunnel.Info) { Autorun: expandAutorun(d), LockAutoRun: expandLockAutorun(d), }, - Spec: expandServiceTunnelSpec(d), + Spec: spec, } return } func resourceServiceTunnelCreate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { - err := setCluster(d, m) + c := m.(*client.Holder) + state, err := TunFromState(d) if err != nil { return diag.FromErr(err) } - c := m.(*client.Holder) - tun, err := c.ServiceTunnel.Create(TunFromState(d)) + tun, err := c.ServiceTunnel.Create(state) if err != nil { return diag.FromErr(err) } @@ -195,7 +249,11 @@ func resourceServiceTunnelCreate(ctx context.Context, d *schema.ResourceData, m func resourceServiceTunnelUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) (diagnostics diag.Diagnostics) { c := m.(*client.Holder) - tun, err := c.ServiceTunnel.Update(d.Id(), TunFromState(d)) + state, err := TunFromState(d) + if err != nil { + return diag.FromErr(err) + } + tun, err := c.ServiceTunnel.Update(d.Id(), state) if err != nil { return diag.FromErr(err) } @@ -212,9 +270,14 @@ func attachPolicy(c *client.Holder, d *schema.ResourceData) (err error) { if policy == nil { return } + policyEnforcing := d.Get("policy_enforcing") + if policyEnforcing == nil { + return + } + _, err = c.ServiceTunnel.AttachPolicy(d.Id(), servicetunnel.PolicyAttachmentPost{ PolicyID: policy.(string), - Enabled: true, + Enabled: policyEnforcing.(bool), }) if err != nil { return fmt.Errorf("failed to attach policy to service tunnel: %s", err) @@ -238,7 +301,7 @@ func resourceServiceTunnelRead(ctx context.Context, d *schema.ResourceData, m in if err != nil { return diag.FromErr(err) } - err = flattenServiceTunnelSpec(d, tun) + err = flattenServiceTunnelSpec(d, tun.Spec.Spec) if err != nil { return diag.FromErr(err) } @@ -250,6 +313,15 @@ func resourceServiceTunnelRead(ctx context.Context, d *schema.ResourceData, m in if err != nil { return diag.FromErr(err) } + + policyEnforcing := false + if strings.EqualFold("TRUE", policy.Enabled) { + policyEnforcing = true + } + err = d.Set("policy_enforcing", policyEnforcing) + if err != nil { + return diag.FromErr(err) + } return } @@ -280,7 +352,6 @@ func resourceServiceTunnelDetachPolicy(d *schema.ResourceData, c *client.Holder) if err != nil { return } - // This may not be necessary after policy refactor err = c.PolicyAttachment.Delete(attachedPolicy.PolicyID) if err != nil { return @@ -288,171 +359,271 @@ func resourceServiceTunnelDetachPolicy(d *schema.ResourceData, c *client.Holder) return } -func expandServiceTunnelSpec(d *schema.ResourceData) (expanded servicetunnel.Spec) { - ats := convertSchemaSetToStringSlice(d.Get("access_tiers").(*schema.Set)) - conns := convertSchemaSetToStringSlice(d.Get("connectors").(*schema.Set)) - inclCidrs := convertSchemaSetToStringSlice(d.Get("public_cidrs_include").(*schema.Set)) - exclCidrs := convertSchemaSetToStringSlice(d.Get("public_cidrs_exclude").(*schema.Set)) - inclDomains := convertSchemaSetToStringSlice(d.Get("public_domains_include").(*schema.Set)) - exclDomains := convertSchemaSetToStringSlice(d.Get("public_domains_exclude").(*schema.Set)) - inclApplications := convertSchemaSetToStringSlice(d.Get("applications_include").(*schema.Set)) - exclApplications := convertSchemaSetToStringSlice(d.Get("applications_exclude").(*schema.Set)) - - var peers []servicetunnel.PeerAccessTier - 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 { - peer := servicetunnel.PeerAccessTier{ - Cluster: d.Get("cluster").(string), - AccessTiers: []string{"*"}, - Connectors: conns, +func expandServiceTunnelSpec(d *schema.ResourceData) (expanded servicetunnel.Spec, err error) { + peers, err := expandPeerAccessTiers(d) + if err != nil { + return + } + + expanded = servicetunnel.Spec{ + PeerAccessTiers: peers, + } + nameResolution, err := expandNameResolution(d) + if err != nil { + return + } + if nameResolution != nil { + expanded.NameResolution = nameResolution + } + return +} + +func expandNameResolution(d *schema.ResourceData) (nameResolutionRef *dns.NameResolutionInfo, err error) { + nameResolutionSet := d.Get("name_resolution").(*schema.Set) + var nameResolution dns.NameResolutionInfo + nameResolution.NameServers = make([]string, 0) + nameResolution.DnsSearchDomains = make([]string, 0) + for _, eachNameResolution := range nameResolutionSet.List() { + eachNameResolutionItem, ok := eachNameResolution.(map[string]interface{}) + if !ok { + err = fmt.Errorf("unable to read name_resolution") + return + } + nameServer, ok := eachNameResolutionItem["name_servers"].([]interface{}) + if !ok { + err = fmt.Errorf("unable to read name_servers") + return } + for _, eachNameServer := range nameServer { + eachNameServerString, ok := eachNameServer.(string) + if ok { + nameResolution.NameServers = append(nameResolution.NameServers, eachNameServerString) + } + } + dnsSearchDomains, ok := eachNameResolutionItem["dns_search_domains"].([]interface{}) + if !ok { + err = fmt.Errorf("unable to read dns_search_domains") + return + } + for _, eachDnsSearchDomains := range dnsSearchDomains { + eachDnsSearchDomainsString, ok := eachDnsSearchDomains.(string) + if ok { + nameResolution.DnsSearchDomains = append(nameResolution.DnsSearchDomains, eachDnsSearchDomainsString) + } + } + } + if len(nameResolution.NameServers) > 0 || len(nameResolution.DnsSearchDomains) > 0 { + nameResolutionRef = &nameResolution + } + return +} - if accessTierGroup != "" { - peer.AccessTiers = nil - peer.Connectors = nil - peer.AccessTierGroup = accessTierGroup +func expandPeerAccessTiers(d *schema.ResourceData) (peers []servicetunnel.PeerAccessTier, err error) { + peers = make([]servicetunnel.PeerAccessTier, 0) + peerAccessTierConfigs := d.Get("network_settings").(*schema.Set) + for _, eachPeer := range peerAccessTierConfigs.List() { + var peer servicetunnel.PeerAccessTier + eachPeerAccessTier, ok := eachPeer.(map[string]interface{}) + if !ok { + err = fmt.Errorf("unable to parse PeerAccessTier") + return + } + if len(eachPeerAccessTier) == 0 { + continue } - peers = append(peers, peer) - } else { - // If multiple accessTiers are set create peer foreach. - for i, eachAts := range ats { - peer := servicetunnel.PeerAccessTier{ - Cluster: d.Get("cluster").(string), - AccessTiers: []string{eachAts}, - Connectors: nil, + if connectorsRaw, ok := eachPeerAccessTier["connectors"]; ok { + connectors, ok := connectorsRaw.([]interface{}) + if !ok { + err = fmt.Errorf("unable to parse connectors") + return + } + + for _, eachConnector := range connectors { + connectorString, ok := eachConnector.(string) + if ok { + peer.Connectors = append(peer.Connectors, connectorString) + } + } + + } + + atsRaw, ok := eachPeerAccessTier["access_tiers"] + // Ignore access_tier if set if there is connector set and set as {*} as it would be a global edge access_tier + if ok && len(peer.Connectors) == 0 { + ats, ok := atsRaw.([]interface{}) + if !ok { + err = fmt.Errorf("unable to parse access_tiers") + return } - if (inclCidrs != nil) || (exclCidrs != nil) || (inclDomains != nil) || (exclDomains != nil) || (inclApplications != nil) || (exclApplications != nil) { - publicTrafficAccessTier, ok := d.GetOk("public_traffic_tunnel_via_access_tier") - - if strings.EqualFold(publicTrafficAccessTier.(string), eachAts) || - /* if only one access tier */ len(ats) == 1 || - /* backward compatibility */ (!ok && i == 0) { - peer.PublicCIDRs = &servicetunnel.IncludeExclude{ - Include: inclCidrs, - Exclude: exclCidrs, - } - peer.PublicDomains = &servicetunnel.IncludeExclude{ - Include: inclDomains, - Exclude: exclDomains, - } - peer.Applications = &servicetunnel.IncludeExclude{ - Include: inclApplications, - Exclude: exclApplications, - } + for _, eachAt := range ats { + eachAtString, ok := eachAt.(string) + if ok { + peer.AccessTiers = append(peer.AccessTiers, eachAtString) } } - peers = append(peers, peer) + } else if len(peer.Connectors) > 0 { + peer.AccessTiers = []string{"*"} } - } - expanded = servicetunnel.Spec{ - PeerAccessTiers: peers, + if atGroupRaw, ok := eachPeerAccessTier["access_tier_group"]; ok { + atGroup, ok := atGroupRaw.(string) + if !ok { + err = fmt.Errorf("unable to parse access_tier_group") + return + } + if atGroup != "" && len(peer.AccessTiers) > 0 { + err = fmt.Errorf("invalid configuration cannot set both access_tier_group and access_tiers") + return + } + if atGroup != "" { + peer.AccessTierGroup = atGroup + } + } + + if clusterNameRaw, ok := eachPeerAccessTier["cluster"]; ok { + clusterName, ok := clusterNameRaw.(string) + if !ok { + err = fmt.Errorf("unable to parse cluster") + return + } + if clusterName != "" { + peer.Cluster = clusterName + } + } + + if len(peer.Connectors) > 0 && peer.Cluster == "" { + peer.Cluster = "global-edge" + } + + if publicCIDRsRaw, ok := eachPeerAccessTier["public_cidrs"]; ok { + publicCIDRs, myErr := extractIncludeExclude("public_cidrs", publicCIDRsRaw) + if myErr != nil { + err = myErr + return + } + peer.PublicCIDRs = publicCIDRs + } + + if publicDomainsRaw, ok := eachPeerAccessTier["public_domains"]; ok { + publicDomains, myErr := extractIncludeExclude("public_domains", publicDomainsRaw) + if myErr != nil { + err = myErr + return + } + peer.PublicDomains = publicDomains + } + + if applicationsRaw, ok := eachPeerAccessTier["applications"]; ok { + applications, myErr := extractIncludeExclude("applications", applicationsRaw) + if myErr != nil { + err = myErr + return + } + peer.Applications = applications + } + peers = append(peers, peer) } return } -func flattenServiceTunnelSpec(d *schema.ResourceData, tun servicetunnel.ServiceTunnelInfo) (err error) { - if len(tun.Spec.PeerAccessTiers) == 0 { +func extractIncludeExclude(key string, inputRaw interface{}) (extracted *servicetunnel.IncludeExclude, err error) { + var inputBlock servicetunnel.IncludeExclude + inputRawSet, ok := inputRaw.(*schema.Set) + if !ok { + err = fmt.Errorf("unable to parse " + key) return } - // set common parameters using first peer. - p1 := tun.Spec.PeerAccessTiers[0] - err = d.Set("cluster", p1.Cluster) - if err != nil { - return err + inputList := inputRawSet.List() + if len(inputList) > 1 { + err = fmt.Errorf("max length is 1 for " + key) + return } - // if connectors set => global-edge - if len(p1.Connectors) > 0 { - err = d.Set("connectors", p1.Connectors) - if err != nil { - return err + for _, eachInput := range inputList { + input, ok := eachInput.(map[string]interface{}) + if !ok { + err = fmt.Errorf("unable to read " + key + " block") + return } - err = d.Set("access_tiers", nil) - if err != nil { - return err - } - } else { - var ats []string - err = d.Set("connectors", nil) - if err != nil { - return err - } - for _, eachPeer := range tun.Spec.PeerAccessTiers { - ats = append(ats, eachPeer.AccessTiers...) - if eachPeer.PublicCIDRs != nil { - if len(eachPeer.PublicCIDRs.Include) > 0 { - err = d.Set("public_cidrs_include", eachPeer.PublicCIDRs.Include) - if err != nil { - return err - } - } - if len(eachPeer.PublicCIDRs.Exclude) > 0 { - err = d.Set("public_cidrs_exclude", eachPeer.PublicCIDRs.Exclude) - if err != nil { - return err - } - } - if len(eachPeer.AccessTiers) > 0 { - err = d.Set("public_traffic_tunnel_via_access_tier", eachPeer.AccessTiers[0]) - if err != nil { - return err - } - } - + if inputInclude, ok := input["include"]; ok { + inputIncludeList, ok := inputInclude.([]interface{}) + if !ok { + err = fmt.Errorf("unable to read " + key + "inlude ist") } - if eachPeer.PublicDomains != nil { - if len(eachPeer.PublicDomains.Include) > 0 { - err = d.Set("public_domains_include", eachPeer.PublicDomains.Include) - if err != nil { - return err - } - } - if len(eachPeer.PublicDomains.Exclude) > 0 { - err = d.Set("public_domains_exclude", eachPeer.PublicDomains.Exclude) - if err != nil { - return err - } - } - if len(eachPeer.AccessTiers) > 0 { - err = d.Set("public_traffic_tunnel_via_access_tier", eachPeer.AccessTiers[0]) - if err != nil { - return err - } + for _, eachInputInclude := range inputIncludeList { + eachInputIncludeString, ok := eachInputInclude.(string) + if ok { + inputBlock.Include = append(inputBlock.Include, eachInputIncludeString) } } - if eachPeer.Applications != nil { - if len(eachPeer.Applications.Include) > 0 { - err = d.Set("applications_include", eachPeer.Applications.Include) - if err != nil { - return err - } - } - if len(eachPeer.Applications.Exclude) > 0 { - err = d.Set("applications_exclude", eachPeer.Applications.Exclude) - if err != nil { - return err - } - } - if len(eachPeer.AccessTiers) > 0 { - err = d.Set("public_traffic_tunnel_via_access_tier", eachPeer.AccessTiers[0]) - if err != nil { - return err - } - } + } + if inputExclude, ok := input["exclude"]; ok { + inputExcludeList, ok := inputExclude.([]interface{}) + if !ok { + err = fmt.Errorf("unable to read " + key + "exclude ist") } - err = d.Set("access_tier_group", eachPeer.AccessTierGroup) - if err != nil { - return err + for _, eachInputExclude := range inputExcludeList { + eachInputExcludeString, ok := eachInputExclude.(string) + if ok { + inputBlock.Exclude = append(inputBlock.Exclude, eachInputExcludeString) + } } + } + extracted = &inputBlock + } + return +} + +func flattenServiceTunnelSpec(d *schema.ResourceData, spec servicetunnel.Spec) (err error) { + if len(spec.PeerAccessTiers) == 0 { + return + } + + flattened := make([]interface{}, 0) + for _, eachPeerAccessTier := range spec.PeerAccessTiers { + eachPeerAccessTierMap := make(map[string]interface{}) + // if connectors are set access_tiers are inferred to be * + if len(eachPeerAccessTier.AccessTiers) > 0 && eachPeerAccessTier.AccessTiers[0] != "*" { + eachPeerAccessTierMap["access_tiers"] = eachPeerAccessTier.AccessTiers + } + if len(eachPeerAccessTier.Connectors) > 0 { + eachPeerAccessTierMap["connectors"] = eachPeerAccessTier.Connectors + } + if eachPeerAccessTier.AccessTierGroup != "" { + eachPeerAccessTierMap["access_tier_group"] = eachPeerAccessTier.AccessTierGroup + } + // set cluster only if not global-edge as global edge is auto set. + if eachPeerAccessTier.Cluster != "" && eachPeerAccessTier.Cluster != "global-edge" { + eachPeerAccessTierMap["cluster"] = eachPeerAccessTier.Cluster + } + if eachPeerAccessTier.PublicCIDRs != nil { + publicCIDRs := make(map[string]interface{}) + publicCIDRs["include"] = eachPeerAccessTier.PublicCIDRs.Include + publicCIDRs["exclude"] = eachPeerAccessTier.PublicCIDRs.Exclude + eachPeerAccessTierMap["public_cidrs"] = []map[string]interface{}{publicCIDRs} + } + if eachPeerAccessTier.PublicDomains != nil { + publicDomains := make(map[string]interface{}) + publicDomains["include"] = eachPeerAccessTier.PublicDomains.Include + publicDomains["exclude"] = eachPeerAccessTier.PublicDomains.Exclude + eachPeerAccessTierMap["public_domains"] = []map[string]interface{}{publicDomains} } - err = d.Set("access_tiers", ats) - if err != nil { - return err + + if eachPeerAccessTier.Applications != nil { + applications := make(map[string]interface{}) + applications["include"] = eachPeerAccessTier.Applications.Include + applications["exclude"] = eachPeerAccessTier.Applications.Exclude + eachPeerAccessTierMap["applications"] = applications } + if len(eachPeerAccessTierMap) > 0 { + flattened = append(flattened, eachPeerAccessTierMap) + } + } + err = d.Set("network_settings", flattened) + if err != nil { + return err } return } diff --git a/banyan/resource_service_tunnel_test.go b/banyan/resource_service_tunnel_test.go index 3dc80483..97d73a86 100644 --- a/banyan/resource_service_tunnel_test.go +++ b/banyan/resource_service_tunnel_test.go @@ -17,12 +17,16 @@ func TestSchemaServiceTunnel_tunnel_at(t *testing.T) { "name": "tunnel-at", "description": "describe tunnel-at", "autorun": true, - "cluster": "cluster1", - "access_tiers": []interface{}{"gcp-tdnovpn-v1", "gcp-tdnovpn-v2"}, "lock_autorun": true, + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "access_tiers": []interface{}{"gcp-tdnovpn-v1"}, + }, + }, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_at) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec, _ := os.ReadFile("./specs/service_tunnel/tunnel-at.json") var ref_obj servicetunnel.Info @@ -35,11 +39,16 @@ func TestSchemaServiceTunnel_tunnel_conn(t *testing.T) { svc_tunnel_conn := map[string]interface{}{ "name": "global-edge-tunnel", "description": "Geo DNS to multiple ATs", - "cluster": "managed-cl-edge1", - "connectors": []interface{}{"gcp-test-drive", "td-gcp-tdnovpn"}, + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "managed-cl-edge1", + "access_tiers": []interface{}{"*"}, + "connectors": []interface{}{"gcp-test-drive", "td-gcp-tdnovpn"}, + }, + }, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_conn) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec, _ := os.ReadFile("./specs/service_tunnel/tunnel-conn.json") var ref_obj servicetunnel.Info @@ -50,18 +59,33 @@ func TestSchemaServiceTunnel_tunnel_conn(t *testing.T) { func TestSchemaServiceTunnel_tunnel_public(t *testing.T) { svc_tunnel_public := map[string]interface{}{ - "name": "tunnel-domains", - "description": "describe tunnel-domains", - "cluster": "cluster1", - "access_tiers": []interface{}{"gcp-tdnovpn-v2"}, - "public_cidrs_include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, - "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": "", + "name": "tunnel-domains", + "description": "describe tunnel-domains", + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "access_tiers": []interface{}{"gcp-tdnovpn-v2"}, + "public_cidrs": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, + }, + }, + "public_domains": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, + }, + }, + "applications": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, + }, + }, + }, + }, } + d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec, _ := os.ReadFile("./specs/service_tunnel/tunnel-public.json") var ref_obj servicetunnel.Info @@ -72,18 +96,32 @@ func TestSchemaServiceTunnel_tunnel_public(t *testing.T) { func TestSchemaServiceTunnel_tunnel_public_one_at(t *testing.T) { svc_tunnel_public := map[string]interface{}{ - "name": "tunnel-domains", - "description": "describe tunnel-domains", - "cluster": "cluster1", - "access_tiers": []interface{}{"gcp-tdnovpn-v2"}, - "public_cidrs_include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, - "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": "", + "name": "tunnel-domains", + "description": "describe tunnel-domains", + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "access_tiers": []interface{}{"gcp-tdnovpn-v2"}, + "public_cidrs": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, + }, + }, + "public_domains": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, + }, + }, + "applications": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, + }, + }, + }, + }, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec, _ := os.ReadFile("./specs/service_tunnel/tunnel-public.json") var ref_obj servicetunnel.Info @@ -94,18 +132,32 @@ func TestSchemaServiceTunnel_tunnel_public_one_at(t *testing.T) { func TestSchemaServiceTunnel_tunnel_public_select_at_from_multiple(t *testing.T) { svc_tunnel_public := map[string]interface{}{ - "name": "tunnel-domains", - "description": "describe tunnel-domains", - "cluster": "cluster1", - "access_tiers": []interface{}{"gcp-tdnovpn-v1", "gcp-tdnovpn-v2"}, - "public_cidrs_include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, - "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": "", + "name": "tunnel-domains", + "description": "describe tunnel-domains", + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "access_tiers": []interface{}{"gcp-tdnovpn-v2"}, + "public_cidrs": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"}, + }, + }, + "public_domains": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"}, + }, + }, + "applications": []interface{}{ + map[string]interface{}{ + "include": []interface{}{"067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"}, + }, + }, + }, + }, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec, _ := os.ReadFile("./specs/service_tunnel/tunnel-public-multiple-at.json") var ref_obj servicetunnel.Info @@ -150,8 +202,12 @@ func TestAccServiceTunnel_basic(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "realdescription" - access_tiers = [banyan_accesstier.example.name] - policy = banyan_policy_tunnel.example.id + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.example.id + policy_enforcing = false } `, rName, rName, rName, rName), Check: resource.ComposeTestCheckFunc( @@ -189,8 +245,11 @@ func TestAccServiceTunnel_basic(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "some description" - access_tiers = [banyan_accesstier.example.name] - policy = banyan_policy_tunnel.example.id + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.example.id } `, rName, rName, rName, rName), Check: resource.ComposeTestCheckFunc( @@ -241,8 +300,11 @@ func TestAccServiceTunnel_change_policy(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "realdescription" - access_tiers = [banyan_accesstier.example.name] - policy = banyan_policy_tunnel.example.id + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.example.id } `, rName, rName, rName, rName), Check: resource.ComposeTestCheckFunc( @@ -284,8 +346,11 @@ func TestAccServiceTunnel_change_policy(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "some description" - access_tiers = [banyan_accesstier.example.name] - policy = banyan_policy_tunnel.new.id + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.new.id } `, rName, rName, rName, rName, rName), Check: resource.ComposeTestCheckFunc( @@ -298,13 +363,17 @@ 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", + "name": "tunnel-domains", + "description": "describe tunnel-domains", + "network_settings": []interface{}{ + map[string]interface{}{ + "cluster": "cluster1", + "access_tier_group": "atg-1", + }, + }, } d := schema.TestResourceDataRaw(t, TunnelSchema(), svc_tunnel_public) - svc_obj := TunFromState(d) + svc_obj, _ := TunFromState(d) json_spec := []byte(`{ "kind": "BanyanServiceTunnel", @@ -364,8 +433,11 @@ func TestAccServiceTunnel_with_access_tier_group(t *testing.T) { resource "banyan_service_tunnel" "example" { name = "%s" description = "realdescription" - access_tier_group = "new-grp-1" - policy = banyan_policy_tunnel.example.id + network_settings { + cluster = "cluster1" + access_tier_group = "new-grp-1" + } + policy = banyan_policy_tunnel.example.id } `, rName, rName), Check: resource.ComposeTestCheckFunc( diff --git a/banyan/specs/service_tunnel/tunnel-at.json b/banyan/specs/service_tunnel/tunnel-at.json index 6596ea7d..af53e969 100644 --- a/banyan/specs/service_tunnel/tunnel-at.json +++ b/banyan/specs/service_tunnel/tunnel-at.json @@ -25,13 +25,6 @@ [ "gcp-tdnovpn-v1" ] - }, - { - "cluster": "cluster1", - "access_tiers": - [ - "gcp-tdnovpn-v2" - ] } ] } diff --git a/banyan/specs/service_tunnel/tunnel-public-multiple-at-multiple-configuration.json b/banyan/specs/service_tunnel/tunnel-public-multiple-at-multiple-configuration.json new file mode 100644 index 00000000..e4f00a03 --- /dev/null +++ b/banyan/specs/service_tunnel/tunnel-public-multiple-at-multiple-configuration.json @@ -0,0 +1,111 @@ +{ + "kind": "BanyanServiceTunnel", + "api_version": "rbac.banyanops.com", + "type": "origin", + "metadata": { + "name": "MultipleATMultipleConfig", + "friendly_name": "MultipleATMultipleConfig", + "description": "Access to resources", + "autorun": false, + "lock_autorun": false, + "tags": { + "icon": "", + "description_link": "" + } + }, + "spec": { + "peer_access_tiers": [ + { + "cluster": "cluster1", + "access_tiers": [ + "my-accesstier-1" + ], + "public_cidrs": { + "include": [], + "exclude": [] + }, + "public_domains": { + "include": [ + "my-domain-1.dev", + "my-domain-2.dev", + "my-domain-3.dev", + "my-domain-4.dev" + ], + "exclude": [] + }, + "applications": { + "include": [], + "exclude": [] + }, + "access_tier_group": "" + }, + { + "cluster": "cluster1", + "access_tiers": [ + "my-accesstier-2" + ], + "public_cidrs": { + "include": [], + "exclude": [] + }, + "public_domains": { + "include": [ + "my-domain.com" + ], + "exclude": [] + }, + "applications": { + "include": [], + "exclude": [] + }, + "access_tier_group": "" + }, + { + "cluster": "cluster1", + "access_tiers": [ + "my-accesstier-3" + ], + "public_cidrs": { + "include": [], + "exclude": [] + }, + "public_domains": { + "include": [ + "my-domain.org" + ], + "exclude": [] + }, + "applications": { + "include": [], + "exclude": [] + }, + "access_tier_group": "" + }, + { + "cluster": "cluster1", + "access_tiers": [ + "my-accesstier-4" + ], + "public_cidrs": { + "include": [], + "exclude": [] + }, + "public_domains": { + "include": [ + "my-domain-1.net", + "my-domain-2.net" + ], + "exclude": [ + "my-domain-3.net", + "my-domain-4.net" + ] + }, + "applications": { + "include": [], + "exclude": [] + }, + "access_tier_group": "" + } + ] + } +} \ 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 deb9f780..354b0395 100644 --- a/banyan/specs/service_tunnel/tunnel-public-multiple-at.json +++ b/banyan/specs/service_tunnel/tunnel-public-multiple-at.json @@ -19,13 +19,6 @@ { "peer_access_tiers": [ - { - "cluster": "cluster1", - "access_tiers": - [ - "gcp-tdnovpn-v1" - ] - }, { "cluster": "cluster1", "access_tiers": diff --git a/client/dns/nameresolution.go b/client/dns/nameresolution.go new file mode 100644 index 00000000..0d2f0242 --- /dev/null +++ b/client/dns/nameresolution.go @@ -0,0 +1,6 @@ +package dns + +type NameResolutionInfo struct { + NameServers []string `json:"name_servers,omitempty"` + DnsSearchDomains []string `json:"dns_search_domains,omitempty"` +} diff --git a/client/servicetunnel/client.go b/client/servicetunnel/client.go index 46910ad6..1ae2c11b 100644 --- a/client/servicetunnel/client.go +++ b/client/servicetunnel/client.go @@ -31,7 +31,7 @@ type Client interface { Delete(id string) (err error) AttachPolicy(id string, post PolicyAttachmentPost) (created PolicyAttachmentInfo, err error) DeletePolicy(tunID string, policyID string) (err error) - GetPolicy(id string) (policy PolicyAttachmentInfo, err error) + GetPolicy(id string) (policy GetPolicyAttachmentInfo, err error) } func (a *ServiceTunnel) Get(id string) (spec ServiceTunnelInfo, err error) { @@ -52,8 +52,9 @@ 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, + Autorun: spec.Metadata.Autorun, + LockAutoRun: spec.Metadata.LockAutoRun, + Tags: spec.Metadata.Tags, }, Spec: spec.Spec, }) @@ -77,6 +78,9 @@ func (a *ServiceTunnel) Update(id string, spec Info) (updated ServiceTunnelInfo, Name: spec.Metadata.Name, FriendlyName: spec.Metadata.FriendlyName, Description: spec.Metadata.Description, + Autorun: spec.Metadata.Autorun, + LockAutoRun: spec.Metadata.LockAutoRun, + Tags: spec.Metadata.Tags, }, Spec: spec.Spec, }) @@ -97,9 +101,9 @@ func (a *ServiceTunnel) Delete(id string) (err error) { } // GetPolicy returns the policy attached to the service tunnel -func (a *ServiceTunnel) GetPolicy(id string) (policy PolicyAttachmentInfo, err error) { +func (a *ServiceTunnel) GetPolicy(id string) (policy GetPolicyAttachmentInfo, err error) { path := fmt.Sprintf("%s/%s/%s/security_policy", apiVersion, component, id) - var j PolicyResponse + var j GetPolicyResponse resp, err := a.restClient.Read(apiVersion, component, id, path) if err != nil { return policy, nil @@ -173,7 +177,7 @@ func specFromResponse(respData []byte) (created ServiceTunnelInfo, err error) { FriendlyName: spec.FriendlyName, Description: spec.Description, Enabled: spec.Enabled, - Spec: jSpec.Spec, + Spec: jSpec, CreatedAt: spec.CreatedAt, CreatedBy: spec.CreatedBy, UpdatedAt: spec.UpdatedAt, diff --git a/client/servicetunnel/service_tunnel.go b/client/servicetunnel/service_tunnel.go index 666d160b..1771b25f 100644 --- a/client/servicetunnel/service_tunnel.go +++ b/client/servicetunnel/service_tunnel.go @@ -1,13 +1,25 @@ package servicetunnel +import "github.com/banyansecurity/terraform-banyan-provider/client/dns" + +type GetPolicyAttachmentInfo struct { + ID string `json:"id"` + PolicyID string `json:"policy_id"` + PolicyName string `json:"policy_name"` + AttachedToID string `json:"attached_to_id"` + AttachedToType string `json:"attached_to_type"` + AttachedBy string `json:"attached_by"` + AttachedAt int64 `json:"Attached_at"` + Enabled string `json:"enabled"` +} type PolicyAttachmentInfo struct { ID string `json:"id"` PolicyID string `json:"policy_id"` - PolicyVersion int `json:"policy_version"` + PolicyVersion int64 `json:"policy_version"` ServiceTunnelID string `json:"service_tunnel_id"` AttachedBy string `json:"attached_by"` AttachedAt int64 `json:"Attached_at"` - // BROKEN Enabled bool `json:"enabled"` //true/false: true => Enforced; false => Permissive mode + Enabled bool `json:"enabled"` } type PolicyAttachmentPost struct { @@ -20,7 +32,13 @@ type PolicyResponse struct { ErrorCode int `json:"error_code"` ErrorDescription string `json:"error_description"` Data PolicyAttachmentInfo `json:"data"` - Count int `json:"count"` +} + +type GetPolicyResponse struct { + RequestId string `json:"request_id"` + ErrorCode int `json:"error_code"` + ErrorDescription string `json:"error_description"` + Data GetPolicyAttachmentInfo `json:"data"` } // ServiceTunnelInfo used to send data to shield over websocket from restapi @@ -31,11 +49,13 @@ type ServiceTunnelInfo struct { FriendlyName string `json:"friendly_name"` Description string `json:"description"` Enabled bool `json:"enabled"` - Spec Spec `json:"spec"` + Spec Info `json:"spec"` CreatedAt int64 `json:"created_at"` CreatedBy string `json:"created_by"` UpdatedAt int64 `json:"updated_at"` UpdatedBy string `json:"updated_by"` + + ActiveConnectionsCount int64 `json:"active_connections_count"` } // Contains the spec string from the api response @@ -67,22 +87,21 @@ type Metadata struct { Name string `json:"name,omitempty"` FriendlyName string `json:"friendly_name,omitempty"` Description string `json:"description,omitempty"` - Tags Tags `json:"tags"` Autorun bool `json:"autorun"` LockAutoRun bool `json:"lock_autorun"` + Tags Tags `json:"tags"` } // Tags represents the metadata tags type Tags struct { - Template *string `json:"template,omitempty"` - UserFacing *string `json:"user_facing,omitempty"` Icon *string `json:"icon,omitempty"` DescriptionLink *string `json:"description_link,omitempty"` } // Spec represents the attributes stanza of a Info. type Spec struct { - PeerAccessTiers []PeerAccessTier `json:"peer_access_tiers"` + PeerAccessTiers []PeerAccessTier `json:"peer_access_tiers"` + NameResolution *dns.NameResolutionInfo `json:"name_resolution,omitempty"` } type PeerAccessTier struct { diff --git a/docs/resources/service_tunnel.md b/docs/resources/service_tunnel.md index 55e17081..504a7a08 100644 --- a/docs/resources/service_tunnel.md +++ b/docs/resources/service_tunnel.md @@ -27,10 +27,79 @@ resource "banyan_accesstier" "example" { resource "banyan_service_tunnel" "example" { name = "example-anyone-high" description = "tunnel allowing anyone with a high trust level" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.anyone-high.id + policy_enforcing = true +} + +resource "banyan_service_tunnel" "example1" { + name = "example-anyone-high" + description = "tunnel allowing anyone with a high trust level" + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + network_settings { + connectors = ["myconnector"] + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + network_settings { + cluster = "cluster1" + access_tiers = ["myaccesstier1"] + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + + network_settings { + cluster = "cluster1" + access_tier_group = "atg" + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + name_resolution { + name_servers = ["8.8.8.8"] + dns_search_domains = ["mylocal.local"] + } policy = banyan_policy_tunnel.anyone-high.id + policy_enforcing = true } + + resource "banyan_policy_tunnel" "anyone-high" { name = "allow anyone" description = "${banyan_accesstier.example.name} allow" @@ -72,14 +141,21 @@ resource "banyan_accesstier" "example" { resource "banyan_service_tunnel" "users" { name = "corporate network" description = "tunnel allowing anyone with a high trust level access to 443" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } policy = banyan_policy_tunnel.anyone-high.id + polict_enforcing = true } resource "banyan_service_tunnel" "administrators" { name = "corporate network admin" description = "tunnel allowing administrators access to the networks" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } policy = banyan_policy_tunnel.administrators.id } @@ -127,25 +203,65 @@ 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 - `autorun` (Boolean) Autorun for the service, if set true service would autorun on the app -- `cluster` (String, Deprecated) (Depreciated) Sets the cluster / shield for the 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 -- `public_domains_include` (Set of String) Specifies the domains that should be that should be included in the tunnel, ex: cnn.com -- `public_traffic_tunnel_via_access_tier` (String) Access Tier to be used to tunnel through public traffic +- `name_resolution` (Block Set, Max: 1) Private Search Domains (see [below for nested schema](#nestedblock--name_resolution)) +- `network_settings` (Block Set) Add a network that will be accessible via this Service Tunnel. (see [below for nested schema](#nestedblock--network_settings)) +- `policy_enforcing` (Boolean) Policy Enforcing / Permissive ### Read-Only - `id` (String) ID of the service tunnel key in Banyan + + +### Nested Schema for `name_resolution` + +Optional: + +- `dns_search_domains` (List of String) +- `name_servers` (List of String) + + + +### Nested Schema for `network_settings` + +Optional: + +- `access_tier_group` (String) AccessTier group name +- `access_tiers` (List of String) +- `applications` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--network_settings--applications)) +- `cluster` (String) cluster name where access-tier belongs to +- `connectors` (List of String) +- `public_cidrs` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--network_settings--public_cidrs)) +- `public_domains` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--network_settings--public_domains)) + + +### Nested Schema for `network_settings.applications` + +Optional: + +- `exclude` (List of String) +- `include` (List of String) + + + +### Nested Schema for `network_settings.public_cidrs` + +Optional: + +- `exclude` (List of String) +- `include` (List of String) + + + +### Nested Schema for `network_settings.public_domains` + +Optional: + +- `exclude` (List of String) +- `include` (List of String) ## Import Import is supported using the following syntax: ```shell diff --git a/examples/resources/banyan_service_tunnel/resource.tf b/examples/resources/banyan_service_tunnel/resource.tf index 293d8548..c208cbdc 100644 --- a/examples/resources/banyan_service_tunnel/resource.tf +++ b/examples/resources/banyan_service_tunnel/resource.tf @@ -14,10 +14,79 @@ resource "banyan_accesstier" "example" { resource "banyan_service_tunnel" "example" { name = "example-anyone-high" description = "tunnel allowing anyone with a high trust level" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + policy = banyan_policy_tunnel.anyone-high.id + policy_enforcing = true +} + +resource "banyan_service_tunnel" "example1" { + name = "example-anyone-high" + description = "tunnel allowing anyone with a high trust level" + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } + network_settings { + connectors = ["myconnector"] + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + network_settings { + cluster = "cluster1" + access_tiers = ["myaccesstier1"] + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + + network_settings { + cluster = "cluster1" + access_tier_group = "atg" + public_cidrs { + include = ["8.8.8.8/32", "75.75.75.75/32", "75.75.76.76/32"] + exclude = ["99.99.99.99/32"] + } + public_domains { + include = ["cnn.com", "icanhazip.com", "fast.com", "yahoo.com", "banyansecurity.io"] + exclude = ["excluded.com"] + } + applications { + include = ["067c3a25-8271-4764-89dd-c3543ac99a5a", "0b90e7d0-e8fc-43fb-95b7-4ad5d6881bb8"] + exclude = ["067c3a25-8271-4764-89dd-c3543ac99a5c"] + } + } + name_resolution { + name_servers = ["8.8.8.8"] + dns_search_domains = ["mylocal.local"] + } policy = banyan_policy_tunnel.anyone-high.id + policy_enforcing = true } + + resource "banyan_policy_tunnel" "anyone-high" { name = "allow anyone" description = "${banyan_accesstier.example.name} allow" diff --git a/examples/resources/banyan_service_tunnel_l4_policy/resource.tf b/examples/resources/banyan_service_tunnel_l4_policy/resource.tf index aa012c09..0af15ea3 100644 --- a/examples/resources/banyan_service_tunnel_l4_policy/resource.tf +++ b/examples/resources/banyan_service_tunnel_l4_policy/resource.tf @@ -27,14 +27,21 @@ resource "banyan_accesstier" "example" { resource "banyan_service_tunnel" "users" { name = "corporate network" description = "tunnel allowing anyone with a high trust level access to 443" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } policy = banyan_policy_tunnel.anyone-high.id + polict_enforcing = true } resource "banyan_service_tunnel" "administrators" { name = "corporate network admin" description = "tunnel allowing administrators access to the networks" - access_tiers = [banyan_accesstier.example.name] + network_settings { + cluster = "cluster1" + access_tiers = [banyan_accesstier.example.name] + } policy = banyan_policy_tunnel.administrators.id }