Nutshell Series

πŸ“˜ Terraform Commands Cheatsheet

Terraform is a popular Infrastructure-as-Code (IaC) tool that lets you provision and manage infrastructure efficiently.
This cheatsheet covers the most common and essential Terraform CLI commands, grouped by category for quick reference.


πŸš€ Getting Started

terraform -help                   # Show all commands
terraform version                 # Show current Terraform version
terraform -install-autocomplete   # Enable shell autocomplete

πŸ“¦ Initialization

Initialize a working directory containing Terraform configuration files.

terraform init           # Initialize Terraform in the current directory
terraform init -upgrade  # Re-download modules/providers with the latest versions

βœ… Validate & Format

terraform validate       # Check if configuration is valid
terraform fmt            # Format .tf files to canonical style
terraform fmt -recursive # Format files in all subdirectories
terraform fmt -check     # Checks if all files are formatted

πŸ“‹ Plan & Apply

terraform plan                  # Show what changes will be applied
terraform plan -out=tfplan      # Save plan to a file
terraform apply                 # Apply changes
terraform apply tfplan          # Apply saved plan
terraform apply -auto-approve   # Apply without asking for confirmation

πŸ”₯ Destroy

terraform destroy                 # Destroy infrastructure
terraform destroy -auto-approve   # Destroy without confirmation

πŸ“‚ State Management

Inspect and modify Terraform’s state file.

terraform state list             # List resources in state
terraform state show <address>   # Show resource details
terraform state rm <address>     # Remove a resource from state
terraform state mv <src> <dest>  # Move resource in state

🌎 Workspaces

Workspaces let you manage multiple environments (e.g., dev, staging, prod).

terraform workspace list        # List all workspaces
terraform workspace show        # Show current workspace
terraform workspace new dev     # Create a new workspace
terraform workspace select dev  # Switch to a workspace

πŸ”Œ Providers & Modules

terraform providers          # Show required providers
terraform providers mirror ./mirror-dir   # Download provider plugins
terraform get                # Download and update modules
terraform get -update        # Re-fetch modules

πŸ›  Debugging & Misc

terraform graph              # Generate dependency graph (DOT format)
terraform refresh            # Update state with real infrastructure
terraform output             # Show outputs from configuration
terraform output             # Show specific output
TF_LOG=DEBUG terraform plan  # Enable debug logging

πŸ“‘ Quick Workflow Example

terraform init
terraform validate
terraform plan -out=tfplan
terraform apply tfplan
terraform output
terraform destroy

πŸš€ Conclusion

This cheatsheet provides a quick reference for everyday Terraform usage.
From init to destroy, mastering these commands will speed up your infrastructure automation workflow.
Bookmark this page and use it as your go-to Terraform CLI reference!

Nutshell Series

πŸ”§ Dependency Injection (DI) Explained: Transient vs Scoped vs Singleton

Dependency Injection (DI) is a design pattern that simplifies how objects and their dependencies are managed in an application. Instead of classes creating their own dependencies, DI provides those dependencies from the outside. This makes applications cleaner, testable, and maintainable.

βš™οΈ What is Dependency Injection?

At its core, DI is about inversion of control: your classes don’t create what they need; a container provides them. This container decides:

  • How to create objects
  • When to reuse objects
  • How to dispose of them when no longer needed

πŸ“Œ Service Lifetimes

When you register services in a DI container, you usually choose a lifetime:

  • Transient – A new instance is created every time it’s requested.
  • Scoped – One instance is created per request (or unit of work).
  • Singleton – A single instance is shared across the entire application lifetime.

πŸ”„ Transient

A new instance is created each time the service is requested. Best for lightweight, stateless services.

// Example in C#
services.AddTransient<IEmailService, EmailService>();

πŸ“‚ Scoped

A new instance is created once per request, but reused within that request. Useful for services like database contexts.

// Example in C#
services.AddScoped<IDbContext, AppDbContext>();

β™Ύ Singleton

A single instance is created and reused for the entire lifetime of the application. Perfect for loggers, configuration readers, and caching providers.

// Example in C#
services.AddSingleton<ILogger, Logger>();

