Skip to content

Commit

Permalink
IAP brand & client (GoogleCloudPlatform#3135)
Browse files Browse the repository at this point in the history
* IAP brand & client

* First pass at review

* get rid of extra_schema entry

* Make GOOGLE_ORG_DOMAIN a test variable
  • Loading branch information
drebes authored and Nathan Klish committed May 18, 2020
1 parent df712f6 commit 93c01d4
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 1 deletion.
72 changes: 72 additions & 0 deletions products/iap/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,75 @@ objects:
name: 'name'
description: Name of the instance.
required: true
- !ruby/object:Api::Resource
name: 'Brand'
base_url: 'projects/{{project}}/brands'
self_link: '{{name}}'
input: true
description: |
OAuth brand data. Only "Organization Internal" brands can be created
programatically via API. To convert it into an external brands
please use the GCP Console.
parameters:
- !ruby/object:Api::Type::String
name: 'name'
description: |
Output only. Identifier of the brand, in the format
`projects/{project_number}/brands/{brand_id}`. NOTE: The brand
identification corresponds to the project number as only one
brand per project can be created.
output: true
properties:
- !ruby/object:Api::Type::String
name: 'supportEmail'
description: |
Support email displayed on the OAuth consent screen. Can be either a
user or group email. When a user email is specified, the caller must
be the user with the associated email address. When a group email is
specified, the caller can be either a user or a service account which
is an owner of the specified group in Cloud Identity.
required: true
- !ruby/object:Api::Type::String
name: 'applicationTitle'
description: |
Application name displayed on OAuth consent screen.
required: true
- !ruby/object:Api::Type::Boolean
name: 'orgInternalOnly'
description: |
Whether the brand is only intended for usage inside the GSuite organization only.
output: true
- !ruby/object:Api::Resource
name: 'Client'
base_url: '{{brand}}/identityAwareProxyClients'
self_link: '{{client_id}}'
input: true
description: |
Contains the data that describes an Identity Aware Proxy owned client.
parameters:
- !ruby/object:Api::Type::String
name: 'clientId'
api_name: name
description: |
Output only. Unique identifier of the OAuth client.
output: true
- !ruby/object:Api::Type::String
name: 'brand'
description: |
Identifier of the brand to which this client
is attached to. The format is
`projects/{project_number}/brands/{brand_id}/identityAwareProxyClients/{client_id}`.
input: true
required: true
url_param_only: true
properties:
- !ruby/object:Api::Type::String
name: 'secret'
description: |
Output only. Client secret of the OAuth client.
output: true
- !ruby/object:Api::Type::String
name: 'displayName'
description: |
Human-friendly name given to the OAuth client.
required: true
47 changes: 47 additions & 0 deletions products/iap/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,53 @@ overrides: !ruby/object:Overrides::ResourceOverrides
vars:
instance_name: "tunnel-vm"
primary_resource_name: "fmt.Sprintf(\"tf-test-tunnel-vm%s\", context[\"random_suffix\"])"
Brand: !ruby/object:Overrides::Terraform::ResourceOverride
description: |
{{description}}
~> **Note:** Brands can be created only once for a Google Cloud Platform
project and cannot be deleted. Destroying a Terraform-managed Brand
will remove it from state but *will not delete the resource on the server.*
id_format: '{{name}}'
import_format: ['{{name}}']
examples:
- !ruby/object:Provider::Terraform::Examples
name: "iap_brand"
primary_resource_id: "project_brand"
vars:
project_id: 'brand-proj-'
test_env_vars:
org_id: :ORG_ID
org_domain: :ORG_DOMAIN
skip_test: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_delete: templates/terraform/custom_delete/skip_delete.go.erb
custom_import: templates/terraform/custom_import/iap_brand.go.erb
post_create: templates/terraform/post_create/set_computed_name.erb
Client: !ruby/object:Overrides::Terraform::ResourceOverride
id_format: '{{brand}}/identityAwareProxyClients/{{client_id}}'
self_link: '{{brand}}/identityAwareProxyClients/{{client_id}}'
import_format: ['{{brand}}/identityAwareProxyClients/{{client_id}}']
examples:
- !ruby/object:Provider::Terraform::Examples
name: "iap_client"
primary_resource_id: "project_client"
vars:
project_id: 'brand-proj-'
test_env_vars:
org_id: :ORG_ID
org_domain: :ORG_DOMAIN
docs: !ruby/object:Provider::Terraform::Docs
attributes: |
* `client_id`: The OAuth2 ID of the client.
properties:
clientId: !ruby/object:Overrides::Terraform::PropertyOverride
custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb
secret: !ruby/object:Overrides::Terraform::PropertyOverride
sensitive: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
post_create: templates/terraform/post_create/iap_client.go.erb
custom_import: templates/terraform/custom_import/iap_client.go.erb
# This is for copying files over
files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
Expand Down
1 change: 1 addition & 0 deletions provider/terraform/examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def config_documentation
CREDENTIALS: 'my/credentials/filename.json',
REGION: 'us-west1',
ORG_ID: '123456789',
ORG_DOMAIN: 'example.com',
ORG_TARGET: '123456789',
BILLING_ACCT: '000000-0000000-0000000-000000',
SERVICE_ACCT: 'emailAddress:my@service-account.com'
Expand Down
18 changes: 18 additions & 0 deletions templates/terraform/custom_import/iap_brand.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
config := meta.(*Config)

// current import_formats can't import fields with forward slashes in their value
if err := parseImportId([]string{"(?P<name>.+)"}, d, config); err != nil {
return nil, err
}

nameParts := strings.Split(d.Get("name").(string), "/")
if len(nameParts) != 4 {
return nil, fmt.Errorf(
"Saw %s when the name is expected to have shape %s",
d.Get("name"),
"projects/{{project}}/brands/{{name}}",
)
}

d.Set("project", nameParts[1])
return []*schema.ResourceData{d}, nil
19 changes: 19 additions & 0 deletions templates/terraform/custom_import/iap_client.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
config := meta.(*Config)

// current import_formats can't import fields with forward slashes in their value
if err := parseImportId([]string{"(?P<brand>.+)"}, d, config); err != nil {
return nil, err
}

nameParts := strings.Split(d.Get("brand").(string), "/")
if len(nameParts) != 6 {
return nil, fmt.Errorf(
"Saw %s when the name is expected to have shape %s",
d.Get("brand").(string),
"projects/{{project_number}}/brands/{{brand_id}}/identityAwareProxyClients/{{client_id}}",
)
}

d.Set("brand", fmt.Sprintf("projects/%s/brands/%s", nameParts[1], nameParts[3]))
d.Set("client_id", nameParts[5])
return []*schema.ResourceData{d}, nil
4 changes: 3 additions & 1 deletion templates/terraform/env_var_context.go.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<% example.test_env_vars&.each do |var_name, var_type| -%>
<% if var_type == :ORG_ID -%>
"<%= var_name -%>": getTestOrgFromEnv(t),
<% elsif var_type == :ORG_DOMAIN -%>
"<%= var_name -%>": getTestOrgDomainFromEnv(t),
<% elsif var_type == :CREDENTIALS -%>
"<%= var_name -%>": getTestCredsFromEnv(t),
<% elsif var_type == :REGION -%>
Expand All @@ -16,4 +18,4 @@
<% elsif var_type == :FIRESTORE_PROJECT_NAME -%>
"<%= var_name -%>": getTestFirestoreProjectFromEnv(t),
<% end -%>
<% end -%>
<% end -%>
16 changes: 16 additions & 0 deletions templates/terraform/examples/iap_brand.tf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
resource "google_project" "project" {
project_id = "tf-test%{random_suffix}"
name = "tf-test%{random_suffix}"
org_id = "<%= ctx[:test_env_vars]['org_id'] %>"
}

resource "google_project_service" "project_service" {
project = google_project.project.project_id
service = "iap.googleapis.com"
}

resource "google_iap_brand" "project_brand" {
support_email = "support@<%= ctx[:test_env_vars]['org_domain'] %>"
application_title = "Cloud IAP protected Application"
project = google_project_service.project_service.project
}
21 changes: 21 additions & 0 deletions templates/terraform/examples/iap_client.tf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resource "google_project" "project" {
project_id = "tf-test%{random_suffix}"
name = "tf-test%{random_suffix}"
org_id = "<%= ctx[:test_env_vars]['org_id'] %>"
}

resource "google_project_service" "project_service" {
project = google_project.project.project_id
service = "iap.googleapis.com"
}

resource "google_iap_brand" "project_brand" {
support_email = "support@<%= ctx[:test_env_vars]['org_domain'] %>"
application_title = "Cloud IAP protected Application"
project = google_project_service.project_service.project
}

resource "google_iap_client" "project_client" {
display_name = "Test Client"
brand = google_iap_brand.project_brand.name
}
5 changes: 5 additions & 0 deletions templates/terraform/post_create/iap_client.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
brand := d.Get("brand")
clientId := flattenIapClientClientId(res["name"], d, config)

d.Set("client_id", clientId)
d.SetId(fmt.Sprintf("%s/identityAwareProxyClients/%s", brand, clientId))
55 changes: 55 additions & 0 deletions third_party/terraform/tests/resource_iap_brand_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package google

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestAccIapBrand_iapBrandExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"org_id": getTestOrgFromEnv(t),
"org_domain": getTestOrgDomainFromEnv(t),
"random_suffix": acctest.RandString(10),
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccIapBrand_iapBrandExample(context),
},
{
ResourceName: "google_iap_brand.project_brand",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"project"},
},
},
})
}

