DEV Community

Cover image for Embedding Storage Operations into a File Portal — From ARP/AI Incident Response to Regulatory Retention Management (Part 2)

Embedding Storage Operations into a File Portal — From ARP/AI Incident Response to Regulatory Retention Management (Part 2)

Run detection through containment from the screen — ARP/AI, SnapLock, audit logs (part 2 of 3)

A Japanese version of this article is available: 日本語版

Introduction

In Part 1, I looked at putting a file portal on top of the S3 Access Point of Amazon FSx for NetApp ONTAP (hereafter FSx for ONTAP S3 AP, or S3 AP), comparing Amplify Gen2 and Nextcloud as two approaches. The portal at that point stopped at "browse the files" — the moment you wanted to know something about the storage layer, you had to go back to ONTAP System Manager or the CLI.

Once people started using it, the first two things that came back were "I want to check whether ARP has detected anything myself" and "is this snapshot actually locked?" Both requests came from team members outside storage administration, and the sticking point was the same: you cannot check any of it without a VPN connection to the management LIF. So I added ONTAP operations features to the Amplify Gen2 portal, up to the point where health checks and incident first response can be done entirely in a browser.

Here's the conclusion up front:

  • ONTAP System Manager-equivalent admin operations can be executed from a browser through AppSync + Lambda
  • Separating storage-admin from regular users with Cognito Groups gives you a safe split between read-only viewing and change operations
  • Managing ransomware response as four states — Detected → Contained → Investigating → Resolved — removes the hesitation from first response
  • Turning regulatory retention periods (FISC 7 years / SOX 5 years / HIPAA 6 years) into presets prevents day-count mistakes

In this article, I'll cover the design of the storage operations features embedded in the portal, the ONTAP REST API implementation behind them, and the points I was careful about when handling irreversible operations.

The admin operation path for the storage operations features in the portal. The user's web browser reaches AWS Amplify over HTTPS, Amazon Cognito handles authentication and group checks, and AWS AppSync invokes an AWS Lambda function inside the VPC. That Lambda reads credentials from AWS Secrets Manager and drives the ONTAP REST API on Amazon FSx for NetApp ONTAP

Light theme shown. A dark theme version is available, and every figure is listed in the architecture diagram index.

Relationship to existing tools: This portal makes the same storage management operations previously available only through ONTAP System Manager, ONTAP CLI, or REST API accessible from a browser with Cognito authentication. It is not a replacement for those tools — it's an additional layer that provides browser-based access to the same operations.

The features added are as follows:

  • Storage Dashboard: a 4-card health overview
  • ARP/AI Incident Lifecycle: managed as four states — Detected → Contained → Investigating → Resolved
  • S3 Object Lock Configuration UI: select a bucket, specify a retention mode, apply
  • PHI Guardrail: structurally blocks AI processing for paths such as /dicom/
  • EMS Events: real-time ONTAP alert display
  • Regulatory Retention Presets: FISC 7-year / SOX 5-year / HIPAA 6-year
  • Welcome Modal: first-time user onboarding
  • Audit Log: file access trail via CloudTrail, viewable in the UI
  • FlexClone Restore: one-click recovery from snapshots
  • Athena Query: SQL analysis on NAS data

Scope: this article is an implementation record of adding "operations features usable by members outside storage administration" to the file portal built in Part 1. Part 3 covers AI agent integration.

Repository: solutions/amplify-portal/


Why Embed Admin Operations in a Portal

ONTAP System Manager is a powerful Web UI, but accessing it requires a VPN connection to the management LIF. When team members outside storage administration (security staff, compliance officers, data protection teams) want to "check ARP status" or "verify whether a snapshot is locked," they have no self-service path.

Motivation for embedding admin operations:

  1. Security staff should be able to instantly check ransomware detection state and execute containment actions
  2. Compliance officers should be able to verify retention settings and audit logs themselves
  3. Operations teams should be able to check ONTAP alerts without opening another tool

Cognito Groups (storage-admin / authenticated) separate authorization — regular users are read-only, only admins can execute changes.

What You Used to Do vs What You Can Do Now

Operation Previous Method Portal Method
Check ARP threats and contain VPN to System Manager → Security panel → manual block Dashboard detection → one-click containment
WORM-lock a snapshot CLI: volume snapshot modify-retention or direct REST API call Lock panel → select preset → apply
DR failover with SnapMirror CLI: snapmirror break / snapmirror resync Status list → click action button

Storage Dashboard — Admin Landing Page

The first thing admins see after login is a 4-card health dashboard. This follows ONTAP System Manager's "dashboard first" pattern.

┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│ 💾 12       │  │ 🛡️ 8         │  │ 🔐 5        │  │ 📊 3.2x     │
│ Volumes     │  │ARP Protected│  │ Locked Snaps│  │ Efficiency  │
│ Avg: 62%    │  │✅ No threats│  │ Tamperproof │  │ 69% saved   │
└─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘
Enter fullscreen mode Exit fullscreen mode

The 4 Cards

Card Shows Navigates to
Volume Capacity Volume count + average utilization Volume Manager
ARP/AI Protection Protected volumes + threat count ARP Admin
Locked Snapshots Locked snapshot count Snapshot Admin
Storage Efficiency Dedup/compression ratio + savings Efficiency Panel

Implementation

Four APIs fetched in parallel with Promise.allSettled. If one fails (e.g., ARP not configured), remaining cards still render.

const [volResp, arpResp, snapResp, effResp] = await Promise.allSettled([
  adminQuery({ action: "listVolumes", params: JSON.stringify({}) }),
  adminQuery({ action: "listArpVolumes", params: JSON.stringify({}) }),
  protectionQuery({ action: "listSnapshots", params: JSON.stringify({ maxResults: 50 }) }),
  adminQuery({ action: "getEfficiencyStats", params: JSON.stringify({}) }),
]);
Enter fullscreen mode Exit fullscreen mode

