Skip to content

Commit

Permalink
Add data sources for private link connection information (#533)
Browse files Browse the repository at this point in the history
* AWS Private Link data source

* GCP PSC data source

* Azure Private Link data source

* Docs

* Changelog
  • Loading branch information
tobio authored Sep 15, 2022
1 parent 0274dcc commit 246c504
Show file tree
Hide file tree
Showing 15 changed files with 1,001 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .changelog/533.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
datasource/privatelink: Adds data sources to obtain AWS/Azure Private Link, and GCP Private Service Connect configuration data.
```
29 changes: 29 additions & 0 deletions docs/data-sources/ec_aws_privatelink_endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
page_title: "Elastic Cloud: ec_aws_privatelink_endpoint"
description: |-
Retrieves infomation about the AWS Private Link configuration for a given region.
---

# Data Source: ec_aws_privatelink_endpoint

Use this data source to retrieve information about the AWS Private Link configuration for a given region. Further documentation on how to establish a PrivateLink connection can be found in the ESS [documentation](https://www.elastic.co/guide/en/cloud/current/ec-traffic-filtering-vpc.html).

~> **NOTE:** This data source provides data relevant to the Elasticsearch Service (ESS) only, and should not be used for ECE.

## Example Usage

```hcl
data "ec_aws_privatelink_endpoint" "us-east-1" {
region = "us-east-1"
}
```

## Argument Reference

* `region` (Required) - Region to retrieve the Private Link configuration for.

## Attributes Reference

* `vpc_service_name` - The VPC service name used to connect to the region.
* `domain_name` - The domain name to used in when configuring a private hosted zone in the VPCE connection.
* `zone_ids` - The IDs of the availability zones hosting the VPC endpoints.
28 changes: 28 additions & 0 deletions docs/data-sources/ec_azure_privatelink_endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
page_title: "Elastic Cloud: ec_azure_privatelink_endpoint"
description: |-
Retrieves infomation about the Azure Private Link configuration for a given region.
---

# Data Source: ec_azure_privatelink_endpoint

Use this data source to retrieve information about the Azure Private Link configuration for a given region. Further documentation on how to establish a PrivateLink connection can be found in the ESS [documentation](https://www.elastic.co/guide/en/cloud/current/ec-traffic-filtering-vnet.html).

~> **NOTE:** This data source provides data relevant to the Elasticsearch Service (ESS) only, and should not be used for ECE.

## Example Usage

```hcl
data "ec_azure_privatelink_endpoint" "eastus" {
region = "eastus"
}
```

## Argument Reference

* `region` (Required) - Region to retrieve the Private Link configuration for.

## Attributes Reference

* `service_alias` - The service alias to establish a connection to.
* `domain_name` - The domain name to used in when configuring a private hosted zone in the VNet connection.
28 changes: 28 additions & 0 deletions docs/data-sources/ec_gcp_private_service_connect_endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
page_title: "Elastic Cloud: ec_gcp_private_service_connect_endpoint"
description: |-
Retrieves infomation about the GCP Private Service Connect configuration for a given region.
---

# Data Source: ec_gcp_private_service_connect_endpoint

Use this data source to retrieve information about the Azure Private Link configuration for a given region. Further documentation on how to establish a PrivateLink connection can be found in the ESS [documentation](https://www.elastic.co/guide/en/cloud/current/ec-traffic-filtering-psc.html).

~> **NOTE:** This data source provides data relevant to the Elasticsearch Service (ESS) only, and should not be used for ECE.

## Example Usage

```hcl
data "ec_gcp_private_service_connect_endpoint" "us-central1" {
region = "us-central1"
}
```

## Argument Reference

* `region` (Required) - Region to retrieve the Private Link configuration for.

## Attributes Reference

* `service_attachment_uri` - The service attachment URI to attach the PSC endpoint to.
* `domain_name` - The domain name to point towards the PSC endpoint.
10 changes: 5 additions & 5 deletions docs/guides/configuring-sso-ec-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: |-

# Configuring a SAML provider for an Elastic Cloud Deployment

A common use case for the Elastic Cloud Terraform provider is to spin up an Elastic Cloud deployment preconfigured with an SSO Identity provider (SAML2.0 or OIDC based)
A common use case for the Elastic Cloud Terraform provider is to spin up an Elastic Cloud deployment preconfigured with an SSO Identity provider (SAML2.0 or OIDC based)

Relying on the URL generated by Elastic Cloud creates a cyclic dependency, where the Elasticsearch cluster configuration requires the Kibana URL, which only exists after the deployment is created. You can avoid the cyclic dependency by configuring the deployment with an alias, which allows you to know the final Kibana URL before the deployment is created.

Expand Down Expand Up @@ -62,7 +62,7 @@ resource "ec_deployment" "elastic-sso" {
Let's take a closer look at one specific argument here:

```hcl
format("%s-%s",var.name,substr("${random_uuid.uuid.result}",0,6))
name = format("%s-%s", var.name, substr("${random_uuid.uuid.result}", 0, 6))
```

This will tell terraform to create a string, that looks like `<deployment-name>-<6-digits-of-uuid>`
Expand All @@ -71,9 +71,9 @@ You will configure the deployment alias field to be the same, so if the deployme
Then, by using a variable in the `es.yml` file and a terraform templating mechanism, you can generate your own `es.yml` file. Your variable is named kibana_url, as seen in the ec_deployment resource:

```hcl
config{
user_settings_yaml = templatefile("./es.yml",{kibana_url=format("https://%s-%s.kb.us-east-1.aws.found.io:9243",var.name,substr("${random_uuid.uuid.result}",0,6))})
}
config {
user_settings_yaml = templatefile("./es.yml", { kibana_url = format("https://%s-%s.kb.us-east-1.aws.found.io:9243", var.name, substr("${random_uuid.uuid.result}", 0, 6)) })
}
```

This specific template uses your name and UUID to determine the URL for the Elasticsearch deployment before it is even created, and stores it in the `es.yml` file.
Expand Down
82 changes: 82 additions & 0 deletions ec/ecdatasource/privatelinkdatasource/aws_datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package privatelinkdatasource

import (
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// AwsDataSource returns the ec_aws_privatelink_endpoint data source schema.
func AwsDataSource() *schema.Resource {
return &schema.Resource{
ReadContext: readContextFor(provider{
name: "aws",
populateResource: populateAwsResource,
}),

Schema: newAwsSchema(),

Timeouts: &schema.ResourceTimeout{
Default: schema.DefaultTimeout(5 * time.Minute),
},
}
}

func newAwsSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Required: true,
},

// Computed
"vpc_service_name": {
Type: schema.TypeString,
Computed: true,
},
"domain_name": {
Type: schema.TypeString,
Computed: true,
},
"zone_ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
}
}

func populateAwsResource(regionData map[string]interface{}, d *schema.ResourceData) error {
if err := copyToStateAs[string]("vpc_service_name", regionData, d); err != nil {
return err
}

if err := copyToStateAs[string]("domain_name", regionData, d); err != nil {
return err
}

if err := copyToStateAs[[]interface{}]("zone_ids", regionData, d); err != nil {
return err
}

return nil
}
87 changes: 87 additions & 0 deletions ec/ecdatasource/privatelinkdatasource/aws_datasource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package privatelinkdatasource

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/assert"

"github.com/elastic/terraform-provider-ec/ec/internal/util"
)

func Test_AwsDataSource_ReadContext(t *testing.T) {
tests := []struct {
name string
region string
diag diag.Diagnostics
endpoint *schema.ResourceData
}{
{
name: "invalid region returns unknown regino error",
region: "unknown",
diag: diag.FromErr(fmt.Errorf("%w: unknown", errUnknownRegion)),
endpoint: util.NewResourceData(t, util.ResDataParams{
ID: "myID",
State: map[string]interface{}{
"id": "myID",
"region": "unknown",
},
Schema: newAwsSchema(),
}),
},
{
name: "valid region returns endpoint",
region: "ap-northeast-1",
endpoint: util.NewResourceData(t, util.ResDataParams{
ID: "myID",
State: map[string]interface{}{
"id": "myID",
"region": "ap-northeast-1",
"vpc_service_name": "com.amazonaws.vpce.ap-northeast-1.vpce-svc-0e1046d7b48d5cf5f",
"domain_name": "vpce.ap-northeast-1.aws.elastic-cloud.com",
"zone_ids": []interface{}{"apne1-az1", "apne1-az2", "apne1-az4"},
},
Schema: newAwsSchema(),
}),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deploymentsSchemaArg := schema.TestResourceDataRaw(t, newAwsSchema(), nil)
deploymentsSchemaArg.SetId("myID")
_ = deploymentsSchemaArg.Set("region", tt.region)

source := AwsDataSource()

d := source.ReadContext(context.Background(), deploymentsSchemaArg, nil)
if tt.diag != nil {
assert.Equal(t, d, tt.diag)
} else {
assert.Nil(t, d)
}

assert.Equal(t, tt.endpoint.State().Attributes, deploymentsSchemaArg.State().Attributes)
})
}
}
71 changes: 71 additions & 0 deletions ec/ecdatasource/privatelinkdatasource/azure_datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package privatelinkdatasource

import (
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// AzureDataSource returns the ec_gcp_privateserviceconnect_endpoint data source schema.
func AzureDataSource() *schema.Resource {
return &schema.Resource{
ReadContext: readContextFor(provider{
name: "azure",
populateResource: populateAzureResource,
}),

Schema: newAzureSchema(),

Timeouts: &schema.ResourceTimeout{
Default: schema.DefaultTimeout(5 * time.Minute),
},
}
}

func newAzureSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Required: true,
},

// Computed
"service_alias": {
Type: schema.TypeString,
Computed: true,
},
"domain_name": {
Type: schema.TypeString,
Computed: true,
},
}
}

func populateAzureResource(regionData map[string]interface{}, d *schema.ResourceData) error {
if err := copyToStateAs[string]("service_alias", regionData, d); err != nil {
return err
}

if err := copyToStateAs[string]("domain_name", regionData, d); err != nil {
return err
}

return nil
}
Loading

0 comments on commit 246c504

Please sign in to comment.