πŸ“Š When to Use Each?

  • Transient – For short-lived, stateless operations (e.g., helpers, formatters).
  • Scoped – For services tied to a single request or unit of work (e.g., DbContext).
  • Singleton – For shared state or expensive-to-create services (e.g., loggers, configuration, caching).

πŸš€ Conclusion

Dependency Injection ensures better code structure, easier testing, and improved flexibility.
Choosing the right lifetime β€” Transient, Scoped, or Singleton β€” helps you balance performance with resource management.

Nutshell Series

Fixing Azure Token Issuer Mismatch Error: β€œPrimary Access Token is from the Wrong Issuer”

I recently ran into a frustrating Azure authentication error while working with ARM (Azure Resource Manager) APIs.
The error looked like this:

Cache-Control: no-cache
Pragma: no-cache
WWW-Authenticate: Bearer authorization_uri="https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", error="invalid_token", error_description="The primary access token is from the wrong issuer. It must match the tenant associated with this subscription. Please use correct authority to get the token."
x-ms-failure-cause: gateway
x-ms-request-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

The Problem

The critical clue was:

The primary access token is from the wrong issuer. It must match the tenant associated with this subscription.

When I decoded the token using JWT.io, the iss (issuer)
claim was:

f8cdef31-a31e-4b4a-93e4-5f571e91255

That GUID is the Microsoft Services tenant β€” it appears when you sign in with a personal Microsoft account (MSA).
My Azure subscription, however, was tied to a specific Azure Active Directory (AAD) tenant, so Azure rejected the token because the issuer didn’t match.

What Caused It

  • I logged in using a personal Microsoft account (MSA).
  • The subscription belonged to an Azure AD tenant (not the Microsoft Services tenant).
  • Using VisualStudioCodeCredential or DefaultAzureCredential still returned tokens from the wrong issuer because the underlying login session was wrong.

Solution β€” Steps to Fix

The fix is straightforward: log into the correct tenant, set the subscription, and use credentials that respect the CLI session.

1) Log in to the correct tenant

az login --tenant <your-tenant-id>

2) Set the subscription

az account set --subscription <your-subscription-id-or-name>

3) Use Azure CLI credentials in C#

Instead of DefaultAzureCredential, switch to AzureCliCredential and fetch the token directly (this uses the Azure CLI credentials stored during az login β€” so make sure you’re logged in from the terminal):

// using Azure.Identity and Azure.Core
// var credential = new DefaultAzureCredential();
var credential = new AzureCliCredential();

string[] scopes = new[] { "https://management.azure.com/.default" };

var token = (await credential.GetTokenAsync(new TokenRequestContext(scopes))).Token;

// Optional alternative with explicit cancellation token
// token = (await credential.GetTokenAsync(new TokenRequestContext(scopes),
//     System.Threading.CancellationToken.None)).Token;

Note: This uses Azure CLI credentials stored during az login, so ensure you are logged in to the correct tenant and subscription in your terminal before running this code.

Key Takeaways

  • If your JWT iss claim is f8cdef31-a31e-4b4a-93e4-5f571e91255, you’re using a Microsoft Services tenant token (MSA) β€” it won’t work for subscriptions tied to an Azure AD tenant.
  • Fix the login by targeting the correct tenant with az login --tenant <tenant-id> and then set the subscription with az account set --subscription <subscription-id-or-name>.
  • Using AzureCliCredential in C# picks up tokens from your active Azure CLI session and helps avoid issuer mismatch issues.
Nutshell Series

πŸ” Azure AD App: Set Long-Term Secret (Two Easy Ways)

Need a long-lasting client secret for a non-production app? Here are two ways to create a secret that mimics no expiry β€” ideal for automation, CI/CD, or UAT setups.

βœ… Option 1: Azure CLI

Use this for a quick and easy credential reset:

az ad app credential reset --id ********-****-****-****-************ --years 299 --append --display-name uat-automation-secret-longterm
  • --years 299: Secret valid for ~299 years
  • --append: Keeps existing secrets
  • --display-name: Helps identify the secret

πŸ”„ Option 2: Microsoft Graph API (addPassword)

You can also use Microsoft Graph’s addPassword endpoint for full control.

POST Request

POST https://graph.microsoft.com/v1.0/applications/{app-id}/addPassword
Authorization: Bearer <token>
Content-Type: application/json

Request Body