Why Promise.allSettled over Promise.all: with Promise.all, one failure rejects everything. On a storage dashboard, "ARP not configured" is a normal state, not an error.


ARP/AI Incident Lifecycle

After ONTAP Autonomous Ransomware Protection (ARP/AI) detects a threat, the response flow is managed across 4 states.

State Transitions

🔴 Detected
  → 🟠 Contained
    → 🟡 Investigating
      → 🟢 Resolved
Enter fullscreen mode Exit fullscreen mode

The ARP/AI incident lifecycle tracked as four states. Detected moves to Contained on containment, then to Investigating, and finally to Resolved. The notes list what each state records

Light theme shown. A dark theme version is available.

What's Recorded at Each State

State Timestamp Additional Data
Detected detectedAt
Contained containedAt blockedUsers[], blockedIps[], snapshotName
Investigating notes (free text)
Resolved resolvedAt

Containment Actions

Actions executable directly from the portal:

Action ONTAP REST API Effect
Block SMB User name-mapping deny (win→unix) Immediately denies target user's SMB access
Block NFS IP export-policy deny rule Immediately denies NFS access from target IP
Full Containment snapshot + block + disconnect Preserves snapshot + blocks all + disconnects sessions
Unblock delete name-mapping/export-policy rules Recovery after investigation

This implements the equivalent of NetApp DII Storage Workload Security blocking directly via ONTAP REST API.

Implementation

// useIncidentState hook — persists per-volume in localStorage
export type IncidentState = "none" | "detected" | "contained" | "investigating" | "resolved";

export function useIncidentState(volumeName: string) {
  const [incident, setIncident] = useState<IncidentRecord>(() => loadIncident(volumeName));

  const markContained = useCallback((snapshot?: string, users?: string[], ips?: string[]) => {
    transition("contained", { snapshotName: snapshot, blockedUsers: users || [], blockedIps: ips || [] });
  }, [transition]);

  // ...
}
Enter fullscreen mode Exit fullscreen mode

The UI displays a state badge with the next action button changing dynamically:

[🔴 Detected] → [Execute Containment] button
[🟠 Contained] → [Start Investigation] button
[🟡 Investigating] → [Resolve] button
[🟢 Resolved] → (complete)
Enter fullscreen mode Exit fullscreen mode

Current limitation: Incident state is stored in localStorage and not shared across browsers. There is also a risk of losing incident state if the browser crashes. DynamoDB persistence is recommended for production use so that multiple members see the same state.

Incident response note: After executing containment actions, integrate with your existing incident runbooks (PagerDuty, OpsGenie, etc.). Portal containment is a first-response action and should be positioned as part of your full incident management workflow.

Security note: Executing containment actions (SMB block, NFS IP block) requires membership in the storage-admin group. Unblocking requires the same privilege, so even if a regular user's browser session is compromised, the attacker cannot lift a block. Compromise of a storage-admin account itself is guarded by Cognito MFA.

Multi-tenant note: When multiple teams (tenants) share the same portal, ensure tenant A cannot view tenant B's ARP alerts by combining Cognito Groups with volume-level access control. In the current implementation, all storage-admin group members can view ARP status for all volumes. If tenant isolation is required, consider deploying separate portal instances per SVM.


PHI Guardrail — Structurally Blocking AI Processing

Prevents the "accidentally sent PHI data to an external AI" scenario at the UI level in HIPAA environments.

How It Works

Files in paths containing /dicom/, /phi/, /pii/, /hipaa/, or /protected-health/ have their AI processing button automatically disabled.

const isPhiPath = (path: string): boolean => {
  const lower = path.toLowerCase();
  return /\/(dicom|phi|pii|hipaa|protected-health)[\/-]/.test(`/${lower}`) ||
         lower.startsWith("dicom/") || lower.startsWith("phi/") || lower.startsWith("pii/");
};
Enter fullscreen mode Exit fullscreen mode

UI display:

Normal folder: [⚡ Run AI Processing]     ← clickable
PHI folder:    [🚫 PHI — AI Blocked]      ← disabled, not clickable
Enter fullscreen mode Exit fullscreen mode

Design Intent

  • Guardrail, not detect-and-respond: rather than "processed it, then discovered it was PHI," this prevents processing from starting at all
  • Cannot be bypassed even by admins: the button itself is disabled regardless of permissions
  • Depends on folder naming convention: path-pattern based, so it presupposes organizational folder structure rules

Important limitation: This guardrail blocks based on folder path only — it does NOT scan file contents. A file like /contracts/sensitive-patient.pdf placed outside PHI paths will not be blocked. For content-based PHI detection, combine with Bedrock Guardrails (response filtering) described in Part 3. Path guardrail + content filtering gives you ideal 2-layer defense.

HIPAA note: Using this portal in a HIPAA environment presupposes a Business Associate Agreement (BAA) with AWS. Cognito, Lambda, S3, Step Functions, and Bedrock are all HIPAA eligible services. The PHI guardrail is an additional UI-level defense — both the BAA and technical controls are required.


S3 Object Lock — WORM Protection for Output Buckets

AI processing results and compliance reports are stored in standard S3 buckets outside FSx for ONTAP. The portal provides a UI to configure S3 Object Lock on these output buckets.

3-Tab Lock Panel

Tab Target Purpose
ONTAP SnapLock Volumes WORM protection for NAS data (shared across NFS/SMB/S3 AP)
S3 Object Lock S3 Buckets WORM protection for AI processing results
Tamperproof Snapshot Snapshots Tamper prevention for specific snapshots

S3 Object Lock Configuration Flow

1. Fetch bucket list → select from dropdown
2. Choose mode:
   - Governance: Authorized users can override (recommended for AI output)
   - Compliance: No one, including root, can delete until retention expires (regulatory archives)
