You can update a Google Cloud project from TrendAI Cloud One File Storage Security
(C1FSS) to TrendAI Vision One™ File Security Storage (V1FSS) using the TrendAI Vision One console and the Google
Cloud console. This topic covers the preparation, settings, and behavior changes that
apply to both update paths.
NoteThree parts of this update have no console page on either side. Cloud Storage notification
configurations are not shown anywhere in the Google Cloud console, the V1FSS deployment
package must be applied with Terraform from a shell, and the promote and quarantine
destinations are set in that package's
main.tf file rather than in either console. Expect to work in Cloud Shell alongside both
consoles. |
Choose an update path
Two update paths are available. Both do the same work; they differ only in the order
of two actions: turning on V1FSS scanning, and removing the C1FSS bucket notification.
Update paths
|
Path
|
Order
|
Result
|
|
Zero downtime
|
Turn on V1FSS first, remove C1FSS after
|
An overlap where both products scan every new object
|
|
Brief downtime
|
Remove C1FSS first, turn on V1FSS after
|
A gap where neither product scans
|
-
Zero downtime: Choose this path if scanning must not be interrupted. Be aware that during the interval before C1FSS scanning stops, every new object is scanned by both C1FSS and V1FSS. If the promote-or-quarantine plugin is in use and you carry its settings over to V1FSS, both products also move the same objects, which can cause race conditions. These lead to inconsistent object metadata, an inconsistent file state (one product moves an object while the other is still reading it), or duplicate processing (both products attempt the same move, and whichever one wins deletes the source while the other logs a failure).
-
Brief downtime: Choose this path if you can tolerate a short interruption of scanning. Scanning pauses only between removing the C1FSS bucket notification and turning on scanning in the TrendAI Vision One console, which is typically a few minutes. This path has the least chance of problems during the update, and is the better choice if you use the promote-or-quarantine plugin.
Before you begin
Work through all six checks below before you change anything. They apply to both update
paths.
-
Confirm that V1FSS can replace your C1FSS layout.Two C1FSS layouts have no V1FSS equivalent. Check both before you plan anything else.
Supported C1FSS layouts
C1FSS layoutUpdate supported?All-in-One (scanner stack and storage stack together)YesScanner stack only, or storage stack only, in the same projectYesSeveral storage stacks in one projectYes. They collapse into one V1FSS stack.Cross-project, with buckets in one project and the scanner in anotherNoMulti-region or dual-region bucketsNo. V1FSS for GCP protects single-region buckets only.
Important
A cross-project layout changes your whole plan. Every V1FSS resource is scoped to a single project, and a bucket can only be served by a scanner in its own project. If C1FSS runs hub-and-spoke, you need one V1FSS deployment for each project that holds buckets, and the hub scanner project goes away. Check the Cloud One console to confirm whether your current setup is cross-project, and if it is, plan the per-project split before you change anything. -
Check whether you use the promote-or-quarantine plugin.C1FSS can move clean or malicious objects to other buckets, but only through a separate plugin deployed once per scanning bucket. V1FSS has this capability built in, but the settings do not carry across automatically, and one default differs in a way that changes where your files land. The plugin is also not part of any C1FSS stack, so nothing else in this update finds or removes it.Run the following in Cloud Shell.
gcloud functions list --filter="name~promote-and-quarantine" --format="value(name,region)"
If the command returns anything, read Update promote and quarantine settings before you start, and record the plugin settings now. You need them before you install V1FSS, not after. -
Record what C1FSS protects, and how. Do this first, before you make any changes.The C1FSS Bucket Listener is a Cloud Functions (1st gen) function with a
google.storage.object.finalizetrigger. Cloud Functions creates a notification configuration on your bucket to deliver those events, and that notification configuration is what you remove at cutover. Record its details now: they are your baseline for confirming that C1FSS has stopped scanning, and for confirming that it comes back correctly if you roll back. Some of this information becomes unreadable once the C1FSS stacks are gone.-
In the Cloud One console, go to and note each stack's name, type (scanner, storage, or All-in-One), and region.
-
In Cloud Shell, run the following to find the bucket that each Bucket Listener protects, along with everything else you need for cutover.
OUTFILE="c1fss-inventory-$(date +%Y%m%d).csv" echo "function,region,bucket,c1_notification_id,c1_notification_topic,object_finalize_count" > "$OUTFILE" gcloud functions list --filter="name~bucket-listener" --format=json </dev/null \ | jq -r '.[] | (.name | split("/")) | "\(.[5]),\(.[3])"' \ | while IFS=, read -r fn region; do bucket=$(gcloud functions describe "$fn" --region="$region" \ --format="value(eventTrigger.resource)" </dev/null | sed 's#.*/buckets/##') if [ -z "$bucket" ]; then echo "$fn,$region,,MISSING,MISSING,0" >> "$OUTFILE" continue fi notifs=$(gcloud storage buckets notifications list "gs://$bucket" --format=json </dev/null 2>/dev/null) id=$(echo "$notifs" | jq -r '[.[]."Notification Configuration" | select(.topic | test("cloud-functions-"))][0].id // "MISSING"') topic=$(echo "$notifs" | jq -r '[.[]."Notification Configuration" | select(.topic | test("cloud-functions-"))][0].topic // "MISSING"') count=$(echo "$notifs" | jq '[.[]."Notification Configuration" | select(.event_types == null or any(.event_types[]; . == "OBJECT_FINALIZE"))] | length') echo "$fn,$region,$bucket,$id,$topic,$count" >> "$OUTFILE" done column -s, -t "$OUTFILE" echo "Saved to: $(pwd)/$OUTFILE" -
Download the CSV file from Cloud Shell and save it somewhere accessible, alongside the Cloud One stack names and regions from the first step. A text file or a ticket comment is enough.
Between the CSV file and the stack list you have everything the update needs: which function protects which bucket, the region to select when you generate the deployment package, the C1FSS notificationidandtopicto delete at cutover and confirm on rollback, the function name to redeploy for rollback and delete at teardown, and theOBJECT_FINALIZEcount that is your baseline for the sixth check below.
Note
If a bucket has no notification configuration pointing at a Cloud Functions topic, C1FSS is not scanning it. Leave that bucket out of the update. -
-
Identify which C1FSS generation you have.C1FSS shipped two GCP deployment mechanisms, and teardown differs between them. Run the following in Cloud Shell.
gcloud deployment-manager deployments list
C1FSS deployment generations
ResultGenerationTeardown commandDeployments named<prefix>-scanneror<prefix>-storageDeployment Managergcloud deployment-manager deployments deleteNo deployments listedTerraformterraform destroy, run in the directory you were told to keep -
Confirm that you have the required permissions and tools.
-
Permissions on the Google Cloud project: For the full list, see Google Cloud required permissions.
-
Terraform in Cloud Shell: Cloud Shell provides
gcloud,gsutil, andjq, but it no longer preinstalls Terraform. Install Terraform yourself, becausedeploy.shdoes not run without it.