func testAccIapBrand_iapBrandExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_project" "project" {
project_id = "tf-test%{random_suffix}"
name = "tf-test%{random_suffix}"
org_id = "%{org_id}"
}
resource "google_project_service" "project_service" {
project = google_project.project.project_id
service = "iap.googleapis.com"
}
resource "google_iap_brand" "project_brand" {
support_email = "support@%{org_domain}"
application_title = "Cloud IAP protected Application"
project = google_project_service.project_service.project
}
`, context)
}
9 changes: 9 additions & 0 deletions third_party/terraform/utils/provider_test.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ var orgEnvVars = []string{
"GOOGLE_ORG",
}

var orgEnvDomainVars = []string{
"GOOGLE_ORG_DOMAIN",
}

var serviceAccountEnvVars = []string{
"GOOGLE_SERVICE_ACCOUNT",
}
Expand Down Expand Up @@ -669,6 +673,11 @@ func getTestOrgFromEnv(t *testing.T) string {
return multiEnvSearch(orgEnvVars)
}

func getTestOrgDomainFromEnv(t *testing.T) string {
skipIfEnvNotSet(t, orgEnvDomainVars...)
return multiEnvSearch(orgEnvDomainVars)
}

func getTestOrgTargetFromEnv(t *testing.T) string {
skipIfEnvNotSet(t, orgTargetEnvVars...)
return multiEnvSearch(orgTargetEnvVars)
Expand Down
6 changes: 6 additions & 0 deletions third_party/terraform/website-compiled/google.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,12 @@
<li<%%= sidebar_current("docs-google-iap") %>>
<a href="#">Google IAP Resources</a>
<ul class="nav">
<li<%%= sidebar_current("docs-google-iap-brand") %>>
<a href="/docs/providers/google/r/iap_brand.html">google_iap_brand</a>
</li>
<li<%%= sidebar_current("docs-google-iap-client") %>>
<a href="/docs/providers/google/r/iap_client.html">google_iap_client</a>
</li>
<li<%%= sidebar_current("docs-google-iap-tunnel-instance-iam") %>>
<a href="/docs/providers/google/r/iap_tunnel_instance_iam.html">google_iap_tunnel_instance_iam_binding</a>
</li>
Expand Down

0 comments on commit 93c01d4

Please sign in to comment.