{
  "passwordCredential": {
    "displayName": "uat-automation-secret-longterm",
    "endDateTime": "2324-07-17T23:59:59Z"
  }
}

Tip: endDateTime is in UTC format. Set a far future date (e.g., 299 years ahead) to mimic “no expiry”.

⚠️ Security Reminder

  • Use only in non-production scenarios
  • Store secrets in Key Vault, not in code
  • Prefer Managed Identity or Federated Credentials for production

Both methods are effective β€” choose the one that fits your environment or automation strategy.

Nutshell Series, Security

πŸ” Common Security Testing Terminologies

Term Full Form Purpose Category
SAST Static Application Security Testing Analyzes code or binaries to find vulnerabilities before runtime. Static
Secure Code Review β€” Manual or automated inspection of code for security flaws. Static
DAST Dynamic Application Security Testing Simulates attacks on a running application to find security issues. Dynamic
Fuzzing Fuzz Testing Sends malformed or random data to discover crashes and bugs. Dynamic
Pen Testing Penetration Testing Ethical hacking to uncover and exploit real-world vulnerabilities. Dynamic
IAST Interactive Application Security Testing Combines SAST and DAST with real-time analysis via instrumentation. Hybrid
RASP Runtime Application Self-Protection Monitors and protects applications in real-time during execution. Hybrid
SCA Software Composition Analysis Identifies vulnerabilities in open-source and third-party components. Component-based
VAPT Vulnerability Assessment and Penetration Testing Combines scanning and exploitation to assess security posture. Operational
Threat Modeling β€” Identifies and prioritizes threats early in the development lifecycle. Operational
Bug Bounty β€” Rewards external security researchers for responsibly reporting vulnerabilities. Operational
Nutshell Series, Security

🧾 SAST vs DAST Comparison

Feature SAST (Static Application Security Testing) DAST (Dynamic Application Security Testing)
Testing Type White-box Black-box
Access to Code Required (analyzes source code or binaries) Not required (tests from outside the app)
When Used Early in SDLC (during coding/build phase) Later in SDLC (during or after deployment)
What It Tests Source code, bytecode, or binaries Running application, web interfaces, APIs
Finds Code-level issues (e.g., SQL injection, secrets) Runtime issues (e.g., logic flaws, auth problems)
False Positives Higher (due to theoretical analysis) Lower (based on real execution)
Speed Fast (no need to run the app) Slower (requires deployed app and interactions)
Tool Examples SonarQube, Checkmarx, Fortify OWASP ZAP, Burp Suite, Acunetix
Language Dependency Language-specific Language-agnostic
Use Case Secure code review, CI/CD integration Real-world attack simulation, post-deployment testing
Nutshell Series

Fixing Logic App VNet Integration: “Access to the path ‘C:\home\data\Functions\secrets\Sentinels’ is denied.”

If you’re integrating Azure Logic Apps Standard with a VNet and private endpoints, you may encounter this nasty error after deploying your app or modifying your networking configuration:

Access to the path ‘C:\home\data\Functions\secrets\Sentinels’ is denied.

Despite following Microsoft’s recommended steps, the issue may persist. In this post, I’ll break down the actual root causes, explain why the error happens, and offer a practical trick that can resolve it, especially after switching from public to private networking.

πŸ” Root Cause

This error usually happens when:

  • Your Logic App is moved from public access to a VNet-integrated private network.
  • The storage account (used to host runtime content and secrets) has private endpoints enabled, but DNS or firewall rules aren’t set up properly.
  • Deployment tools like ARM or Terraform don’t handle the WEBSITE_CONTENTOVERVNET setting correctly during creation.

βœ… Microsoft Recommendations to Try First

  1. Enable WEBSITE_CONTENTOVERVNET = 1 in Configuration settings of the Logic App.
  2. Ensure the storage account has:
    • VNet access with correct subnet delegations
    • Private DNS zone linked to your VNet (file, blob, queue, table)
  3. Enable β€œAllow storage account key access” in the storage account’s Configuration blade.
  4. If using ARM or Terraform:
    • Separate your appSettings into a nested resource of type [Microsoft.Web/sites/config]

But here’s the truth: Even after doing all this, the error may still appear.

πŸ› οΈ Trick That Actually Works

