{"slug": "putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of", "title": "Putting FSx for ONTAP operations on a file portal on AWS — 182 actions, and the design of delegation and record (Part 4)", "summary": "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.", "body_md": "[Part 1](https://dev.to/aws-builders/adding-a-file-portal-to-fsx-for-ontap-s3-access-points-choosing-between-amplify-gen2-and-887) built the foundation of a file portal on top of Amazon FSx for NetApp ONTAP (FSx for ONTAP) S3 access points. [Part 2](https://dev.to/aws-builders/embedding-storage-operations-into-a-file-portal-from-arpai-incident-response-to-regulatory-1oih) added ransomware response and WORM retention. [Part 3](https://dev.to/aws-builders/embedding-ai-agents-into-a-file-portal-from-agentcore-mcp-to-multi-agent-teams-part-3-19m1) put AI agents on it.\n\nThose 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.\n\nThe 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.\n\n**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.\n\n**What this part does not cover**:\n\nUp front:\n\nThe repository is [solutions/amplify-portal/](https://github.com/Yoshiki0705/FSx-for-ONTAP-S3AccessPoints-Serverless-Patterns/tree/main/solutions/amplify-portal).\n\n| Item | Value |\n|---|---|\n| Date | 2026-09-02 (JST) |\n| Region | ap-northeast-1 |\n| ONTAP version | 9.18.1P3D1 |\n| Portal | Amplify Gen2 sandbox: AppSync + Cognito + VPC Lambdas |\n| Lambda runtime | Python 3.13 |\n| How the action count was taken |\n`scripts/portal_action_types.py --check` and `scripts/check_portal_action_params.py`\n|\n| Cleanup | Test sandboxes deleted. One working stack retained |\n\nFirst, the premise. Without routing through an additional third-party SaaS, three management interfaces reach FSx for ONTAP.\n\n| Interface | Path | Reach |\n|---|---|---|\n| AWS Management Console / FSx API | IAM | The AWS-side operations on file systems, SVMs and volumes; backups |\n| ONTAP CLI (SSH) | SSH to the management endpoint | Roughly an ONTAP cluster administrator |\n| ONTAP REST API | HTTPS to the management endpoint | The CLI's operations, programmatically |\n\nThe sources, and how anything outside this list is treated, are in [Management interfaces](https://github.com/Yoshiki0705/FSx-for-ONTAP-S3AccessPoints-Serverless-Patterns/blob/main/docs/en/fsx-ontap-management-interfaces.md). The CLI and REST management endpoints are reachable **only from inside the VPC or through a Transit Gateway peered network**.\n\nOne consequence follows directly. Consider an everyday request: add a volume, or raise one quota. Answering it needs `fsxadmin`\n\n-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.\n\nThat separation is what the portal does.\n\n`storage-admin`\n\n) 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.\n\nThe 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.\n\n``` bash\n$ python3 scripts/portal_action_types.py --check\nDISPATCH ACTION TYPES: PASS (182 actions declared, matching the handlers)\n\n$ python3 scripts/check_portal_action_params.py\nPORTAL ACTION PARAMS: PASS (187 literal call sites, 182 actions\nacross 12 endpoints, 1 call(s) not statically readable)\n```\n\nThe 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`\n\n, so code that sends `{snapshotName, retentionDays}`\n\nto an action reading `snapshotId`\n\nand `expiryTime`\n\ncompiles, lints, renders a button, and fails on every click. That shipped. Now CI fails until the reconciliation agrees.\n\nBy domain.\n\n| Domain | Operations |\n|---|---|\n| Volume lifecycle | Create / resize / delete / bring online, for both FlexVol and FlexGroup |\n| FlexGroup capacity rebalance | Read state / start / stop / schedule |\n| FlexCache | Create / list / resize / write-back toggle / delete |\n| FlexClone | Create / list / split |\n| SnapMirror | Create / list / transfer history / update now / quiesce / resume / break / resync / abort / delete |\n| Snapshots | List / create / delete / lock / policy create / assign / enable locking |\n| SnapLock and WORM | Read configuration / change retention, S3 Object Lock retention |\n| ARP/AI (ransomware protection) | State change / bulk enable / suspect list and clear / surge parameters |\n| Containment | Block NFS IP / block SMB user / disconnect sessions / list active blocks |\n| QoS | Policy create / update / delete / assign to and release from a volume |\n| Quotas | Rule create / update / delete / usage report / per-volume enforcement |\n| SMB | Share create, update, delete; local users and groups; members; name mapping |\n| Qtrees | Create / update / rename / delete |\n| Export policies | Policy and rule create / delete |\n| FPolicy and Vscan | Policy and event create / enable / delete |\n| Peering | Cluster peer and SVM peer create / accept / delete, intercluster LIFs |\n| Cluster inventory | Nodes / licenses / LIFs / protocols / DNS / jobs, EMS events |\n| S3 | Bucket list, Object Lock status and retention |\n\n182 is not every ONTAP operation. Operations that need advanced privilege are absent from the REST API, so they cannot appear on this screen.\n\nThe 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`\n\n— and **it did not look disabled either**. Pressing it did nothing.\n\nOn 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.\n\nAdmin 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.\n\nThe copy limit is the clearest case. It is **easy to confuse with the upload limit**, so the measured values are split out.\n\n| Operation | Limit | Measured |\n|---|---|---|\nUpload (single `PutObject` ) |\n5 GiB |\n`MaxSizeAllowed` = 5,368,709,120 |\n| Upload (multipart, whole object) | 50 GiB |\n53,687,091,200. Checked only at `CompleteMultipartUpload`\n|\nDownload (`GetObject` ) |\nNo limit | Objects over 50 GiB were retrieved |\nCopy (single `CopyObject` ) |\n5 GiB | As above |\nCopy (`UploadPartCopy` ) |\nUnusable |\nDocumented as Supported; every form returned `NoSuchKey`\n|\n\nUploads do reach 50 GiB (measured with multipart). Copies, though, have no path past 5 GiB. `UploadPartCopy`\n\nis listed as Supported in [Access point compatibility](https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/access-points-for-fsxn-object-api-support.html) and returned `NoSuchKey`\n\nin every form measured. Rename, move, copy, trash and restore in the portal are all `CopyObject`\n\n, so that 5 GiB becomes the screen's limit.\n\nThe units caught me out as well. The AWS documentation's \"5 GB\" and \"50 GB\" both turned out to be binary when measured. `MaxSizeAllowed`\n\nfrom `PutObject`\n\nis 5,368,709,120 = 5 × 1024³, not the decimal 5,000,000,000. The detail is in [the object size limit verification](https://github.com/Yoshiki0705/FSx-for-ONTAP-S3AccessPoints-Serverless-Patterns/blob/main/docs/s3ap-object-size-limits-verification.md).\n\nRather than surfacing an S3 error halfway through, the portal checks the size before the copy and refuses with a reason.\n\n`{key}`\n\nis 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.\n\nThe guard's 5 GiB threshold is the same value as the measured `MaxSizeAllowed`\n\n.\n\nOn 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.**\n\nThe free-space estimate for a clone split (`volume clone split estimate`\n\n) 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.\n\nFor 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:\n\n- The SnapLock type (compliance) can only be set at creation and cannot be changed or removed afterwards\n- Under compliance, nobody can delete until retention expires. Not the account administrator, and not AWS\n- While one unexpired WORM file remains, this volume, its SVM, and the\nfile systemcannot be deleted- While the file system cannot be deleted, it keeps billing\n- A newly created empty volume can still be deleted. It stops being deletable when the first file is committed to WORM\n\nThe 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.**\n\nSnapshot 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.\n\nA 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.\n\nIrreversible operations carry a type-to-confirm (the keyword typed in capitals). The API also requires `acknowledgeIrreversible`\n\n, so a call that bypasses the UI passes the same check.\n\nWhat 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.\n\nThe order here is worth stating honestly. After writing the section above I ran the screen, and **the lock indicator was broken.**\n\nONTAP keeps two expiry fields on a snapshot. `expiry_time`\n\nis the snapshot lock; `snaplock_expiry_time`\n\nis 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.**\n\nIt surfaced because two panels disagreed about the same snapshot. The panel counting lock state said `lockedSnapshotCount: 1`\n\n; the list said `isTamperproof: false`\n\n. **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.\n\nThe 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\").\n\n| # | What to write down |\n|---|---|\n| 1 |\nDo 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 |\n| 2 |\nDecide the unit of delegation per operation. Do not bundle volume creation and enabling SnapLock under one permission |\n| 3 |\nIn the description of an irreversible operation, include the parent resource and the bill. \"This volume becomes undeletable\" is not enough |\n| 4 |\nLeave no unpressable buttons. Show the missing input. Where a feature is absent, say it is absent and why |\n| 5 |\nIf one fact is displayed in two places, add a test that reconciles them. While only one is being read, a broken display looks correct |\n\n\"Unverified\" is not \"impossible\". The boundary of this article, stated as a boundary:\n\n| Item | State |\n|---|---|\n| Behaviour under concurrent users | Unmeasured. Only single-operation latency was observed |\n| Operations needing advanced privilege | Out of scope. Absent from the REST API, so they cannot be on the screen |\n| Enabling SnapLock compliance from the screen |\nDeliberately not done. Irreversible, and it would make a test file system undeletable for months |\n| Multi-tier delegation with more Cognito groups | Unverified. There is one tier, `storage-admin`\n|\n| Long-term retention and search of the audit record | Unverified. The record is kept; no retention design was done |\n\nPart 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.\n\nPutting 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.\n\nHalf 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.\n\nAnd one display defect surfaced after the article was written. **Until two panels were reconciled, the broken indicator looked correct.**\n\n*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.*", "url": "https://wpnews.pro/news/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of", "canonical_source": "https://dev.to/aws-builders/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-design-of-425g", "published_at": "2026-09-04 00:57:42+00:00", "updated_at": "2026-09-04 01:24:21.888296+00:00", "lang": "en", "topics": ["developer-tools", "ai-infrastructure"], "entities": ["Amazon FSx for ONTAP", "AWS", "Amplify Gen2", "AppSync", "Cognito", "Lambda", "Secrets Manager", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of", "markdown": "https://wpnews.pro/news/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of.md", "text": "https://wpnews.pro/news/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of.txt", "jsonld": "https://wpnews.pro/news/putting-fsx-for-ontap-operations-on-a-file-portal-on-aws-182-actions-and-the-of.jsonld"}}