3. Specify retention days
4. [Apply] sets Object Lock Configuration
Enter fullscreen mode Exit fullscreen mode

When to Use SnapLock vs S3 Object Lock

Characteristic ONTAP SnapLock S3 Object Lock
Target Files on NAS volumes Objects in S3 buckets
Access protocols NFS/SMB/S3 AP S3 API
Use case Source data WORM protection AI results/reports protection
Regulatory SEC 17a-4, FISC, HIPAA, NARA SEC 17a-4, HIPAA

Combining both achieves "source data AND processing results both tamper-proof."

Compliance framework note: The AWS services used by this portal (Cognito, Lambda, S3, Step Functions, Bedrock, AppSync) are in scope for ISMAP and SOC 2. FedRAMP environments for US government agencies require deployment in AWS GovCloud regions. Confirm compliance requirements with your legal and compliance teams — this portal is a technical implementation pattern and does not provide compliance judgments.


Regulatory Retention Period Presets

The Tamperproof Snapshot lock form offers retention periods as dropdown selections.

Preset List

Preset Retention Days Regulatory Basis
30 days 30 Short-term validation
90 days 90 Quarterly
1 year 365 Annual
SOX/J-SOX 1,825 (5 years) Securities Exchange Act — financial records retention
HIPAA 2,192 (6 years) Medical records minimum retention
FISC 2,557 (7 years) Center for Financial Industry Information Systems standard, Chapter 9

Compliance note: FISC/SOX/HIPAA presets are provided for technical convenience. Whether the regulatory mapping and retention periods apply to your organization's specific situation should be validated with your legal and compliance teams. Regulatory interpretation varies by industry, business scope, and jurisdiction.

Why Presets Are Needed

SnapLock retention settings are irreversible. Once a snapshot is locked, the retention period cannot be shortened.

  • Prevents "how many days is 5 years?" calculation errors
  • Each preset shows a tooltip with regulatory basis
  • Minimizes risk of incorrect selection (can extend but never shorten)
<option value={1825} title="SOX/J-SOX: Financial records must be retained for 5 years">
  1,825 days — SOX/J-SOX (5 years)
</option>
<option value={2192} title="HIPAA: Medical records require minimum 6-year retention">
  2,192 days — HIPAA (6 years)
</option>
<option value={2557} title="FISC: Financial institution data requires 7-year retention">
  2,557 days — FISC (7 years)
</option>
Enter fullscreen mode Exit fullscreen mode

EMS Events — ONTAP Alert Viewer

Retrieves events from ONTAP's Event Management System (EMS) with severity alert/error/emergency and displays them in the admin panel.

Backend Implementation

def _get_ems_events(http, headers, event):
    """ONTAP REST: GET /api/support/ems/events"""
    max_records = min(event.get("maxRecords", 20), 50)
    severity_filter = event.get("severity", "alert,error,emergency")

    query = f"/support/ems/events?max_records={max_records}"
    query += f"&severity={severity_filter}"
    query += "&order_by=time desc"
    query += "&fields=time,severity,message.name,message.text,node.name"

    data = _ontap_request(http, headers, "GET", query)
    events = [
        {
            "time": e.get("time", ""),
            "severity": e.get("severity", ""),
            "messageName": e.get("message", {}).get("name", ""),
            "messageText": e.get("message", {}).get("text", ""),
            "node": e.get("node", {}).get("name", ""),
        }
        for e in data.get("records", [])
    ]
    return {"events": events, "count": len(events)}
Enter fullscreen mode Exit fullscreen mode

Example Events

Severity Message Name Meaning
emergency ha.takeover.byPartner HA partner takeover
alert raid.disk.predictiveFailure Disk predictive failure
error scsiblade.san.netLIFDown SAN LIF down
alert arw.volume.attack ARP detected ransomware attack

Storage administrators can check recent alerts directly in the portal without accessing ONTAP System Manager or CLI.

Refresh frequency note: EMS events are fetched on demand when the dashboard is displayed (not by periodic polling). If you need real-time alerting, push EMS events via EventBridge + SNS instead (see fsxn-observability-integrations). The portal is for "checking recent events"; for "detecting in real time," consider pairing it with a separate observability stack.


Welcome Modal — First-Time Onboarding

First-time users see a 3-step guided tour.

3 Steps

  1. 📂 File Browsing — Browse and search NAS files from your browser
  2. AI Processing — Select files and trigger AI/ML workflows
  3. 🔒 Data Protection — Snapshots, WORM locks, ransomware protection

Implementation

export function WelcomeModal() {
  const [dismissed, setDismissed] = useState(() => {
    try { return localStorage.getItem("portal-welcome-dismissed") === "true"; }
    catch { return false; }
  });

  if (dismissed) return null;

  // 3-step carousel with dot navigation
  // "Don't show again" checkbox → localStorage persistence
}
Enter fullscreen mode Exit fullscreen mode

Design Intent

  • Standard onboarding pattern in SaaS products
  • Often omitted in internal tools, but highly effective for conveying "what this portal can do" in 10 seconds
  • localStorage state management, works without backend changes

Resource Management — 20-Panel Card-Grid Admin

ONTAP admin operations organized into 5 categories × 20 panels.

Category Structure

Category Panels
🗄️ Storage Volumes / 🧬 FlexClone / ⚡ FlexCache / Qtrees / Quotas / Efficiency
🔐 Access Control Export Policies / SMB Shares / 👤 Local Users / 🔀 Name Mapping / QoS
🛡️ Data Protection ARP/AI / Snapshots / SnapLock / 📡 FPolicy / 🦠 Vscan / 🪞 SnapMirror
🖥️ Cluster 🔗 Peering / 🖥️ Cluster Information
🤖 Services AI Settings

Each panel displays as a card grid, clicking navigates to the detail view. Follows System Manager's card-based navigation.