If you’re stuck and everything seems configured correctly, try this workaround that’s helped in many real-world deployments:

πŸ’‘ Scale up your Logic App to WS2 tier temporarily and then scale it back down to WS1.

Why this works:

When switching from public to private storage/VNet, the Logic App runtime may get β€œstuck” in an inconsistent state, especially regarding storage path mounting or internal config sync.

Scaling up to WS2 forces:

  • A runtime refresh
  • A full reinitialization of the hosting environment
  • Resync of private DNS/storage endpoints

πŸš€ Step-by-Step: Fix It

  1. Go to your Logic App resource.
  2. Navigate to Scale Up blade.
  3. Change SKU to WS2 (higher tier) and hit Apply.
  4. Wait until the deployment is successful (1–2 mins).
  5. Now go back and revert the SKU back to WS1.

βœ… After this step, your Logic App should restart and mount the secret paths correctly.

🧠 Final Thoughts

This issue is not well-documented, but it’s common when moving to private networking in enterprise deployments. Logic Apps tightly depend on the underlying storage account, and improper sync between the app’s network context and the storage endpoints can lead to the above error.

Scaling the app up and down is a safe way to force the platform to re-establish all bindings.

πŸ“Œ Quick Checklist

  • βœ… VNet Integration configured
  • βœ… Private endpoints enabled for Storage Account
  • βœ… Private DNS zones linked
  • βœ… WEBSITE_CONTENTOVERVNET = 1
  • βœ… Allow storage account key access
  • βœ… Storage access via system-assigned managed identity
  • βœ… Scale-up and scale-down trick applied

πŸ’¬ Have You Faced This?

Drop your experience or questions in the comments β€” Azure networking errors can be painful, but you’re not alone!

Nutshell Series

Power Query vs SQL Joins

The following table compares Power Query Join Kinds with their equivalent SQL Join types. Each join kind is explained with a visual icon and SQL analogy.

Join Kind Icon Description SQL Equivalent
Left Outer

Returns all rows from the left table and matching rows from the right. Non-matching right rows are set to null. LEFT JOIN
Right Outer

Returns all rows from the right table and matching rows from the left. Non-matching left rows are set to null. RIGHT JOIN
Full Outer

Returns all rows from both tables. Where there’s no match, nulls are inserted. FULL OUTER JOIN
Inner

Returns only rows with matching values in both tables. INNER JOIN
Left Anti

Returns rows from the left table that have no match in the right table. LEFT JOIN ... WHERE right.id IS NULL
Right Anti

Returns rows from the right table that have no match in the left table. RIGHT JOIN ... WHERE left.id IS NULL
Full Outer Anti

Returns all rows from both tables where there’s no matches

FULL OUTER JOIN ... WHERE left.id IS NULL AND right.id IS NULL

Nutshell Series

πŸ” Struggling with Connect-ExchangeOnline Errors in PowerShell? Here’s How I Solved It!


If you’ve ever tried to connect to Exchange Online using PowerShell and hit a brick wall, you’re not alone. I recently ran into two frustrating errors while using Connect-ExchangeOnline, and after a lot of head-scratching (and Googling), I finally found a clean, working solution.

Let me walk you through what went wrong and how you can fix it β€” especially if you’re working in a non-interactive or automation-heavy environment.


⚠️ Error #1: β€œA window handle must be configured”

This was the first error I got when running a simple connection command:

A window handle must be configured. See https://aka.ms/msal-net-wam#parent-window-handles

This usually happens when PowerShell tries to use Windows Web Account Manager (WAM) to launch a browser-based login β€” but there’s no interactive UI available. If you’re running a script in a headless setup (like Azure Automation, GitHub Actions, or a remote server), this error is a dead end.

πŸ”§ Tried Fix: Using -DisableWAM

Disabling WAM seemed like a logical next step. I ran:

Connect-ExchangeOnline -DisableWAM

But that only led me straight into this new error:

Failed to connect to Exchange Online: An HttpListenerException occurred while listening on http://localhost:49747/ for the system browser to complete the login.

It also suggested running this from an admin shell:

netsh http add iplisten 127.0.0.1

But honestly? That felt like duct-taping the problem instead of solving it.


βœ… The Real Fix: Use an Access Token Instead

