diff --git a/google/data_source_google_client_openid_userinfo.go b/google/data_source_google_client_openid_userinfo.go new file mode 100644 index 00000000000..16ae672398c --- /dev/null +++ b/google/data_source_google_client_openid_userinfo.go @@ -0,0 +1,36 @@ +package google + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceGoogleClientOpenIDUserinfo() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleClientOpenIDUserinfoRead, + Schema: map[string]*schema.Schema{ + "email": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGoogleClientOpenIDUserinfoRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + // See https://github.com/golang/oauth2/issues/306 for a recommendation to do this from a Go maintainer + // URL retrieved from https://accounts.google.com/.well-known/openid-configuration + res, err := sendRequest(config, "GET", "https://openidconnect.googleapis.com/v1/userinfo", nil) + if err != nil { + return fmt.Errorf("error retrieving userinfo for your provider credentials; have you enabled the 'https://www.googleapis.com/auth/userinfo.email' scope? error: %s", err) + } + + d.SetId(time.Now().UTC().String()) + d.Set("email", res["email"]) + + return nil +} diff --git a/google/data_source_google_client_openid_userinfo_test.go b/google/data_source_google_client_openid_userinfo_test.go new file mode 100644 index 00000000000..2883f7be053 --- /dev/null +++ b/google/data_source_google_client_openid_userinfo_test.go @@ -0,0 +1,46 @@ +package google + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceGoogleClientOpenIDUserinfo_basic(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGoogleClientOpenIDUserinfo_basic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_client_openid_userinfo.me", "email"), + ), + }, + }, + }) +} + +const testAccCheckGoogleClientOpenIDUserinfo_basic = ` +provider "google" { + alias = "google-scoped" + + # We need to add an additional scope to test this; because our tests rely on + # every env var being set, we can just add an alias with the appropriate + # scopes. This will fail if someone uses an access token instead of creds + # unless they've configured the userinfo.email scope. + scopes = [ + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/ndev.clouddns.readwrite", + "https://www.googleapis.com/auth/devstorage.full_control", + "https://www.googleapis.com/auth/userinfo.email", + ] +} + +data "google_client_openid_userinfo" "me" { + provider = "google.google-scoped" +} +` diff --git a/google/provider.go b/google/provider.go index a54845dcdef..3d79e9c1087 100644 --- a/google/provider.go +++ b/google/provider.go @@ -81,6 +81,7 @@ func Provider() terraform.ResourceProvider { "google_billing_account": dataSourceGoogleBillingAccount(), "google_dns_managed_zone": dataSourceDnsManagedZone(), "google_client_config": dataSourceGoogleClientConfig(), + "google_client_openid_userinfo": dataSourceGoogleClientOpenIDUserinfo(), "google_cloudfunctions_function": dataSourceGoogleCloudFunctionsFunction(), "google_compute_address": dataSourceGoogleComputeAddress(), "google_compute_backend_service": dataSourceGoogleComputeBackendService(), diff --git a/website/docs/d/datasource_google_client_openid_userinfo.html.markdown b/website/docs/d/datasource_google_client_openid_userinfo.html.markdown new file mode 100644 index 00000000000..ff3ec08703e --- /dev/null +++ b/website/docs/d/datasource_google_client_openid_userinfo.html.markdown @@ -0,0 +1,100 @@ +--- +layout: "google" +page_title: "Google: google_client_openid_userinfo" +sidebar_current: "docs-google-datasource-client-openid-userinfo" +description: |- + Get OpenID userinfo about the credentials used with the Google provider, specifically the email. +--- + +# google\_client\_openid\_userinfo + +Get OpenID userinfo about the credentials used with the Google provider, +specifically the email. + +When the `https://www.googleapis.com/auth/userinfo.email` scope is enabled in +your provider block, this datasource enables you to export the email of the +account you've authenticated the provider with; this can be used alongside +`data.google_client_config`'s `access_token` to perform OpenID Connect +authentication with GKE and configure an RBAC role for the email used. + +~> This resource will only work as expected if the provider is configured to +use the `https://www.googleapis.com/auth/userinfo.email` scope! You will +receive an error otherwise. + +## Example Usage - exporting an email + +```hcl +provider "google" { + scopes = [ + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/ndev.clouddns.readwrite", + "https://www.googleapis.com/auth/devstorage.full_control", + "https://www.googleapis.com/auth/userinfo.email", + ] +} + +data "google_client_openid_userinfo" "me" {} + +output "my-email" { + value = "${data.google_client_openid_useremail.me.email}" +} +``` + +## Example Usage - OpenID Connect w/ Kubernetes provider + RBAC IAM role + +```hcl +provider "google" { + scopes = [ + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/ndev.clouddns.readwrite", + "https://www.googleapis.com/auth/devstorage.full_control", + "https://www.googleapis.com/auth/userinfo.email", + ] +} + +data "google_client_openid_userinfo" "provider_identity" {} + +data "google_client_config" "provider" {} + +data "google_container_cluster" "my_cluster" { + name = "my-cluster" + zone = "us-east1-a" +} + +provider "kubernetes" { + load_config_file = false + + host = "https://${data.google_container_cluster.my_cluster.endpoint}" + token = "${data.google_client_config.provider.access_token}" + cluster_ca_certificate = "${base64decode(data.google_container_cluster.my_cluster.master_auth.0.cluster_ca_certificate)}" +} + +resource "kubernetes_cluster_role_binding" "user" { + metadata { + name = "provider-user-admin" + } + + role_ref { + api_group = "rbac.authorization.k8s.io" + kind = "ClusterRole" + name = "cluster-admin" + } + + subject { + kind = "User" + name = "${data.google_client_openid_useremail.provider_identity.email}" + } +} +``` + +## Argument Reference + +There are no arguments available for this data source. + +## Attributes Reference + +The following attributes are exported: + +* `email` - The email of the account used by the provider to authenticate with GCP. diff --git a/website/google.erb b/website/google.erb index 36356f00ffd..a0db3dabd49 100644 --- a/website/google.erb +++ b/website/google.erb @@ -39,6 +39,9 @@ > google_client_config + > + google_client_openid_userinfo + > google_cloudfunctions_function