The Resource management landing page in the portal. A storage health row of four cards sits above five categories — Storage, Access control, Data protection, Cluster and AI services — holding twenty panel cards in total

The Cluster category covers the part the AWS Management Console does not expose. Cluster peering and SVM peering had to be done from the ONTAP CLI or by hand-writing REST calls, which is a real operational cost for an AWS-centric team that otherwise never leaves the console.

New Panel Highlights

Vscan — "Zero to Configured" Setup Guidance

Vscan (antivirus scanning) has the highest setup barrier of any ONTAP feature — it requires external Windows/Linux servers and antivirus vendor licenses. When unconfigured, the Vscan panel displays a 5-step guided wizard:

  1. Vendor selection (6-vendor comparison table with license page links)
  2. NetApp Antivirus Connector download
  3. EC2 deployment (architecture diagram + AWS Blog/GitHub samples)
  4. ONTAP CLI commands (scanner-pool / policy / enable)
  5. Verification in this panel

Even someone starting from "what is Vscan?" can follow the setup path directly from the portal.

The Vscan panel with the setup guide expanded. It lists interoperable products with links to their license pages, where to obtain the connector, an architecture line, and example ONTAP CLI commands for scanner-pool, on-access-policy and enable

One correction from the first version of this panel: the guidance only rendered while Vscan was disabled, so it disappeared the moment Vscan came up — exactly when you still want the scanner-side steps and the interoperability matrix link. It now stays reachable from a toolbar toggle in both states.

FlexClone — Instant Zero-Copy Clones

Create and split volume clones from the UI for ransomware recovery, forensics, or dev/test. Metadata-only copy completes in seconds with near-zero additional capacity.

SnapMirror — Replication Lifecycle Management

Monitor DR and cross-region replication relationships in the browser and execute actions (sync, break, resync, quiesce, resume, delete). Click a relationship to expand the last 10 transfer records (size, duration, success/failure). Lag times exceeding your RPO target display in red so they are noticed immediately.

DR planning note: SnapMirror Break/Resync operations are executable from the browser, but understand the RPO impact before clicking Break. After a break, the replication relationship is severed and resync requires delta transfer. For production environments, pair the confirmation dialog (implemented) with your team's DR runbook procedures.

FlexCache — Remote Read Cache CRUD

Create FlexCache volumes (async, with prepopulate path support), view the list (origin→cache arrow display), and delete (automated 3-step: unmount→offline→delete). When unconfigured, guidance is displayed with a datalist for selecting origin volumes.

Async polling note: FlexCache creation uses async polling to detect completion. If the user closes the browser during creation, the ONTAP-side operation continues. The created volume appears on the next list refresh — no data loss or inconsistent state results.

Cluster and SVM Peering — the gap the console leaves

Peering is a two-sided operation, and the authentication passphrase has to travel between the two clusters. The panel drives one side at a time.

The Peering panel showing the cluster peers tab. Two peers are listed with state badges — one available and authenticated, one pending with authentication absent — each with Accept and Delete actions

The prerequisite that trips people up is the intercluster LIF, so it gets its own tab rather than being left as a footnote. Both clusters need at least one in up state, and TCP 11104, 11105 plus ICMP have to be allowed between their addresses — the intercluster LIF addresses, not the management LIF.

The intercluster LIF tab listing two LIFs in up state on separate nodes, with a Ready for peering badge and a note that cluster peering needs at least one such LIF on both sides

The flow is: check the LIFs, create the peer on one cluster with Generate passphrase, then enter that passphrase under Accept on the other. The generated value is shown once — ONTAP returns it in the creation response only, so the panel surfaces it in a banner you have to dismiss deliberately. Lose it and the peer has to be deleted and recreated.

SVM peers come after the cluster peer reaches available, and are accepted on the remote side without a passphrase. An SVM-level SnapMirror additionally needs the source subtype default and the destination dp_destination.

Cluster Information — nodes, licences, LIFs, protocols, DNS, jobs

The Cluster information panel overview tab, showing the cluster name and ONTAP version, with the node and licence lists empty and a note under each explaining that this is expected on FSx for ONTAP rather than an error

Four tabs: overview (cluster name and version, nodes, licences), interfaces (LIF list with enable/disable), services (NFS, SMB and S3 state with enable/disable, plus the SVM DNS domains and servers), and jobs.

The overview tab is quieter than that list suggests. On the cluster I tested (ONTAP 9.17.1P7D1) both /cluster/nodes and /cluster/licensing/licenses returned zero records with no error, because AWS manages the cluster rather than the tenant. The first version of the panel rendered that as a bare "No nodes", which reads as a failure, so it now states that an empty list is expected here. The cluster name and ONTAP version come from /cluster and are still populated.

The jobs tab matters more than it looks. FlexCache creation, FlexClone split, SnapMirror transfers and peering all run as asynchronous ONTAP jobs, so this is where their progress and, more usefully, their failure reasons show up.

The Cluster information services tab. NFS, CIFS and S3 are listed as enabled with their detail column showing the AD domain for CIFS, each with a Disable action, above the DNS domains and servers form

DNS note: an AD-joined SVM resolves its domain controllers through the servers set here. A wrong value breaks SMB, and on an AD-joined SVM it also makes S3 Access Point data operations fail with AccessDenied — while HeadBucket keeps succeeding, which sends you looking at IAM instead of the file system layer.

Destructive operations are gated in both layers

SnapMirror break, resync and delete, Vscan and FPolicy policy deletion, peer deletion, and disabling a LIF or a protocol all show an inline confirmation row before anything is sent.

The Vscan panel with a delete confirmation row expanded under the policy, warning that deleting the policy stops its scope being scanned, with Execute and Cancel buttons

The confirmation is not only in the UI. The Lambda refuses the same actions unless confirm=true is present, so a direct call that bypasses the browser is rejected identically. That split matters: a UI-only guard is a suggestion, not a control.

