<?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: Hassan Aftab</title>
    <description>The latest articles on DEV Community by Hassan Aftab (@hassan_aftab).</description>
    <link>https://dev.to/hassan_aftab</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1616077%2F5ea6d5e4-cc2e-4793-80b9-b418cd660553.jpg</url>
      <title>DEV Community: Hassan Aftab</title>
      <link>https://dev.to/hassan_aftab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hassan_aftab"/>
    <language>en</language>
    <item>
      <title>AI-Powered Penetration Testing: How I Used Claude + Kali Linux MCP to Automate Security Assessments</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Thu, 22 Jan 2026 08:37:25 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/ai-powered-penetration-testing-how-i-used-claude-kali-linux-mcp-to-automate-security-assessments-20d3</link>
      <guid>https://dev.to/hassan_aftab/ai-powered-penetration-testing-how-i-used-claude-kali-linux-mcp-to-automate-security-assessments-20d3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: The Future of Offensive Security is Conversational
&lt;/h2&gt;

&lt;p&gt;Picture this: Instead of juggling multiple terminal windows, memorizing command syntax, and manually piecing together scan results, you simply have a conversation with an AI that executes security tools, analyzes findings, and generates comprehensive reports—all in real-time.&lt;/p&gt;

&lt;p&gt;Sounds like science fiction? It's not. I just completed a full penetration test using Claude Desktop connected to a Kali Linux MCP (Model Context Protocol) server, and the experience has fundamentally changed how I think about security assessments.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through exactly how I set this up, what I discovered, and why this approach is a game-changer for DevSecOps professionals.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Traditional Pen Testing
&lt;/h2&gt;

&lt;p&gt;As security professionals, we've all been there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terminal juggling&lt;/strong&gt;: Multiple SSH sessions, tmux panes, and terminal tabs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command syntax hell&lt;/strong&gt;: Was it &lt;code&gt;nmap -sV -sC&lt;/code&gt; or &lt;code&gt;-sC -sV&lt;/code&gt;? Do I need &lt;code&gt;sudo&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context switching&lt;/strong&gt;: Running a scan, analyzing output, documenting findings, then moving to the next tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report fatigue&lt;/strong&gt;: Hours spent formatting findings into readable reports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge gaps&lt;/strong&gt;: Junior analysts missing critical steps in methodology&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't get me wrong—traditional pen testing works. But it's slow, error-prone, and doesn't scale well for modern DevSecOps teams conducting continuous security assessments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter AI-Assisted Security Testing
&lt;/h2&gt;

&lt;p&gt;The idea is simple but powerful: What if we could have a conversational interface to our security tools?&lt;/p&gt;

&lt;p&gt;Instead of this traditional workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Terminal 1: Port scanning&lt;/span&gt;
nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 80,443 target.example.com &lt;span class="nt"&gt;-oN&lt;/span&gt; nmap_results.txt

&lt;span class="c"&gt;# Terminal 2: Directory enumeration  &lt;/span&gt;
ffuf &lt;span class="nt"&gt;-u&lt;/span&gt; https://target.example.com/FUZZ &lt;span class="nt"&gt;-w&lt;/span&gt; wordlist.txt &lt;span class="nt"&gt;-mc&lt;/span&gt; 200,403

&lt;span class="c"&gt;# Terminal 3: Header analysis&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://target.example.com

&lt;span class="c"&gt;# Terminal 4: Take notes, start writing report...&lt;/span&gt;
vim findings.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Me: "Run nmap on ports 80 and 443, then check for common vulnerabilities with other tools"

AI: *Executes scans, analyzes results, identifies issues*
    "I've completed the assessment. Found strong security headers but 
    discovered CSP using 'unsafe-inline'. Here's the full report..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't just about convenience—it's about &lt;strong&gt;fundamentally rethinking how we approach security testing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technology Stack
&lt;/h2&gt;

&lt;p&gt;Here's what I used to make this work:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Claude Desktop&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The AI interface that understands security context and can reason about findings. Claude can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand security terminology and concepts&lt;/li&gt;
&lt;li&gt;Chain multiple tools together logically&lt;/li&gt;
&lt;li&gt;Analyze output for actual vulnerabilities (not just running tools)&lt;/li&gt;
&lt;li&gt;Generate professional reports with prioritized findings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Kali Linux MCP Server&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A Model Context Protocol server that provides Claude with secure access to a Kali Linux environment. Think of it as a bridge between the AI and your security tools.&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sandboxed execution environment&lt;/li&gt;
&lt;li&gt;Support for all standard Kali tools&lt;/li&gt;
&lt;li&gt;Background job management for long-running scans&lt;/li&gt;
&lt;li&gt;Output parsing and structured results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Traditional Security Tools&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The same tools we know and love:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;nmap&lt;/strong&gt; - Port scanning and service detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ffuf&lt;/strong&gt; - Directory and file enumeration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;whatweb&lt;/strong&gt; - Technology fingerprinting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;curl&lt;/strong&gt; - HTTP analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;netcat&lt;/strong&gt; - Network connectivity testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference? Now they're orchestrated by AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Assessment: A Real-World Example
&lt;/h2&gt;