After some digging, I found a better way β€” one that doesn’t depend on browser pop-ups, localhost listeners, or WAM. The trick is to generate an access token using your Azure AD app and pass it directly to the Connect-ExchangeOnline command.

πŸ“Œ Step 1: Register an Azure App

  1. Go to Azure Portal β†’ App Registrations.
  2. Create a new app registration.
  3. Under “API Permissions”, add Exchange.ManageAsApp.
  4. Create a client secret or upload a certificate (for secure token access).

πŸ›  Step 2: Generate Access Token via PowerShell

$tenantId = "<your-tenant-id>"
$clientId = "<your-client-id>"
$clientSecret = "<your-client-secret>"
$scope = "https://outlook.office365.com/.default"

$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
    -Body @{
        client_id     = $clientId
        scope         = $scope
        client_secret = $clientSecret
        grant_type    = "client_credentials"
    }

$accessToken = $tokenResponse.access_token

πŸ”— Step 3: Connect Using the Token

Connect-ExchangeOnline -AccessToken $accessToken -Organization "<your-tenant-domain>"

And that’s it β€” no browser, no WAM, no port listeners. Just a clean, programmatic login.


πŸ’‘ Pro Tips

  • This method is great for automation scripts in environments like Azure Automation, GitHub Actions, or even headless servers.
  • Make sure your app has the right permissions and you’ve granted admin consent in Azure AD.
  • This method is meant for admin tasks, not user mailbox actions (like reading emails).

🧩 Wrapping Up

If you’re facing authentication issues with Connect-ExchangeOnline, don’t waste hours trying to debug listener ports or browser issues. Switching to access token-based authentication saved me so much time β€” and now my scripts run flawlessly, even in automated pipelines.

Got questions? Drop them in the comments below β€” happy to help!

Nutshell Series

Complete List of DNS Record Types and Their Purpose

DNS (Domain Name System) records are instructions stored in authoritative DNS servers that provide information about a domain, such as its IP address, mail servers, and other services. Understanding different DNS record types is essential for managing domains and configuring networks efficiently.

πŸ“Œ DNS Record Types Explained

Record Type Full Form Purpose
A Address Record Maps a domain to an IPv4 address.
AAAA IPv6 Address Record Maps a domain to an IPv6 address.
CNAME Canonical Name Alias of one domain to another (no IP).
MX Mail Exchange Specifies mail server for receiving emails.
TXT Text Holds human-readable notes, SPF, DKIM, DMARC records.
NS Name Server Specifies authoritative name servers for domain.
SOA Start of Authority Provides domain metadata: serial number, refresh, retry, etc.
PTR Pointer Used for reverse DNS lookups (IP β†’ domain).
SRV Service Locator Specifies host and port for specific services.
CAA Certification Authority Authorization Specifies which CAs are allowed to issue certificates.
NAPTR Name Authority Pointer Used in conjunction with SRV records for VoIP, SIP, ENUM.
DNSKEY DNS Public Key Contains public keys used in DNSSEC.
DS Delegation Signer Used to secure delegation in DNSSEC.
RRSIG Resource Record Signature Cryptographic signature for DNSSEC data.
NSEC Next Secure Record Used in DNSSEC to prove a record does not exist.
NSEC3 Next Secure Record v3 Improved DNSSEC denial of existence.
TLSA Transport Layer Security Authentication Used with DANE to associate TLS certificates with domain names.
SPF Sender Policy Framework Defines authorized email servers. Deprecated in favor of TXT.
LOC Location Specifies geographical location of a host.
HINFO Host Information Specifies CPU and OS type of a host (rarely used).
RP Responsible Person Provides email address of the person responsible for the domain.
AFSDB AFS Database Specifies servers for AFS (Andrew File System).
X25 X.25 Address Maps domain to an X.25 address (obsolete).
ISDN ISDN Address Maps domain to an ISDN number (obsolete).
KEY Key Record Used for cryptographic keys in DNSSEC (deprecated).
SIG Signature Record Used to store digital signatures in DNSSEC (deprecated in favor of RRSIG).

Note: Not all record types are commonly used. DNSSEC-related records (like DNSKEY, DS, RRSIG) are crucial for securing DNS. Legacy types like X25 and ISDN are mostly obsolete today.