Getting this wrong is instructive. In the first cut, the Vscan and FPolicy delete buttons sent no confirm flag and had no confirmation row, and the handler did not check for one either — while the documentation already claimed the operation was confirm-gated. The button appeared to work and the docs looked right. The fix was to make all three agree, and to pin the contract in tests: for every confirm-gated action, assert it refuses without confirm and succeeds with exactly the parameters the UI sends. The second half of that assertion is the one that would have caught it.


Security Model

Layer Implementation
Authentication Cognito User Pool + MFA (TOTP/SMS)
Authorization (API) Cognito Groups (storage-admin / authenticated)
Authorization (Files) S3 AP + UNIX/Windows file system identity
Transport encryption HTTPS (AppSync) + TLS 1.2 (ONTAP REST API)
Secrets management Secrets Manager (ONTAP credentials)
Audit CloudTrail S3 data events
WORM SnapLock (Compliance/Enterprise) + S3 Object Lock
Ransomware protection ONTAP ARP/AI + portal containment actions
PHI protection Path-based guardrail (AI processing block)

Only users in the storage-admin group can execute admin operations (volume creation, SnapLock configuration, ARP containment, etc.). Regular users are limited to file browsing and AI processing.

Enterprise SSO note: Cognito User Pool supports SAML 2.0 and OIDC federation. To integrate with an existing IdP such as Okta, Azure AD, or Google Workspace, see Cognito's Adding SAML identity providers. Group mapping lets you map IdP groups to the Cognito storage-admin group.

Infrastructure protection note: Amplify Hosting is served via Amazon CloudFront, so AWS Shield Standard (DDoS protection) is automatically applied. If additional WAF rules are needed, attach AWS WAF to the CloudFront distribution.


Usage Scenarios

Scenario 1: Ransomware Response

1. Storage Dashboard shows 🚨 ARP Threats: 1
2. Navigate to ARP/AI panel → view threat details
3. Click [Contain] → SMB user blocked + snapshot taken
4. State transitions to 🟠 Contained
5. After forensic analysis, [Investigation Complete] → [Resolve]
6. Unblock to resume normal operations
Enter fullscreen mode Exit fullscreen mode

Scenario 2: Compliance Audit

1. Lock panel → SnapLock tab to review Compliance volume list
2. Tamperproof tab to apply FISC 7-year lock to snapshots
3. S3 Object Lock tab to verify output bucket retention settings
4. Audit Trail to review operation history
Enter fullscreen mode Exit fullscreen mode

Scenario 3: Daily Monitoring

1. Storage Dashboard — glance at 4 cards (30 seconds)
2. If any volume exceeds 85% capacity, drill into Volume Manager
3. Check EMS Events for recent alerts
4. No issues → done
Enter fullscreen mode Exit fullscreen mode

Design Trade-offs

Design Decision Benefit Trade-off
localStorage (Incident State) Simple deployment Not shared across browsers; incident state can be lost if the browser crashes. DynamoDB migration recommended for production
PHI path regex Simple, immediate Requires folder naming convention compliance
Generic Dispatch (8 endpoints) Avoids CFn 1MB limit IAM policy granularity is coarser
VPC split Cold start optimization Two types of Lambda required
Promise.allSettled (Dashboard) Resilient to partial failures Failed cards show 0
Regulatory presets (hardcoded) Ready to use immediately Code change needed if regulations update

Rollback Procedure

Recovery paths if a portal update causes problems:

Situation Rollback method
Frontend UI issue One-click revert to the previous build from the Amplify Hosting console
Lambda function issue git revert + git push triggers automatic redeploy (Amplify Gen2)
ONTAP configuration change issue Restore directly via ONTAP REST API (export-policy, name-mapping, etc.)
Cognito configuration change CDK stack rollback is not available. Revert manually to the previous state

Because frontend and backend are both under Git management, git revert + git push rolls back immediately. Some ONTAP-side changes (such as enabling SnapLock) are irreversible, so verification before execution matters.


8-Language Support (i18n)

All admin features included, the entire portal supports 8 languages:

Code Language
ja 日本語
en English
ko 한국어
zh-CN 简体中文
zh-TW 繁體中文
fr Français
de Deutsch
es Español

Technical terms (ONTAP, SnapLock, FlexClone, S3 AP, ARP/AI, WORM, FISC, SOX, HIPAA) are not translated. Browser navigator.language auto-detection with instant switching via the header language picker.


Audit Log — Checking "Who Accessed What and When" in the UI

The most frequent request from compliance officers was "I want to check the file access trail myself." Grepping CloudTrail logs from the CLI is not realistic for anyone outside the security team.

The portal's Audit tab runs filtered queries:

Filter Example
File path Show only accesses under /contracts/
Event type READ / WRITE / ALL
Time range 2026-07-01 – 2026-07-28

Architecture

AppSync Query → Lambda → Athena SQL → CloudTrail S3 Data Event logs
Enter fullscreen mode Exit fullscreen mode

The path for reviewing audit logs from the UI. The web browser calls an AWS Lambda function through AWS AppSync, and Amazon Athena runs the SQL. Athena reads the table definition from AWS Glue (Data Catalog) and scans the Amazon S3 logs where AWS CloudTrail recorded the S3 data events

Light theme shown. A dark theme version is available.

CloudTrail S3 data events are registered as a Glue table and queried with Athena. Results display in table form, and access denials (AccessDenied) are highlighted in red.

Prerequisites

  • Enable data events for the S3 AP ARN on a CloudTrail Trail
  • Create the Athena table via Glue Crawler or a manual CREATE TABLE
  • Set ATHENA_AUDIT_DATABASE, ATHENA_AUDIT_TABLE, and ATHENA_AUDIT_OUTPUT as Lambda environment variables

