From a1148dcb796db0e047fab565d7154cb6299b3ea7 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Wed, 14 Jan 2026 22:19:07 +0000 Subject: [PATCH] Adding serviceAccountAuthConfig to google_dialogflow_cx_webhook; (#16083) [upstream:3e5b319874394530c83b2ef137790fcb89389909] Signed-off-by: Modular Magician --- .changelog/16083.txt | 3 + .../resource_dialogflow_cx_webhook.go | 146 ++++++++++++++++++ ..._dialogflow_cx_webhook_generated_meta.yaml | 2 + ...ce_dialogflow_cx_webhook_generated_test.go | 119 ++++++++++++++ .../r/dialogflow_cx_webhook.html.markdown | 99 ++++++++++++ 5 files changed, 369 insertions(+) create mode 100644 .changelog/16083.txt diff --git a/.changelog/16083.txt b/.changelog/16083.txt new file mode 100644 index 00000000000..78bd4431b90 --- /dev/null +++ b/.changelog/16083.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dialogflowcx: added `serviceAccountAuthConfig ` field to `google_dialogflow_cx_webhook` resource +``` \ No newline at end of file diff --git a/google/services/dialogflowcx/resource_dialogflow_cx_webhook.go b/google/services/dialogflowcx/resource_dialogflow_cx_webhook.go index 909c96cceb5..20bd2589464 100644 --- a/google/services/dialogflowcx/resource_dialogflow_cx_webhook.go +++ b/google/services/dialogflowcx/resource_dialogflow_cx_webhook.go @@ -257,6 +257,27 @@ Format: 'projects/{project}/secrets/{secret}/versions/{version}'`, }, }, }, + "service_account_auth_config": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration for authentication using a service account.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service_account": { + Type: schema.TypeString, + Required: true, + Description: `The email address of the service account used to authenticate the webhook call. +Dialogflow uses this service account to exchange an access token and the access +token is then sent in the **Authorization** header of the webhook request. + +The service account must have the **roles/iam.serviceAccountTokenCreator** role +granted to the +[Dialogflow service agent](https://cloud.google.com/iam/docs/service-agents?_gl=1*1jsujvh*_ga*NjYxMzU3OTg2LjE3Njc3MzQ4NjM.*_ga_WH2QY8WWF5*czE3Njc3MzQ2MjgkbzIkZzEkdDE3Njc3MzQ3NzQkajYwJGwwJGgw#dialogflow-service-agent).`, + }, + }, + }, + }, "service_agent_auth": { Type: schema.TypeString, Optional: true, @@ -431,6 +452,27 @@ Format: 'projects/{project}/secrets/{secret}/versions/{version}'`, }, }, }, + "service_account_auth_config": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration for authentication using a service account.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service_account": { + Type: schema.TypeString, + Required: true, + Description: `The email address of the service account used to authenticate the webhook call. +Dialogflow uses this service account to exchange an access token and the access +token is then sent in the **Authorization** header of the webhook request. + +The service account must have the **roles/iam.serviceAccountTokenCreator** role +granted to the +[Dialogflow service agent](https://cloud.google.com/iam/docs/service-agents?_gl=1*1jsujvh*_ga*NjYxMzU3OTg2LjE3Njc3MzQ4NjM.*_ga_WH2QY8WWF5*czE3Njc3MzQ2MjgkbzIkZzEkdDE3Njc3MzQ3NzQkajYwJGwwJGgw#dialogflow-service-agent).`, + }, + }, + }, + }, "service_agent_auth": { Type: schema.TypeString, Optional: true, @@ -965,6 +1007,8 @@ func flattenDialogflowCXWebhookGenericWebService(v interface{}, d *schema.Resour flattenDialogflowCXWebhookGenericWebServiceSecretVersionsForRequestHeaders(original["secretVersionsForRequestHeaders"], d, config) transformed["service_agent_auth"] = flattenDialogflowCXWebhookGenericWebServiceServiceAgentAuth(original["serviceAgentAuth"], d, config) + transformed["service_account_auth_config"] = + flattenDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfig(original["serviceAccountAuthConfig"], d, config) transformed["uri"] = flattenDialogflowCXWebhookGenericWebServiceUri(original["uri"], d, config) transformed["webhook_type"] = @@ -1059,6 +1103,23 @@ func flattenDialogflowCXWebhookGenericWebServiceServiceAgentAuth(v interface{}, return v } +func flattenDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["service_account"] = + flattenDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfigServiceAccount(original["serviceAccount"], d, config) + return []interface{}{transformed} +} +func flattenDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfigServiceAccount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenDialogflowCXWebhookGenericWebServiceUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -1113,6 +1174,8 @@ func flattenDialogflowCXWebhookServiceDirectoryGenericWebService(v interface{}, flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaders(original["secretVersionsForRequestHeaders"], d, config) transformed["service_agent_auth"] = flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAgentAuth(original["serviceAgentAuth"], d, config) + transformed["service_account_auth_config"] = + flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfig(original["serviceAccountAuthConfig"], d, config) transformed["uri"] = flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceUri(original["uri"], d, config) transformed["webhook_type"] = @@ -1207,6 +1270,23 @@ func flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAgentAuth return v } +func flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["service_account"] = + flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfigServiceAccount(original["serviceAccount"], d, config) + return []interface{}{transformed} +} +func flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfigServiceAccount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenDialogflowCXWebhookServiceDirectoryGenericWebServiceUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -1318,6 +1398,13 @@ func expandDialogflowCXWebhookGenericWebService(v interface{}, d tpgresource.Ter transformed["serviceAgentAuth"] = transformedServiceAgentAuth } + transformedServiceAccountAuthConfig, err := expandDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfig(original["service_account_auth_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccountAuthConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccountAuthConfig"] = transformedServiceAccountAuthConfig + } + transformedUri, err := expandDialogflowCXWebhookGenericWebServiceUri(original["uri"], d, config) if err != nil { return nil, err @@ -1476,6 +1563,32 @@ func expandDialogflowCXWebhookGenericWebServiceServiceAgentAuth(v interface{}, d return v, nil } +func expandDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedServiceAccount, err := expandDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfigServiceAccount(original["service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccount"] = transformedServiceAccount + } + + return transformed, nil +} + +func expandDialogflowCXWebhookGenericWebServiceServiceAccountAuthConfigServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandDialogflowCXWebhookGenericWebServiceUri(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } @@ -1592,6 +1705,13 @@ func expandDialogflowCXWebhookServiceDirectoryGenericWebService(v interface{}, d transformed["serviceAgentAuth"] = transformedServiceAgentAuth } + transformedServiceAccountAuthConfig, err := expandDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfig(original["service_account_auth_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccountAuthConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccountAuthConfig"] = transformedServiceAccountAuthConfig + } + transformedUri, err := expandDialogflowCXWebhookServiceDirectoryGenericWebServiceUri(original["uri"], d, config) if err != nil { return nil, err @@ -1750,6 +1870,32 @@ func expandDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAgentAuth( return v, nil } +func expandDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedServiceAccount, err := expandDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfigServiceAccount(original["service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccount"] = transformedServiceAccount + } + + return transformed, nil +} + +func expandDialogflowCXWebhookServiceDirectoryGenericWebServiceServiceAccountAuthConfigServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandDialogflowCXWebhookServiceDirectoryGenericWebServiceUri(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_meta.yaml b/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_meta.yaml index 2bdd5ccb7fe..d42649a187c 100644 --- a/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_meta.yaml +++ b/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_meta.yaml @@ -24,6 +24,7 @@ fields: field: generic_web_service.secret_versions_for_request_headers.key - api_field: genericWebService.secretVersionsForRequestHeaders.value.secretVersion field: generic_web_service.secret_versions_for_request_headers.secret_version + - api_field: genericWebService.serviceAccountAuthConfig.serviceAccount - api_field: genericWebService.serviceAgentAuth - api_field: genericWebService.uri - api_field: genericWebService.webhookType @@ -46,6 +47,7 @@ fields: field: service_directory.generic_web_service.secret_versions_for_request_headers.key - api_field: serviceDirectory.genericWebService.secretVersionsForRequestHeaders.value.secretVersion field: service_directory.generic_web_service.secret_versions_for_request_headers.secret_version + - api_field: serviceDirectory.genericWebService.serviceAccountAuthConfig.serviceAccount - api_field: serviceDirectory.genericWebService.serviceAgentAuth - api_field: serviceDirectory.genericWebService.uri - api_field: serviceDirectory.genericWebService.webhookType diff --git a/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_test.go b/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_test.go index ba157c1163a..f1a82bc13a6 100644 --- a/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_test.go +++ b/google/services/dialogflowcx/resource_dialogflow_cx_webhook_generated_test.go @@ -328,6 +328,125 @@ resource "google_dialogflow_cx_webhook" "flexible_webhook" { `, context) } +func TestAccDialogflowCXWebhook_dialogflowcxWebhookWithServiceAccountAuthExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "service_account": envvar.GetTestServiceAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDialogflowCXWebhookDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDialogflowCXWebhook_dialogflowcxWebhookWithServiceAccountAuthExample(context), + }, + { + ResourceName: "google_dialogflow_cx_webhook.webhook_use_service_account", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"generic_web_service.0.oauth_config.0.client_secret", "parent", "service_directory.0.generic_web_service.0.oauth_config.0.client_secret"}, + }, + }, + }) +} + +func testAccDialogflowCXWebhook_dialogflowcxWebhookWithServiceAccountAuthExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_dialogflow_cx_agent" "agent" { + display_name = "tf-test-dialogflowcx-agent%{random_suffix}" + location = "global" + default_language_code = "en" + supported_language_codes = ["it","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} + + +resource "google_dialogflow_cx_webhook" "webhook_use_service_account" { + parent = google_dialogflow_cx_agent.agent.id + display_name = "MyWebhook" + generic_web_service { + uri = "https://example.googleapis.com" + webhook_type = "STANDARD" + service_account_auth_config { + service_account = "%{service_account}" + } + } +} +`, context) +} + +func TestAccDialogflowCXWebhook_dialogflowcxWebhookServiceDirectoryWithServiceAccountAuthExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "service_account": envvar.GetTestServiceAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDialogflowCXWebhookDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDialogflowCXWebhook_dialogflowcxWebhookServiceDirectoryWithServiceAccountAuthExample(context), + }, + { + ResourceName: "google_dialogflow_cx_webhook.webhook_use_service_account", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"generic_web_service.0.oauth_config.0.client_secret", "parent", "service_directory.0.generic_web_service.0.oauth_config.0.client_secret"}, + }, + }, + }) +} + +func testAccDialogflowCXWebhook_dialogflowcxWebhookServiceDirectoryWithServiceAccountAuthExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_dialogflow_cx_agent" "agent" { + display_name = "tf-test-dialogflowcx-agent%{random_suffix}" + location = "us-central1" + default_language_code = "en" + supported_language_codes = ["it","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} + + +resource "google_dialogflow_cx_webhook" "webhook_use_service_account" { + parent = google_dialogflow_cx_agent.agent.id + display_name = "MyWebhook" + service_directory { + service = "projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service" + generic_web_service { + uri = "https://example.googleapis.com" + webhook_type = "STANDARD" + service_account_auth_config { + service_account = "%{service_account}" + } + } + } +} +`, context) +} + func testAccCheckDialogflowCXWebhookDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/website/docs/r/dialogflow_cx_webhook.html.markdown b/website/docs/r/dialogflow_cx_webhook.html.markdown index beca54d23f0..2c8ca6e71ee 100644 --- a/website/docs/r/dialogflow_cx_webhook.html.markdown +++ b/website/docs/r/dialogflow_cx_webhook.html.markdown @@ -228,6 +228,73 @@ resource "google_dialogflow_cx_webhook" "flexible_webhook" { } } ``` +## Example Usage - Dialogflowcx Webhook With Service Account Auth + + +```hcl +resource "google_dialogflow_cx_agent" "agent" { + display_name = "dialogflowcx-agent" + location = "global" + default_language_code = "en" + supported_language_codes = ["it","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} + + +resource "google_dialogflow_cx_webhook" "webhook_use_service_account" { + parent = google_dialogflow_cx_agent.agent.id + display_name = "MyWebhook" + generic_web_service { + uri = "https://example.googleapis.com" + webhook_type = "STANDARD" + service_account_auth_config { + service_account = "my@service-account.com" + } + } +} +``` +## Example Usage - Dialogflowcx Webhook Service Directory With Service Account Auth + + +```hcl +resource "google_dialogflow_cx_agent" "agent" { + display_name = "dialogflowcx-agent" + location = "us-central1" + default_language_code = "en" + supported_language_codes = ["it","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} + + +resource "google_dialogflow_cx_webhook" "webhook_use_service_account" { + parent = google_dialogflow_cx_agent.agent.id + display_name = "MyWebhook" + service_directory { + service = "projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service" + generic_web_service { + uri = "https://example.googleapis.com" + webhook_type = "STANDARD" + service_account_auth_config { + service_account = "my@service-account.com" + } + } + } +} +``` ## Argument Reference @@ -341,6 +408,11 @@ The following arguments are supported: The generated token is sent in the Authorization header. Possible values are: `NONE`, `ID_TOKEN`, `ACCESS_TOKEN`. +* `service_account_auth_config` - + (Optional) + Configuration for authentication using a service account. + Structure is [documented below](#nested_generic_web_service_service_account_auth_config). + * `uri` - (Required) The webhook URI for receiving POST requests. It must use https protocol. @@ -388,6 +460,17 @@ The following arguments are supported: The SecretManager secret version resource storing the header value. Format: `projects/{project}/secrets/{secret}/versions/{version}` +The `service_account_auth_config` block supports: + +* `service_account` - + (Required) + The email address of the service account used to authenticate the webhook call. + Dialogflow uses this service account to exchange an access token and the access + token is then sent in the **Authorization** header of the webhook request. + The service account must have the **roles/iam.serviceAccountTokenCreator** role + granted to the + [Dialogflow service agent](https://cloud.google.com/iam/docs/service-agents?_gl=1*1jsujvh*_ga*NjYxMzU3OTg2LjE3Njc3MzQ4NjM.*_ga_WH2QY8WWF5*czE3Njc3MzQ2MjgkbzIkZzEkdDE3Njc3MzQ3NzQkajYwJGwwJGgw#dialogflow-service-agent). + The `service_directory` block supports: * `service` - @@ -465,6 +548,11 @@ The following arguments are supported: The generated token is sent in the Authorization header. Possible values are: `NONE`, `ID_TOKEN`, `ACCESS_TOKEN`. +* `service_account_auth_config` - + (Optional) + Configuration for authentication using a service account. + Structure is [documented below](#nested_service_directory_generic_web_service_service_account_auth_config). + * `uri` - (Required) The webhook URI for receiving POST requests. It must use https protocol. @@ -512,6 +600,17 @@ The following arguments are supported: The SecretManager secret version resource storing the header value. Format: `projects/{project}/secrets/{secret}/versions/{version}` +The `service_account_auth_config` block supports: + +* `service_account` - + (Required) + The email address of the service account used to authenticate the webhook call. + Dialogflow uses this service account to exchange an access token and the access + token is then sent in the **Authorization** header of the webhook request. + The service account must have the **roles/iam.serviceAccountTokenCreator** role + granted to the + [Dialogflow service agent](https://cloud.google.com/iam/docs/service-agents?_gl=1*1jsujvh*_ga*NjYxMzU3OTg2LjE3Njc3MzQ4NjM.*_ga_WH2QY8WWF5*czE3Njc3MzQ2MjgkbzIkZzEkdDE3Njc3MzQ3NzQkajYwJGwwJGgw#dialogflow-service-agent). + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: