cd /news/developer-tools/putting-fsx-for-ontap-operations-on-… · home topics developer-tools article
[ARTICLE · art-121013] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Putting FSx for ONTAP operations on a file portal on AWS — 182 actions, and the design of delegation and record (Part 4)

A developer detailed the design of an administrative file portal for Amazon FSx for ONTAP, which now supports 182 storage operations across 12 endpoints. The portal centralizes delegation and record-keeping, replacing direct SSH or ONTAP credentials with a Lambda-based path inside the VPC. The project is open-source on GitHub.

read12 min views1 publishedSep 4, 2026

Part 1 built the foundation of a file portal on top of Amazon FSx for NetApp ONTAP (FSx for ONTAP) S3 access points. Part 2 added ransomware response and WORM retention. Part 3 put AI agents on it.

Those parts were screens for people who handle files. From here the subject is the people who operate the storage itself. Volume create and resize, FlexCache, FlexClone, SnapMirror, snapshot policies, QoS, quotas, SMB shares. The portal now reaches 182 operations.

The readers I have in mind are infrastructure owners running FSx for ONTAP, and developers building this kind of admin screen with Amplify Gen2. ONTAP terms get a one-line gloss on first use, so ONTAP operations experience is not assumed. You can start here without Parts 1-3.

What this part covers is what had to be decided to put operations on a screen: the design of delegation and record, and the treatment of buttons that cannot be pressed and buttons that were never built.

What this part does not cover:

Up front:

The repository is solutions/amplify-portal/.

Item Value
Date 2026-09-02 (JST)
Region ap-northeast-1
ONTAP version 9.18.1P3D1
Portal Amplify Gen2 sandbox: AppSync + Cognito + VPC Lambdas
Lambda runtime Python 3.13
How the action count was taken
scripts/portal_action_types.py --check and scripts/check_portal_action_params.py
Cleanup Test sandboxes deleted. One working stack retained

First, the premise. Without routing through an additional third-party SaaS, three management interfaces reach FSx for ONTAP.

Interface Path Reach
AWS Management Console / FSx API IAM The AWS-side operations on file systems, SVMs and volumes; backups
ONTAP CLI (SSH) SSH to the management endpoint Roughly an ONTAP cluster administrator
ONTAP REST API HTTPS to the management endpoint The CLI's operations, programmatically

The sources, and how anything outside this list is treated, are in Management interfaces. The CLI and REST management endpoints are reachable only from inside the VPC or through a Transit Gateway peered network.

One consequence follows directly. Consider an everyday request: add a volume, or raise one quota. Answering it needs fsxadmin

-equivalent credentials and a path into the VPC. So every request lands on the infrastructure owner, and none of it can be handed to anyone else.

That separation is what the portal does.

storage-admin

) decides who may run what, per operation. No SSH key and no ONTAP credential is handed out. The credential lives in Secrets Manager and only the Lambda reads itDescribing the portal's benefit as "no VPN needed" would be wrong, though. The Lambda that calls the ONTAP REST API is inside the VPC. The path did not disappear; what holds it moved from a person to a Lambda. That distinction affects operational design, so the repository documentation words it the same way.

The portal reaches 182 actions across 12 endpoints. That number is not maintained by hand. A script reconciles the generated types against the handlers and prints it.

$ python3 scripts/portal_action_types.py --check
DISPATCH ACTION TYPES: PASS (182 actions declared, matching the handlers)

$ python3 scripts/check_portal_action_params.py
PORTAL ACTION PARAMS: PASS (187 literal call sites, 182 actions
across 12 endpoints, 1 call(s) not statically readable)

The reason it is not counted by hand is not that the number grew. Types do not cross the boundary between the screen and the Lambda. The portal's dispatch takes an untyped params

, so code that sends {snapshotName, retentionDays}

to an action reading snapshotId

and expiryTime

compiles, lints, renders a button, and fails on every click. That shipped. Now CI fails until the reconciliation agrees.

By domain.

Domain Operations
Volume lifecycle Create / resize / delete / bring online, for both FlexVol and FlexGroup
FlexGroup capacity rebalance Read state / start / stop / schedule
FlexCache Create / list / resize / write-back toggle / delete
FlexClone Create / list / split
SnapMirror Create / list / transfer history / update now / quiesce / resume / break / resync / abort / delete
Snapshots List / create / delete / lock / policy create / assign / enable locking
SnapLock and WORM Read configuration / change retention, S3 Object Lock retention
ARP/AI (ransomware protection) State change / bulk enable / suspect list and clear / surge parameters
Containment Block NFS IP / block SMB user / disconnect sessions / list active blocks
QoS Policy create / update / delete / assign to and release from a volume
Quotas Rule create / update / delete / usage report / per-volume enforcement
SMB Share create, update, delete; local users and groups; members; name mapping
Qtrees Create / update / rename / delete
Export policies Policy and rule create / delete
FPolicy and Vscan Policy and event create / enable / delete
Peering Cluster peer and SVM peer create / accept / delete, intercluster LIFs
Cluster inventory Nodes / licenses / LIFs / protocols / DNS / jobs, EMS events
S3 Bucket list, Object Lock status and retention

182 is not every ONTAP operation. Operations that need advanced privilege are absent from the REST API, so they cannot appear on this screen.

The containment operations for ransomware response (block an NFS IP, block an SMB user, disconnect sessions) cannot run without a target. Previously the button simply went disabled

— and it did not look disabled either. Pressing it did nothing.

On a screen someone reads during an incident, a button that does nothing is indistinguishable from a broken one. Each button now states what the operation does and what is still missing, and lists the inputs it needs. There is also a note that the grey text is a placeholder and not a value.

Admin features are not hidden from users who lack the permission. They are greyed out with a "storage-admin required" badge. What the screen can do stays visible, and AppSync refuses the call if it is attempted.

The copy limit is the clearest case. It is easy to confuse with the upload limit, so the measured values are split out.

Operation Limit Measured
Upload (single PutObject )
5 GiB
MaxSizeAllowed = 5,368,709,120
Upload (multipart, whole object) 50 GiB
53,687,091,200. Checked only at CompleteMultipartUpload
Download (GetObject )
No limit Objects over 50 GiB were retrieved
Copy (single CopyObject )
5 GiB As above
Copy (UploadPartCopy )
Unusable
Documented as Supported; every form returned NoSuchKey

Uploads do reach 50 GiB (measured with multipart). Copies, though, have no path past 5 GiB. UploadPartCopy

is listed as Supported in Access point compatibility and returned NoSuchKey

in every form measured. Rename, move, copy, trash and restore in the portal are all CopyObject

, so that 5 GiB becomes the screen's limit.

The units caught me out as well. The AWS documentation's "5 GB" and "50 GB" both turned out to be binary when measured. MaxSizeAllowed

from PutObject

is 5,368,709,120 = 5 × 1024³, not the decimal 5,000,000,000. The detail is in the object size limit verification.

Rather than surfacing an S3 error halfway through, the portal checks the size before the copy and refuses with a reason.

{key}

is 6.2 GiB. A single copy is limited to 5 GiB, and the multipart copy that would lift the limit is not usable on this Access Point, so this operation cannot be completed from the portal. Move the file over NFS or SMB instead.

The guard's 5 GiB threshold is the same value as the measured MaxSizeAllowed

.

On the same reasoning, no button was built for converting a FlexVol to a FlexGroup. The conversion is ONTAP CLI advanced-privilege only, with no REST equivalent. Instead the screen carries the prerequisites, the irreversibility, the treatment of existing snapshots, and what AWS recommends — a copy into a new FlexGroup with AWS DataSync rather than an in-place conversion. Writing down that something is absent, and why, is more useful than a button that cannot be pressed.

The free-space estimate for a clone split (volume clone split estimate

) is the same. It exists only in the CLI, so it cannot appear here. Rather than omitting it silently, the screen says why it is missing.

For operations that cannot be undone — SnapLock, snapshot locking — a confirmation dialog does not cover it, because the person pressing it does not know what becomes undeletable. The screen says this:

  • The SnapLock type (compliance) can only be set at creation and cannot be changed or removed afterwards
  • Under compliance, nobody can delete until retention expires. Not the account administrator, and not AWS
  • While one unexpired WORM file remains, this volume, its SVM, and the file systemcannot be deleted- While the file system cannot be deleted, it keeps billing
  • A newly created empty volume can still be deleted. It stops being deletable when the first file is committed to WORM