Note
Step 1 of either update path runs./deploy.sh precheck. That command is a Terraform plan, which shows you what would be created. It is not a permissions check, so confirm your permissions separately. -
-
Check the notification slots on each bucket. This check applies to GCP only.A bucket can hold at most 10 notification configurations for a single event type. C1FSS uses one, and V1FSS needs one more. If a bucket already has 9 or more
OBJECT_FINALIZEconfigurations, turning it on in V1FSS fails silently: TrendAI Vision One logs the failure internally and continues, and the bucket stays unprotected with no error in the console.for b in <bucket-1> <bucket-2>; do n=$(gcloud storage buckets notifications list "gs://$b" 2>/dev/null | grep -c 'OBJECT_FINALIZE' || true) echo "$b: $n OBJECT_FINALIZE notification(s)" done
Any bucket at 9 or above needs a slot freed before you turn it on.
Update promote and quarantine settings
Skip this section if
gcloud functions list --filter="name~promote-and-quarantine" returns nothing. Without the plugin, C1FSS only wrote object metadata, and V1FSS
does the same.In C1FSS, promote and quarantine were a separate plugin deployed once per scanning
bucket, with its own Terraform state. In V1FSS they are built into the post-scan action
service and configured on the
module "file-storage-security" block in the deployment package's main.tf file. V1FSS ships with the destinations empty, which tags objects in place, so you
set them in the package before you install.Record the plugin settings first
Every plugin instance names its resources with a shared 10-character suffix, which
is visible in the function name. Run the following in Cloud Shell to list each instance
and its region.
gcloud functions list --filter="name~promote-and-quarantine" --format=json </dev/null \
| jq -r '.[] | (.name | split("/")) | "\(.[5])\t\(.[3])"' | column -t
The plugin's whole configuration is four environment variables. In the Google Cloud
console, go to , or run the following.
gcloud functions describe <plugin-function-name> --format="value(environmentVariables)"
Plugin settings to record
|
Setting
|
What it means
|
PROMOTE_STORAGE_BUCKET |
Destination for clean objects. An empty value means promote was turned off.
|
PROMOTE_MODE |
move, which deletes the source object, or copy, which leaves it |
QUARANTINE_STORAGE_BUCKET |
Destination for malicious objects. An empty value means quarantine was turned off.
|
QUARANTINE_MODE |
move or copy |
There is no failure or isolation destination. The plugin only ever acted on clean
and malicious results. Also note which bucket each instance acts on: it is the scanning
bucket of the C1FSS storage stack the plugin was deployed alongside, which you can
match by the scan-result Pub/Sub topic the plugin is triggered from.
Set the values in main.tf
Open
main.tf in the unzipped package. Cloud Shell includes an editor, which you open with cloudshell edit main.tf. Find the module "file-storage-security" block and set the following three values.-
Where objects go. Each destination is a JSON string, resolved in the order custom, then regional, then global.
# If every protected bucket used the same destination: clean_bucket = jsonencode({ global = "my-clean-bucket" }) quarantine_bucket = jsonencode({ global = "my-quarantine-bucket" }) # If destinations differed per source bucket: quarantine_bucket = jsonencode({ custom = { "source-bucket-1" = { destBucket = "quarantine-bucket-1", destRegion = "us-east1" } "source-bucket-2" = { destBucket = "quarantine-bucket-2", destRegion = "us-west1" } } }) # Or per region, keyed by region name, with an optional global fallback: quarantine_bucket = jsonencode({ "us-east1" = "quarantine-use1", global = "quarantine-fallback" })Leave a variable asjsonencode({})if that action was turned off. Those objects are tagged in place, exactly as before.
Important
Useglobalonly if every bucket you are protecting had a plugin for that action. Aglobalvalue applies to all of them, including buckets that never had a plugin, and those buckets were only tagged under C1FSS. If you give them a destination, V1FSS starts moving their objects. If only some buckets had a plugin, use thecustomform, which affects only the source buckets you list. -
Where objects land inside the destination. You must change this value.
use_source_bucket_as_folder = false
The package ships withtrue, which is the correct default for a new deployment but not for an update.Destination paths
ConfigurationPath your objects land atC1FSS plugin<destination>/<object>V1FSS withfalse<destination>/<object>, the same as C1FSSV1FSS withtrue<destination>/<source-bucket>/<object>, which is differentIf anything reads your quarantined or promoted objects by path,truebreaks it at cutover. Note the trade-off that the setting exists for: withfalse, two source buckets that hold an object of the same name overwrite each other in the destination. C1FSS behaved the same way, sofalsematches your current behavior. If that was only safe because each plugin instance had its own destination bucket, keep that arrangement with thecustomform rather than collapsing to oneglobaldestination. -
Leave the failure destination empty, to match C1FSS.
failure_bucket = jsonencode({})The C1FSS plugin had no failure destination, so objects whose scan failed stayed where they were. V1FSS can move them somewhere instead, which is a new capability but not your current behavior.
For more information about destination buckets in V1FSS, see Customized destination buckets in GCP.
Two behaviors that cannot be carried over
-
Copy mode. If
PROMOTE_MODEorQUARANTINE_MODEwascopy, the plugin left the original object in place. V1FSS always moves the object: it copies the object to the destination and then deletes the original. Make sure nothing depends on the original staying in the source bucket. -
Destinations in another project. V1FSS grants its post-scan action service account
roles/storage.objectAdminon each destination bucket as part of the Terraform apply, so the identity you rundeploy.shwith needs permission to set IAM on that bucket. If a destination is in another project and you cannot grant that permission, the apply fails on the binding. Move the bucket into this project, or ask the other project's administrator to grant the…-action-tagservice account access after you deploy.
ImportantThe plugin replaces an object's metadata in full, not only the
fss- keys, immediately before it copies the object to the destination. For objects the
plugin acts on, both the V1FSS keys and any custom metadata of your own are absent
from the destination copy. This is existing C1FSS behavior and the update does not
change it. |
What changes after the update
V1FSS is not an exact feature-for-feature match for C1FSS. Review the following before
you delete anything.
What is different
-
Bucket selection is a console setting, not a deployment parameter. C1FSS fixed the scanning bucket when you deployed the stack, one stack per bucket. V1FSS deploys once for each project, and you turn buckets on and off in the TrendAI Vision One console.
-
Only one V1FSS stack is supported for each project. V1FSS records its deployment metadata in a secret with a fixed name, so a second stack in the same project fails to apply. Several C1FSS storage stacks collapse into one V1FSS stack, which is usually what you want, but it is not optional.
-
V1FSS grants itself project-wide access to Cloud Storage. Instead of per-bucket IAM bindings, it creates two project-level custom roles that cover every bucket in the project. There is no option to scope access to individual buckets. If the per-bucket model in C1FSS was a control you relied on, review this before you update.
-
V1FSS uses Cloud Run v2 instead of Cloud Functions (1st gen), so it does not depend on the Cloud Build, Cloud Functions, or Deployment Manager APIs.
-
Promote and quarantine always move objects, never copy them, and they are configured once in the deployment package rather than once for each bucket in a separate plugin.
-
The scan-result Pub/Sub topic changed, along with the shape of its messages. If you had your own subscriber on the C1FSS
…-scan-result-topictopic, subscribe it to the V1FSS topic and update your parser. -
Scan history stays in Cloud One. TrendAI Vision One starts fresh at cutover. Export anything you need to keep before your Cloud One tenant is removed.
What does not carry over
-
A cross-project scanner: A V1FSS deployment is confined to one project. A hub-and-spoke C1FSS layout becomes one V1FSS deployment for each project that holds buckets.
-
Object prefix filtering (
objectFilterPrefix): The V1FSS Terraform supports it, but the path that a TrendAI Vision One managed deployment uses cannot set it. If C1FSS scanned only a prefix of a bucket, V1FSS scans the whole bucket. Check your object volumes first, because for a prefix that covered a small part of a large bucket, this is a significant change in how much is scanned. -
Per-bucket IAM scoping (
disableScanningBucketIAMBinding): No equivalent in V1FSS. -
Reporting object keys to the backend (
reportObjectKey): No equivalent in V1FSS. Object keys are always hashed in telemetry. -
Multi-region and dual-region buckets: Not protected by either product's V1FSS path. They always report as not deployed.
What you gain, and might want to set up afterward
-
Detections in TrendAI Vision One XDR and Workbench visibility, alongside the rest of your security data.
-
Object moving without a separate plugin, built into V1FSS and configured once instead of once for each bucket, with no extra service account or custom roles of its own to manage.
-
A destination for failed scans (
failure_bucket). The C1FSS plugin left those objects in place. -
Better failure handling, with three dead-letter queues and exponential backoff instead of one queue, and daily automatic credential rotation.
-
A configurable metadata format: separated keys, which is the default and matches C1FSS, a single merged key, or no metadata at all.
Common questions
Which update path should I use?
Use zero downtime if you cannot pause scanning. Use brief downtime if you can, and
especially if you use the promote-or-quarantine plugin and are carrying its settings
over. The plugin is the one case where the overlap causes real problems rather than
just duplicate work.
How long is the brief downtime?
Only the gap between removing the C1FSS bucket notification and turning on scanning
in the TrendAI Vision One console. Both are single actions, so it is typically a few
minutes. The duration depends on you, not on any deployment step.
In the zero-downtime path, why not remove the C1FSS bucket notification before validating?
Validating during the overlap makes results hard to attribute, so you validate on
a bucket that C1FSS never protected instead. There is no overlap on that bucket, so
nothing holds the overlap window open, and every result is attributable to V1FSS.
Removing the C1FSS notification first would not shorten the update, because V1FSS
is already turned on in both orders. It would only move the risk earlier: if V1FSS
turned out to be misconfigured, you would find out with your real buckets already
unprotected. You still get end-to-end confirmation on a bucket that C1FSS protected,
at the check point at the end of step 3, after the C1FSS notification is gone but
before its other resources are deleted. At that point attribution is unambiguous and
rollback is still available.
Which buckets does C1FSS actually protect?
The Cloud One console's page names the scanning bucket behind each storage stack. Confirm it against the
bucket itself with
gcloud storage buckets notifications list gs://<bucket>. If there is no notification configuration pointing at a Cloud Functions topic, C1FSS
is not scanning that bucket.Why are my objects being scanned twice?
In the zero-downtime path, both products are turned on during the overlap. That is
how the path avoids downtime, and it stops when you remove the C1FSS bucket notification.
My fss- object metadata keeps changing, or keys keep disappearing.
This is expected during the overlap. C1FSS replaces the whole
fss- metadata set on each scan, which removes the extra keys that V1FSS writes, while
V1FSS merges its keys instead. It stops as soon as C1FSS is torn down. Do not make
anything depend on fss- metadata until then.I turned on a bucket, the console accepted it, but nothing is being scanned.
Check the notification count with
gcloud storage buckets notifications list gs://<bucket>. Cloud Storage caps notifications at 10 for each event type, and when that cap is
reached, TrendAI Vision One logs the failure internally and continues, so the bucket
stays unprotected with no visible error. Free a slot and turn the bucket on again.
See Before you begin.My buckets do not appear on the Inventory page.
TrendAI Vision One discovers buckets by probing your project when your deployment
registers, and then on a roughly hourly schedule. Wait and refresh.
A bucket shows as not deployed and will not turn on.
That bucket's region has no registered V1FSS scanner. Either the region is not supported,
you did not select it when you generated the deployment package, or the probe has
not caught up. You also see this for a multi-region or dual-region bucket, which cannot
be protected at all.
The deploy.sh script fails immediately, saying that Terraform is not a real binary.
Cloud Shell no longer preinstalls Terraform. Install it and run the command again.
See Before you begin.
The deploy.sh install command failed. Can I run it again?
Yes. The script is Terraform behind a Cloud Storage backend in your own project, so
running it again continues from the recorded state rather than starting over. Fix
whatever it reported and run the same command again. Do not delete the state bucket
between attempts, and check
deploy_gcp.log for what happened.The Terraform apply failed on a disabled API.
The
deploy.sh script enables only some of the APIs that V1FSS needs. The one that is missing is
most often run.googleapis.com or cloudscheduler.googleapis.com. Enable the full list and run ./deploy.sh install again.The Terraform apply failed, saying that the secret exists.
There is already a V1FSS stack in this project, and only one is supported. Either
use the existing stack, or remove it with
./deploy.sh uninstall from its package directory before you deploy again.The Terraform destroy command refuses to delete the C1FSS custom roles.
This is expected, because the roles are marked
prevent_destroy in the C1FSS gcp-configuration module. Delete the roles directly from in the Google Cloud console, or with gcloud iam roles delete, and leave gcp-configuration alone.How do I remove the V1FSS deployment?
Run
bash ./deploy.sh uninstall from the package directory. Be careful if this project has other TrendAI Vision One
features connected, because the command destroys the whole Cloud Account Management
Terraform state, which means every feature that package deployed, not only File Security
Storage. To remove only File Security Storage, clear it in the TrendAI Vision One
console, download the regenerated package, and run ./deploy.sh install again. The uninstall command also leaves the TrendAI Vision One cloud account record in place unless you
add --delete_cloud_account.Teardown left buckets, roles, or APIs behind. Is that a problem?
The
trend_micro_fss_* custom roles and the appspot service account binding are stale grants to a Cloud One service account, so remove
them. Artifact, pattern-update, and gcf-sources-* buckets are harmless, and you can delete them if you prefer not to keep them. Enabled
APIs are harmless. A leftover qua-pro-plugin-sa-… service account is not harmless, because it can delete objects in your buckets.I already installed V1FSS, and now I want to set the promote and quarantine destinations.
Edit
main.tf in the package directory and run bash ./deploy.sh install again. This is an update, not a new deployment. If you no longer have the package,
download it again from the TrendAI Vision One console. The regenerated package ships
with the destinations empty, so apply your edits again before you install.Objects are moving, but landing at a different path than they did under C1FSS.
This is the
use_source_bucket_as_folder setting. The package ships with true, which prefixes the destination path with the source bucket name, and the C1FSS plugin
did not. Set it to false and run ./deploy.sh install again. See Update promote and quarantine settings.Can I do this without Cloud Shell?
Yes, from any machine that has
gcloud, jq, and Terraform installed, that is authenticated with gcloud auth login, and that is pointed at the correct project. Cloud Shell is recommended only because
it already has most of these, with ambient credentials.Can I update several projects at once?
Each project is an independent update, with its own deployment package, its own registration,
and its own buckets. The package also includes
org_deploy.sh, which runs deploy.sh against every project in an organization or folder. That is useful for a large number
of projects, but it does not change the per-project process described here.