If these are unconfigured, the UI displays "configuration required" guidance with the setup steps. The design treats this as onboarding rather than an error.

Data Retention

Query results are stored in the Athena workgroup output location (S3). Retention of the original CloudTrail logs is controlled by the S3 bucket lifecycle policy on the Trail's bucket. Set retention periods such as FISC 7 years or HIPAA 6 years according to your audit requirements.

Cost note: If you store audit trails in DynamoDB, storage costs grow in large environments. Set a retention policy (TTL) and archive old records to S3 Glacier. CloudTrail log retention is controlled separately via the Trail's lifecycle policy.


FlexClone Restore — Instant Recovery from Snapshots

When recovering from ransomware damage or accidental deletion, the requirement is "I want to go back to the snapshot from before the infection." Previously this meant creating a FlexClone from the CLI and attaching an S3 AP as a sequence of manual operations.

In the portal, from the 📸 button on the Files tab:

1. Enter the snapshot name (e.g., daily.2026-07-18_0010)
2. Click [Clone & Attach]
3. Step Functions automatically runs FlexClone creation → S3 AP attach
4. FlexClone information appears on the Results tab
Enter fullscreen mode Exit fullscreen mode

FlexClone Status Display

🔄 FlexClone Volume
  Volume:  clone-uc6-20260718-abc123
  Parent:  vol_data
  Status:  🟢 online
  Created: 2026-07-18 15:00:00
  Size:    128 MB
  S3 AP:   clone-uc6-abc123-s3alias
Enter fullscreen mode Exit fullscreen mode

Use Cases

Scenario Purpose
Ransomware recovery Immediate access to a pre-infection snapshot
Forensics Isolate a point-in-time copy for investigation
Testing Validate against a clone without touching production data

FlexClone is a metadata-only copy, so it completes in seconds with near-zero additional capacity. Differential capacity is consumed only as writes occur.

Accessibility note: Confirmation dialogs for FlexCache deletion and volume deletion are displayed inline. For screen reader users, confirmation messages are announced via role="alertdialog" and aria-describedby. Keyboard navigation (Tab/Enter/Escape) is fully supported.

Throughput note: A FlexClone volume shares the throughput budget with its parent volume. If clones are used actively in parallel in production, account for the performance impact on the parent volume. For read-oriented uses such as forensics this is typically not a concern.


Athena Query — SQL Analytics on NAS Data

When files on FSx for ONTAP are cataloged via Glue Crawler, you can run SQL queries using Athena. The portal's "Analytics" tab lets you enter a database name and SQL, and execute directly.

There is no need to open the AWS Athena console separately — everything completes inside the portal.

UI Layout

┌──────────────────────────────────────────────────┐
 SQL Query (Athena)      [default        ]        
├──────────────────────────────────────────────────┤
 💡 How to use: catalog files on FSx for ONTAP    
 with Glue Crawler, then analyze them here with   
 SQL.                                             
  📝 View query examples (collapsible)           
├──────────────────────────────────────────────────┤
 SHOW TABLES IN default                           
                                                  
 [Run query]                                      
└──────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Usage Flow

  1. First time: run SHOW TABLES IN default to discover available tables
  2. Once you know table names: execute specific SELECT queries
  3. Results: displayed in table form

Practical Query Examples

-- Find large files (capacity planning)
SELECT key, size FROM default.s3_objects
WHERE size > 1000000000
ORDER BY size DESC LIMIT 20

-- Total size of a specific folder (project sizing)
SELECT SUM(size) as total_bytes
FROM default.s3_objects
WHERE key LIKE 'engineering/%'

-- Files modified in last 7 days (change tracking)
SELECT key, last_modified
FROM default.s3_objects
WHERE last_modified > current_date - interval '7' day
Enter fullscreen mode Exit fullscreen mode

The portal UI includes an expandable "View query examples" section, so even users unfamiliar with SQL can get started by copy-pasting.

Not just "browse the files" but "ask questions of the data" — directly from the portal.

File Formats Glue Crawler Recognizes

Category Formats
Structured data CSV, TSV, JSON, Parquet, ORC, Avro
Logs Apache/NGINX logs, CloudTrail JSON
Documents — (text extraction requires Textract or Bedrock)

CAD/EDA binary files cannot be cataloged by Glue Crawler, but file metadata (size, last modified, path) is still retrievable.

Athena Cost Optimization Tips

Athena bills on the volume of data scanned ($5/TB). Ways to keep costs down:

  • Date partitions (year=/month=/day=) reduce scan volume when a WHERE clause narrows the time range
  • With columnar formats such as Parquet/ORC, specifying only the columns you need instead of SELECT * reduces cost
  • Make it a habit to always add a LIMIT clause to exploratory queries
  • Setting a query limit on the Athena workgroup (for example 10 GB/day) caps unexpected scan volume

Cost Awareness

Rough additional cost if every feature in this article is enabled:

Resource Estimate Notes
VPC Lambda (Admin) ~$5/month Depends on invocation frequency. Negligible for daily checks
CloudTrail S3 Data Events ~$10–$50/month Proportional to file access volume
Athena queries $5/TB scanned Audit queries scan little; partitions reduce it further
Secrets Manager $0.40/secret/month One ONTAP credential
DemoMode $0 No FSx for ONTAP needed. Runs on S3 alone

The cost of FSx for ONTAP itself (~$194/month at 128 MBps) was covered in Part 1. The portal's incremental cost depends on usage frequency, but evaluating in DemoMode adds nothing.


Deployment Time Estimates

Step Time Prerequisite
DemoMode deploy ~15 min Amplify CLI installed
Add VPC + ONTAP connectivity ~30 min FSx for ONTAP file system running
Audit Log configuration ~20 min CloudTrail + Glue Crawler
Full feature deploy ~60 min All of the above