The last two lines are the point. The effect of an irreversible operation does not stop at the resource; it propagates to the parent and to the bill. A test environment is the worst place to put a file system you cannot delete for six months.

Snapshot locking is written up with its asymmetry intact. A lock can only be extended, never shortened or released. The policy side is reversible: removing the retention, switching policies, or detaching stops new locks. But snapshots already locked stay until they expire. Compressing that asymmetry into one sentence makes one half of it wrong.

A retention count does not act as a ceiling either. Locked snapshots cannot be rotated out, so they accumulate past the count until expiry and consume the space. That is on the screen too.

Irreversible operations carry a type-to-confirm (the keyword typed in capitals). The API also requires acknowledgeIrreversible

, so a call that bypasses the UI passes the same check.

What is written here is the technical blast radius of an operation. Which retention period satisfies your regulatory requirements is a legal and compliance judgement, and neither this article nor the portal stands in for it.

The order here is worth stating honestly. After writing the section above I ran the screen, and the lock indicator was broken.

ONTAP keeps two expiry fields on a snapshot. expiry_time

is the snapshot lock; snaplock_expiry_time

is the expiry that comes from a SnapLock volume. The portal writes a lock to the former, and the snapshot list was reading only the latter. So a snapshot locked from the portal was always shown as unlocked.

It surfaced because two panels disagreed about the same snapshot. The panel counting lock state said lockedSnapshotCount: 1

; the list said isTamperproof: false

. A state where one of them is wrong cannot be seen from either one alone. Both fields are read now, and four tests that fail against the old code were added.

The same run produced a measurement on blast radius. A locked snapshot does not block deletion of its volume. The delete was attempted and the volume left the list twenty seconds later. Unexpired WORM files under SnapLock block deletion all the way up to the file system; a snapshot lock is confined to that snapshot. That matched the screen's wording ("other snapshots and the volume itself are unaffected").

# What to write down
1
Do not write "no VPN required." A Lambda holds the path into the VPC. An audit asks who can use that path, not whether it exists
2
Decide the unit of delegation per operation. Do not bundle volume creation and enabling SnapLock under one permission
3
In the description of an irreversible operation, include the parent resource and the bill. "This volume becomes undeletable" is not enough
4
Leave no unpressable buttons. Show the missing input. Where a feature is absent, say it is absent and why
5
If one fact is displayed in two places, add a test that reconciles them. While only one is being read, a broken display looks correct

"Unverified" is not "impossible". The boundary of this article, stated as a boundary:

Item State
Behaviour under concurrent users Unmeasured. Only single-operation latency was observed
Operations needing advanced privilege Out of scope. Absent from the REST API, so they cannot be on the screen
Enabling SnapLock compliance from the screen
Deliberately not done. Irreversible, and it would make a test file system undeletable for months
Multi-tier delegation with more Cognito groups Unverified. There is one tier, storage-admin
Long-term retention and search of the audit record Unverified. The record is kept; no retention design was done

Part 5 covers what the real cluster refused while these 182 actions were being built: why creating a FlexGroup on FSx for ONTAP always fails with the defaults, why a capacity rebalance never starts with ONTAP's defaults, and the two places the documentation and the running system disagreed.

Putting operations on a screen was not a matter of listing features. Three paths already reach the file system and none of them went away, so what a screen adds is delegation and record, not reach. Getting that backwards produces the claim that a VPN is no longer needed.

Half the screen's job turned out to be saying what cannot be done rather than showing what can. Name the missing input on a button that cannot be pressed, write down absent features with the reason, and give irreversible operations their blast radius. Where a limit is measurable — the 5 GiB copy — using the measured value directly in the guard keeps the screen and the storage saying the same thing.

And one display defect surfaced after the article was written. Until two panels were reconciled, the broken indicator looked correct.

The figures come from one specific environment and configuration and will differ with workload and setup. This article does not stand in for governance or regulatory judgement.

── more in #developer-tools 4 stories · sorted by recency
── more on @amazon fsx for ontap 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/putting-fsx-for-onta…] indexed:0 read:12min 2026-09-04 ·