<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ADEEL ABBAS</title>
    <description>The latest articles on DEV Community by ADEEL ABBAS (@adeelabbas).</description>
    <link>https://dev.to/adeelabbas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg</url>
      <title>DEV Community: ADEEL ABBAS</title>
      <link>https://dev.to/adeelabbas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adeelabbas"/>
    <language>en</language>
    <item>
      <title>Building an Edge-Native Biometric Redaction Pipeline with Cloudinary</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Fri, 02 Oct 2026 05:14:43 +0000</pubDate>
      <link>https://dev.to/adeelabbas/building-an-edge-native-biometric-redaction-pipeline-with-cloudinary-1me5</link>
      <guid>https://dev.to/adeelabbas/building-an-edge-native-biometric-redaction-pipeline-with-cloudinary-1me5</guid>
      <description>&lt;p&gt;Most developers recognize &lt;strong&gt;Cloudinary&lt;/strong&gt; as the premier platform for image hosting, responsive breakpoints, and automated format optimization (&lt;code&gt;f_auto,q_auto&lt;/code&gt;). But treating Cloudinary solely as a media asset CDN underutilizes one of its most powerful capabilities: &lt;strong&gt;edge-native programmable media as a compliance and privacy engine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When building modern KYC, onboarding, or regulatory workflows, organizations routinely ingest identity documents (passports, driver's licenses, employee badges). While verification teams only need names and document numbers, unredacted facial biometrics are frequently stored across internal databases, creating severe GDPR, CCPA, and Zero-Trust liabilities.&lt;/p&gt;

&lt;p&gt;To solve this, I built &lt;strong&gt;&lt;a href="https://veriscrub.vercel.app" rel="noopener noreferrer"&gt;VeriScrub&lt;/a&gt;&lt;/strong&gt; (&lt;a href="https://github.com/adeelabbas1214/veriscrub" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;), a production-grade application that turns Cloudinary into an automated, zero-storage visual PII redaction pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Media Problem: Why Traditional Redaction Fails
&lt;/h2&gt;

&lt;p&gt;Handling document sanitization on self-hosted infrastructure presents serious operational hurdles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Heavy Compute Overhead:&lt;/strong&gt; Running OpenCV, Sharp, or ImageMagick inside containerized backend runtimes causes CPU throttling, high memory spikes, and concurrency bottlenecks under burst uploads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Biometric Data Exposure:&lt;/strong&gt; Passing raw images through backend application memory risks exposing sensitive biometrics in server logs, crash dumps, and unencrypted disk caches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret Leakage Risks:&lt;/strong&gt; Direct client-to-cloud uploads often tempt developers into exposing master API secrets inside frontend code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cloudinary solves this natively by combining &lt;strong&gt;asymmetric cryptographic request signing&lt;/strong&gt; with &lt;strong&gt;real-time AI computer vision transformations&lt;/strong&gt; executed entirely at the edge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                      [ User Browser ]
                             │
     1. Request Signed Token │  ▲ 4. Receive Dynamic
        (Folder / Timestamp) │  │    Transformed Asset URLs
                             ▼  │
               [ Next.js API: /api/sign-intake ]
                             │
                             │ (HMAC-SHA1 Signature Generation)
                             ▼
              [ Cloudinary Edge / Pipeline ]
                             ▲
                             │ 2. Direct Multipart Form Upload
                             │    (Zero Local Server Storage)
                      [ User Browser ]
                             │
                             ▼ 3. Real-Time Vision Processing
             [ e_blur_faces / e_pixelate_faces ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  1. Zero-Storage Ingest via Cloudinary Signed Uploads
&lt;/h2&gt;

&lt;p&gt;VeriScrub ensures raw biometrics never touch web application servers. Instead of sending media files through Next.js API routes, the browser requests a cryptographic signature bound to strict upload parameters using Cloudinary's Node.js SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/sign-intake/route.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;v2&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloudinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cloud_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_CLOUD_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;api_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_API_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;veriscrub_quarantine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Generate an HMAC-SHA1 signature locked to this folder and timestamp&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;api_sign_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;folder&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_API_SECRET&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cloudName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOUDINARY_CLOUD_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser receives this single-use signature and dispatches a multipart upload directly to &lt;code&gt;https://api.cloudinary.com/v1_1/${cloudName}/image/upload&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt; Master API secrets stay secure on the server, while the client uploads directly to an isolated intake folder without exposing backend infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Dynamic Computer Vision at the Edge
&lt;/h2&gt;

&lt;p&gt;Once Cloudinary ingests the document and assigns an immutable &lt;code&gt;public_id&lt;/code&gt;, VeriScrub does not perform any manual pixel manipulation. Instead, it leverages Cloudinary’s transformation URL parameters to trigger facial detection models on the fly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/pipeline.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildDocumentPipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cloudName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://res.cloudinary.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cloudName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/image/upload`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Optimized Raw Asset (auto format &amp;amp; quality compression)&lt;/span&gt;
    &lt;span class="na"&gt;rawOptimized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/f_auto,q_auto/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. High-Strength Gaussian Blur on Detected Faces&lt;/span&gt;
    &lt;span class="na"&gt;auditBlurred&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/e_blur_faces:1000/f_auto,q_auto/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Mosaic Pixelation Mask&lt;/span&gt;
    &lt;span class="na"&gt;auditPixelated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/e_pixelate_faces:35/f_auto,q_auto/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Scanner Forensics Mode (sharpen text while keeping biometrics masked)&lt;/span&gt;
    &lt;span class="na"&gt;scannerContrast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/e_blur_faces:1000/e_contrast:30/e_sharpen:100/f_auto,q_auto/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deep Dive into Cloudinary's Transformation Magic:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;e_blur_faces:1000&lt;/code&gt;:&lt;/strong&gt; Cloudinary automatically locates facial coordinate bounding boxes across ID cards and applies an intensive 1000-radius Gaussian blur, eradicating iris patterns and facial contour geometry while keeping document borders legible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;e_pixelate_faces:35&lt;/code&gt;:&lt;/strong&gt; Applies a mosaic grid over facial regions, neutralizing adversarial AI deconvolution algorithms that attempt to reverse-engineer blurred imagery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;e_contrast:30/e_sharpen:100&lt;/code&gt;:&lt;/strong&gt; Enhances high-frequency microprint, ID card serial numbers, and OCR fields so automated text parsers can process documents cleanly while the biometric region stays obscured.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Real-Time Inspection &amp;amp; Direct Blob Downloads
&lt;/h2&gt;

&lt;p&gt;VeriScrub features a dual-layer split slider that synchronizes Cloudinary's raw baseline (&lt;code&gt;f_auto,q_auto&lt;/code&gt;) and the redacted transformation variant in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"relative w-full aspect-[16/10] overflow-hidden rounded-xl border border-slate-800 bg-slate-950"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Cloudinary Redacted Variant */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getCurrentUrl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Redacted document"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 w-full h-full object-contain"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Raw Image Layer with Dynamic Clipping */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 overflow-hidden"&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sliderPos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rawOptimized&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Raw document"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 w-full h-full object-contain max-w-none"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt;
    &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
    &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sliderPos&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSliderPos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 opacity-0 cursor-ew-resize w-full h-full z-20"&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To export the sanitized document locally without intermediate backend proxying, VeriScrub streams the Cloudinary CDN response directly into an in-memory client blob:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDownload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getCurrentUrl&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blobUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blobUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`sanitized_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;activeTab&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_document.jpg`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revokeObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blobUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Cloudinary Unlocks for Privacy Engineering
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;URL-Driven Security:&lt;/strong&gt; Instead of spinning up containerized image processing workers, Cloudinary allows developers to express complex privacy rules declaratively through simple URL transformation chains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Compute Overhead:&lt;/strong&gt; Facial detection and multi-stage transformations execute in sub-seconds across Cloudinary's distributed edge infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilient Compliance Architecture:&lt;/strong&gt; By combining signed uploads with short-lived retention policies on intake folders, organizations can achieve true Zero-Trust media ingestion with minimal codebase complexity.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Project Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://veriscrub.vercel.app" rel="noopener noreferrer"&gt;https://veriscrub.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📂 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/adeelabbas1214/veriscrub" rel="noopener noreferrer"&gt;https://github.com/adeelabbas1214/veriscrub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How are you leveraging Cloudinary's dynamic transformations beyond standard asset optimization? Let's discuss in the comments below!&lt;/p&gt;

</description>
      <category>cloudinary</category>
      <category>webdev</category>
      <category>security</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Share your thoughts/suggestions 🙂</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Fri, 02 Jan 2026 16:42:33 +0000</pubDate>
      <link>https://dev.to/adeelabbas/share-your-thoughtssuggestions-j92</link>
      <guid>https://dev.to/adeelabbas/share-your-thoughtssuggestions-j92</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-story__hidden-navigation-link"&gt;Automated Reporting System&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/adeelabbas" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" alt="adeelabbas profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adeelabbas" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ADEEL ABBAS
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ADEEL ABBAS
                
                
              
              &lt;div id="story-author-preview-content-3138609" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adeelabbas" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ADEEL ABBAS&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 31 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" id="article-link-3138609"&gt;
          Automated Reporting System
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/lambda"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;lambda&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/s3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;s3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/awscommunitybuilder"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;awscommunitybuilder&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;17&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>aws</category>
      <category>lambda</category>
      <category>s3</category>
      <category>awscommunitybuilder</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Thu, 01 Jan 2026 06:22:03 +0000</pubDate>
      <link>https://dev.to/adeelabbas/-1ba0</link>
      <guid>https://dev.to/adeelabbas/-1ba0</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-story__hidden-navigation-link"&gt;Automated Reporting System&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/adeelabbas" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" alt="adeelabbas profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adeelabbas" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ADEEL ABBAS
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ADEEL ABBAS
                
                
              
              &lt;div id="story-author-preview-content-3138609" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adeelabbas" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ADEEL ABBAS&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 31 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" id="article-link-3138609"&gt;
          Automated Reporting System
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/lambda"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;lambda&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/s3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;s3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/awscommunitybuilder"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;awscommunitybuilder&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;17&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adeelabbas/automated-reporting-system-47ob#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>aws</category>
      <category>lambda</category>
      <category>s3</category>
      <category>awscommunitybuilder</category>
    </item>
    <item>
      <title>Automated Reporting System</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Wed, 31 Dec 2025 15:49:13 +0000</pubDate>
      <link>https://dev.to/adeelabbas/automated-reporting-system-47ob</link>
      <guid>https://dev.to/adeelabbas/automated-reporting-system-47ob</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;br&gt;
We’ll build a system using &lt;strong&gt;AWS Lambda&lt;/strong&gt; and other &lt;strong&gt;serverless&lt;/strong&gt; tools to automate daily &lt;strong&gt;reporting&lt;/strong&gt;. The system will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Collect data from multiple sources.&lt;/li&gt;
&lt;li&gt;   Generate a &lt;strong&gt;PDF&lt;/strong&gt; report.&lt;/li&gt;
&lt;li&gt;   Send the report via &lt;strong&gt;email&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;   Trigger this process &lt;strong&gt;daily&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This guide assumes you have a basic understanding of &lt;strong&gt;AWS&lt;/strong&gt;. Let’s start!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create an S3 Bucket&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;strong&gt;S3&lt;/strong&gt; service.&lt;/li&gt;
&lt;li&gt; Click &lt;strong&gt;Create bucket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Name your bucket (e.g., &lt;code&gt;daily-reports-s3-bucket&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Keep other settings &lt;strong&gt;default&lt;/strong&gt; and click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; This bucket will &lt;strong&gt;store&lt;/strong&gt; the reports if needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshz86eld3mi4fqpy77bx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshz86eld3mi4fqpy77bx.webp" alt="S3" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Verify an Email Address in SES&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Amazon SES&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Navigate to &lt;strong&gt;Email Addresses&lt;/strong&gt; under &lt;strong&gt;Identity Management&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Click Verify a &lt;strong&gt;New&lt;/strong&gt; Email Address and enter your &lt;strong&gt;email&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Check your email &lt;strong&gt;inbox&lt;/strong&gt; and click the &lt;strong&gt;verification link&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows &lt;strong&gt;SES&lt;/strong&gt; to send &lt;strong&gt;emails&lt;/strong&gt; from this address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdwrcfi7whnajybdkimh.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdwrcfi7whnajybdkimh.webp" alt="SES" width="800" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Write the Lambda Function&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Go to &lt;strong&gt;AWS Lambda&lt;/strong&gt; and click the &lt;strong&gt;Create function&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Choose:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;    &lt;strong&gt;Author from scratch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;    Function name: daily-report-lambda.&lt;/li&gt;
&lt;li&gt;    Runtime: &lt;code&gt;Python 3.9 (or later)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;   Click the &lt;strong&gt;Create&lt;/strong&gt; function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code for the Lambda Function&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll to the &lt;strong&gt;Code&lt;/strong&gt; section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replace&lt;/strong&gt; the default code with the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
from fpdf import FPDF
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

def lambda_handler(event, context):
    try:
        # Generate the PDF report
        pdf = FPDF()
        pdf.add_page()
        pdf.set_font("Arial", size=12)
        pdf.cell(200, 10, txt="Daily Report", ln=True, align="C")
        pdf.cell(200, 10, txt="This is your automated report.", ln=True)

        # Save the PDF
        report_path = "/tmp/daily_report.pdf"
        pdf.output(report_path)

        # Upload to S3 (Optional)
        s3 = boto3.client('s3')
        bucket_name = "daily-reports-s3-bucket"
        s3.upload_file(report_path, bucket_name, "daily_report.pdf")

        # Send email via SES with attachment using raw email
        ses = boto3.client('ses')
        msg = MIMEMultipart()
        msg['From'] = "sender_email@gmail.com"  # Replace with your SES verified email
        msg['To'] = "receiver_email@gmail.com"  # Replace with recipient email
        msg['Subject'] = "Daily Report"

        # Attach the text body
        body = MIMEText("Please find the attached report.", 'plain')
        msg.attach(body)

        # Attach the PDF report
        with open(report_path, 'rb') as file:
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(file.read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', f'attachment; filename={os.path.basename(report_path)}')
            msg.attach(part)

        # Send the email using SES's send_raw_email
        response = ses.send_raw_email(
            Source=msg['From'],
            Destinations=[msg['To']],
            RawMessage={'Data': msg.as_string()}
        )

        return {"status": "success", "response": response}

    except Exception as e:
        return {"status": "error", "message": str(e)}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Install Libraries Locally and Deploy (Optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will use third-party libraries like &lt;code&gt;fpdf&lt;/code&gt;, as &lt;code&gt;fpdf&lt;/code&gt; is not available in &lt;strong&gt;Lambda&lt;/strong&gt;, package them &lt;strong&gt;locally&lt;/strong&gt;:&lt;br&gt;
Install &lt;code&gt;fpdf&lt;/code&gt; locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;pip install fpdf&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zip&lt;/strong&gt; the files and upload them to the &lt;strong&gt;Lambda&lt;/strong&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxar17vlw10q8fb7dp7zy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxar17vlw10q8fb7dp7zy.webp" alt="lambda" width="696" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Set Up EventBridge Trigger&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;EventBridge&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Click Create &lt;strong&gt;rule&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Name: &lt;code&gt;daily-report-trigger&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Define pattern: &lt;strong&gt;Schedule&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Cron expression: &lt;code&gt;"cron(0 9 * * ? *)" (9:00 AM UTC daily).&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Under &lt;strong&gt;Target&lt;/strong&gt;, choose your &lt;strong&gt;Lambda&lt;/strong&gt; function (&lt;code&gt;daily-report-lambda&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmci31utwhea4n2wynxli.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmci31utwhea4n2wynxli.webp" alt="Cron" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Test the Lambda Function&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;Test&lt;/strong&gt; tab in your &lt;strong&gt;Lambda&lt;/strong&gt; function.&lt;/li&gt;
&lt;li&gt;Create a new &lt;strong&gt;test&lt;/strong&gt; event (leave it blank).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Test&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Check your email &lt;strong&gt;inbox&lt;/strong&gt; for the report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0isfnaudjhjcpg2t5ui.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0isfnaudjhjcpg2t5ui.webp" alt="Report" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You’ve built a serverless reporting system! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Cloud Learning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adeel Abbas&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>s3</category>
      <category>awscommunitybuilder</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Sun, 28 Dec 2025 10:56:41 +0000</pubDate>
      <link>https://dev.to/adeelabbas/-402c</link>
      <guid>https://dev.to/adeelabbas/-402c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d" class="crayons-story__hidden-navigation-link"&gt;Restrict IAM User Access after AWS Budget Limit is reached&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/adeelabbas" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" alt="adeelabbas profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adeelabbas" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ADEEL ABBAS
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ADEEL ABBAS
                
                
              
              &lt;div id="story-author-preview-content-3126605" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adeelabbas" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1969939%2Fe97e539f-858b-45a0-9dd5-0697a2a58dd4.jpeg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ADEEL ABBAS&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 25 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d" id="article-link-3126605"&gt;
          Restrict IAM User Access after AWS Budget Limit is reached
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/lambda"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;lambda&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/iam"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;iam&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/awsbilling"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;awsbilling&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;14&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>lambda</category>
      <category>aws</category>
      <category>iam</category>
      <category>awsbilling</category>
    </item>
    <item>
      <title>Restrict IAM User Access after AWS Budget Limit is reached</title>
      <dc:creator>ADEEL ABBAS</dc:creator>
      <pubDate>Thu, 25 Dec 2025 11:27:16 +0000</pubDate>
      <link>https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d</link>
      <guid>https://dev.to/adeelabbas/restrict-iam-user-access-after-aws-budget-limit-is-reached-l9d</guid>
      <description>&lt;p&gt;&lt;strong&gt;💰 Automatically Restrict IAM User Access After AWS Budget Limit is Reached&lt;/strong&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;At &lt;strong&gt;2:37 AM&lt;/strong&gt;, the &lt;strong&gt;AWS bill&lt;/strong&gt; silently crossed its limit, no alarms, no humans watching.&lt;br&gt;
Seconds later, an &lt;strong&gt;unseen Lambda&lt;/strong&gt; woke up, and just like that, the IAM user’s access vanished mid-click.&lt;br&gt;
The cloud didn’t &lt;strong&gt;crash&lt;/strong&gt;, it &lt;strong&gt;locked&lt;/strong&gt; the door 🔒&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;🎯Goal&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a spend limit (budget) in &lt;strong&gt;AWS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Send an alert using &lt;strong&gt;Amazon SNS&lt;/strong&gt; when the limit is reached.&lt;/li&gt;
&lt;li&gt;Trigger an &lt;strong&gt;AWS Lambda&lt;/strong&gt; function that will restrict an &lt;strong&gt;IAM&lt;/strong&gt; user.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;IAM&lt;/strong&gt; user will lose &lt;strong&gt;AWS&lt;/strong&gt; access automatically when the budget is &lt;strong&gt;exceeded&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic &lt;strong&gt;AWS&lt;/strong&gt; &lt;strong&gt;Account&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM&lt;/strong&gt; user to test&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM permissions&lt;/strong&gt; to create &lt;strong&gt;budgets&lt;/strong&gt;, &lt;strong&gt;Lambda&lt;/strong&gt; functions, and &lt;strong&gt;SNS&lt;/strong&gt; topics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔧 Step 1: Create an AWS Budget&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the AWS Console, choose &lt;strong&gt;Billing&lt;/strong&gt;, then &lt;strong&gt;Budgets&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Budget&lt;/strong&gt; name: &lt;strong&gt;Cost Budget&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Spend limit (let &lt;code&gt;$10&lt;/code&gt; per month).&lt;/li&gt;
&lt;li&gt;Add an alert threshold at &lt;code&gt;100%&lt;/code&gt; of the budget.&lt;/li&gt;
&lt;li&gt;Create a new &lt;strong&gt;SNS Topic&lt;/strong&gt; when prompted (we'll configure  later).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🛠️ Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Budget: &lt;code&gt;$10/month&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Alert at: &lt;code&gt;100%&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔔 Step 2: Create an SNS Topic&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Amazon SNS choose &lt;strong&gt;Topics&lt;/strong&gt; then &lt;strong&gt;Create Topic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Standard Topic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the name (let: BudgetExceedTopic).&lt;/li&gt;
&lt;li&gt;Click Create Topic.&lt;/li&gt;
&lt;li&gt;Subscribe &lt;strong&gt;Lambda&lt;/strong&gt; to &lt;strong&gt;SNS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We will will link this 
&lt;strong&gt;SNS topic&lt;/strong&gt; to a &lt;strong&gt;Lambda&lt;/strong&gt; function in the next step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🖥️ Step 3: Create a Lambda Function&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Lambda&lt;/strong&gt; → &lt;strong&gt;Create Function&lt;/strong&gt; → &lt;strong&gt;Author from scratch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Function name: RestrictIAMUserFunction&lt;/li&gt;
&lt;li&gt;Runtime: Python &lt;code&gt;3.12&lt;/code&gt; (or latest)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcaianldabmxzruwlsfx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcaianldabmxzruwlsfx.webp" alt=" " width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste This Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
import json

iam = boto3.client('iam')

def lambda_handler(event, context):
    user_name = 'adeel'  # Change this to your IAM username

    deny_policy = {
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*"
        }]
    }

    iam.put_user_policy(
        UserName=user_name,
        PolicyName='DenyAllPolicy',
        PolicyDocument=json.dumps(deny_policy)
    )

    return {"status": f"Permissions restricted for user {user_name}"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🔒 Step 4: Add IAM Permissions to Lambda&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Lambda needs permissions to:&lt;/li&gt;
&lt;li&gt;Write logs&lt;/li&gt;
&lt;li&gt;Attach IAM policies
&lt;strong&gt;Inline Policy to Add:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrakbllnjw1c80dd6zu2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrakbllnjw1c80dd6zu2.webp" alt=" " width="730" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👉 Replace YOUR_ACCOUNT_ID With your AWS Account ID.&lt;/li&gt;
&lt;li&gt;If you want to restrict all users, use:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;"Resource": "arn:aws:iam::YOUR_ACCOUNT_ID:user/*"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔗 Step 5: Connect SNS to Lambda&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your &lt;strong&gt;SNS Topic&lt;/strong&gt;, choose &lt;strong&gt;Subscriptions&lt;/strong&gt;, then &lt;strong&gt;Create&lt;/strong&gt; Subscription.&lt;/li&gt;
&lt;li&gt;Choose Protocol: &lt;strong&gt;AWS Lambda&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose the Lambda function we just &lt;strong&gt;created&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Confirm &lt;strong&gt;subscription&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✔️ Now, when the budget threshold is &lt;strong&gt;exceeded&lt;/strong&gt;, SNS will automatically &lt;strong&gt;trigger&lt;/strong&gt; the Lambda function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6qtudmtbduc4h6hn8uh.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6qtudmtbduc4h6hn8uh.webp" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Step 6: Review and Test&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Budget Alerts&lt;/strong&gt; should now trigger your SNS topic when the budget is crossed.&lt;/li&gt;
&lt;li&gt;SNS will trigger the &lt;strong&gt;Lambda&lt;/strong&gt; function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt; will restrict the &lt;strong&gt;IAM&lt;/strong&gt; user by attaching a &lt;strong&gt;deny-all&lt;/strong&gt; policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✔️ You can verify this by checking the user in IAM ( Inline Policies )&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Key Tips&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Budgets update a few times a day, so the restriction is not instant, but timely.&lt;/li&gt;
&lt;li&gt;Always test on a non-production user first.&lt;/li&gt;
&lt;li&gt;You can enhance this by making the Lambda dynamically read the username from the SNS message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✨ Happy Cloud Learning!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you found this blog helpful, Subscribe here:&lt;br&gt;
&lt;a href="https://www.youtube.com/@CloudTipsByAD" rel="noopener noreferrer"&gt;CloudTipsByAD&lt;/a&gt; &lt;/p&gt;

</description>
      <category>lambda</category>
      <category>aws</category>
      <category>iam</category>
      <category>awsbilling</category>
    </item>
  </channel>
</rss>