&lt;p&gt;Let me walk you through an actual security assessment I performed using this setup. (All identifying information has been anonymized for obvious reasons.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: Reconnaissance
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "Let's run a quick nmap scan on ports 80 and 443"&lt;/p&gt;

&lt;p&gt;Claude immediately executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 80,443 target.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within seconds, I had results showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Port 80&lt;/strong&gt;: Returns 426 Upgrade Required (forcing HTTPS ✅)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port 443&lt;/strong&gt;: nginx server, valid SSL certificate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology&lt;/strong&gt;: HTML5 Single Page Application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's where it gets interesting—Claude didn't just dump the nmap output. It &lt;strong&gt;analyzed&lt;/strong&gt; it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The application properly enforces HTTPS. Port 80 returns 426 Upgrade Required, &lt;br&gt;
which is better than a simple 301 redirect. The SSL certificate is valid and &lt;br&gt;
the server is running nginx. Let's check the security headers next."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Phase 2: Security Header Analysis
&lt;/h3&gt;

&lt;p&gt;Without me having to specify the exact curl command, Claude proactively ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://target.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And immediately identified the security posture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Strong Controls Found:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HSTS with preload (max-age=31536000)&lt;/li&gt;
&lt;li&gt;X-Frame-Options: SAMEORIGIN&lt;/li&gt;
&lt;li&gt;X-XSS-Protection: 1; mode=block&lt;/li&gt;
&lt;li&gt;X-Content-Type-Options: nosniff&lt;/li&gt;
&lt;li&gt;Secure cookies with HttpOnly and SameSite flags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Concerns Identified:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content-Security-Policy uses 'unsafe-inline'&lt;/li&gt;
&lt;li&gt;Multiple trusted external domains in CSP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude didn't just list these—it explained the security implications of each finding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: Directory Enumeration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "Let's try ffuf for directory enumeration"&lt;/p&gt;

&lt;p&gt;Claude executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffuf &lt;span class="nt"&gt;-u&lt;/span&gt; https://target.example.com/FUZZ &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/common.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-mc&lt;/span&gt; 200,204,301,302,307,401,403,405 &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-fc&lt;/span&gt; 404 &lt;span class="nt"&gt;-t&lt;/span&gt; 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Results&lt;/strong&gt;: 4,750 paths tested in ~25 seconds at 190 req/sec&lt;/p&gt;

&lt;p&gt;The interesting part? Claude automatically analyzed the results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4,674 paths&lt;/strong&gt; returned 200 with identical content (typical SPA behavior)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;19 paths&lt;/strong&gt; returned 403 Forbidden (sensitive files properly blocked)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2 paths&lt;/strong&gt; returned 301 redirects (potential misconfiguration!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 4: Deep Dive on Findings
&lt;/h3&gt;

&lt;p&gt;Here's where AI really shines. Claude noticed something interesting in the redirects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/assets → http://target.example.com:4200/assets/
/media  → http://target.example.com:4200/media/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude's analysis:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"These redirects reference port 4200, which is the default port for Angular &lt;br&gt;
development servers. This suggests either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A development server is running in production&lt;/li&gt;
&lt;li&gt;Nginx is misconfigured&lt;/li&gt;
&lt;li&gt;Assets aren't being served properly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me test if port 4200 is accessible..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude then &lt;strong&gt;automatically&lt;/strong&gt; ran netcat to test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-zv&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 5 target.example.com 4200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: Port 4200 is NOT accessible externally (good!), but the configuration issue remains.&lt;/p&gt;

&lt;p&gt;This kind of &lt;strong&gt;contextual reasoning&lt;/strong&gt;—connecting dots between different findings—is where AI really excels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 5: Comprehensive Reporting
&lt;/h3&gt;

&lt;p&gt;At the end, I simply said: "Generate a comprehensive security report"&lt;/p&gt;

&lt;p&gt;Claude produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Executive summary with risk rating&lt;/li&gt;
&lt;li&gt;✅ Detailed findings with CVSS-style severity ratings&lt;/li&gt;
&lt;li&gt;✅ Technical details for each vulnerability&lt;/li&gt;
&lt;li&gt;✅ Prioritized remediation recommendations&lt;/li&gt;
&lt;li&gt;✅ Compliance mapping (OWASP Top 10)&lt;/li&gt;
&lt;li&gt;✅ Evidence with exact commands and output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total time from start to final report&lt;/strong&gt;: ~15 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional approach&lt;/strong&gt;: Would have taken 2-3 hours&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Findings (Anonymized)
&lt;/h2&gt;

&lt;p&gt;Here's what the assessment uncovered:&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 Strong Security Controls (Good News)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTTPS Enforcement&lt;/strong&gt;: Perfect implementation with 426 status code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Headers&lt;/strong&gt;: Comprehensive set of modern security headers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Access Controls&lt;/strong&gt;: All sensitive files (.git, .env, .svn) properly blocked with 403&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie Security&lt;/strong&gt;: HttpOnly, Secure, and SameSite flags properly set&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS&lt;/strong&gt;: Valid certificate, HTTP/2 enabled&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🟡 Medium Priority Issues
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CSP 'unsafe-inline'&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both script-src and style-src allow inline scripts&lt;/li&gt;
&lt;li&gt;Reduces XSS protection effectiveness&lt;/li&gt;
&lt;li&gt;Recommendation: Remove 'unsafe-inline', use nonce-only approach&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Port 4200 References&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redirects expose internal development port&lt;/li&gt;
&lt;li&gt;Suggests nginx misconfiguration&lt;/li&gt;
&lt;li&gt;Recommendation: Fix asset serving configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Development Environment Exposure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain clearly marked as "dev"&lt;/li&gt;
&lt;li&gt;robots.txt confirms staging environment&lt;/li&gt;
&lt;li&gt;Recommendation: Implement IP whitelisting or VPN access&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🟢 Low Priority Observations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Broad CSP Domain Trust&lt;/strong&gt;: Multiple Azure services in allow-list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Header Exposure&lt;/strong&gt;: nginx version visible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificate Expiration&lt;/strong&gt;: Valid for 2 more months&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Overall Risk Rating&lt;/strong&gt;: LOW-MEDIUM&lt;/p&gt;

&lt;p&gt;The application has solid security fundamentals with room for CSP hardening and access control improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Value: Beyond Tool Execution
&lt;/h2&gt;

&lt;p&gt;Here's what makes this approach truly powerful—it's not just about running tools faster. It's about:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Intelligent Analysis&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Claude doesn't just execute commands; it understands security concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recognizes what 'unsafe-inline' means for CSP&lt;/li&gt;
&lt;li&gt;Knows that port 4200 is an Angular dev server&lt;/li&gt;
&lt;li&gt;Understands the relationship between findings&lt;/li&gt;
&lt;li&gt;Prioritizes issues based on actual risk&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Contextual Reasoning&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When Claude found the port 4200 reference, it didn't stop there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tested if the port was accessible&lt;/li&gt;
&lt;li&gt;Explained what port 4200 typically indicates&lt;/li&gt;
&lt;li&gt;Suggested multiple potential causes&lt;/li&gt;
&lt;li&gt;Recommended specific fixes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Adaptive Methodology&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The assessment flow was dynamic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Started with broad reconnaissance&lt;/li&gt;
&lt;li&gt;Dove deeper based on findings&lt;/li&gt;
&lt;li&gt;Connected related issues&lt;/li&gt;
&lt;li&gt;Adjusted scan parameters based on results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Knowledge Transfer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Every step was explained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why each tool was chosen&lt;/li&gt;
&lt;li&gt;What the output means&lt;/li&gt;
&lt;li&gt;How findings relate to security principles&lt;/li&gt;
&lt;li&gt;What the business impact is&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it &lt;strong&gt;perfect for training junior security analysts&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Applications
&lt;/h2&gt;

&lt;p&gt;This approach works incredibly well for:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Continuous Security Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Integrate AI-assisted scanning into CI/CD pipelines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your CI/CD pipeline&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Scan&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;claude-security-scan --target $STAGING_URL \&lt;/span&gt;
                         &lt;span class="s"&gt;--output security-report.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Compliance Audits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;"Check this application against OWASP Top 10 and generate a compliance report"&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Security Training&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Junior analysts can learn by watching Claude's methodology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which tools to use when&lt;/li&gt;
&lt;li&gt;How to interpret results&lt;/li&gt;
&lt;li&gt;What findings matter most&lt;/li&gt;
&lt;li&gt;How to communicate risk&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Bug Bounty Hunting&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Accelerate reconnaissance phase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quick subdomain enumeration&lt;/li&gt;
&lt;li&gt;Technology fingerprinting&lt;/li&gt;
&lt;li&gt;Common vulnerability checks&lt;/li&gt;
&lt;li&gt;Automated documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Red Team Exercises&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Chain complex attack scenarios:&lt;br&gt;
"Enumerate subdomains, identify web applications, scan for vulnerabilities, &lt;br&gt;
and generate target priority list"&lt;/p&gt;
&lt;h2&gt;
  
  
  The Limitations (Let's Be Honest)
&lt;/h2&gt;

&lt;p&gt;This approach isn't perfect. Here's what it &lt;strong&gt;doesn't&lt;/strong&gt; do:&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Complex Exploitation
&lt;/h3&gt;

&lt;p&gt;Claude can identify vulnerabilities but won't automatically exploit them. SQLi, XSS, and RCE still require human expertise.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Social Engineering
&lt;/h3&gt;

&lt;p&gt;No AI assistance for phishing, pretexting, or physical security testing.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Zero-Day Discovery
&lt;/h3&gt;

&lt;p&gt;This accelerates known vulnerability scanning, not novel vulnerability research.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Replace Critical Thinking
&lt;/h3&gt;

&lt;p&gt;AI amplifies human skills; it doesn't replace security expertise and judgment.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Handle Authentication
&lt;/h3&gt;

&lt;p&gt;Complex authenticated scanning still requires manual session management.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ethical Considerations
&lt;/h2&gt;

&lt;p&gt;Let me be crystal clear: &lt;strong&gt;Always get explicit written authorization before security testing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This technology makes scanning easier, which also means it's easier to accidentally (or intentionally) test unauthorized systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Golden rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✅ Get written permission before ANY security testing&lt;/li&gt;
&lt;li&gt;✅ Stay within authorized scope&lt;/li&gt;
&lt;li&gt;✅ Document everything&lt;/li&gt;
&lt;li&gt;✅ Report findings responsibly&lt;/li&gt;
&lt;li&gt;✅ Anonymize data when sharing publicly&lt;/li&gt;
&lt;li&gt;❌ Never test production systems without approval&lt;/li&gt;
&lt;li&gt;❌ Never share sensitive findings publicly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unauthorized security testing is illegal in most jurisdictions. Don't be that person.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting It Up Yourself
&lt;/h2&gt;

&lt;p&gt;Want to try this? Here's how to get started:&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude Desktop (or API access)&lt;/li&gt;
&lt;li&gt;Docker (for Kali Linux container)&lt;/li&gt;
&lt;li&gt;Basic understanding of security tools&lt;/li&gt;
&lt;li&gt;Authorization for a test environment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Quick Start: &lt;a href="https://github.com/hassanaftab93/pentesting-mcp-setup" rel="noopener noreferrer"&gt;Follow this Guide&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# 1. Clone the Kali MCP server&lt;/span&gt;
git clone https://github.com/hassanaftab93/kali-docker-mcp

&lt;span class="c"&gt;# 2. Build the Docker container&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;kali-mcp-server
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; kali-mcp &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# 3. Run the server&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 kali-mcp

&lt;span class="c"&gt;# 4. Configure Claude Desktop&lt;/span&gt;
&lt;span class="c"&gt;# Add MCP server configuration to settings&lt;/span&gt;

&lt;span class="c"&gt;# 5. Start testing!&lt;/span&gt;
&lt;span class="c"&gt;# Open Claude Desktop and start conversing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;(Note: URLs anonymized for security. Search for "Kali MCP Server" or "MCP penetration testing" for actual repositories)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Future of Security Testing
&lt;/h2&gt;

&lt;p&gt;This is just the beginning. Here's where I see this going:&lt;/p&gt;
&lt;h3&gt;
  
  
  Short Term (Now - 6 months)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Integration with more specialized tools (Burp Suite, Metasploit)&lt;/li&gt;
&lt;li&gt;Automated exploit validation&lt;/li&gt;
&lt;li&gt;Real-time vulnerability database lookups&lt;/li&gt;
&lt;li&gt;Custom security workflow automation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Medium Term (6-18 months)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI-assisted exploit development&lt;/li&gt;
&lt;li&gt;Automated threat modeling&lt;/li&gt;
&lt;li&gt;Intelligent false positive filtering&lt;/li&gt;
&lt;li&gt;Natural language security policies&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Long Term (18+ months)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Autonomous security testing agents&lt;/li&gt;
&lt;li&gt;AI-powered red team exercises&lt;/li&gt;
&lt;li&gt;Predictive vulnerability analysis&lt;/li&gt;
&lt;li&gt;Self-healing security systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  My Take: Augmentation, Not Replacement
&lt;/h2&gt;

&lt;p&gt;Here's the bottom line: &lt;strong&gt;AI won't replace security professionals&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;But security professionals who use AI will replace those who don't.&lt;/p&gt;

&lt;p&gt;This technology handles the tedious parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool execution&lt;/li&gt;
&lt;li&gt;Output parsing&lt;/li&gt;
&lt;li&gt;Report generation&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While we focus on the parts that require human expertise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical thinking&lt;/li&gt;
&lt;li&gt;Exploit development&lt;/li&gt;
&lt;li&gt;Business context&lt;/li&gt;
&lt;li&gt;Strategic recommendations&lt;/li&gt;
&lt;li&gt;Client communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The future of offensive security is &lt;strong&gt;collaborative&lt;/strong&gt;—humans and AI working together.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion: The Paradigm Shift
&lt;/h2&gt;

&lt;p&gt;Going from traditional pen testing to AI-assisted security assessment feels like going from punch cards to a modern IDE. The fundamental skills are the same, but the experience is night and day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What took 3 hours now takes 15 minutes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What required deep tool knowledge now requires clear communication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was tedious documentation is now automatic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't about making security testing easier (though it does). It's about making it &lt;strong&gt;better&lt;/strong&gt;, &lt;strong&gt;faster&lt;/strong&gt;, and &lt;strong&gt;more consistent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're in DevSecOps, offensive security, or security research, I highly recommend exploring AI-assisted workflows. Start small—automate one part of your process—and expand from there.&lt;/p&gt;

&lt;p&gt;The tools are ready. The technology works. The only question is: &lt;strong&gt;Are you ready to adapt?&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Resources &amp;amp; Further Reading
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tools Mentioned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Desktop / Claude API&lt;/li&gt;
&lt;li&gt;Kali Linux&lt;/li&gt;
&lt;li&gt;nmap, ffuf, whatweb, curl&lt;/li&gt;
&lt;li&gt;Model Context Protocol (MCP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Learning Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OWASP Testing Guide&lt;/li&gt;
&lt;li&gt;Model Context Protocol Documentation
&lt;/li&gt;
&lt;li&gt;Kali Linux Documentation&lt;/li&gt;
&lt;li&gt;AI Safety in Security Testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Communities:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;r/netsec&lt;/li&gt;
&lt;li&gt;HackerOne Community&lt;/li&gt;
&lt;li&gt;AI Security Research Groups&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  About This Article
&lt;/h2&gt;

&lt;p&gt;This assessment was performed on an authorized test environment with explicit permission. All identifying information has been anonymized. The findings and methodology shared here are for educational purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions? Comments?&lt;/strong&gt; Drop them below or connect with me on LinkedIn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Found this useful?&lt;/strong&gt; Share it with your security team and help spread knowledge about AI-assisted security testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;#cybersecurity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#ai&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#devops&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#testing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#automation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#tutorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#webdev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#cloudcomputing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>devops</category>
      <category>security</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>App of Apps Pattern: Efficient Kubernetes Deployment Strategies with Terraform and ArgoCD</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Thu, 23 Jan 2025 19:21:50 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/app-of-apps-pattern-efficient-kubernetes-deployment-strategies-with-terraform-and-argocd-ch9</link>
      <guid>https://dev.to/hassan_aftab/app-of-apps-pattern-efficient-kubernetes-deployment-strategies-with-terraform-and-argocd-ch9</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cloud-Native Technologies Overview&lt;/li&gt;
&lt;li&gt;Terraform, Kubernetes, ArgoCD Integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Traditional Infrastructure Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Manual Management Pitfalls&lt;/li&gt;
&lt;li&gt;Deployment Complexities&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Modern Infrastructure Approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure as Code&lt;/li&gt;
&lt;li&gt;GitOps Principles&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Terraform: Infrastructure Provisioning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cluster Configuration&lt;/li&gt;
&lt;li&gt;Network Setup&lt;/li&gt;
&lt;li&gt;Resource Management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. ArgoCD Configuration
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Initial Setup&lt;/li&gt;
&lt;li&gt;RBAC Configuration&lt;/li&gt;
&lt;li&gt;Login Procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. GitOps Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Repository Structures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Application Repository&lt;/li&gt;
&lt;li&gt;GitOps Repository&lt;/li&gt;
&lt;li&gt;Manifest Management&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation Strategies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Repository Configuration&lt;/li&gt;
&lt;li&gt;ArgoCD CLI Commands&lt;/li&gt;
&lt;li&gt;"App of Apps" Pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. GitOps Philosophical Principles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Declarative Configuration&lt;/li&gt;
&lt;li&gt;Version Control&lt;/li&gt;
&lt;li&gt;Automated Synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Organizational Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure Team Advantages&lt;/li&gt;
&lt;li&gt;Development Team Improvements&lt;/li&gt;
&lt;li&gt;Operational Efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Practical Implementation Strategy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure Definition&lt;/li&gt;
&lt;li&gt;ArgoCD Deployment&lt;/li&gt;
&lt;li&gt;Continuous Integration Workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Technology Synergy&lt;/li&gt;
&lt;li&gt;Scalability and Agility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Recommended Tools And Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure Tools&lt;/li&gt;
&lt;li&gt;Monitoring Solutions&lt;/li&gt;
&lt;li&gt;Version Control Platforms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the rapidly evolving landscape of cloud-native technologies, organizations are continuously seeking strategies to streamline infrastructure provisioning, enhance deployment reliability, and improve team collaboration.&lt;/p&gt;

&lt;p&gt;The combination of Terraform, Kubernetes, ArgoCD, and GitOps principles offers a powerful solution to these challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Traditional Infrastructure Challenge
&lt;/h2&gt;

&lt;p&gt;Traditionally, infrastructure management and application deployments were manual, error-prone processes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent environments&lt;/li&gt;
&lt;li&gt;Configuration drift&lt;/li&gt;
&lt;li&gt;Limited visibility into changes&lt;/li&gt;
&lt;li&gt;Complex rollback procedures&lt;/li&gt;
&lt;li&gt;Slow and risky deployments&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%2F1f5hjvw4gc901ym606cc.jpeg" 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%2F1f5hjvw4gc901ym606cc.jpeg" alt="Traditional Infra Deployments to K8s" width="800" height="883"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Enter the Modern Approach Infrastructure as Code and GitOps
&lt;/h2&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%2Fsmopnx4kpm5ic5jn2u1d.jpeg" 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%2Fsmopnx4kpm5ic5jn2u1d.jpeg" alt="ArgoCD deployment methods" width="800" height="848"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform Infrastructure Provisioning Reimagined
&lt;/h3&gt;

&lt;p&gt;Terraform transforms infrastructure management by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defining infrastructure using declarative configuration files&lt;/li&gt;
&lt;li&gt;Supporting multi-cloud and hybrid cloud deployments&lt;/li&gt;
&lt;li&gt;Enabling consistent, reproducible infrastructure creation&lt;/li&gt;
&lt;li&gt;Providing a clear, version-controlled view of infrastructure state&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Terraform Kubernetes Cluster Provisioning Example
&lt;/h4&gt;

&lt;p&gt;In a project, where my &lt;a href="https://github.com/hassanaftab93/gitops-with-terraform-argocd-demoapp" rel="noopener noreferrer"&gt;project&lt;/a&gt; structure is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── Makefile
├── README.md
├── plans
│   └── plan.tfplan
├── resources.helm.tf
├── resources.main.tf
├── resources.outputs.tf
├── resources.variables.tf
├── terraform.backend.tf
├── terraform.data.tf
├── terraform.locals.tf
└── terraform.provider.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;resources.main.tf&lt;/code&gt;, I define the resources required to spin the kubernetes cluster as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"network_security_group"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/network_security_group"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rnd-nsg"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

  &lt;span class="nx"&gt;rules&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;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nsg-rule-1"&lt;/span&gt;
      &lt;span class="nx"&gt;priority&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inbound"&lt;/span&gt;
      &lt;span class="nx"&gt;access&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
      &lt;span class="nx"&gt;protocol&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;source_port_range&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;destination_port_range&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;source_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;destination_address_prefix&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="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nsg-rule-2"&lt;/span&gt;
      &lt;span class="nx"&gt;priority&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Outbound"&lt;/span&gt;
      &lt;span class="nx"&gt;access&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
      &lt;span class="nx"&gt;protocol&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;source_port_range&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;destination_port_range&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;source_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;destination_address_prefix&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="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"virtual_network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/virtual_network"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rndvnet"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;address_space&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"k8ssubnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/subnet"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rndsubnetk8s"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;service_endpoints&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.Web"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;delegation_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="nx"&gt;service_delegation_name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="nx"&gt;service_delegation_actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"podsubnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/subnet"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rndsubnetpods"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.2.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;service_endpoints&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;delegation_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aks-delegation"&lt;/span&gt;
  &lt;span class="nx"&gt;service_delegation_name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.ContainerService/managedClusters"&lt;/span&gt;
  &lt;span class="nx"&gt;service_delegation_actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/subnets/join/action"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"subnet_nsg_association"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/subnet_network_security_group_association"&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;k8ssubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
  &lt;span class="nx"&gt;network_security_group_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;k8ssubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"container_registry"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/container_registry"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rndacrteo"&lt;/span&gt;
  &lt;span class="nx"&gt;sku&lt;/span&gt;                              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Standard"&lt;/span&gt;
  &lt;span class="nx"&gt;is_admin_enabled&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;is_public_network_access_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/kubernetes/kubernetes_cluster"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"k8s-cluster"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;node_count&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;dns_prefix&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rndaks"&lt;/span&gt;
  &lt;span class="nx"&gt;vnet_subnet_id&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;k8ssubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
  &lt;span class="nx"&gt;vm_size&lt;/span&gt;                              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Standard_A2_v2"&lt;/span&gt;
  &lt;span class="nx"&gt;pod_subnet_id&lt;/span&gt;                        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;podsubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
  &lt;span class="nx"&gt;kubernetes_version&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.30.0"&lt;/span&gt;
  &lt;span class="nx"&gt;is_role_based_access_control_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;sku_tier&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Free"&lt;/span&gt;
  &lt;span class="nx"&gt;default_node_pool_name&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"k8spool"&lt;/span&gt;
  &lt;span class="nx"&gt;service_cidr&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.1.0.0/16"&lt;/span&gt;
  &lt;span class="nx"&gt;dns_service_ip&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.1.0.10"&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;k8ssubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;podsubnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"k8s_role_assignment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/role_assignment"&lt;/span&gt;
  &lt;span class="nx"&gt;principal_id&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubelet_identity_object_id&lt;/span&gt;
  &lt;span class="nx"&gt;role_definition_name&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AcrPull"&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;                            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;skip_service_principal_aad_check&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;resources.helm.tf&lt;/code&gt;, I define the resources required to configure the helm charts into the above provisioned cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"ingress_nginx"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/helm/helm_release"&lt;/span&gt;

  &lt;span class="nx"&gt;chart&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ingress-nginx"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ingress-nginx"&lt;/span&gt;
  &lt;span class="nx"&gt;create_namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ingress-nginx"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
    controller:
      service:
        type: LoadBalancer
&lt;/span&gt;&lt;span class="no"&gt;    EOF
&lt;/span&gt;  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://kubernetes.github.io/ingress-nginx"&lt;/span&gt;
  &lt;span class="nx"&gt;providers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;helm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;helm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helmk8s&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_kubernetes_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubernetes&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::ssh://git@ssh.dev.azure.com/v3/&amp;lt;organizationName&amp;gt;/&amp;lt;projectName&amp;gt;/&amp;lt;repoName&amp;gt;//modules/helm/helm_release"&lt;/span&gt;

  &lt;span class="nx"&gt;chart&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argo-cd"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt;
  &lt;span class="nx"&gt;create_namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
    server:
      service:
        type: ClusterIP
      configs:
        params:
          "server.insecure": "true"
    admin:
        username: admin
&lt;/span&gt;&lt;span class="no"&gt;    EOF
&lt;/span&gt;  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://argoproj.github.io/argo-helm"&lt;/span&gt;
  &lt;span class="nx"&gt;providers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;helm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;helm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helmk8s&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_kubernetes_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubernetes&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;Next, we need to run a few commands to be able to access argoCD's server / CLI&lt;/p&gt;

&lt;h5&gt;
  
  
  ArgoCD Initial Setup and Configuration Guide
&lt;/h5&gt;

&lt;h6&gt;
  
  
  1. Password Reset and Retrieval
&lt;/h6&gt;

&lt;h6&gt;
  
  
  # Command Breakdown
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reset the admin secret by clearing existing password data&lt;/span&gt;
kubectl patch secret argocd-secret &lt;span class="nt"&gt;-n&lt;/span&gt; argocd &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"data": {"admin.password": null, "admin.passwordMtime": null}}'&lt;/span&gt;

&lt;span class="c"&gt;##### Restart ArgoCD server to generate new password&lt;/span&gt;
kubectl delete pods &lt;span class="nt"&gt;-n&lt;/span&gt; argocd &lt;span class="nt"&gt;-l&lt;/span&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;argocd-server

&lt;span class="c"&gt;##### Retrieve the initial admin password&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; argocd get secret argocd-initial-admin-secret &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.data.password}"&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use this password later&lt;/p&gt;

&lt;h6&gt;
  
  
  # What This Does
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Clears existing admin password&lt;/li&gt;
&lt;li&gt;Triggers ArgoCD to generate a new password&lt;/li&gt;
&lt;li&gt;Extracts the new password for login&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  2. RBAC (Role-Based Access Control) Configuration
&lt;/h6&gt;

&lt;h6&gt;
  
  
  # Edit RBAC ConfigMap
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; argocd edit configmap argocd-rbac-cm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  # RBAC Policy Configuration
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;policy.csv&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="s"&gt; Grant full admin access to all applications&lt;/span&gt;
&lt;span class="err"&gt;p&lt;/span&gt;&lt;span class="s"&gt;, role:admin, applications, *, *, *&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="s"&gt; Set default role to admin&lt;/span&gt;
&lt;span class="err"&gt;p&lt;/span&gt;&lt;span class="s"&gt;olicy.default: role:admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  # Policy Explanation
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;p, role:admin, applications, *, *, *&lt;/code&gt;: Provides full access to all applications&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;policy.default: role:admin&lt;/code&gt;: Sets admin as the default role for all users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; In our case, we set role:admin, since there will only be one cluster admin that will have access to the kubernetes and/or argoCD server&lt;/p&gt;

&lt;h6&gt;
  
  
  3. Restart ArgoCD Server
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Restart ArgoCD to apply RBAC changes&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; argocd rollout restart deployment argocd-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  4. Login to ArgoCD
&lt;/h6&gt;

&lt;p&gt;Since we don't expose our argocd server as a LoadBalancer, or Ingress, we need to access it using port-forwarding, this ensures further security&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Forward port to access ArgoCD server locally&lt;/span&gt;
kubectl port-forward service/argocd-server &lt;span class="nt"&gt;-n&lt;/span&gt; argocd 8888:443

&lt;span class="c"&gt;##### Login using admin credentials&lt;/span&gt;
argocd login 127.0.0.1:8888 &lt;span class="nt"&gt;--username&lt;/span&gt; admin &lt;span class="nt"&gt;--password&lt;/span&gt; &amp;lt;retrieved-password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use argocd CLI as well as, open &lt;code&gt;localhost:8888&lt;/code&gt; in the browser and ... Voila!&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%2Fqj3vn8yskal7u6k0i5rr.png" 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%2Fqj3vn8yskal7u6k0i5rr.png" alt="ArgoCD Login Page" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Important Notes
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security Warning&lt;/strong&gt;: The default admin role provides full cluster access&lt;/li&gt;
&lt;li&gt;Regularly rotate credentials&lt;/li&gt;
&lt;li&gt;Use strong, unique passwords&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  GitOps Workflow
&lt;/h3&gt;

&lt;p&gt;ArgoCD bridges the gap between Git repositories and Kubernetes clusters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarative continuous delivery&lt;/li&gt;
&lt;li&gt;Automatic synchronization of application states&lt;/li&gt;
&lt;li&gt;Easy rollbacks and versioning&lt;/li&gt;
&lt;li&gt;Support for multiple sync strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ArgoCD Application Configuration
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Application Repo
&lt;/h5&gt;

&lt;p&gt;This repo contains the application code for the microservices, it can be one repo per microservice or it can be a monorepo that holds all microservice code.&lt;/p&gt;

&lt;p&gt;It also contains the Pipelines that build and push the images to the Container Registry&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./project
├── Azure-Pipelines
│   ├── azure-pipelines.yml
│   ├── azure-pipelines2.yml
│   └── azure-pipelines3.yml
├── Docker
│   ├── Dockerfile.1
│   ├── Dockerfile.2
│   ├── Dockerfile.3
│   └── nginx.conf
├── demo-app
│   ├── README.md
│   ├── angular.json
│   ├── package.json
│   ├── public
│   │   └── favicon.ico
│   ├── src
│   │   ├── app
│   │   │   ├── app.component.css
│   │   │   ├── app.component.html
│   │   │   ├── app.component.spec.ts
│   │   │   ├── app.component.ts
│   │   │   ├── app.config.server.ts
│   │   │   ├── app.config.ts
│   │   │   └── app.routes.ts
│   │   ├── index.html
│   │   ├── main.server.ts
│   │   ├── main.ts
│   │   ├── server.ts
│   │   └── styles.css
│   ├── tsconfig.app.json
│   ├── tsconfig.json
│   └── tsconfig.spec.json
├── demo-app2
│   ├── README.md
│   ├── angular.json
│   ├── package.json
│   ├── public
│   │   └── favicon.ico
│   ├── src
│   │   ├── app
│   │   │   ├── app.component.css
│   │   │   ├── app.component.html
│   │   │   ├── app.component.spec.ts
│   │   │   ├── app.component.ts
│   │   │   ├── app.config.server.ts
│   │   │   ├── app.config.ts
│   │   │   └── app.routes.ts
│   │   ├── index.html
│   │   ├── main.server.ts
│   │   ├── main.ts
│   │   ├── server.ts
│   │   └── styles.css
│   ├── tsconfig.app.json
│   ├── tsconfig.json
│   └── tsconfig.spec.json
└── demo-app3
    ├── README.md
    ├── angular.json
    ├── package.json
    ├── public
    │   └── favicon.ico
    ├── src
    │   ├── app
    │   │   ├── app.component.css
    │   │   ├── app.component.html
    │   │   ├── app.component.spec.ts
    │   │   ├── app.component.ts
    │   │   ├── app.config.server.ts
    │   │   ├── app.config.ts
    │   │   └── app.routes.ts
    │   ├── index.html
    │   ├── main.server.ts
    │   ├── main.ts
    │   ├── server.ts
    │   └── styles.css
    ├── tsconfig.app.json
    ├── tsconfig.json
    └── tsconfig.spec.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's setup the Azure Pipelines for all 3 demo apps, so images can be pushed into ACR for later deployment&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%2Fevm4s8o8py9i42qf5773.png" 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%2Fevm4s8o8py9i42qf5773.png" alt="Azure DevOps Screenshot" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h5&gt;
  
  
  GitOps Repo
&lt;/h5&gt;

&lt;p&gt;Next, we have the GitOps Repo that will be configured with ArgoCD to be monitored&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./demo-app-manifests
├── manifests
│   ├── argocd
│   │   ├── argocd-application-master
│   │   │   └── masterapp.yaml
│   │   └── argocd-applications
│   │       ├── demo-app-argoapp.yaml
│   │       ├── demo-app2-argoapp.yaml
│   │       └── demo-app3-argoapp.yaml
│   └── main
│       ├── demo-app
│       │   ├── deployment.yaml
│       │   └── service-ingress.yaml
│       ├── demo-app2
│       │   ├── deployment.yaml
│       │   └── service-ingress.yaml
│       └── demo-app3
│           ├── deployment.yaml
│           └── service-ingress.yaml
└── readmes
    ├── README.md
    └── argoCD.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manifests folder is crucial for managing your Kubernetes deployments and configurations using ArgoCD. Here's a detailed look at its contents:&lt;/p&gt;

&lt;p&gt;argocd:&lt;/p&gt;

&lt;p&gt;argocd-application-master/masterapp.yaml: &lt;/p&gt;

&lt;p&gt;The main ArgoCD application configuration.&lt;/p&gt;

&lt;p&gt;argocd-applications:&lt;/p&gt;

&lt;p&gt;Contains multiple ArgoCD application configurations (demo-app-argoapp.yaml, demo-app2-argoapp.yaml, demo-app3-argoapp.yaml), following the "App of Apps" pattern.&lt;/p&gt;

&lt;p&gt;This pattern allows you to manage multiple applications under a single ArgoCD application.&lt;/p&gt;

&lt;p&gt;main:&lt;/p&gt;

&lt;p&gt;demo-app, demo-app2, demo-app3:&lt;/p&gt;

&lt;p&gt;Each folder contains Kubernetes manifests for deploying and exposing the respective frontend applications.&lt;/p&gt;

&lt;p&gt;deployment.yaml:&lt;/p&gt;

&lt;p&gt;Defines the deployment configuration for the application.&lt;/p&gt;

&lt;p&gt;service-ingress.yaml:&lt;/p&gt;

&lt;p&gt;Configures the service and ingress for the application.&lt;/p&gt;

&lt;h6&gt;
  
  
  Run Important ArgoCLI Commands
&lt;/h6&gt;

&lt;p&gt;Add the Azure DevOps repository to ArgoCD using the SSH URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    argocd repo add git@ssh.dev.azure.com:v3/myteo/Cloud/demo-app-manifests &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ssh-private-key-path&lt;/span&gt; ~/.ssh/id_azure &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--upsert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new ArgoCD project named demo-app-project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    argocd proj create demo-app-project &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--dest&lt;/span&gt; https://kubernetes.default.svc,&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"demo app project"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--src&lt;/span&gt; git@ssh.dev.azure.com:v3/myteo/Cloud/demo-app-manifests &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--upsert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; ./manifests/argocd/argocd-application-master/masterapp.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deploys the master app to the argocd instance, which will now manage all the argoapps referenced under ./manifests/argocd/argocd-applications&lt;/p&gt;

&lt;p&gt;This design is called the "App of Apps" pattern, similar to the master-slave node concept&lt;/p&gt;

&lt;p&gt;The master app now handles deployment of any app yamls configured under the argocd-applications directory&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%2F9v0d83sfox4eqtrolfbp.png" 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%2F9v0d83sfox4eqtrolfbp.png" alt="ArgoCD Dashboard showing overview" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  GitOps The Philosophical Shift
&lt;/h2&gt;

&lt;p&gt;GitOps represents a paradigm shift in infrastructure and application management:&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Principles
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Configuration&lt;/strong&gt;: Everything is defined as code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: Git becomes the single source of truth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Synchronization&lt;/strong&gt;: Continuous reconciliation of desired and actual states&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immutable Infrastructure&lt;/strong&gt;: Predictable, reproducible environments&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Benefits of This Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Infrastructure Teams
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reduced manual intervention&lt;/li&gt;
&lt;li&gt;Improved consistency&lt;/li&gt;
&lt;li&gt;Enhanced security through controlled changes&lt;/li&gt;
&lt;li&gt;Faster recovery from failures&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Development Teams
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Self-service deployment model&lt;/li&gt;
&lt;li&gt;Increased visibility&lt;/li&gt;
&lt;li&gt;Simplified collaboration&lt;/li&gt;
&lt;li&gt;Faster time-to-market&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Organizations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lower operational complexity&lt;/li&gt;
&lt;li&gt;Reduced human error&lt;/li&gt;
&lt;li&gt;Better compliance and auditing&lt;/li&gt;
&lt;li&gt;Scalable infrastructure management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Implementation Strategy
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Infrastructure with Terraform&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Kubernetes cluster configurations&lt;/li&gt;
&lt;li&gt;Set up networking and security groups&lt;/li&gt;
&lt;li&gt;Configure node pools and cluster settings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install ArgoCD on Kubernetes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy ArgoCD using Terraform or kubectl&lt;/li&gt;
&lt;li&gt;Configure repository connections&lt;/li&gt;
&lt;li&gt;Set up application deployment configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implement GitOps Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store all configurations in Git repositories&lt;/li&gt;
&lt;li&gt;Use pull requests for change management&lt;/li&gt;
&lt;li&gt;Leverage ArgoCD for continuous deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The synergy of Terraform, Kubernetes, ArgoCD, and GitOps principles offers a robust, scalable approach to modern infrastructure and application management. By embracing these technologies, organizations can achieve unprecedented levels of efficiency, reliability, and agility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Tools and Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;ArgoCD&lt;/li&gt;
&lt;li&gt;Helm&lt;/li&gt;
&lt;li&gt;GitHub/GitLab/Azure DevOps&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>argocd</category>
      <category>terraform</category>
      <category>git</category>
    </item>
    <item>
      <title>A Step-by-Step Guide to CI/CD Pipeline for Angular App with Azure Container Apps</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Tue, 10 Dec 2024 09:18:38 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/a-step-by-step-guide-to-cicd-pipeline-for-angular-app-with-azure-container-apps-3b79</link>
      <guid>https://dev.to/hassan_aftab/a-step-by-step-guide-to-cicd-pipeline-for-angular-app-with-azure-container-apps-3b79</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Prerequisites
&lt;/li&gt;
&lt;li&gt;
Step 1: Dockerfile
&lt;/li&gt;
&lt;li&gt;
Step 2: Azure Pipelines Configuration
&lt;/li&gt;
&lt;li&gt;
Step 3: Additional Azure CLI Configuration
&lt;/li&gt;
&lt;li&gt;
Best Practices
&lt;/li&gt;
&lt;li&gt;
Troubleshooting
&lt;/li&gt;
&lt;li&gt;
Conclusion
&lt;/li&gt;
&lt;li&gt;
Resources
&lt;/li&gt;
&lt;li&gt;
Dockerizing Other Technology Stacks
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Azure DevOps account&lt;/li&gt;
&lt;li&gt;Azure Subscription&lt;/li&gt;
&lt;li&gt;Angular project&lt;/li&gt;
&lt;li&gt;Azure CLI installed&lt;/li&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;li&gt;Azure Container Registry&lt;/li&gt;
&lt;li&gt;Azure Container Apps environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Dockerfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Build Angular application&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build &lt;span class="nt"&gt;--configuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production

&lt;span class="c"&gt;# Stage 2: Serve with Nginx&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /usr/src/app/dist/your-angular-app /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; nginx.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Azure Pipelines Configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Azure Container Registry details&lt;/span&gt;
  &lt;span class="na"&gt;acrName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yourcontainerregistry'&lt;/span&gt;
  &lt;span class="na"&gt;imageRepository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;angular-app'&lt;/span&gt;
  &lt;span class="na"&gt;dockerfilePath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dockerfile'&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(Build.BuildId)'&lt;/span&gt;

  &lt;span class="c1"&gt;# Azure Container Apps details&lt;/span&gt;
  &lt;span class="na"&gt;containerAppName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-container-app-name'&lt;/span&gt;
  &lt;span class="na"&gt;resourceGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-resource-group'&lt;/span&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Test&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BuildAndTest&lt;/span&gt;
    &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;vmImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ubuntu-latest'&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodeTool@0&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;versionSpec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;16.x'&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Node.js'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;npm ci&lt;/span&gt;
        &lt;span class="s"&gt;npm run lint&lt;/span&gt;
        &lt;span class="s"&gt;npm run test -- --watch=false --browsers=ChromeHeadless&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;lint,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker@2&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Docker&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Image'&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
        &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(imageRepository)&lt;/span&gt;
        &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(dockerfilePath)&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;$(tag)&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker@2&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Push&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Registry'&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
        &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(imageRepository)&lt;/span&gt;
        &lt;span class="na"&gt;containerRegistry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(acrServiceConnection)&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;$(tag)&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Approval&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment Approval&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ApprovalJob&lt;/span&gt;
    &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;server&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation@0&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Please&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;approve&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deployment'&lt;/span&gt;
        &lt;span class="na"&gt;onTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reject'&lt;/span&gt;
        &lt;span class="na"&gt;timeoutInMinutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Azure Container Apps&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Approval&lt;/span&gt;
  &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;succeeded()&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DeployToContainerApp&lt;/span&gt;
    &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;vmImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ubuntu-latest'&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production'&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;runOnce&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AzureCLI@2&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Apps'&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;azureSubscription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Your-Azure-Subscription'&lt;/span&gt;
              &lt;span class="na"&gt;scriptType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bash'&lt;/span&gt;
              &lt;span class="na"&gt;scriptLocation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inlineScript'&lt;/span&gt;
              &lt;span class="na"&gt;inlineScript&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                &lt;span class="s"&gt;# Login to Azure Container Registry&lt;/span&gt;
                &lt;span class="s"&gt;az acr login --name $(acrName)&lt;/span&gt;

                &lt;span class="s"&gt;# Update Container App with new image&lt;/span&gt;
                &lt;span class="s"&gt;az containerapp update \&lt;/span&gt;
                  &lt;span class="s"&gt;--name $(containerAppName) \&lt;/span&gt;
                  &lt;span class="s"&gt;--resource-group $(resourceGroup) \&lt;/span&gt;
                  &lt;span class="s"&gt;--image $(acrName).azurecr.io/$(imageRepository):$(tag)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Additional Azure CLI Configuration
&lt;/h2&gt;

&lt;p&gt;Before running the pipeline, set up your Azure Container Apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create Container Registry&lt;/span&gt;
az acr create &lt;span class="nt"&gt;--resource-group&lt;/span&gt; your-resource-group &lt;span class="se"&gt;\&lt;/span&gt;
              &lt;span class="nt"&gt;--name&lt;/span&gt; yourcontainerregistry &lt;span class="se"&gt;\&lt;/span&gt;
              &lt;span class="nt"&gt;--sku&lt;/span&gt; Basic

&lt;span class="c"&gt;# Create Container Apps Environment&lt;/span&gt;
az containerapp &lt;span class="nb"&gt;env &lt;/span&gt;create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; your-container-app-environment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; your-resource-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt; eastus

&lt;span class="c"&gt;# Create Container App&lt;/span&gt;
az containerapp create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; your-container-app-name &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; your-resource-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--environment&lt;/span&gt; your-container-app-environment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; yourcontainerregistry.azurecr.io/angular-app:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-port&lt;/span&gt; 80 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ingress&lt;/span&gt; external
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use Azure Key Vault for sensitive configurations&lt;/li&gt;
&lt;li&gt;Implement comprehensive testing before deployment&lt;/li&gt;
&lt;li&gt;Use managed identities for secure access&lt;/li&gt;
&lt;li&gt;Set up proper RBAC for deployment&lt;/li&gt;
&lt;li&gt;Configure health checks in Container Apps&lt;/li&gt;
&lt;li&gt;Use staging slots for zero-downtime deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Verify network configurations&lt;/li&gt;
&lt;li&gt;Check container logs in Azure Portal&lt;/li&gt;
&lt;li&gt;Ensure proper IAM roles are assigned&lt;/li&gt;
&lt;li&gt;Validate ACR permissions&lt;/li&gt;
&lt;li&gt;Check Container Apps network settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This pipeline provides a robust CI/CD workflow for deploying an Angular application to Azure Container Apps with a manual approval stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/container-apps/" rel="noopener noreferrer"&gt;Azure Container Apps Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/" rel="noopener noreferrer"&gt;Azure DevOps Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" rel="noopener noreferrer"&gt;Docker Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;so in summary, The pipeline includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build and test stage&lt;/li&gt;
&lt;li&gt;Manual approval stage&lt;/li&gt;
&lt;li&gt;Deployment to Azure Container Apps&lt;/li&gt;
&lt;li&gt;Azure Container Registry integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dockerizing Other Technology Stacks
&lt;/h2&gt;

&lt;p&gt;The Dockerfile approach demonstrated for the Angular application can be easily adapted to other popular technology stacks as well&lt;/p&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>containerapps</category>
      <category>cicd</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Mon, 09 Dec 2024 06:08:04 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/-lb7</link>
      <guid>https://dev.to/hassan_aftab/-lb7</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/hassan_aftab" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F1616077%2F5ea6d5e4-cc2e-4793-80b9-b418cd660553.jpg" alt="hassan_aftab"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/hassan_aftab/why-rootless-containers-matter-a-security-perspective-59ni" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Why Rootless Containers Matter: A Security Perspective&lt;/h2&gt;
      &lt;h3&gt;Hassan Aftab ・ Dec 9 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#container&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#kubernetes&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloudcomputing&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Why Rootless Containers Matter: A Security Perspective</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Mon, 09 Dec 2024 05:58:28 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/why-rootless-containers-matter-a-security-perspective-59ni</link>
      <guid>https://dev.to/hassan_aftab/why-rootless-containers-matter-a-security-perspective-59ni</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What Are Rootless Containers?&lt;/li&gt;
&lt;li&gt;Security Risks in Root Containers&lt;/li&gt;
&lt;li&gt;How Rootless Containers Mitigate Security Risks&lt;/li&gt;
&lt;li&gt;Comparison: Root vs. Rootless Containers&lt;/li&gt;
&lt;li&gt;Challenges and Limitations of Rootless Containers&lt;/li&gt;
&lt;li&gt;Compliant Dockerfile for Rootless Containers&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Containers have revolutionized the way software is built, shipped, and deployed, offering unparalleled scalability and portability. However, with great power comes great responsibility, particularly in ensuring the security of containerized applications.&lt;/p&gt;

&lt;p&gt;One of the most significant advancements in this area is the advent of &lt;strong&gt;rootless containers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we explore why rootless containers matter and compare the security vulnerabilities of traditional root containers with rootless alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Rootless Containers?
&lt;/h2&gt;

&lt;p&gt;Rootless containers are a form of containerization where the container runtime and processes inside the container do not require root (administrator) privileges on the host system.&lt;/p&gt;

&lt;p&gt;This contrasts with traditional containers, which often run with elevated privileges and can pose significant security risks if compromised.&lt;/p&gt;

&lt;p&gt;Rootless containers achieve isolation using technologies such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Namespaces&lt;/strong&gt;: Mapping container users to unprivileged host users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cgroups&lt;/strong&gt;: Limiting resource usage without elevated permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seccomp and AppArmor&lt;/strong&gt;: Enhancing security through system call filtering and mandatory access control.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security Risks in Root Containers
&lt;/h2&gt;

&lt;p&gt;Traditional root-based containers introduce several potential vulnerabilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privilege Escalation&lt;/strong&gt;:&lt;br&gt;
If an attacker gains control of a root-based container, they can potentially escalate privileges to take control of the host system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Namespace Escape&lt;/strong&gt;:&lt;br&gt;
Misconfigurations or vulnerabilities in the container runtime could allow attackers to break out of the container and access the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Insecure Defaults&lt;/strong&gt;:&lt;br&gt;
Many container environments are configured with defaults that prioritize ease of use over security, such as granting broad access to host resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Untrusted Images&lt;/strong&gt;:&lt;br&gt;
Pulling and running unverified container images increases the risk of running malicious code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Rootless Containers Mitigate Security Risks
&lt;/h2&gt;

&lt;p&gt;Rootless containers address these issues in the following ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Root Privileges&lt;/strong&gt;:&lt;br&gt;
Since rootless containers run without root privileges on the host, even if an attacker compromises the container, they cannot gain root access to the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Isolation&lt;/strong&gt;:&lt;br&gt;
By leveraging user namespaces, rootless containers ensure that processes inside the container cannot interact with sensitive host resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Attack Surface&lt;/strong&gt;:&lt;br&gt;
Running without elevated permissions minimizes the pathways an attacker can exploit to compromise the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stronger Defaults&lt;/strong&gt;:&lt;br&gt;
Rootless container runtimes are often designed with security-first principles, reducing the likelihood of insecure configurations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparison: Root vs. Rootless Containers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Root Containers&lt;/th&gt;
&lt;th&gt;Rootless Containers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Host Privileges&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Require root privileges on the host&lt;/td&gt;
&lt;td&gt;Do not require root privileges on the host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Risk of Privilege Escalation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easier to configure for complex setups&lt;/td&gt;
&lt;td&gt;May require additional setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Broad compatibility with existing tools&lt;/td&gt;
&lt;td&gt;Limited compatibility with some legacy tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Higher risk of host compromise&lt;/td&gt;
&lt;td&gt;Stronger isolation and lower risk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Challenges and Limitations of Rootless Containers
&lt;/h2&gt;

&lt;p&gt;While rootless containers significantly enhance security, they are not without challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead&lt;/strong&gt;:&lt;br&gt;
Rootless containers may introduce minor performance trade-offs due to additional isolation layers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility Issues&lt;/strong&gt;:&lt;br&gt;
Some containerized applications or tools may not work seamlessly in a rootless environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt;:&lt;br&gt;
Initial setup and troubleshooting can be more complex compared to root-based containers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Compliant Dockerfile for Rootless Containers
&lt;/h2&gt;

&lt;p&gt;Below is a Dockerfile designed to adhere to best practices for rootless containers. It avoids running processes as the root user and implements security-focused configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use a minimal base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; debian:bullseye-slim&lt;/span&gt;

&lt;span class="c"&gt;# Set a non-root user and group&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; USERNAME=appuser&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; USER_UID=1001&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; USER_GID=1001&lt;/span&gt;

&lt;span class="c"&gt;# Create the non-root user&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$USER_GID&lt;/span&gt; &lt;span class="nv"&gt;$USERNAME&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    useradd &lt;span class="nt"&gt;--uid&lt;/span&gt; &lt;span class="nv"&gt;$USER_UID&lt;/span&gt; &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$USER_GID&lt;/span&gt; &lt;span class="nt"&gt;--shell&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;--create-home&lt;/span&gt; &lt;span class="nv"&gt;$USERNAME&lt;/span&gt;

&lt;span class="c"&gt;# Switch to the non-root user&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; $USERNAME&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/$USERNAME/app&lt;/span&gt;

&lt;span class="c"&gt;# Copy application files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=$USER_UID:$USER_GID . .&lt;/span&gt;

&lt;span class="c"&gt;# Install application dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/&lt;span class="nv"&gt;$USERNAME&lt;/span&gt;/app/data &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 700 /home/&lt;span class="nv"&gt;$USERNAME&lt;/span&gt;/app

&lt;span class="c"&gt;# Define the entry point and ensure it runs as the non-root user&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["./entrypoint.sh"]&lt;/span&gt;

&lt;span class="c"&gt;# Expose the necessary ports (non-root port numbers)&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="c"&gt;# Start the application&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./app"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of the Dockerfile:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimal Base Image&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;debian:bullseye-slim&lt;/code&gt; image is used to minimize the attack surface.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Non-Root User&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new user (&lt;code&gt;appuser&lt;/code&gt;) is created with limited privileges to ensure processes do not run as root.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;File Ownership&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application files are copied with ownership set to the non-root user for proper permissions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secure Ports&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ports above 1024 (e.g., 8080) are exposed, as binding to lower ports requires root privileges.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strict Permissions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application directories are created with strict permissions (700) to prevent unauthorized access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Entrypoint and CMD&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;ENTRYPOINT&lt;/code&gt; and &lt;code&gt;CMD&lt;/code&gt; are set to ensure the application runs securely under the non-root user.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This Dockerfile follows best practices for rootless containers, ensuring enhanced security and compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As container adoption continues to grow, so does the importance of addressing security risks. Rootless containers provide a robust solution for mitigating many of the vulnerabilities associated with traditional root-based containers.&lt;/p&gt;

&lt;p&gt;By running without elevated privileges and offering enhanced isolation, they empower organizations to build more secure containerized environments.&lt;/p&gt;

&lt;p&gt;However, adopting rootless containers requires careful consideration of their limitations and potential impacts on workflows.&lt;/p&gt;

&lt;p&gt;By balancing security with usability, organizations can leverage rootless containers to create safer, more resilient infrastructures for their applications.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>container</category>
      <category>kubernetes</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Using Docker for Penetration Testing: A Practical Guide</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Fri, 06 Dec 2024 08:09:39 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/using-docker-for-penetration-testing-a-practical-guide-44lj</link>
      <guid>https://dev.to/hassan_aftab/using-docker-for-penetration-testing-a-practical-guide-44lj</guid>
      <description>&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Why Use Docker for Penetration Testing?&lt;/li&gt;
&lt;li&gt;Popular Docker Images for Penetration Testing&lt;/li&gt;
&lt;li&gt;
Setting Up Docker for Penetration Testing

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Example: Running Kali Linux in a Container&lt;/li&gt;
&lt;li&gt;Example: Using OWASP ZAP&lt;/li&gt;
&lt;li&gt;Example: Running Nikto&lt;/li&gt;
&lt;li&gt;Example: Running Nmap&lt;/li&gt;
&lt;li&gt;Example: Reporting with Dradis&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Best Practices&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Penetration testing often requires a variety of tools, each with specific dependencies and configurations. Installing and maintaining these tools directly on your system can be cumbersome and messy. This is where Docker comes in, offering a clean, efficient, and portable way to set up your penetration testing environment.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how to use Docker for penetration testing, why it’s beneficial, and provide some practical examples to get you started.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Docker for Penetration Testing?
&lt;/h2&gt;

&lt;p&gt;Here are a few reasons why Docker is an excellent choice for penetration testing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt;: Each tool runs in its own container, preventing conflicts between dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: Containers can run consistently across different environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt;: Pre-built Docker images are available for many popular penetration testing tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: You can easily manage different versions of tools by specifying the desired image tags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick Setup&lt;/strong&gt;: No need to install dependencies manually; just pull the required image and start using it.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Popular Docker Images for Penetration Testing
&lt;/h2&gt;

&lt;p&gt;Here are some popular Docker images you can use to set up your penetration testing environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/kalilinux/kali-linux-docker" rel="noopener noreferrer"&gt;Kali Linux&lt;/a&gt;&lt;/strong&gt;: The go-to Linux distribution for penetration testers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/owasp/zap2docker-stable" rel="noopener noreferrer"&gt;OWASP ZAP&lt;/a&gt;&lt;/strong&gt;: An open-source web application security scanner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/metasploitframework/metasploit-framework" rel="noopener noreferrer"&gt;Metasploit Framework&lt;/a&gt;&lt;/strong&gt;: A widely used penetration testing framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/sullo/nikto" rel="noopener noreferrer"&gt;Nikto&lt;/a&gt;&lt;/strong&gt;: A web server scanner for detecting vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/eddiethweb/sqlmap" rel="noopener noreferrer"&gt;SQLMap&lt;/a&gt;&lt;/strong&gt;: An automated tool for SQL injection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/instrumentisto/nmap" rel="noopener noreferrer"&gt;Nmap&lt;/a&gt;&lt;/strong&gt;: A powerful network discovery and security auditing tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/dradis/dradispro-ce" rel="noopener noreferrer"&gt;Reporting Tools (Dradis)&lt;/a&gt;&lt;/strong&gt;: A collaboration and reporting platform for penetration testers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setting Up Docker for Penetration Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before starting, ensure you have Docker installed on your system. You can download and install Docker from the &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Running Kali Linux in a Container
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull the Kali Linux image&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker pull kalilinux/kali-linux-docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run a container&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-it&lt;/span&gt; kalilinux/kali-linux-docker /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install your required tools within the container&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nmap metasploit-framework nikto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Save the configured container as an image&lt;/strong&gt; (optional):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker commit &amp;lt;container_id&amp;gt; kalilinux/with-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can reuse this customized image without reconfiguring it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Using OWASP ZAP
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull the OWASP ZAP image&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker pull owasp/zap2docker-stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the container with GUI support&lt;/strong&gt; (requires X11 forwarding):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DISPLAY&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; /tmp/.X11-unix:/tmp/.X11-unix owasp/zap2docker-stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start scanning&lt;/strong&gt;:
Use the OWASP ZAP GUI to configure and initiate scans.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: Running Nikto
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run a container&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-it&lt;/span&gt; kalilinux/with-tools /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run a Nikto scan&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   nikto &lt;span class="nt"&gt;-h&lt;/span&gt; example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: Running Nmap
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run an Nmap scan&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 80,443 example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: Reporting with Dradis
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull the Dradis image&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker pull dradis/dradispro-ce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the Dradis container&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 dradis/dradispro-ce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access the Dradis interface&lt;/strong&gt;:
Open your browser and navigate to &lt;code&gt;http://localhost:3000&lt;/code&gt; to start creating reports.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Bind Mounts&lt;/strong&gt;: Mount directories from your host system into the container for easy data sharing.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/data:/data kalilinux/with-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Network Modes&lt;/strong&gt;: Use Docker’s network modes (bridge, host, etc.) to simulate different network scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Images&lt;/strong&gt;: Create custom Dockerfiles for commonly used toolsets to save time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Be cautious with sensitive data in containers and clean up unused containers and images.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker simplifies the setup and management of penetration testing tools, making it a valuable asset for security professionals. By using pre-built images or creating custom containers, you can streamline your workflow, reduce setup time, and focus on testing.&lt;/p&gt;

&lt;p&gt;Whether you’re a beginner or an experienced penetration tester, leveraging Docker can enhance your productivity and efficiency.&lt;/p&gt;

&lt;p&gt;Happy testing! If you have any favorite Docker-based tools or tips, feel free to share them in the comments below.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>security</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Check out my latest article on Jupyter Notebooks and Docker</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Fri, 29 Nov 2024 09:26:54 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/check-out-my-latest-article-on-jupyter-notebooks-and-docker-449i</link>
      <guid>https://dev.to/hassan_aftab/check-out-my-latest-article-on-jupyter-notebooks-and-docker-449i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/hassan_aftab" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F1616077%2F5ea6d5e4-cc2e-4793-80b9-b418cd660553.jpg" alt="hassan_aftab"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/hassan_aftab/jupyter-notebooks-in-docker-4a29" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Jupyter Notebooks in Docker&lt;/h2&gt;
      &lt;h3&gt;Hassan Aftab ・ Nov 29 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#datascience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dataengineering&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Jupyter Notebooks in Docker</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Fri, 29 Nov 2024 09:16:31 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/jupyter-notebooks-in-docker-4a29</link>
      <guid>https://dev.to/hassan_aftab/jupyter-notebooks-in-docker-4a29</guid>
      <description>&lt;h2&gt;
  
  
  Why use Docker for Jupyter Notebooks?
&lt;/h2&gt;

&lt;p&gt;Docker provides an efficient and reproducible environment for running Jupyter Notebooks. With Docker, you can create isolated containers that ensure the dependencies and configurations for your Jupyter Notebooks are consistent across different systems. This is particularly useful for data science projects, where managing dependencies and ensuring reproducibility is crucial.&lt;/p&gt;

&lt;p&gt;In this article, we will cover how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up Docker for Jupyter Notebooks.&lt;/li&gt;
&lt;li&gt;Use pre-built Jupyter Docker images.&lt;/li&gt;
&lt;li&gt;Customize your Jupyter Notebook environment with a custom Dockerfile.&lt;/li&gt;
&lt;li&gt;Manage persistent data storage for notebooks.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. &lt;strong&gt;Setting up Docker&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Docker
&lt;/h3&gt;

&lt;p&gt;Before using Docker, ensure it is installed on your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;: Follow the &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker Engine installation guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows/Mac&lt;/strong&gt;: Install Docker Desktop from &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;Docker’s official website&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verify Docker installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Docker Service
&lt;/h3&gt;

&lt;p&gt;Ensure the Docker service is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start docker  &lt;span class="c"&gt;# Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. &lt;strong&gt;Using Pre-Built Jupyter Docker Images&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://jupyter-docker-stacks.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Jupyter Project&lt;/a&gt; provides pre-built Docker images with various configurations. These images come with pre-installed packages tailored for data science, machine learning, and scientific computing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Available Images
&lt;/h3&gt;

&lt;p&gt;Some popular Jupyter Docker images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jupyter/base-notebook&lt;/code&gt;: 

&lt;ul&gt;
&lt;li&gt;Minimal Jupyter Notebook environment.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;jupyter/scipy-notebook&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Includes scientific computing libraries like NumPy, SciPy, and pandas.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;jupyter/tensorflow-notebook&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Includes TensorFlow and Keras for machine learning.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;jupyter/r-notebook&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Supports R in Jupyter.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running a Jupyter Notebook Container
&lt;/h3&gt;

&lt;p&gt;To start a Jupyter Notebook using the &lt;code&gt;scipy-notebook&lt;/code&gt; image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 jupyter/scipy-notebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the container starts, you will see a URL with a token in the logs, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8888/?token=&amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy this URL into your browser to access the Jupyter Notebook interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Jupyter with a Named Volume
&lt;/h3&gt;

&lt;p&gt;To persist your work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/home/jovyan/work jupyter/scipy-notebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command mounts your current directory to the container's &lt;code&gt;work&lt;/code&gt; directory, ensuring changes are saved locally.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;strong&gt;Customizing Your Jupyter Environment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If the pre-built images don’t meet your needs, you can create a custom Docker image with your own dependencies and configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Custom Dockerfile
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;Dockerfile&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;   FROM jupyter/scipy-notebook

   &lt;span class="c"&gt;# Install additional Python packages&lt;/span&gt;
   RUN pip install matplotlib seaborn

   &lt;span class="c"&gt;# Set a custom working directory&lt;/span&gt;
   WORKDIR /home/jovyan/my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Build the Docker image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-custom-jupyter &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the container:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/home/jovyan/work my-custom-jupyter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Conda Environments
&lt;/h3&gt;

&lt;p&gt;To include a Conda environment, modify the &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; jupyter/scipy-notebook&lt;/span&gt;

&lt;span class="c"&gt;# Create and activate a Conda environment&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;conda create &lt;span class="nt"&gt;-n&lt;/span&gt; myenv &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3.9 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"source activate myenv"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.bashrc

&lt;span class="c"&gt;# Install packages in the new environment&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;conda &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; myenv pandas matplotlib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. &lt;strong&gt;Persistent Data Storage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By default, any data or notebooks created inside a Docker container are lost when the container stops. To avoid this, you can use Docker volumes or bind mounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Docker Volumes
&lt;/h3&gt;

&lt;p&gt;Volumes are managed by Docker and provide a way to persist data independently of the container lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create jupyter-data

docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 &lt;span class="nt"&gt;-v&lt;/span&gt; jupyter-data:/home/jovyan/work jupyter/scipy-notebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;jupyter-data&lt;/code&gt; volume will persist your notebooks and files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Bind Mounts
&lt;/h3&gt;

&lt;p&gt;Bind mounts map a local directory to a directory inside the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/home/jovyan/work jupyter/scipy-notebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This maps the current directory (&lt;code&gt;$(pwd)&lt;/code&gt;) to &lt;code&gt;/home/jovyan/work&lt;/code&gt; in the container.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;strong&gt;Advanced Usage&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;To allow multiple users to access your Jupyter Notebook over a network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8888 &lt;span class="nt"&gt;--ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 jupyter/scipy-notebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Share the URL with the token for access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Docker Compose
&lt;/h3&gt;

&lt;p&gt;For more complex setups, use Docker Compose to manage multiple services (e.g., Jupyter + a database):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;jupyter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jupyter/scipy-notebook&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8888:8888"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./notebooks:/home/jovyan/work&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker is an excellent tool for running and managing Jupyter Notebooks in a reproducible and isolated environment. Whether you use pre-built images or create custom ones, Docker simplifies dependency management and ensures consistent environments for your projects. By leveraging persistent storage and tools like Docker Compose, you can scale your Jupyter Notebook workflows to handle complex, multi-container setups.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>docker</category>
      <category>dataengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>Securing Your Web Applications (DAST): A Deep Dive into OWASP ZAP Scans with Docker</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Tue, 15 Oct 2024 15:35:03 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/securing-your-web-applications-dast-a-deep-dive-into-owasp-zap-scans-with-docker-m6i</link>
      <guid>https://dev.to/hassan_aftab/securing-your-web-applications-dast-a-deep-dive-into-owasp-zap-scans-with-docker-m6i</guid>
      <description>&lt;h1&gt;
  
  
  Scanning Localhost Application with Docker ZAP
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Scanning Localhost Application with Docker ZAP

&lt;ul&gt;
&lt;li&gt;Table of Contents&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Key Features of ZAP&lt;/li&gt;
&lt;li&gt;Benefits of Using ZAP for DAST&lt;/li&gt;
&lt;li&gt;Getting Started with ZAP&lt;/li&gt;
&lt;li&gt;Setting up TIWAP&lt;/li&gt;
&lt;li&gt;Step-by-Step Instructions to Set Up the Web Application&lt;/li&gt;
&lt;li&gt;Docker Installation Instructions&lt;/li&gt;
&lt;li&gt;Execution Instructions&lt;/li&gt;
&lt;li&gt;Step 1: Pull the ZAP Docker Image&lt;/li&gt;
&lt;li&gt;Step 2: Start Your Localhost Application&lt;/li&gt;
&lt;li&gt;
Step 3: Run the ZAP Scan

&lt;ul&gt;
&lt;li&gt;Explanation of the Command&lt;/li&gt;
&lt;li&gt;Additional Flags to Pass to Image&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Command Output&lt;/li&gt;

&lt;li&gt;Step 4: Retrieve the HTML Report&lt;/li&gt;

&lt;li&gt;Additional Tips&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Dynamic Application Security Testing (DAST) is a type of security testing that involves testing an application in its running state. Unlike static analysis, which examines the source code, DAST scans an application from the outside in, simulating an attacker’s perspective. This approach helps identify vulnerabilities that might be exploited in a real-world attack scenario, such as SQL injection, cross-site scripting (XSS), and other web application vulnerabilities.&lt;/p&gt;

&lt;p&gt;One of the most popular tools for performing DAST is the Zed Attack Proxy (ZAP), an open-source security scanner maintained by the Open Web Application Security Project (OWASP). ZAP is designed to be easy to use, even for those new to application security, while also providing powerful features for advanced users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of ZAP
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated Scanning&lt;/strong&gt;: ZAP can automatically scan web applications for security vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passive Scanning&lt;/strong&gt;: Monitors HTTP traffic and passively scans for vulnerabilities without altering the request-response cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active Scanning&lt;/strong&gt;: Actively probes the web application for vulnerabilities by sending various types of malicious requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spidering&lt;/strong&gt;: Crawls the web application to discover all the pages and endpoints that need to be tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Integration&lt;/strong&gt;: Provides a robust API that allows for integration with CI/CD pipelines for continuous security testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt;: Supports various add-ons and plugins to extend its functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits of Using ZAP for DAST
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive Coverage&lt;/strong&gt;: ZAP can identify a wide range of vulnerabilities, including those listed in the OWASP Top Ten.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt;: Its intuitive interface and extensive documentation make it accessible for beginners.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community Support&lt;/strong&gt;: Being an OWASP project, ZAP benefits from a large community of contributors and users who help in improving and updating the tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-Effective&lt;/strong&gt;: As an open-source tool, ZAP is free to use, making it an attractive option for organizations of all sizes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started with ZAP
&lt;/h2&gt;

&lt;p&gt;To start using ZAP for DAST scanning, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download and Install ZAP&lt;/strong&gt;: ZAP is available for Windows, macOS, and Linux. You can download it from the &lt;a href="https://www.zaproxy.org/download/" rel="noopener noreferrer"&gt;official ZAP website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Your Browser&lt;/strong&gt;: Set up your web browser to use ZAP as a proxy to capture and inspect the HTTP traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start Scanning&lt;/strong&gt;: Use ZAP's spidering and scanning features to discover and test the web application's endpoints for vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review and Mitigate&lt;/strong&gt;: Analyze the scan results to identify vulnerabilities and take appropriate actions to mitigate them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setting up TIWAP
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step-by-Step Instructions to Set Up the Web Application
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clone the GitHub Repository&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, clone the repository to your local machine. Open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/hassanaftab93/TIWAP.git 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command downloads all the project files from the GitHub repository to a directory named &lt;code&gt;TIWAP&lt;/code&gt; on your local machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Navigate to the Project Directory&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After cloning the repository, navigate into the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd &lt;/span&gt;TIWAP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This changes your current directory to the &lt;code&gt;TIWAP&lt;/code&gt; directory, where the project files are located.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Run Docker Compose to Spin Up the Web Application&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use Docker Compose to build and start the web application. Make sure Docker is installed and running on your system. Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fsen0kvs04nsbvld6vle2.png" 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%2Fsen0kvs04nsbvld6vle2.png" alt="Docker Compose Output" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command uses the &lt;code&gt;docker-compose.yml&lt;/code&gt; file to build the Docker containers and start the application in detached mode (running in the background).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Verify the Application is Running&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running the Docker Compose command, verify that the application is running. Open your web browser and navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   https://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F6wo6iao5wdp3uwynx1sq.png" 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%2F6wo6iao5wdp3uwynx1sq.png" alt="browser webpage" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or you can&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-k&lt;/span&gt; https://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Flukjyc66w712x1x277te.png" 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%2Flukjyc66w712x1x277te.png" alt="curl localhost" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As seen in the images above, the web application up and running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Installation Instructions
&lt;/h2&gt;

&lt;p&gt;In order for you to run any of these commands, you'll need to have Docker installed. You can view the instructions here: &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Get Docker: Installation Instructions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution Instructions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Pull the ZAP Docker Image
&lt;/h3&gt;

&lt;p&gt;First, ensure you have Docker installed and running on your system. Then, pull the latest OWASP ZAP Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull zaproxy/zap-stable:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we start with the zap scans, lets first take a look at the docker image itself&lt;/p&gt;

&lt;p&gt;Lets run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; zaproxy/zap-stable:latest bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will take us inside the running container of the image and show us the contents in its default working dir, which is /zap&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zap@6026a83c9b31:/zap&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
total 5632
drwxr-xr-x 1 zap  zap     4096 Oct  7 16:47 &lt;span class="nb"&gt;.&lt;/span&gt;
drwxr-xr-x 1 root root    4096 Oct 15 15:26 ..
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap    10324 Oct  7 16:45 CHANGELOG.md
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap     2167 Jan  2  1970 README
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap       18 Oct  7 16:47 container
drwxr-xr-x 2 zap  zap     4096 Jan  2  1970 db
drwxr-xr-x 2 zap  zap     4096 Jan  2  1970 lang
drwxr-xr-x 2 zap  zap     4096 Jan  2  1970 lib
drwxr-xr-x 2 zap  zap     4096 Jan  2  1970 license
drwxr-xr-x 2 zap  zap     4096 Oct  7 16:47 plugin
drwxr-xr-x 3 zap  zap     4096 Jan  2  1970 scripts
drwxr-xr-x 1 zap  zap     4096 Oct  7 16:45 webswing
drwxr-xr-x 2 zap  zap     4096 Jan  2  1970 xml
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap  5450049 Jan  2  1970 zap-2.15.0.jar
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap    26496 Oct  7 16:45 zap-api-scan.py
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap    24732 Oct  7 16:45 zap-baseline.py
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap    20576 Oct  7 16:45 zap-full-scan.py
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap     2977 Oct  7 16:45 zap-webswing.sh
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap      319 Oct  7 16:45 zap-x.sh
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap      188 Jan  2  1970 zap.bat
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap   123778 Jan  2  1970 zap.ico
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 zap  zap     4231 Jan  2  1970 zap.sh
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 zap  zap    23306 Oct  7 16:45 zap_common.py

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

&lt;/div&gt;



&lt;p&gt;As seen above in the output, we have 3 main python executable files that we can use for scans, later in the article we will see the flag to pass the python file name to use&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;zap-api-scan.py&lt;/li&gt;
&lt;li&gt;zap-baseline.py&lt;/li&gt;
&lt;li&gt;zap-full-scan.py&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Start Your Localhost Application
&lt;/h3&gt;

&lt;p&gt;Make sure your local application is running on localhost. For example, if it's a web application, it might be accessible at &lt;br&gt;&lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Run the ZAP Scan
&lt;/h3&gt;

&lt;p&gt;Use the following command to run the ZAP scanner against your localhost application. This command assumes your application is accessible on port 8080. Adjust the port number accordingly if your application uses a different port.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Linux/Unix&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/zap/wrk/:rw &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt; zaproxy/zap-stable zap-baseline.py &lt;span class="nt"&gt;-t&lt;/span&gt; https://localhost:8080 &lt;span class="nt"&gt;-r&lt;/span&gt; scan-report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Windows Powershell&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -v ${PWD}:/zap/wrk/:rw --network="host" zaproxy/zap-stable zap-baseline.py -t https://localhost:8080 -r scan-report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Explanation of the Command
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-v $(pwd):/zap/wrk/:rw&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This option mounts the current directory (&lt;code&gt;$(pwd)&lt;/code&gt;) to the &lt;code&gt;/zap/wrk/&lt;/code&gt; directory inside the container. The report will be saved in this directory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--network="host"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells Docker to use the host's network, allowing the Docker container to access &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;zap-full-scan.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a script provided by ZAP for running a full scan, which performs a deeper and more thorough scan. It will take a while though.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-t http://localhost:8000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifies the target URL for the scan. &lt;strong&gt;NOTE: You can however provide URL for your own web app as well, be it on localhost or hosted somewhere, hopefully not in production yet&lt;/strong&gt; :D&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-r scan-report.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifies the name of the report file to generate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Additional Flags to pass to Image
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Usage: zap-baseline.py &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;target&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;options]
    &lt;span class="nt"&gt;-t&lt;/span&gt; target         target URL including the protocol, eg https://www.example.com
Options:
    &lt;span class="nt"&gt;-h&lt;/span&gt;                print this &lt;span class="nb"&gt;help &lt;/span&gt;message
    &lt;span class="nt"&gt;-c&lt;/span&gt; config_file    config file to use to INFO, IGNORE or FAIL warnings
    &lt;span class="nt"&gt;-u&lt;/span&gt; config_url     URL of config file to use to INFO, IGNORE or FAIL warnings
    &lt;span class="nt"&gt;-g&lt;/span&gt; gen_file       generate default config file &lt;span class="o"&gt;(&lt;/span&gt;all rules &lt;span class="nb"&gt;set &lt;/span&gt;to WARN&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;-m&lt;/span&gt; mins           the number of minutes to spider &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;default 1&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;-r&lt;/span&gt; report_html    file to write the full ZAP HTML report
    &lt;span class="nt"&gt;-w&lt;/span&gt; report_md      file to write the full ZAP Wiki &lt;span class="o"&gt;(&lt;/span&gt;Markdown&lt;span class="o"&gt;)&lt;/span&gt; report
    &lt;span class="nt"&gt;-x&lt;/span&gt; report_xml     file to write the full ZAP XML report
    &lt;span class="nt"&gt;-J&lt;/span&gt; report_json    file to write the full ZAP JSON document
    &lt;span class="nt"&gt;-a&lt;/span&gt;                include the alpha passive scan rules as well
    &lt;span class="nt"&gt;-d&lt;/span&gt;                show debug messages
    &lt;span class="nt"&gt;-P&lt;/span&gt;                specify listen port
    &lt;span class="nt"&gt;-D&lt;/span&gt; secs           delay &lt;span class="k"&gt;in &lt;/span&gt;seconds to &lt;span class="nb"&gt;wait &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;passive scanning 
    &lt;span class="nt"&gt;-i&lt;/span&gt;                default rules not &lt;span class="k"&gt;in &lt;/span&gt;the config file to INFO
    &lt;span class="nt"&gt;-I&lt;/span&gt;                &lt;span class="k"&gt;do &lt;/span&gt;not &lt;span class="k"&gt;return &lt;/span&gt;failure on warning
    &lt;span class="nt"&gt;-j&lt;/span&gt;                use the Ajax spider &lt;span class="k"&gt;in &lt;/span&gt;addition to the traditional one
    &lt;span class="nt"&gt;-l&lt;/span&gt; level          minimum level to show: PASS, IGNORE, INFO, WARN or FAIL, use with &lt;span class="nt"&gt;-s&lt;/span&gt; to hide example URLs
    &lt;span class="nt"&gt;-n&lt;/span&gt; context_file   context file which will be loaded prior to spidering the target
    &lt;span class="nt"&gt;-p&lt;/span&gt; progress_file  progress file which specifies issues that are being addressed
    &lt;span class="nt"&gt;-s&lt;/span&gt;                short output format - dont show PASSes or example URLs
    &lt;span class="nt"&gt;-T&lt;/span&gt; mins           max &lt;span class="nb"&gt;time &lt;/span&gt;&lt;span class="k"&gt;in &lt;/span&gt;minutes to &lt;span class="nb"&gt;wait &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;ZAP to start and the passive scan to run
    &lt;span class="nt"&gt;-U&lt;/span&gt; user           username to use &lt;span class="k"&gt;for &lt;/span&gt;authenticated scans - must be defined &lt;span class="k"&gt;in &lt;/span&gt;the given context file &lt;span class="o"&gt;(&lt;/span&gt;post 2.9.0&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;-z&lt;/span&gt; zap_options    ZAP &lt;span class="nb"&gt;command &lt;/span&gt;line options e.g. &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"-config aaa=bbb -config ccc=ddd"&lt;/span&gt;
    &lt;span class="nt"&gt;--hook&lt;/span&gt;            path to python file that define your custom hooks
    &lt;span class="nt"&gt;--auto&lt;/span&gt;            use the automation framework &lt;span class="k"&gt;if &lt;/span&gt;supported &lt;span class="k"&gt;for &lt;/span&gt;the given parameters &lt;span class="o"&gt;(&lt;/span&gt;this will become the default soon&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;--autooff&lt;/span&gt;         &lt;span class="k"&gt;do &lt;/span&gt;not use the automation framework even &lt;span class="k"&gt;if &lt;/span&gt;supported &lt;span class="k"&gt;for &lt;/span&gt;the given parameters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Command Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/zap/wrk/:rw &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt; zaproxy/zap-stable zap-baseline.py &lt;span class="nt"&gt;-t&lt;/span&gt; https://localhost:8080 &lt;span class="nt"&gt;-r&lt;/span&gt; scan-report.html
Using the Automation Framework
Total of 19 URLs
PASS: Vulnerable JS Library &lt;span class="o"&gt;(&lt;/span&gt;Powered by Retire.js&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10003]
PASS: In Page Banner Information Leak &lt;span class="o"&gt;[&lt;/span&gt;10009]
PASS: Cookie No HttpOnly Flag &lt;span class="o"&gt;[&lt;/span&gt;10010]
PASS: Cookie Without Secure Flag &lt;span class="o"&gt;[&lt;/span&gt;10011]
PASS: Cross-Domain JavaScript Source File Inclusion &lt;span class="o"&gt;[&lt;/span&gt;10017]
PASS: Content-Type Header Missing &lt;span class="o"&gt;[&lt;/span&gt;10019]
PASS: Information Disclosure - Debug Error Messages &lt;span class="o"&gt;[&lt;/span&gt;10023]
PASS: Information Disclosure - Sensitive Information &lt;span class="k"&gt;in &lt;/span&gt;URL &lt;span class="o"&gt;[&lt;/span&gt;10024]
PASS: Information Disclosure - Sensitive Information &lt;span class="k"&gt;in &lt;/span&gt;HTTP Referrer Header &lt;span class="o"&gt;[&lt;/span&gt;10025]
PASS: HTTP Parameter Override &lt;span class="o"&gt;[&lt;/span&gt;10026]
PASS: Open Redirect &lt;span class="o"&gt;[&lt;/span&gt;10028]
PASS: Cookie Poisoning &lt;span class="o"&gt;[&lt;/span&gt;10029]
PASS: User Controllable Charset &lt;span class="o"&gt;[&lt;/span&gt;10030]
PASS: User Controllable HTML Element Attribute &lt;span class="o"&gt;(&lt;/span&gt;Potential XSS&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10031]
PASS: Viewstate &lt;span class="o"&gt;[&lt;/span&gt;10032]
PASS: Directory Browsing &lt;span class="o"&gt;[&lt;/span&gt;10033]
PASS: Heartbleed OpenSSL Vulnerability &lt;span class="o"&gt;(&lt;/span&gt;Indicative&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10034]
PASS: Server Leaks Information via &lt;span class="s2"&gt;"X-Powered-By"&lt;/span&gt; HTTP Response Header Field&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10037]
PASS: X-Backend-Server Header Information Leak &lt;span class="o"&gt;[&lt;/span&gt;10039]
PASS: Secure Pages Include Mixed Content &lt;span class="o"&gt;[&lt;/span&gt;10040]
PASS: HTTP to HTTPS Insecure Transition &lt;span class="k"&gt;in &lt;/span&gt;Form Post &lt;span class="o"&gt;[&lt;/span&gt;10041]
PASS: HTTPS to HTTP Insecure Transition &lt;span class="k"&gt;in &lt;/span&gt;Form Post &lt;span class="o"&gt;[&lt;/span&gt;10042]
PASS: User Controllable JavaScript Event &lt;span class="o"&gt;(&lt;/span&gt;XSS&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10043]
PASS: Big Redirect Detected &lt;span class="o"&gt;(&lt;/span&gt;Potential Sensitive Information Leak&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10044]
PASS: Retrieved from Cache &lt;span class="o"&gt;[&lt;/span&gt;10050]
PASS: X-ChromeLogger-Data &lt;span class="o"&gt;(&lt;/span&gt;XCOLD&lt;span class="o"&gt;)&lt;/span&gt; Header Information Leak &lt;span class="o"&gt;[&lt;/span&gt;10052]
PASS: Cookie without SameSite Attribute &lt;span class="o"&gt;[&lt;/span&gt;10054]
PASS: CSP &lt;span class="o"&gt;[&lt;/span&gt;10055]
PASS: X-Debug-Token Information Leak &lt;span class="o"&gt;[&lt;/span&gt;10056]
PASS: Username Hash Found &lt;span class="o"&gt;[&lt;/span&gt;10057]
PASS: X-AspNet-Version Response Header &lt;span class="o"&gt;[&lt;/span&gt;10061]
PASS: PII Disclosure &lt;span class="o"&gt;[&lt;/span&gt;10062]
PASS: Timestamp Disclosure &lt;span class="o"&gt;[&lt;/span&gt;10096]
PASS: Hash Disclosure &lt;span class="o"&gt;[&lt;/span&gt;10097]
PASS: Cross-Domain Misconfiguration &lt;span class="o"&gt;[&lt;/span&gt;10098]
PASS: Weak Authentication Method &lt;span class="o"&gt;[&lt;/span&gt;10105]
PASS: Reverse Tabnabbing &lt;span class="o"&gt;[&lt;/span&gt;10108]
PASS: Dangerous JS Functions &lt;span class="o"&gt;[&lt;/span&gt;10110]
PASS: Session Management Response Identified &lt;span class="o"&gt;[&lt;/span&gt;10112]
PASS: Verification Request Identified &lt;span class="o"&gt;[&lt;/span&gt;10113]
PASS: Script Served From Malicious Domain &lt;span class="o"&gt;(&lt;/span&gt;polyfill&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10115]
PASS: Private IP Disclosure &lt;span class="o"&gt;[&lt;/span&gt;2]
PASS: Session ID &lt;span class="k"&gt;in &lt;/span&gt;URL Rewrite &lt;span class="o"&gt;[&lt;/span&gt;3]
PASS: Script Passive Scan Rules &lt;span class="o"&gt;[&lt;/span&gt;50001]
PASS: Stats Passive Scan Rule &lt;span class="o"&gt;[&lt;/span&gt;50003]
PASS: Insecure JSF ViewState &lt;span class="o"&gt;[&lt;/span&gt;90001]
PASS: Java Serialization Object &lt;span class="o"&gt;[&lt;/span&gt;90002]
PASS: Sub Resource Integrity Attribute Missing &lt;span class="o"&gt;[&lt;/span&gt;90003]
PASS: Insufficient Site Isolation Against Spectre Vulnerability &lt;span class="o"&gt;[&lt;/span&gt;90004]
PASS: Charset Mismatch &lt;span class="o"&gt;[&lt;/span&gt;90011]
PASS: WSDL File Detection &lt;span class="o"&gt;[&lt;/span&gt;90030]
PASS: Loosely Scoped Cookie &lt;span class="o"&gt;[&lt;/span&gt;90033]
WARN-NEW: Re-examine Cache-control Directives &lt;span class="o"&gt;[&lt;/span&gt;10015] x 2 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/robots.txt &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Missing Anti-clickjacking Header &lt;span class="o"&gt;[&lt;/span&gt;10020] x 1 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: X-Content-Type-Options Header Missing &lt;span class="o"&gt;[&lt;/span&gt;10021] x 6 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/index.css &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;console.png &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;debugger.js &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;style.css &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Information Disclosure - Suspicious Comments &lt;span class="o"&gt;[&lt;/span&gt;10027] x 3 
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;debugger.js &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;debugger.js &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Strict-Transport-Security Header Not Set &lt;span class="o"&gt;[&lt;/span&gt;10035] x 12 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/app.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/helper/db_manager.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/index.css &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;console.png &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Server Leaks Version Information via &lt;span class="s2"&gt;"Server"&lt;/span&gt; HTTP Response Header Field &lt;span class="o"&gt;[&lt;/span&gt;10036] x 12 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/app.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/helper/db_manager.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/index.css &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;console.png &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Content Security Policy &lt;span class="o"&gt;(&lt;/span&gt;CSP&lt;span class="o"&gt;)&lt;/span&gt; Header Not Set &lt;span class="o"&gt;[&lt;/span&gt;10038] x 8 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/app.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/helper/db_manager.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?btn&lt;span class="o"&gt;=&lt;/span&gt;Confirm+Pin&amp;amp;pin&lt;span class="o"&gt;=&lt;/span&gt;ZAP &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/sitemap.xml &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Storable and Cacheable Content &lt;span class="o"&gt;[&lt;/span&gt;10049] x 12 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/app.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/helper/db_manager.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/index.css &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;console.png &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Permissions Policy Header Not Set &lt;span class="o"&gt;[&lt;/span&gt;10063] x 9 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/app.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/app/helper/db_manager.py &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?__debugger__&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&amp;amp;cmd&lt;span class="o"&gt;=&lt;/span&gt;resource&amp;amp;f&lt;span class="o"&gt;=&lt;/span&gt;debugger.js &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login?btn&lt;span class="o"&gt;=&lt;/span&gt;Confirm+Pin&amp;amp;pin&lt;span class="o"&gt;=&lt;/span&gt;ZAP &lt;span class="o"&gt;(&lt;/span&gt;404 Not Found&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Source Code Disclosure - SQL &lt;span class="o"&gt;[&lt;/span&gt;10099] x 1 
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Modern Web Application &lt;span class="o"&gt;[&lt;/span&gt;10109] x 2 
        https://localhost:8080 &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Authentication Request Identified &lt;span class="o"&gt;[&lt;/span&gt;10111] x 1 
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Absence of Anti-CSRF Tokens &lt;span class="o"&gt;[&lt;/span&gt;10202] x 1 
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
WARN-NEW: Application Error Disclosure &lt;span class="o"&gt;[&lt;/span&gt;90022] x 1 
        https://localhost:8080/login &lt;span class="o"&gt;(&lt;/span&gt;500 Internal Server Error&lt;span class="o"&gt;)&lt;/span&gt;
FAIL-NEW: 0     FAIL-INPROG: 0  WARN-NEW: 14    WARN-INPROG: 0  INFO: 0 IGNORE: 0       PASS: 52

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Retrieve the HTML Report
&lt;/h3&gt;

&lt;p&gt;Once the scan is complete, an HTML report named &lt;code&gt;scan-report.html&lt;/code&gt; will be saved in your current working directory. You can open this file in any web browser to view the detailed security scan report.&lt;/p&gt;

&lt;p&gt;Here is the report it generates:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://html-preview.github.io/?url=https://github.com/hassanaftab93/dast-scanning-owasp/blob/main/scan-report.html" rel="noopener noreferrer"&gt;Scan Report - Generated for TIWAP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your generated report can be shared with your teams to make the proper fixes required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scan Duration&lt;/strong&gt;: Depending on the complexity and size of your application, the scan may take some time. Ensure your application remains running until the scan is completed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Considerations&lt;/strong&gt;: Regularly update the Docker image with &lt;code&gt;docker pull owasp/zap2docker-stable&lt;/code&gt; to ensure you are using the latest security checks and features.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>docker</category>
      <category>owasp</category>
    </item>
    <item>
      <title>Why Prometheus and Grafana are Essential for Monitoring in DevOps and How They Enhance the SDLC</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Mon, 14 Oct 2024 13:44:07 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/why-prometheus-and-grafana-are-essential-for-monitoring-in-devops-and-how-they-enhance-the-sdlc-gmk</link>
      <guid>https://dev.to/hassan_aftab/why-prometheus-and-grafana-are-essential-for-monitoring-in-devops-and-how-they-enhance-the-sdlc-gmk</guid>
      <description>&lt;p&gt;In the evolving world of software development and operations, &lt;strong&gt;monitoring&lt;/strong&gt; has become a key pillar for ensuring system reliability, scalability, and performance. With the rise of cloud-native applications, micro services, and containerization, traditional monitoring tools often struggle to keep up with the highly dynamic and distributed nature of modern infrastructures.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;Grafana&lt;/strong&gt;—two powerful open-source tools that have rapidly become the go-to solutions for monitoring and visualization in the DevOps ecosystem. These tools not only help monitor infrastructure in real-time but also contribute significantly to the &lt;strong&gt;Software Development Life Cycle (SDLC)&lt;/strong&gt; by enhancing the feedback loop, improving visibility, and boosting the efficiency of Continuous Integration/Continuous Deployment (CI/CD) pipelines.&lt;/p&gt;

&lt;p&gt;In this article, we'll dive into why these tools are critical for DevOps and how they improve the SDLC.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Prometheus?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prometheus&lt;/strong&gt; is an open-source systems monitoring and alerting toolkit, originally developed by SoundCloud and now maintained by the Cloud Native Computing Foundation (CNCF). It was designed to handle modern, dynamic, and cloud-native infrastructures, making it an ideal choice for monitoring microservices and Kubernetes-based environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of Prometheus:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Metrics Collection:&lt;/strong&gt; Prometheus scrapes metrics from endpoints at specified intervals, enabling real-time monitoring of various systems and services. These metrics are then stored in a time-series database, optimized for high performance and scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Discovery:&lt;/strong&gt; Prometheus can automatically discover services using different service discovery mechanisms like Kubernetes, Consul, and others, making it highly suitable for dynamic environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Query Language (PromQL):&lt;/strong&gt; Prometheus uses a powerful query language called &lt;strong&gt;PromQL&lt;/strong&gt; to aggregate and analyze metrics. You can create complex queries to extract detailed insights from your metrics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-dimensional Data Model:&lt;/strong&gt; Prometheus allows metrics to be enriched with labels (key-value pairs), enabling more detailed filtering and aggregation of metrics based on various dimensions like service name, region, instance type, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting:&lt;/strong&gt; Prometheus integrates with the &lt;strong&gt;Alertmanager&lt;/strong&gt;, enabling teams to configure highly flexible alerting rules. You can trigger alerts based on custom-defined thresholds or unexpected patterns and send notifications through various channels (Slack, PagerDuty, email, etc.).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is Grafana?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Grafana&lt;/strong&gt; is a powerful open-source analytics and visualization tool that allows teams to query, visualize, and alert on metrics from multiple sources. While it supports many data sources like Prometheus, Elasticsearch, InfluxDB, and more, it’s particularly known for its seamless integration with Prometheus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of Grafana:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Dashboards:&lt;/strong&gt; Grafana excels at creating interactive and customizable dashboards. You can visualize metrics in different formats such as time-series graphs, heatmaps, gauges, and more, giving you full control over how your data is presented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Source Agnostic:&lt;/strong&gt; Grafana can pull in data from multiple data sources and visualize them on the same dashboard. This allows teams to correlate metrics from Prometheus with data from other systems like logs, traces, or business analytics tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting and Notifications:&lt;/strong&gt; Grafana provides advanced alerting capabilities. You can define alert rules and conditions directly from your dashboards and get notified when metrics go out of bounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-friendly Interface:&lt;/strong&gt; Grafana’s intuitive interface makes it easy for teams to create complex visualizations and share them across the organization. Its wide range of plugins allows for easy customization and integration with other systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templated Dashboards:&lt;/strong&gt; Grafana’s templating feature allows you to create reusable, dynamic dashboards that can automatically adapt to different environments, services, or teams.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Role of Monitoring in the DevOps Lifecycle
&lt;/h2&gt;

&lt;p&gt;In a DevOps environment, monitoring plays a crucial role at every stage of the Software Development Life Cycle (SDLC). Let’s break down how &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;Grafana&lt;/strong&gt; fit into the different stages of the SDLC.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Development and Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;During development, real-time monitoring helps developers understand the impact of code changes on application performance. By integrating Prometheus into your CI/CD pipeline, you can capture metrics from pre-production environments, such as staging or testing environments, and use Grafana dashboards to visualize them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; Developers can catch performance issues early in the SDLC and optimize code before pushing it to production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Monitoring memory usage, API latency, or database query response times during testing can help identify bottlenecks before the software reaches production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Testing and QA&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the testing phase, observability is crucial to ensure that the system behaves as expected under various loads or edge cases. Prometheus can be configured to collect metrics during automated test runs, and Grafana can visualize the data for easy analysis.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; Teams can validate that the system meets performance benchmarks and remains resilient under stress tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; By using Prometheus to monitor CPU, memory, and network usage during load testing, teams can see how their system scales under different levels of demand.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When code is deployed to production, monitoring becomes vital to track the health and performance of the system. Prometheus can provide real-time metrics on service health, error rates, and request latency. Grafana dashboards can give DevOps teams a comprehensive view of the system’s health during and after deployments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; Real-time feedback allows for faster rollbacks or corrective measures in case of deployment failures or performance degradation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Setting up alerts for increased response time or a high rate of 5xx errors ensures that issues are detected immediately after deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Operations and Maintenance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Post-deployment, continuous monitoring ensures that the application remains healthy and performant in production. Prometheus and Grafana can provide historical data, enabling teams to identify trends and prevent issues from escalating.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; By monitoring system behavior over time, teams can detect patterns (e.g., memory leaks, increasing response times) and plan for proactive maintenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Grafana can visualize long-term trends of CPU utilization, helping teams predict when infrastructure scaling is necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Incident Management&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When issues arise in production, Prometheus and Grafana play a critical role in diagnosing the root cause and mitigating the problem. Prometheus’ alerting system can notify teams about potential outages or performance bottlenecks, and Grafana dashboards can be used to analyze the metrics in real-time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; Faster incident detection and resolution reduce downtime and maintain service reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; When an alert is triggered due to high response latency, Grafana dashboards can help teams drill down into specific microservices or nodes that are underperforming.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prometheus + Grafana: Driving Continuous Improvement in DevOps
&lt;/h2&gt;

&lt;p&gt;By providing &lt;strong&gt;real-time insights&lt;/strong&gt;, &lt;strong&gt;historical analysis&lt;/strong&gt;, and &lt;strong&gt;proactive alerting&lt;/strong&gt;, Prometheus and Grafana empower DevOps teams to continuously improve their systems and processes. Here’s how they drive continuous improvement across the SDLC:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Faster Feedback Loops&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In DevOps, continuous feedback is essential for improving software quality and performance. Prometheus enables teams to gather metrics at every stage of development, while Grafana provides an intuitive way to visualize and analyze these metrics. This combination allows for faster iteration, ensuring that teams can quickly adapt to changing requirements or fix issues as they arise.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Improved Collaboration Between Development and Operations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Prometheus and Grafana act as a bridge between development and operations teams by providing a shared view of the system’s performance. Developers can see how their code changes affect production, while operations teams can track infrastructure metrics. This visibility fosters better communication and collaboration, breaking down traditional silos between the two teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Data-Driven Decision Making&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The real-time and historical data provided by Prometheus and Grafana enables teams to make informed decisions. Whether it's deciding when to scale infrastructure, identifying the root cause of a performance issue, or planning the next deployment, data-driven insights lead to more confident decision-making.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Proactive Problem Solving&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With Prometheus’ powerful alerting system and Grafana’s ability to track trends over time, teams can identify potential issues before they become critical. This allows for proactive problem solving, reducing the likelihood of unplanned downtime and improving system resilience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In the DevOps world, where &lt;strong&gt;speed, reliability, and continuous improvement&lt;/strong&gt; are key, integrating &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;Grafana&lt;/strong&gt; into your monitoring strategy is a game-changer. These tools not only provide deep visibility into system performance but also enhance collaboration, streamline incident response, and improve the overall &lt;strong&gt;Software Development Life Cycle (SDLC)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By embracing Prometheus and Grafana, your team can move beyond reactive troubleshooting and toward a more proactive, data-driven approach to software development and operations.&lt;/p&gt;

&lt;p&gt;Are you ready to take your DevOps monitoring to the next level?&lt;/p&gt;




</description>
      <category>devops</category>
      <category>observability</category>
      <category>monitoring</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Understanding Terraform: A Guide to Effective IaC Practices</title>
      <dc:creator>Hassan Aftab</dc:creator>
      <pubDate>Wed, 12 Jun 2024 22:38:45 +0000</pubDate>
      <link>https://dev.to/hassan_aftab/understanding-terraform-a-guide-to-effective-iac-practices-28pn</link>
      <guid>https://dev.to/hassan_aftab/understanding-terraform-a-guide-to-effective-iac-practices-28pn</guid>
      <description>&lt;h2&gt;
  
  
  What is Terraform?
&lt;/h2&gt;



&lt;p&gt;Terraform is an infrastructure as code (IaC) tool that allows you to build, change, and version cloud and on-premises resources safely and efficiently.&lt;/p&gt;

&lt;p&gt;With Terraform, you define your infrastructure using human-readable configuration files, which can be &lt;strong&gt;versioned, reused, and shared&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It works with a wide range of platforms and services through their APIs, enabling you to manage both low-level components (such as compute instances, storage, and networking) in a consistent manner.&lt;/p&gt;



&lt;h3&gt;
  
  
  The 3 Stage Workflow:
&lt;/h3&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;The Coding Stage&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;Define resources across one or multiple cloud providers and services in your configuration files, depending on your requirements.&lt;/p&gt;

&lt;p&gt;Here is a sample project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── bicep
│   ├── deploy.ps1
│   ├── init.bicep
│   ├── params
│   │   ├── dev.bicepparam
│   │   └── test.bicepparam
│   └── storage.bicep
├── LICENSE
├── Makefile
├── README.md
└── terraform
    ├── modules
    │   ├── container_app
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── container_app_environment
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── container_registry
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── resource_group
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── subnet
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── subnet_network_security_group_association
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   └── virtual_network
    │       ├── main.tf
    │       ├── outputs.tf
    │       └── variables.tf
    └── resources
        ├── backend.tf
        ├── data.tf
        ├── main.tf
        ├── outputs.tf
        ├── provider.tf
        ├── tfvars
        │   ├── dev.tfvars
        │   ├── eun_region.tfvars
        │   └── tags.tfvars
        └── variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;You can however, code the entire thing in a single file if you want, but as we all know, it is considered as a best practice, to adhere to separation of concerns&lt;/p&gt;

&lt;p&gt;Lets breakdown the &lt;a href="https://github.com/hassanaftab93/terraform-example" rel="noopener noreferrer"&gt;project&lt;/a&gt; structure:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;directories:

&lt;ul&gt;
&lt;li&gt;bicep&lt;/li&gt;
&lt;li&gt;terraform&lt;/li&gt;
&lt;li&gt;terraform/module&lt;/li&gt;
&lt;li&gt;terraform/resources&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;files:

&lt;ul&gt;
&lt;li&gt;all files in directories inside terraform/modules/ contain modules for individual resources&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# backend.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# Here we define the provider to use for this directory&lt;/span&gt;

    &lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;storage_account_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"storageAccountName"&lt;/span&gt;
        &lt;span class="nx"&gt;container_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstates"&lt;/span&gt;
        &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"resourceGroupName"&lt;/span&gt;
        &lt;span class="nx"&gt;key&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"resources.tfstate"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# data.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# Here we define the data sources to use for this directory&lt;/span&gt;

    &lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"terraform_remote_state"&lt;/span&gt; &lt;span class="s2"&gt;"resources"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt;

        &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;storage_account_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"storageAccountName"&lt;/span&gt;
            &lt;span class="nx"&gt;container_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstates"&lt;/span&gt;
            &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"resourceGroupName"&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"resources.tfstate"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# In this case, we use the data source to get the existing resource group&lt;/span&gt;

    &lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_resource_group"&lt;/span&gt; &lt;span class="s2"&gt;"existing"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"resourceGroupName"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As shown above, in the directory structure, the modules are defined in the &lt;code&gt;terraform/modules&lt;/code&gt; directory and the resources are defined in the &lt;code&gt;terraform/resources&lt;/code&gt; directory. The main codebase of this project resides in the &lt;code&gt;terraform/resources/main.tf&lt;/code&gt; file.&lt;/p&gt;



&lt;p&gt;Main things to note in the &lt;code&gt;terraform/resources/main.tf&lt;/code&gt; file:&lt;br&gt;
&lt;br&gt;source - defines the module to use&lt;br&gt;
&lt;br&gt;module - defines the resources to create&lt;br&gt;
&lt;br&gt;The use of &lt;code&gt;data.azurerm_resource_group.existing.location&lt;/code&gt; as well as &lt;code&gt;data.azurerm_resource_group.existing.name&lt;/code&gt; to get the location and name of the resource group&lt;br&gt;
&lt;br&gt;The use of depend_on to ensure that the resources are created before the module is executed&lt;br&gt;
&lt;br&gt;Notice the use of $(acrServer) and $(acrUsername) and $(acrPassword) in the container_registry_server, container_registry_username and container_registry_password respectively.&lt;/p&gt;

&lt;p&gt;These variables are defined in Pipelines. Since this information is sensitive, we are hiding it in the codebase and storing these secrets in pipeline variable groups/secrets&lt;/p&gt;

&lt;p&gt;Let's take a look at the contents below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# main.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# Here we define the resources to use for this project&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the network security group&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"network_security_group"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/network_security_group"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;nsg"&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

      &lt;span class="nx"&gt;rules&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;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nsg-rule-1"&lt;/span&gt;
          &lt;span class="nx"&gt;priority&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
          &lt;span class="nx"&gt;direction&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inbound"&lt;/span&gt;
          &lt;span class="nx"&gt;access&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
          &lt;span class="nx"&gt;protocol&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;source_port_range&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;destination_port_range&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;source_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;destination_address_prefix&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="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nsg-rule-2"&lt;/span&gt;
          &lt;span class="nx"&gt;priority&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;
          &lt;span class="nx"&gt;direction&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Outbound"&lt;/span&gt;
          &lt;span class="nx"&gt;access&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
          &lt;span class="nx"&gt;protocol&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;source_port_range&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;destination_port_range&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;source_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
          &lt;span class="nx"&gt;destination_address_prefix&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="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;tags&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the virtual network to use in resources&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"virtual_network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/virtual_network"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;vnet"&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;address_space&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;tags&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the subnet that will be used to create resources under, later on.&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"subnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/subnet"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;subnet"&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network_name&lt;/span&gt;
      &lt;span class="nx"&gt;subnet_address_prefix&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;service_endpoints&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.Web"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;delegation_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"delegation"&lt;/span&gt;
      &lt;span class="nx"&gt;service_delegation_name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.App/environments"&lt;/span&gt;
      &lt;span class="nx"&gt;service_delegation_actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/subnets/join/action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;virtual_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the container app environment, notice the use of module.subnet.subnet_id , this is how we can reference the subnet_id from the subnet module.&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"container_app_environment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/container_app_environment"&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-cntr-env"&lt;/span&gt;
      &lt;span class="nx"&gt;log_analytics_workspace_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log_analytics_workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log_analytics_workspace_id&lt;/span&gt;
      &lt;span class="nx"&gt;infrastructure_subnet_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
      &lt;span class="nx"&gt;internal_load_balancer_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;tags&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the container registry&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"container_registry"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/container_registry"&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;cr"&lt;/span&gt;
      &lt;span class="nx"&gt;sku&lt;/span&gt;                              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Standard"&lt;/span&gt;
      &lt;span class="nx"&gt;is_admin_enabled&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="nx"&gt;is_public_network_access_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;tags&lt;/span&gt;                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the container apps that will be created under the container app environment created earlier&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"container_app"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/container_app"&lt;/span&gt;
      &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;container_app_environment_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Environment_ID&lt;/span&gt;
      &lt;span class="nx"&gt;container_registry_server&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(acrServer)"&lt;/span&gt;
      &lt;span class="nx"&gt;container_registry_username&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(acrUsername)"&lt;/span&gt;
      &lt;span class="nx"&gt;container_registry_password&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(acrPassword)"&lt;/span&gt;
      &lt;span class="nx"&gt;container_apps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

        &lt;span class="c1"&gt;# Notice the use of $(containerAppSecretKey) and $(containerAppSecretValue) in the secret_name and secret_value respectively&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"containerapp1-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;image&lt;/span&gt;                      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"&lt;/span&gt;
          &lt;span class="nx"&gt;cpu&lt;/span&gt;                        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;
          &lt;span class="nx"&gt;memory&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.5Gi"&lt;/span&gt;
          &lt;span class="nx"&gt;target_port&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
          &lt;span class="nx"&gt;transport&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http2"&lt;/span&gt;
          &lt;span class="nx"&gt;external_enabled&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="nx"&gt;allow_insecure_connections&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="nx"&gt;secret_name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(containerAppSecretKey)"&lt;/span&gt;
          &lt;span class="nx"&gt;secret_value&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(containerAppSecretValue)"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"containerapp2-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;image&lt;/span&gt;                      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"&lt;/span&gt;
          &lt;span class="nx"&gt;cpu&lt;/span&gt;                        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;
          &lt;span class="nx"&gt;memory&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.5Gi"&lt;/span&gt;
          &lt;span class="nx"&gt;target_port&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
          &lt;span class="nx"&gt;transport&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"auto"&lt;/span&gt;
          &lt;span class="nx"&gt;external_enabled&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="nx"&gt;allow_insecure_connections&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="nx"&gt;secret_name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(containerAppSecretKey)"&lt;/span&gt;
          &lt;span class="nx"&gt;secret_value&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(containerAppSecretValue)"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;tags&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Defining the network security group association&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"subnet_nsg_association"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../modules/subnet_network_security_group_association"&lt;/span&gt;
      &lt;span class="nx"&gt;subnet_id&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
      &lt;span class="nx"&gt;network_security_group_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="nx"&gt;depends_on&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&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;In the block below, are the contents of output.tf, which contains all the outputs we want to get when the terraform code is run in the terminal / pipeline.&lt;/p&gt;

&lt;p&gt;This can include details such as IPs of services being created, fqdns, etc.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is, since we are using a modular based approach, these outputs must first be exported from an output.tf file inside the module itself, before the implementation of the module that actually outputs it during the run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# outputs.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# Here we define the outputs to use for this directory&lt;/span&gt;

    &lt;span class="c1"&gt;# Container App Environment&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_environment_default_domain"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Default_Domain&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_environment_docker_bridge"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Docker_Bridge_CIDR&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_environment_environment_id"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Environment_ID&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_environment_static_ip_address"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Static_IP_Address&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Container Apps&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_latest_fqdn"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Latest_Revision_Fqdn&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_app_outbound_ips"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Outbound_Ip_Addresses&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Container Registry&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_id"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_sku"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_registry_server"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registry_server&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_admin_enabled"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin_enabled&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_admin_username"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin_username&lt;/span&gt;
      &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"container_registry_admin_password"&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="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin_password&lt;/span&gt;
      &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the next block, are the contents of provider.tf&lt;/p&gt;

&lt;p&gt;We have used &lt;code&gt;skip_provider_registration = true&lt;/code&gt; to skip the provider registration, as sometimes during a Pipeline run, it can causes issues if terraform checks for registered providers. &lt;/p&gt;

&lt;p&gt;Furthermore, here we define the minimum version of the provider we are using as well as the required version of the Terraform CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# provider.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# Here we define the providers to use for this directory&lt;/span&gt;

    &lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;features&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
      &lt;span class="nx"&gt;skip_provider_registration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.7.5"&lt;/span&gt;
      &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;azurerm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/azurerm"&lt;/span&gt;
          &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;=3.96.0"&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;In the next block, are the contents of tfvars/dev.tf&lt;br&gt;
As discussed before, sensitive values are stored in pipeline variable groups/secrets. In this case &lt;code&gt;sql_administrator_login&lt;/code&gt; and &lt;code&gt;sql_administrator_login_password&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# tfvars/dev.tf&lt;/span&gt;
    &lt;span class="c1"&gt;# This file defines the variables to use for this project for the dev environment&lt;/span&gt;

    &lt;span class="nx"&gt;project_name&lt;/span&gt;                 &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Project"&lt;/span&gt;
    &lt;span class="nx"&gt;environment&lt;/span&gt;                  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
    &lt;span class="nx"&gt;administrator_login&lt;/span&gt;          &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(sql_administrator_login)"&lt;/span&gt;
    &lt;span class="nx"&gt;administrator_login_password&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(sql_administrator_login_password)"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Similarly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# tfvars/eun_region.tf&lt;/span&gt;

    &lt;span class="nx"&gt;region_name&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"northeurope"&lt;/span&gt;
    &lt;span class="nx"&gt;region_short&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eun"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the last variables file, are the contents of tfvars/tags.tf, which defines the tags to be applied to the resources. Back in the main.tf file, we used this &lt;code&gt;tags = merge(var.tags)&lt;/code&gt; key-value pair approach to define the tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# tfvars/tags.tf&lt;/span&gt;

    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ServiceName&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="nx"&gt;Department&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Cloud"&lt;/span&gt;
        &lt;span class="nx"&gt;Environment&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
        &lt;span class="nx"&gt;SubEnvironment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nonProd"&lt;/span&gt;
        &lt;span class="nx"&gt;SystemName&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally the variables file that contains the variables and their types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# variables.tf&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region_short"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Short name of region used in project"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Long name of region used in project"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"project_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Project name"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"environment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment name"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"tags"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ServiceName&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="nx"&gt;Department&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="nx"&gt;Environment&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="nx"&gt;SubEnvironment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="nx"&gt;SystemName&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="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"administrator_login"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Administrator login"&lt;/span&gt;
      &lt;span class="nx"&gt;sensitive&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"administrator_login_password"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Administrator login password"&lt;/span&gt;
      &lt;span class="nx"&gt;sensitive&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;





&lt;h4&gt;
  
  
  &lt;strong&gt;The Plan Stage&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In this stage, we are done with defining Infrastructure as Code configurations, now we need Terraform to generate an execution plan based on these configurations and existing infrastructure, describing the changes it will make.&lt;/p&gt;

&lt;p&gt;Before we go ahead and generate a plan, it is considered a good practice to make sure your code is valid and there are no syntax errors, or referencing errors.&lt;/p&gt;

&lt;p&gt;This can be done by switching to your trusty CLI.. again, and running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# This command validates your code and makes sure it's good to go&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt;

&lt;span class="c1"&gt;# And it's just as easy to make your code look much more cleaner with just one command again&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;fmt&lt;/span&gt; &lt;span class="nx"&gt;--recursive&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;terraform fmt --recursive&lt;/code&gt; command formats the current directory as well the child directories and all .tf and .tfvars files, and properly indents all code.&lt;/p&gt;



&lt;p&gt;Below we can see our code is valid!&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%2F8yvsgf6y8tdd8v7ym4z7.png" 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%2F8yvsgf6y8tdd8v7ym4z7.png" alt=" " width="320" height="66"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Finally we can generate a plan by running a simple command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Command to generate plan&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt; &lt;span class="nx"&gt;-o&lt;/span&gt; &lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfplan&lt;/span&gt;

&lt;span class="c1"&gt;# In our case, we are using tfvars file in a directory called tfvars/, now we will need to modify the command a little bit to get the same result&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;eun_region&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt; &lt;span class="nx"&gt;-out&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfplan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Sample output can such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# module.subnet.azurerm_subnet.this will be updated in-place&lt;/span&gt;
  &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;                                             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/subscriptions/GUID_HERE/resourceGroups/project-dev/providers/Microsoft.Network/virtualNetworks/project-vnet-dev/subnets/project-subnet-dev"&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;                                           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project-subnet-dev"&lt;/span&gt;
        &lt;span class="c1"&gt;# (10 unchanged attributes hidden)&lt;/span&gt;

      &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;delegation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"project-subnet-delegation-dev"&lt;/span&gt;

          &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;service_delegation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/subnets/join/action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.App/environments"&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;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Changes&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Outputs&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;storage_account_name&lt;/span&gt;                        &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"projectblobdev"&lt;/span&gt; &lt;span class="nx"&gt;-&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"project1blobdev"&lt;/span&gt;
  &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;storage_account_primary_key&lt;/span&gt;                 &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;These changes are basically compared with a .tfstate file that can exist in your local machine or on the cloud, hosted in a s3 bucket or blob storage.&lt;/p&gt;

&lt;p&gt;In our example above, we used a blob storage service to host the tfstate file.&lt;/p&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;The Apply Stage&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Upon approval of the plan generated in the last step, Terraform applies the proposed changes in the correct order, respecting resource dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Apply command for deploying the infrastructure&lt;/span&gt;
&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfplan&lt;/span&gt;

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

&lt;/div&gt;





&lt;p&gt;This will then finally, deploy your infrastructure to the cloud. You can however, if needed, destroy the infrastructure when done with your usecase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Destroy it all by:&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;eun_region&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt; &lt;span class="nx"&gt;-var-file&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;All in all, It’s a powerful tool for managing infrastructure, allowing you to track changes, maintain consistency, and avoid manual errors.&lt;/p&gt;

&lt;p&gt;And that's not all, at the same time it also ensures, controlled costs in cloud infrastructure, since you can easily create and destroy infrastructure with simple commands.&lt;/p&gt;

&lt;p&gt;This automation can be taken further with Pipelines and gitflow that triggers based on branch that reflects a certain environment.. but that's a topic for another day :D&lt;/p&gt;

&lt;p&gt;You can find the source code by clicking &lt;a href="https://github.com/hassanaftab93/terraform-example/tree/main" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this article was a fun read and helped you gain some deeper insights into terraform modules and best practices.&lt;/p&gt;

&lt;p&gt;Thankyou for the read! &lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
    </item>
  </channel>
</rss>
