diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 51d3a3e98c24..9e8a7dd5c945 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -437,6 +437,7 @@ var handwrittenResources = map[string]*schema.Resource{ "google_folder_organization_policy": resourcemanager.ResourceGoogleFolderOrganizationPolicy(), {{- if ne $.TargetVersionName "ga" }} "google_folder_service_identity": resourcemanager.ResourceFolderServiceIdentity(), + "google_organization_service_identity": resourcemanager.ResourceOrganizationServiceIdentity(), {{- end }} "google_logging_billing_account_sink": logging.ResourceLoggingBillingAccountSink(), "google_logging_billing_account_exclusion": logging.ResourceLoggingExclusion(logging.BillingAccountLoggingExclusionSchema, logging.NewBillingAccountLoggingExclusionUpdater, logging.BillingAccountLoggingExclusionIdParseFunc), diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity.go.tmpl b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity.go.tmpl new file mode 100644 index 000000000000..579af57b5dad --- /dev/null +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity.go.tmpl @@ -0,0 +1,134 @@ +{{- if ne $.TargetVersionName "ga" -}} +package resourcemanager + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-provider-google/google/services/serviceusage" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ResourceOrganizationServiceIdentity() *schema.Resource { + return &schema.Resource{ + Create: resourceOrganizationServiceIdentityCreate, + Read: resourceOrganizationServiceIdentityRead, + Delete: resourceOrganizationServiceIdentityDelete, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "organization": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "email": { + Type: schema.TypeString, + Computed: true, + }, + "member": { + Type: schema.TypeString, + Computed: true, + Description: `The Identity of the Google managed service account in the form 'serviceAccount:{email}'. This value is often used to refer to the service account in order to grant IAM permissions.`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceOrganizationServiceIdentityCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}ServiceUsageBasePath{{"}}"}}organizations/{{"{{"}}organization{{"}}"}}/services/{{"{{"}}service{{"}}"}}:generateServiceIdentity") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Timeout: d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return fmt.Errorf("Error creating Organization Service Identity: %s", err) + } + + var opRes map[string]interface{} + err = serviceusage.ServiceUsageOperationWaitTimeWithResponse( + config, res, &opRes, billingProject, "Creating Organization Service Identity", userAgent, + d.Timeout(schema.TimeoutCreate)) + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished creating Organization Service Identity %q: %#v", d.Id(), res) + + id, err := tpgresource.ReplaceVars(d, config, "organizations/{{"{{"}}organization{{"}}"}}/services/{{"{{"}}service{{"}}"}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + // This API may not return the service identity's details, even if the relevant + // Google API is configured for service identities. + if emailVal, ok := opRes["email"]; ok { + email, ok := emailVal.(string) + if !ok { + return fmt.Errorf("unexpected type for email: got %T, want string", email) + } + if err := d.Set("email", email); err != nil { + return fmt.Errorf("Error setting email: %s", err) + } + if err := d.Set("member", "serviceAccount:"+email); err != nil { + return fmt.Errorf("Error setting member: %s", err) + } + } + return nil +} + +// There is no read endpoint for this API. +func resourceOrganizationServiceIdentityRead(d *schema.ResourceData, meta interface{}) error { + return nil +} + +// There is no delete endpoint for this API. +func resourceOrganizationServiceIdentityDelete(d *schema.ResourceData, meta interface{}) error { + return nil +} +{{- end }} diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_meta.yaml.tmpl b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_meta.yaml.tmpl new file mode 100644 index 000000000000..7ca81c089321 --- /dev/null +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_meta.yaml.tmpl @@ -0,0 +1,12 @@ +{{ if ne $.TargetVersionName "ga" -}} +resource: 'google_organization_service_identity' +generation_type: 'handwritten' +api_service_name: 'serviceusage.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Service' +fields: + - field: 'email' + - field: 'member' + - field: 'organization' + - field: 'service' +{{ end }} diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_test.go.tmpl b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_test.go.tmpl new file mode 100644 index 000000000000..f158f6709fe7 --- /dev/null +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_organization_service_identity_test.go.tmpl @@ -0,0 +1,57 @@ +{{- if ne $.TargetVersionName "ga" -}} +package resourcemanager_test + +import ( + "fmt" + "strings" + "testing" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccOrganizationServiceIdentity_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix ": acctest.RandString(t, 5), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testGoogleOrganizationServiceIdentity_basic(context), + Check: resource.ComposeTestCheckFunc( + // Email field should be non-empty and contain at least an "@". + resource.TestCheckResourceAttrWith("google_organization_service_identity.osconfig_sa", "email", func(value string) error { + if strings.Contains(value, "@") { + return nil + } + return fmt.Errorf("osconfig_sa service identity email value was %s, expected a valid email", value) + }), + // Member field should start with "serviceAccount:" + resource.TestCheckResourceAttrWith("google_organization_service_identity.osconfig_sa", "member", func(value string) error { + if !strings.HasPrefix(value, "serviceAccount:") { + return fmt.Errorf("osconfig_sa organization service identity member value %q does not start with 'serviceAccount:'", value) + } + return nil + }), + ), + }, + }, + }) +} + +func testGoogleOrganizationServiceIdentity_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_organization_service_identity" "osconfig_sa" { + organization = "%{org_id}" + service = "osconfig.googleapis.com" +} +`, context) +} +{{- end }} diff --git a/mmv1/third_party/terraform/website/docs/r/organization_service_identity.html.markdown b/mmv1/third_party/terraform/website/docs/r/organization_service_identity.html.markdown new file mode 100644 index 000000000000..a024277a2170 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/r/organization_service_identity.html.markdown @@ -0,0 +1,69 @@ +--- +subcategory: "Cloud Platform" +description: |- + Generate organization service identity for a service. +--- + +# google_organization_service_identity + +Generate organization service identity for a service. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](../guides/provider_versions.html.markdown) for more details on beta resources. + +~> **Note:** Once created, this resource cannot be updated or destroyed. These +actions are a no-op. + +~> **Note:** This resource can be used to retrieve the emails of the [Google-managed organization service accounts](https://cloud.google.com/iam/docs/service-agents) +of the APIs that Google has configured with a Service Identity. You can run `gcloud beta services identity create --service SERVICE_NAME.googleapis.com --organization ORGANIZATION` to +verify if an API supports this. + +To get more information about Service Identity, see: + +* [API documentation](https://cloud.google.com/service-usage/docs/reference/rest/v1beta1/services/generateServiceIdentity) + +## Example Usage - Organization Service Identity Basic + +```hcl +resource "google_organization_service_identity" "osconfig_sa" { + provider = google-beta + organization = "123456789" + service = "osconfig.googleapis.com" +} + +resource "google_organization_iam_member" "admin" { + org_id = "123456789" + role = "roles/osconfig.serviceAgent" + member = google_organization_service_identity.osconfig_sa.member +} +``` + +## Argument Reference + +The following arguments are supported: + +* `service` - + (Required) + The service to generate identity for. + +- - - + +* `organization` - (Required) The organization in which the resource belongs. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `email` - The email address of the Google managed service account. +* `member` - The Identity of the Google managed service account in the form 'serviceAccount:{email}'. This value is often used to refer to the service account in order to grant IAM permissions. + +## Import + +This resource does not support import. + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: configuration options: + +* `create` - Default is 20 minutes.