What to Expect After Deployment

  • Once the DemoMode deploy completes, the portal is reachable at https://<branch>.amplifyapp.com. Cognito sign-up → log in → the file list shows test data from the S3 bucket
  • Once VPC connectivity is added, the Storage Dashboard shows actual volume counts and utilization, and protected volumes appear in the ARP panel
  • Once all features are deployed, the Audit Log tab can run CloudTrail queries and the Lock panel shows SnapLock/Object Lock settings

Environment Variables and Configuration Parameters

Parameter Description Example Value
DEMO_MODE Run without FSx for ONTAP true (PoC) / false (production)
ONTAP_SECRET_ARN Secrets Manager ARN for ONTAP credentials arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:fsxn-admin-XXXXXX
ATHENA_AUDIT_DATABASE Glue database name for audit queries cloudtrail_logs
ATHENA_AUDIT_TABLE Athena table name for audit queries s3_data_events
ATHENA_AUDIT_OUTPUT S3 location for Athena query results s3://my-audit-results/athena-output/

PoC → Production Checklist

After evaluating in DemoMode, use this checklist when moving to production connectivity:

Category Verification
Network VPC subnet contains the FSx for ONTAP ENIs; Security Group allows TCP 443 (management LIF). Note: NFS (2049) / SMB (445) are for data access and are not needed for the portal's admin operations
Auth Cognito User Pool MFA enabled; storage-admin group members confirmed
Secrets ONTAP credentials registered in Secrets Manager
Audit CloudTrail Trail with S3 data events enabled for the S3 AP ARN
Backup portal-config.ts values in Git (secrets excluded)
Cost CloudTrail data event estimate confirmed (proportional to access volume)
SSO (Optional) SAML/OIDC federation configured if using an enterprise IdP

Role-Based Documentation (8 Languages × 3 Guides)

Alongside the feature additions, role-specific documentation was built. Based on usability principles (visibility of system status, task-oriented structure, ease of error recovery), 3 guides are provided in 8 languages:

Guide Target Role Key Content
User Guide End users Sign in, file operations, AI processing, FAQ
Compliance Guide Security/Compliance officers ARP verification, WORM checks, audit trail, PHI guardrail validation, regulatory mapping (FISC/HIPAA/SOX/NIST/ISO)
Quick Reference All roles 1-page cheat sheet (navigation, tasks by role, status indicators, troubleshooting)

Supported languages: 日本語, English, 한국어, 简体中文, 繁體中文, Français, Deutsch, Español

Design choices for the compliance officer guide:

  • All tasks executable without storage-admin privileges (read-only access is sufficient)
  • Each task includes "Evidence for auditors" instructions
  • Explicit "What you cannot do" escalation table showing who to contact

FlexCache / SnapMirror Management

Direct ONTAP REST API Operations from the Browser

FlexCache, FlexClone, SnapMirror, Vscan, FPolicy, cluster and SVM peering, and the cluster services are all managed through the browser UI — 110 actions in total. A VPC-deployed Lambda connects to the FSx for ONTAP management endpoint via HTTPS, calling ONTAP REST API with credentials from Secrets Manager.

Browser → AppSync (Cognito auth) → Lambda (in VPC) → ONTAP REST API
                                                       ↓
                                                Secrets Manager
                                                (fsxadmin credentials)
Enter fullscreen mode Exit fullscreen mode

Reaching the ONTAP REST API from the browser. The web browser authenticates with Cognito and connects to AWS AppSync; an AWS Lambda function inside the VPC reads the fsxadmin credentials from AWS Secrets Manager and calls the ONTAP REST API on Amazon FSx for NetApp ONTAP. The Lambda sits in the VPC because the ONTAP management LIF is private

Light theme shown. A dark theme version is available.

FlexCache Create UI

The FlexCache create screen in the portal. The origin volume is picked from a dropdown, then cache name, size and prepopulate paths are entered before creating. Existing caches and their state are listed on the same screen

Select the origin volume from a dropdown (datalist), specify cache name, size, and prepopulate paths, then create. The experience mirrors ONTAP System Manager — accessible from any browser with Cognito authentication.

SnapMirror Lifecycle Management

The SnapMirror list screen in the portal. The relationship shows source and destination paths, its policy, a Broken-off state badge, and the action buttons that apply in that state including Resync and Delete

The replication relationship list shows state badges (✅ Snapmirrored / 🔴 Broken-off / 🔄 Transferring / ⏸️ Paused) with context-sensitive action buttons. DR failover (Break → Resync) is fully accessible from the browser. Lag times exceeding your RPO target display in red with a ⚠️ RPO warning.

Lessons Learned

Async Operations with return_timeout=0

FlexCache creation is an asynchronous ONTAP job taking 30-120 seconds. By specifying return_timeout=0, ONTAP returns immediately with 202 Accepted + job UUID, preventing Lambda timeout. The UI auto-refreshes the list at 10s/30s/60s intervals.

One Wrong Field Name Empties the Whole List

The SnapMirror list was requesting fields=...,last_transfer_type,last_transfer_size. last_transfer_size is not a field on /snapmirror/relationships, and ONTAP rejects the entire request when a single field name is unknown:

The value "last_transfer_size" is invalid for field "fields" (<field,...>)
Enter fullscreen mode Exit fullscreen mode

So every relationship vanished — not with a visible error, but as an empty list. What made this survive the test suite is worth noting: the mock ONTAP in the unit tests returns records regardless of which fields are requested, so a test that asserts on the mapped response passes either way. The fix was to assert on the outgoing query string instead. Per-transfer byte counts were already available from /snapmirror/relationships/{uuid}/transfers, so nothing was lost by dropping the field.

Automated 3-Step FlexCache Deletion

Mounted FlexCache volumes cannot be deleted directly. The portal automates:

  1. Remove junction path (unmount)
  2. Set volume offline
  3. Delete FlexCache (async)

Credential Synchronization

