From 239e666dca7e73ad8d837d87ab8bca37397935d9 Mon Sep 17 00:00:00 2001 From: The Magician Date: Thu, 7 Mar 2024 12:00:58 -0800 Subject: [PATCH] App Check DeviceCheck provider (#9978) (#17517) * App Check DeviceCheck provider * Remove minimal example & pattern field * Add real private keys that are not useful anywhere * Limit tests to beta [upstream:e285c09c0a21af2e5fe3721a23522331599c415e] Signed-off-by: Modular Magician --- .changelog/9978.txt | 3 + google/provider/provider_mmv1_resources.go | 5 +- ..._firebase_app_check_device_check_config.go | 379 ++++++++++++++++++ ...base_app_check_device_check_config_test.go | 3 + .../test-fixtures/private-key-2.p8 | 15 + .../test-fixtures/private-key.p8 | 15 + ...pp_check_device_check_config.html.markdown | 161 ++++++++ 7 files changed, 579 insertions(+), 2 deletions(-) create mode 100644 .changelog/9978.txt create mode 100644 google/services/firebaseappcheck/resource_firebase_app_check_device_check_config.go create mode 100644 google/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go create mode 100644 google/services/firebaseappcheck/test-fixtures/private-key-2.p8 create mode 100644 google/services/firebaseappcheck/test-fixtures/private-key.p8 create mode 100644 website/docs/r/firebase_app_check_device_check_config.html.markdown diff --git a/.changelog/9978.txt b/.changelog/9978.txt new file mode 100644 index 00000000000..0f83cc84601 --- /dev/null +++ b/.changelog/9978.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_firebase_app_check_device_check_config` +``` \ No newline at end of file diff --git a/google/provider/provider_mmv1_resources.go b/google/provider/provider_mmv1_resources.go index 947036b65b2..5baf4a7447f 100644 --- a/google/provider/provider_mmv1_resources.go +++ b/google/provider/provider_mmv1_resources.go @@ -389,9 +389,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ } // Resources -// Generated resources: 389 +// Generated resources: 390 // Generated IAM resources: 231 -// Total generated resources: 620 +// Total generated resources: 621 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -738,6 +738,7 @@ var generatedResources = map[string]*schema.Resource{ "google_filestore_snapshot": filestore.ResourceFilestoreSnapshot(), "google_firebase_app_check_app_attest_config": firebaseappcheck.ResourceFirebaseAppCheckAppAttestConfig(), "google_firebase_app_check_debug_token": firebaseappcheck.ResourceFirebaseAppCheckDebugToken(), + "google_firebase_app_check_device_check_config": firebaseappcheck.ResourceFirebaseAppCheckDeviceCheckConfig(), "google_firebase_app_check_play_integrity_config": firebaseappcheck.ResourceFirebaseAppCheckPlayIntegrityConfig(), "google_firebase_app_check_recaptcha_enterprise_config": firebaseappcheck.ResourceFirebaseAppCheckRecaptchaEnterpriseConfig(), "google_firebase_app_check_recaptcha_v3_config": firebaseappcheck.ResourceFirebaseAppCheckRecaptchaV3Config(), diff --git a/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config.go b/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config.go new file mode 100644 index 00000000000..1dd28b7b448 --- /dev/null +++ b/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config.go @@ -0,0 +1,379 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package firebaseappcheck + +import ( + "fmt" + "log" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func ResourceFirebaseAppCheckDeviceCheckConfig() *schema.Resource { + return &schema.Resource{ + Create: resourceFirebaseAppCheckDeviceCheckConfigCreate, + Read: resourceFirebaseAppCheckDeviceCheckConfigRead, + Update: resourceFirebaseAppCheckDeviceCheckConfigUpdate, + Delete: resourceFirebaseAppCheckDeviceCheckConfigDelete, + + Importer: &schema.ResourceImporter{ + State: resourceFirebaseAppCheckDeviceCheckConfigImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "app_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The ID of an +[Apple App](https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.iosApps#IosApp.FIELDS.app_id).`, + }, + "key_id": { + Type: schema.TypeString, + Required: true, + Description: `The key identifier of a private key enabled with DeviceCheck, created in your Apple Developer account.`, + }, + "private_key": { + Type: schema.TypeString, + Required: true, + Description: `The contents of the private key (.p8) file associated with the key specified by keyId.`, + Sensitive: true, + }, + "token_ttl": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Specifies the duration for which App Check tokens exchanged from DeviceCheck artifacts will be valid. +If unset, a default value of 1 hour is assumed. Must be between 30 minutes and 7 days, inclusive. + +A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The relative resource name of the DeviceCheck configuration object`, + }, + "private_key_set": { + Type: schema.TypeBool, + Computed: true, + Description: `Whether the privateKey field was previously set. Since App Check will never return the +privateKey field, this field is the only way to find out whether it was previously set.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceFirebaseAppCheckDeviceCheckConfigCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + tokenTtlProp, err := expandFirebaseAppCheckDeviceCheckConfigTokenTtl(d.Get("token_ttl"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("token_ttl"); !tpgresource.IsEmptyValue(reflect.ValueOf(tokenTtlProp)) && (ok || !reflect.DeepEqual(v, tokenTtlProp)) { + obj["tokenTtl"] = tokenTtlProp + } + keyIdProp, err := expandFirebaseAppCheckDeviceCheckConfigKeyId(d.Get("key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(keyIdProp)) && (ok || !reflect.DeepEqual(v, keyIdProp)) { + obj["keyId"] = keyIdProp + } + privateKeyProp, err := expandFirebaseAppCheckDeviceCheckConfigPrivateKey(d.Get("private_key"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("private_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(privateKeyProp)) && (ok || !reflect.DeepEqual(v, privateKeyProp)) { + obj["privateKey"] = privateKeyProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseAppCheckBasePath}}projects/{{project}}/apps/{{app_id}}/deviceCheckConfig?updateMask=tokenTtl,keyId,privateKey") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new DeviceCheckConfig: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for DeviceCheckConfig: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return fmt.Errorf("Error creating DeviceCheckConfig: %s", err) + } + if err := d.Set("name", flattenFirebaseAppCheckDeviceCheckConfigName(res["name"], d, config)); err != nil { + return fmt.Errorf(`Error setting computed identity field "name": %s`, err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/apps/{{app_id}}/deviceCheckConfig") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating DeviceCheckConfig %q: %#v", d.Id(), res) + + return resourceFirebaseAppCheckDeviceCheckConfigRead(d, meta) +} + +func resourceFirebaseAppCheckDeviceCheckConfigRead(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, "{{FirebaseAppCheckBasePath}}projects/{{project}}/apps/{{app_id}}/deviceCheckConfig") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for DeviceCheckConfig: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("FirebaseAppCheckDeviceCheckConfig %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading DeviceCheckConfig: %s", err) + } + + if err := d.Set("name", flattenFirebaseAppCheckDeviceCheckConfigName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading DeviceCheckConfig: %s", err) + } + if err := d.Set("token_ttl", flattenFirebaseAppCheckDeviceCheckConfigTokenTtl(res["tokenTtl"], d, config)); err != nil { + return fmt.Errorf("Error reading DeviceCheckConfig: %s", err) + } + if err := d.Set("key_id", flattenFirebaseAppCheckDeviceCheckConfigKeyId(res["keyId"], d, config)); err != nil { + return fmt.Errorf("Error reading DeviceCheckConfig: %s", err) + } + if err := d.Set("private_key_set", flattenFirebaseAppCheckDeviceCheckConfigPrivateKeySet(res["privateKeySet"], d, config)); err != nil { + return fmt.Errorf("Error reading DeviceCheckConfig: %s", err) + } + + return nil +} + +func resourceFirebaseAppCheckDeviceCheckConfigUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for DeviceCheckConfig: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + tokenTtlProp, err := expandFirebaseAppCheckDeviceCheckConfigTokenTtl(d.Get("token_ttl"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("token_ttl"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tokenTtlProp)) { + obj["tokenTtl"] = tokenTtlProp + } + keyIdProp, err := expandFirebaseAppCheckDeviceCheckConfigKeyId(d.Get("key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, keyIdProp)) { + obj["keyId"] = keyIdProp + } + privateKeyProp, err := expandFirebaseAppCheckDeviceCheckConfigPrivateKey(d.Get("private_key"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("private_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, privateKeyProp)) { + obj["privateKey"] = privateKeyProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseAppCheckBasePath}}projects/{{project}}/apps/{{app_id}}/deviceCheckConfig") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating DeviceCheckConfig %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("token_ttl") { + updateMask = append(updateMask, "tokenTtl") + } + + if d.HasChange("key_id") { + updateMask = append(updateMask, "keyId") + } + + if d.HasChange("private_key") { + updateMask = append(updateMask, "privateKey") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + + if err != nil { + return fmt.Errorf("Error updating DeviceCheckConfig %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating DeviceCheckConfig %q: %#v", d.Id(), res) + } + + } + + return resourceFirebaseAppCheckDeviceCheckConfigRead(d, meta) +} + +func resourceFirebaseAppCheckDeviceCheckConfigDelete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[WARNING] FirebaseAppCheck DeviceCheckConfig resources"+ + " cannot be deleted from Google Cloud. The resource %s will be removed from Terraform"+ + " state, but will still be present on Google Cloud.", d.Id()) + d.SetId("") + + return nil +} + +func resourceFirebaseAppCheckDeviceCheckConfigImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/apps/(?P[^/]+)/deviceCheckConfig$", + "^(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/apps/{{app_id}}/deviceCheckConfig") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenFirebaseAppCheckDeviceCheckConfigName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenFirebaseAppCheckDeviceCheckConfigTokenTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenFirebaseAppCheckDeviceCheckConfigKeyId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenFirebaseAppCheckDeviceCheckConfigPrivateKeySet(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandFirebaseAppCheckDeviceCheckConfigTokenTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandFirebaseAppCheckDeviceCheckConfigKeyId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandFirebaseAppCheckDeviceCheckConfigPrivateKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go b/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go new file mode 100644 index 00000000000..d75b76cbd65 --- /dev/null +++ b/google/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go @@ -0,0 +1,3 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package firebaseappcheck_test diff --git a/google/services/firebaseappcheck/test-fixtures/private-key-2.p8 b/google/services/firebaseappcheck/test-fixtures/private-key-2.p8 new file mode 100644 index 00000000000..f581bea0e05 --- /dev/null +++ b/google/services/firebaseappcheck/test-fixtures/private-key-2.p8 @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICWwIBAAKBgQCVA/2LQtUYJI8KlNHWzNPzGzVv01qavSbmuW0QYjshxRnXDBk+ +fWZePJAmsyuhU4Y2SkM5Wqvgjo/rDPaRPdTiEtKQuNesRgQeOVmAWDkIXEiieTwb +RYuXbdpZhH86Vt6xOMt14tGPKE5VuuySvTqgQRCvRTylrF3koBc0d/8NVQIDAQAB +AoGAG7qBXH+ULYjoAR0OKv00V2FxwRxAGNknuvk4HTtaK3+Evmpm7CTjfpegb0MZ +1Ew5hjKtbae8oe2FRETGQOKTkS68I/D9PGP4aTzmSkf6PjwXwhlBYp09xxv4nmxV +BCbsoicNMvdk0F7SPblnZBO9i0DpZ8pT9wyPo8QzWBfi5IECQQD8gIOja3Zim4R9 +HVL7Blvhzhl2ibuITV2PKfQ11v0a+Om+rZKwdrhxKgWoguDvvP7ExWSPTZJKSm0J +bzhU+APhAkEAlxR3fY+zSpxHaxbOqZ6cea5cZtyHcX607nW8N037yBErIjcJKL65 +gHx9Vq1Xo24o4C6kyzmh00BnkyXul4439QJAPWvtmaUcaSQ3eE/XzaRgWW9PFlyu +t5tKNPcZprcjXppKEc4bLr3SZAS616DuoqKwvqDds1ZFTbkJCRB6/YBPQQJAeyGG +JYKJyKRIHMJw2pNXymBOFNNlXB29jp/ML3LSYwODGRar01ZmT46mhI8wXxV4IQZC +7xLgjhDumWIP69tQRQJAfuOy4TP2drxNI7fP7YenV1ks6CiLHcBN04f6NItWilTN +Cc+Mv/rio9xO56Yp9oePMaFT9QEzfO/cqX6QvyfblQ== +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/google/services/firebaseappcheck/test-fixtures/private-key.p8 b/google/services/firebaseappcheck/test-fixtures/private-key.p8 new file mode 100644 index 00000000000..d48a562a97b --- /dev/null +++ b/google/services/firebaseappcheck/test-fixtures/private-key.p8 @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICXAIBAAKBgG3vDegwb8uUvns/Iuodo/cNK0eMHxqb+2n16dQnxL7az+ShNWKQ +jTSzXY5y4VexrTdPEU5ZiTPONZXyl4/iFvOnyFxnC6Zjyr+xeIU5X4TmjYq0yCuZ +xbovAWw+E4KUKt1V62avd+hGZHPtCKLfV/uYITG7I8R+GyEAdMoaXP8JAgMBAAEC +gYBsQFf7aabMWx3uks84phNNNOSHQY1nUG2Te5nTVY3BOgo44h2Ffz3sxSq9GJaZ +GdatfehWtIgMQWQ20Xk5L7LUzSxmndHbUIzYU17xZrAsgmjYTwvAQ13If2L6S+pz +EUbTLkMnlbAgvtJ2AqZZZ3LE41N9ey60gVB1cCu9fCXLuQJBANAeoDXXvh7nXdyN +Zd84zXpSk8SLmAmQn1JB7z3oPkrZ0dG42GMOzYw9MP8n2bATHV+OB0/gdUFJAYYp +kwz+bJ8CQQCHObHelAlkH3or+JVECpovNMHs2UGB6yF1ZX0Nep3iR90fhi3BsnVo +IQGdHlQC2NL+iaBF4Mv2/dfZTen1vMtXAkEAk7+KQW8+G7ZpXjBLyCMNTO/e08O+ +VdwEH2OLsslzn7PvTxIJHJnfttWiOSJTWrrXOYUdD8nrtENd/574NFtTRQJAaExD +uJ0NsT/mB0wwNM7IpWhXusrHD+G/aMDidyb/56vuDYZ8fE2c6LesevcNbTS3aMPV +7o+4QcUAWwcRUQxQ+QJBAJEAwwzFnLJtrFYEnz7YNufgjiMrX7CBJCwrXGZpZrHX +EdDDOGiLrm871hc3tNQWmzou9AFIwZFeIOXVdIHIQzk= +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/website/docs/r/firebase_app_check_device_check_config.html.markdown b/website/docs/r/firebase_app_check_device_check_config.html.markdown new file mode 100644 index 00000000000..5825fd2a099 --- /dev/null +++ b/website/docs/r/firebase_app_check_device_check_config.html.markdown @@ -0,0 +1,161 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Firebase App Check" +description: |- + An app's DeviceCheck configuration object. +--- + +# google\_firebase\_app\_check\_device\_check\_config + +An app's DeviceCheck configuration object. Note that the Team ID registered with your +app is used as part of the validation process. Make sure your `google_firebase_apple_app` has a team_id present. + + +To get more information about DeviceCheckConfig, see: + +* [API documentation](https://firebase.google.com/docs/reference/appcheck/rest/v1/projects.apps.deviceCheckConfig) +* How-to Guides + * [Official Documentation](https://firebase.google.com/docs/app-check) + +~> **Warning:** All arguments including the following potentially sensitive +values will be stored in the raw state as plain text: `private_key`. +[Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data). + +## Example Usage - Firebase App Check Device Check Config Full + + +```hcl +resource "google_firebase_apple_app" "default" { + provider = google-beta + + project = "my-project-name" + display_name = "Apple app" + bundle_id = "bundle.id.devicecheck" + team_id = "9987654321" +} + +# It takes a while for App Check to recognize the new app +# If your app already exists, you don't have to wait 30 seconds. +resource "time_sleep" "wait_30s" { + depends_on = [google_firebase_apple_app.default] + create_duration = "30s" +} + +resource "google_firebase_app_check_device_check_config" "default" { + provider = google-beta + + project = "my-project-name" + app_id = google_firebase_apple_app.default.app_id + token_ttl = "7200s" + key_id = "Key ID" + private_key = file("path/to/private-key.p8") + + depends_on = [time_sleep.wait_30s] + + lifecycle { + precondition { + condition = google_firebase_apple_app.default.team_id != "" + error_message = "Provide a Team ID on the Apple App to use App Check" + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `key_id` - + (Required) + The key identifier of a private key enabled with DeviceCheck, created in your Apple Developer account. + +* `private_key` - + (Required) + The contents of the private key (.p8) file associated with the key specified by keyId. + **Note**: This property is sensitive and will not be displayed in the plan. + +* `app_id` - + (Required) + The ID of an + [Apple App](https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.iosApps#IosApp.FIELDS.app_id). + + +- - - + + +* `token_ttl` - + (Optional) + Specifies the duration for which App Check tokens exchanged from DeviceCheck artifacts will be valid. + If unset, a default value of 1 hour is assumed. Must be between 30 minutes and 7 days, inclusive. + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s". + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/apps/{{app_id}}/deviceCheckConfig` + +* `name` - + The relative resource name of the DeviceCheck configuration object + +* `private_key_set` - + Whether the privateKey field was previously set. Since App Check will never return the + privateKey field, this field is the only way to find out whether it was previously set. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +DeviceCheckConfig can be imported using any of these accepted formats: + +* `projects/{{project}}/apps/{{app_id}}/deviceCheckConfig` +* `{{project}}/{{app_id}}` +* `{{app_id}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DeviceCheckConfig using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/apps/{{app_id}}/deviceCheckConfig" + to = google_firebase_app_check_device_check_config.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), DeviceCheckConfig can be imported using one of the formats above. For example: + +``` +$ terraform import google_firebase_app_check_device_check_config.default projects/{{project}}/apps/{{app_id}}/deviceCheckConfig +$ terraform import google_firebase_app_check_device_check_config.default {{project}}/{{app_id}} +$ terraform import google_firebase_app_check_device_check_config.default {{app_id}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).