When changing the fsxadmin password, update both the FSx for ONTAP API and Secrets Manager simultaneously. Updating only one side causes authentication failures that can trigger ONTAP's account lockout mechanism. Recovery: aws fsx update-file-system password reset → Secrets Manager sync.

FSx for ONTAP Specifics

Item FSx for ONTAP On-prem ONTAP
Aggregate specification Not needed (auto-selected) Required
SVM creation AWS API only CLI/REST available
Intra-cluster FlexCache Supported (no peering needed) Supported
fsxadmin password reset aws fsx update-file-system security login password

Coexistence with Existing Tools

This portal is not a replacement for ONTAP System Manager, ONTAP CLI, or REST API. It makes a subset of those operations accessible from a browser UI with Cognito authentication — an additional management layer, not a substitute.

Scenario Portal's Role
Using cloud file-sharing SaaS AI processing and audit for large-scale NAS data only
Running self-hosted file sharing Add S3 AP as External Storage for management operations
Using hybrid file services Add data protection and ARP/AI visibility layer
Using ONTAP System Manager daily Provide visibility to non-storage-admin team members

The portal provides a management layer for NAS-specific capabilities (Snapshot, FlexClone, FlexCache, SnapMirror, ARP/AI) accessible from the browser. Adoption can be incremental — management operations only, AI processing only, or the full suite — depending on existing workflows.

PoC → Production Migration Flow

After evaluating in DemoMode (no FSx for ONTAP required), migrate to production connectivity in three phases:

┌────────────────┐     ┌────────────────┐     ┌────────────────┐
│ Phase 1: PoC   │     │ Phase 2: VPC   │     │ Phase 3: Prod  │
│ (~15 min)      │     │   Connectivity │     │   Hardening    │
│                │     │ (~30 min)      │     │ (~60 min)      │
│ DemoMode=true  │ ──→ │ ONTAP mgmt LIF │ ──→ │ Least-privilege│
│ S3 bucket      │     │ Secrets Mgr    │     │ MFA required   │
│ Auth: Cognito  │     │ VPC Endpoint   │     │ WAF added      │
│                │     │                │     │ Audit enabled  │
└────────────────┘     └────────────────┘     └────────────────┘
Enter fullscreen mode Exit fullscreen mode

Three phases from PoC to production connectivity. Phase 1 runs with DemoMode=true against an S3 bucket only; Phase 2 adds the ONTAP management LIF connection, AWS Secrets Manager, and VPC endpoints; Phase 3 applies least-privilege IAM, required MFA, AWS WAF, and audit logging

Light theme shown. A dark theme version is available.

Phase Time Added Cost What You Get What Changes What Stays the Same
1 (PoC) ~15 min $0 UI/UX evaluation, AI processing test Nothing (fresh deploy)
2 (VPC) ~30 min Lambda VPC ~$5/mo ONTAP admin operations, dashboard Lambda VPC config added, Secrets Manager registered Frontend UI, Cognito settings, S3 bucket config
3 (Prod) ~60 min CloudTrail ~$10–50/mo Audit, WAF, MFA, least-privilege IAM IAM policy tightening, WAF attachment, MFA enforcement Application code, ONTAP connection settings

Post-Deployment Verification

Expected state after each phase completes:

  • After Phase 1: you can log in to the portal, and DemoMode file listing and AI processing tests work. The Storage Dashboard still shows "not connected"
  • After Phase 2: the Storage Dashboard shows actual volume information, and ONTAP data appears in the ARP panel and EMS Events
  • After Phase 3: login is impossible without MFA, CloudTrail records all operations, and WAF applies rate limiting

Irreversible operations warning: The following operations cannot be undone once executed. Verify your organization's policies before enabling them in Phase 2+:

  • SnapLock Compliance enablement: Volume SnapLock type cannot be changed after creation
  • Tamperproof Snapshot retention period: Once set, the period cannot be shortened (only extended)
  • S3 Object Lock Compliance mode: No one, including root, can delete objects until retention expires

For detailed migration steps, see the PoC → Production Guide.

Authorization Model (PoC → Production)

Item PoC Production
AppSync auth allow.authenticated() allow.groups(["storage-admin"])
IAM resource scope "*" Specific ARN patterns
generateClient authMode: "userPool" required Same

In Amplify Gen2 with multiple auth providers, generateClient() must explicitly specify authMode: "userPool" to ensure the Cognito token is sent to AppSync. This is a recommended pattern per official documentation.


Resources


Summary and Next Steps

Building on the file portal from Part 1, ONTAP management operations and data protection features were embedded:

Feature What it enables
Storage Dashboard Health at a glance immediately after login
Incident Lifecycle Ransomware response with state management
PHI Guardrail Structurally prevents AI processing of regulated data
S3 Object Lock Tamper prevention for AI results, configurable from UI
EMS Events ONTAP alerts without CLI
Retention Presets Just pick the regulation, get the right retention
Audit Log "Who accessed what and when" — self-service for compliance
FlexClone Restore Recover from snapshot in seconds
FlexCache CRUD Create/delete read cache volumes from browser
SnapMirror Lifecycle Sync, break, resync, quiesce — DR from a browser
Athena Query Ask SQL questions against NAS data
Welcome Modal First-time users productive in 10 seconds

From a portal that "just browses files" to one that "completes storage operations from the web." Daily monitoring and incident first response now finish in the browser without accessing ONTAP System Manager or CLI.

All code is available in the GitHub repository.

As a next step, after running DemoMode using the instructions in Part 1, try adding the VPC configuration to enable ONTAP connectivity. That gets you to a state where every feature in this article is usable. Migration details are collected in the PoC → Production Guide.

In Part 3, I'll write about embedding AI agents into this portal — completing file operations, analysis, and admin operations in natural language.

I hope this post helps someone out there.

See you next time.

Top comments (0)