Sunday, February 16, 2025

Azure Keyvault secret change notification using Event Grid Subscription and Logic App or Azure function

 To create triggers for changes in Azure Key Vault secrets, you can leverage Azure Event Grid by setting up an event subscription on your Key Vault that will fire an event whenever a secret is updated, deleted, or created, allowing you to then configure an action like a Logic App or Azure Function to respond to these changes. 

Key steps:
  • Configure Event Grid subscription:
    • Go to your Azure Key Vault in the portal. 
    • Navigate to the "Events" tab. 
    • Select "Create event grid subscription". 
    • Choose a suitable Event Grid topic or create a new one. 
    • Select the event types you want to monitor, such as "SecretNewVersionCreated" or "SecretNearExpiry". 
  • Create a consuming application:
    • Logic App: Set up a Logic App with an Event Grid trigger that will be activated when an event is published by your Key Vault. 
    • Azure Function: Develop an Azure Function that is triggered by the Event Grid event and performs the desired actions based on the secret change. 
    Important considerations:
    • Access control:
      Ensure your consuming application (Logic App or Function) has the necessary permissions to access your Key Vault to read the updated secret values. 
    • Filtering events:
      You can filter the events received by your consuming application based on specific secret names or other criteria using Event Grid filters. 
    Example use cases for secret change triggers:
    • Automatic application reconfiguration: When a secret is updated in Key Vault, trigger a deployment to update your application configuration with the new secret value. 
    • Notification alerts: Send notifications to administrators when critical secrets are changed or near expiry. 
    • Data synchronization: Update data in another system based on changes to a secret in Key Vault. 

Friday, February 14, 2025

AKS docker Persistent Volume to decouple .net code deploy without rebuilding image and container

 Here’s how you can implement some of these methods to decouple your .NET web app’s source code deployment from the AKS container image:


1. Use Persistent Volume (PV) and Persistent Volume Claim (PVC)

This method mounts an external Azure Storage account into the AKS pod, allowing your app to read the latest source code without rebuilding the image.

Steps to Implement:

  1. Create an Azure File Share:

    az storage account create --name mystorageaccount --resource-group myResourceGroup --location eastus --sku Standard_LRS
    az storage share create --name myfileshare --account-name mystorageaccount
    
  2. Create a Kubernetes Secret for Storage Credentials:

    kubectl create secret generic azure-secret \
      --from-literal=azurestorageaccountname=mystorageaccount \
      --from-literal=azurestorageaccountkey=$(az storage account keys list --resource-group myResourceGroup --account-name mystorageaccount --query '[0].value' --output tsv)
    
  3. Define a Persistent Volume (PV) and Persistent Volume Claim (PVC):

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: azurefile-pv
    spec:
      capacity:
        storage: 5Gi
      accessModes:
        - ReadWriteMany
      azureFile:
        secretName: azure-secret
        shareName: myfileshare
        readOnly: false
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: azurefile-pvc
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi
    
  4. Mount the Storage in Your Deployment:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-dotnet-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-dotnet-app
      template:
        metadata:
          labels:
            app: my-dotnet-app
        spec:
          containers:
          - name: my-dotnet-app
            image: myacr.azurecr.io/mydotnetapp:latest
            volumeMounts:
            - name: azurefile
              mountPath: /app
          volumes:
          - name: azurefile
            persistentVolumeClaim:
              claimName: azurefile-pvc
    
  5. Deploy the Updated App to AKS:

    kubectl apply -f deployment.yaml
    

Now, your .NET app will dynamically read source code from the Azure File Share without rebuilding the container.


2. Use Sidecar Pattern with a Shared Volume

This method runs a second container inside the same pod to fetch and update the source code.

Steps to Implement:

  1. Modify the Deployment YAML to Add a Sidecar:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-dotnet-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-dotnet-app
      template:
        metadata:
          labels:
            app: my-dotnet-app
        spec:
          volumes:
          - name: shared-volume
            emptyDir: {}
          containers:
          - name: my-dotnet-app
            image: myacr.azurecr.io/mydotnetapp:latest
            volumeMounts:
            - name: shared-volume
              mountPath: /app
          - name: sidecar-git-sync
            image: alpine/git
            command: ["sh", "-c", "while true; do git pull origin main; sleep 60; done"]
            volumeMounts:
            - name: shared-volume
              mountPath: /app
    
  2. Ensure the Sidecar Has Access to the Repo:

    • Store SSH keys or tokens in Kubernetes secrets.
    • Modify the Git sync command to fetch from your repository.
  3. Deploy to AKS:

    kubectl apply -f deployment.yaml
    

Now, the sidecar container will fetch code updates every 60 seconds, and your app container will read from the shared volume.


3. Use .NET Hot Reload with Volume Mounting

This method allows live updates to your .NET web app inside an AKS pod.

Steps to Implement:

  1. Modify Your .NET Dockerfile to Enable Hot Reload:

    FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
    WORKDIR /app
    EXPOSE 80
    
    FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
    WORKDIR /src
    COPY . .
    RUN dotnet restore
    RUN dotnet publish -c Release -o /app
    
    FROM base AS final
    WORKDIR /app
    COPY --from=build /app .
    CMD ["dotnet", "watch", "run", "--urls", "http://+:80"]
    
  2. Mount the Source Code Volume in Deployment YAML:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-dotnet-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-dotnet-app
      template:
        metadata:
          labels:
            app: my-dotnet-app
        spec:
          containers:
          - name: my-dotnet-app
            image: myacr.azurecr.io/mydotnetapp:latest
            volumeMounts:
            - name: source-code
              mountPath: /app
          volumes:
          - name: source-code
            persistentVolumeClaim:
              claimName: azurefile-pvc
    
  3. Deploy to AKS and Start Hot Reload:

    kubectl apply -f deployment.yaml
    

Now, when you update your source code, the changes will reflect in your .NET app without restarting the container.


4. Use Azure DevOps Pipelines to Deploy Just Source Code

Instead of rebuilding the entire container, update only the source code.

Steps to Implement:

  1. Set Up an Azure DevOps Pipeline:

    • Use Azure DevOps Pipelines or GitHub Actions to deploy only source code updates.
    • Configure a build step to sync source code to a persistent volume.
    • Restart only the application process, not the container.
  2. Use Helm to Update the Deployment Without Rebuilding the Image:

    helm upgrade myapp ./helm-chart --set app.sourceVersion=$(git rev-parse HEAD)
    

This will ensure the latest source code is available without triggering a new Docker image build.


Conclusion

The best approach depends on your use case: ✅ For Persistent Source Code Storage: Use Azure File Share with PV/PVC.
For Continuous Sync from Git: Use a sidecar pattern.
For Live Updates During Development: Use .NET Hot Reload.
For Automated Updates in Production: Use Azure DevOps with Helm.

Hope you enjoy please share and comment.🚀

Deploy in AKS web app without rebuilding image and container

 To decouple source code deployment from the container image in an Azure Kubernetes Service (AKS) environment for a .NET web application, you can follow these approaches:

1. Use Persistent Volumes (PV) and Persistent Volume Claims (PVC)

  • Store your source code on an Azure File Share or Azure Blob Storage.
  • Mount the storage as a Persistent Volume (PV) in AKS.
  • Your application pod reads the updated code from the mounted volume without rebuilding the container image.

2. Leverage Azure App Configuration and Feature Flags

  • Store configuration files or dynamic code parts in Azure App Configuration.
  • Use feature flags or environment variables to control runtime behavior without rebuilding the image.

3. Use Sidecar Pattern with a Shared Volume

  • Deploy a sidecar container that continuously fetches updated code (e.g., from Git or a shared storage).
  • The main application container reads from the shared volume.

4. Implement an External Code Server

  • Host the application’s code on an external location (e.g., an Azure Storage Account, NFS, or a remote Git repository).
  • The container only acts as a runtime, pulling the latest code dynamically.

5. Use Kustomize or Helm for Dynamic Config Updates

  • Helm can help manage application deployments, enabling dynamic updates without modifying container images.

6. Use .NET Hot Reload and Volume Mounting

  • If using .NET Core, leverage Hot Reload to apply code changes without restarting the container.
  • Mount the application source code from a storage volume so updates are reflected instantly.

Azure Naming Convention Tools and Best Practices

When working with Microsoft Azure, a well-defined naming convention is crucial for maintaining clarity, consistency, and efficiency across resources. In this guide, we'll explore best practices for naming Azure resources.

Why is a Naming Convention Important?

Following a structured naming convention helps in:

  • Easy resource identification and management.
  • Improved automation and governance.
  • Enhanced collaboration among teams.
  • Reduced ambiguity and errors.

Key Components of an Azure Naming Convention

Each Azure resource name should contain specific elements to provide clarity. A recommended format is:

[Company/Project]-[Workload]-[Environment]-[Region]-[ResourceType]-[Instance]

Example:

contoso-web-prod-eastus-vm01

Best Practices for Azure Naming

  • Use standardized abbreviations: Example: rg for Resource Group, vm for Virtual Machine.
  • Follow a consistent case style: Lowercase for DNS-related resources, PascalCase or camelCase for others.
  • Include environment indicators: Use dev, qa, prod for different environments.
  • Avoid special characters and spaces: Stick to alphanumeric characters and hyphens.
  • Be concise but descriptive: Keep names readable while following Azure’s length limits.

Common Azure Resource Naming Abbreviations

Resource Abbreviation
Resource Group rg
Virtual Machine vm
Storage Account st
App Service app

Tools to Implement Azure Naming Conventions

  • Azure Resource Graph Explorer: Helps in querying and managing resources efficiently.
  • Azure Policy: Enables enforcement of naming conventions automatically.
  • Microsoft Cloud Adoption Framework: Provides best practices and guidance for cloud governance. Learn More

Conclusion

A well-structured Azure naming convention helps keep your cloud resources organized and manageable. By following these best practices, you can ensure clarity, scalability, and consistency in your Azure environment.

References and Tools

Friday, February 7, 2025

Running Parallel Tasks in Azure DevOps YAML Pipeline

1. Running Parallel Jobs

If you want multiple jobs to run in parallel, define them separately under the jobs section.

jobs: - job: Job1 displayName: 'Job 1' pool: vmImage: 'ubuntu-latest' steps: - script: echo "Running Job 1" - job: Job2 displayName: 'Job 2' pool: vmImage: 'ubuntu-latest' steps: - script: echo "Running Job 2"

2. Running Parallel Steps within a Job

Option 1: Using dependsOn for Parallel Execution in Jobs

jobs: - job: Build displayName: 'Build Job' steps: - script: echo "Building the application" - job: Test displayName: 'Test Job' dependsOn: [] # Runs in parallel with Build steps: - script: echo "Running tests" - job: Deploy displayName: 'Deploy Job' dependsOn: [Build, Test] # Runs only after both are completed steps: - script: echo "Deploying the application"

Option 2: Using template for Parallel Execution

Create a separate YAML template file:

# parallel-template.yml steps: - script: echo "Task 1" - script: echo "Task 2"

Then, reference it in the main pipeline:

jobs: - job: ParallelJob steps: - template: parallel-template.yml

Option 3: Using background: true for Background Tasks

steps: - script: echo "Starting Task 1" displayName: 'Task 1' background: true # Runs in the background - script: echo "Starting Task 2" displayName: 'Task 2' background: true # Runs in the background

Best Approach?

  • Use separate jobs if tasks need different agents or environments.
  • Use parallel steps in a job if they share the same environment.
  • Use background tasks for lightweight independent tasks.

Let me know if you need a specific example for your pipeline! 🚀

Wednesday, February 5, 2025

Read ConfigMap of Pods Namespace in AKS using .Net Core

 To fetch ConfigMaps using the above approach, you can modify the code to use the Kubernetes client API for retrieving ConfigMaps.

🔹 Steps to Fetch ConfigMaps in a Namespace

  1. Modify the code to call ListNamespacedConfigMapAsync.
  2. Iterate through the retrieved ConfigMaps.
  3. Extract and display the required details.

Updated C# Code to Fetch ConfigMaps in the openlens Namespace

using System;
using System.Threading.Tasks;
using k8s;
using k8s.Models;

class Program
{
    static async Task Main(string[] args)
    {
        // Load Kubernetes config
        var config = KubernetesClientConfiguration.BuildDefaultConfig();

        // Create Kubernetes client
        IKubernetes client = new Kubernetes(config);

        // Specify the namespace
        string namespaceName = "openlens"; // Change as needed

        try
        {
            // Get the list of ConfigMaps in the namespace
            var configMapList = await client.CoreV1.ListNamespacedConfigMapAsync(namespaceName);

            Console.WriteLine($"ConfigMaps in namespace '{namespaceName}':");

            foreach (var configMap in configMapList.Items)
            {
                Console.WriteLine($"- Name: {configMap.Metadata.Name}");
                Console.WriteLine("  Data:");

                // Display the key-value pairs inside the ConfigMap
                if (configMap.Data != null)
                {
                    foreach (var kvp in configMap.Data)
                    {
                        Console.WriteLine($"    {kvp.Key}: {kvp.Value}");
                    }
                }
                else
                {
                    Console.WriteLine("    (No data)");
                }

                Console.WriteLine(new string('-', 40));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error fetching ConfigMaps: {ex.Message}");
        }
    }
}

How This Works

  1. Uses ListNamespacedConfigMapAsync(namespaceName) to get all ConfigMaps in the given namespace.
  2. Iterates through each ConfigMap and prints:
    • Name
    • Key-value pairs (if any)
  3. Handles errors gracefully.

🔹 Steps to Run

  1. Ensure kubectl is configured correctly.
  2. Install the KubernetesClient NuGet package:
    dotnet add package KubernetesClient
    
  3. Run the program:
    dotnet run
    


Friday, January 24, 2025

Difference Between ID Token, Access Token, and Refresh Token in OAuth & OpenID Connect

Understanding the Difference Between ID Token, Access Token, and Refresh Token in OAuth & OpenID Connect

OAuth 2.0 and OpenID Connect are widely used frameworks for authorization and authentication. These protocols use tokens to securely exchange and validate information between systems. However, understanding the purpose and difference between ID Token, Access Token, and Refresh Token can be challenging. In this article, we’ll break down each token and their specific roles in OAuth and OpenID Connect.

What Is an ID Token?

The ID Token is a JSON Web Token (JWT) issued by the identity provider (IdP) as part of the OpenID Connect protocol. Its primary purpose is to authenticate the user and confirm their identity to the client application. The ID Token contains information about the user, such as:

  • Subject (sub): A unique identifier for the user.
  • Issuer (iss): The identity provider that issued the token.
  • Expiration (exp): The token's validity period.
  • Claims: Additional information like the user’s email, name, or roles.
ID Token Scenario

Illustration of an ID Token in action

What Is an Access Token?

The Access Token is a token issued by the authorization server, enabling the client application to access protected resources (such as APIs) on behalf of the user. Unlike the ID Token, the Access Token:

  • Does not contain user identity information.
  • Is designed to be presented to APIs or resource servers as proof of authorization.
  • Has a short lifespan for security purposes.
Access Token Scenario

Illustration of an Access Token in action

What Is a Refresh Token?

The Refresh Token is a long-lived token used to obtain a new Access Token without requiring the user to log in again. It is issued alongside the Access Token during the authorization process and is stored securely by the client application. Refresh Tokens:

  • Are typically not sent to APIs or resource servers.
  • Have a longer validity period than Access Tokens.
  • Are subject to strict security practices to prevent misuse.

Key Differences at a Glance

Token Type Purpose Contains User Info? Intended Audience
ID Token User authentication and identity confirmation. Yes Client application
Access Token Authorize access to protected resources. No APIs or resource servers
Refresh Token Obtain new Access Tokens without re-authentication. No Authorization server
ID Token vs Access Token Summary

Summary: ID Token vs Access Token vs Refresh Token

Conclusion

Understanding the distinct roles of ID Tokens, Access Tokens, and Refresh Tokens is essential for designing secure and efficient authentication and authorization workflows. While the ID Token is central to user authentication, the Access Token ensures authorized API access, and the Refresh Token enhances user experience by reducing the need for frequent logins.

By using these tokens effectively, you can create robust and secure systems that adhere to modern authentication and authorization standards.

Thursday, January 23, 2025

Understanding Forwarded Headers Middleware in ASP.NET Core

🚀

Introduction

In modern web applications, especially those deployed behind reverse proxies (like Nginx, Apache, or cloud services like AWS and Azure), handling request headers correctly is crucial. The Forwarded Headers Middleware in ASP.NET Core ensures that proxies and load balancers pass the correct client information to the application.

This blog post will cover:
✅ What Forwarded Headers Middleware is
✅ Why it's important
✅ How to configure it in ASP.NET Core with a practical code example


🌟 What is Forwarded Headers Middleware?

When an application is deployed behind a reverse proxy, the proxy modifies request headers. For example:

  • The original client IP is replaced with the proxy server’s IP.
  • The HTTPS scheme may be removed if the proxy forwards requests via HTTP.

To ensure your app detects the correct client details, ASP.NET Core provides the Forwarded Headers Middleware.

🔹 Headers Managed by ForwardedHeadersMiddleware

1️⃣ X-Forwarded-For → Captures the original client IP.
2️⃣ X-Forwarded-Proto → Indicates the original HTTP scheme (HTTP or HTTPS).
3️⃣ X-Forwarded-Host → Contains the original host requested by the client.


🛠️ Configuring Forwarded Headers Middleware in ASP.NET Core

Let’s see how to enable and configure Forwarded Headers Middleware in an ASP.NET Core application.

1️⃣ Install Required Packages (Optional)

If not already installed, ensure the Microsoft.AspNetCore.HttpOverrides package is added:

dotnet add package Microsoft.AspNetCore.HttpOverrides

2️⃣ Configure Forwarded Headers Middleware in Program.cs

Modify your Program.cs file to include the middleware:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// 🌟 Enable Forwarded Headers Middleware
var options = new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};

// 🔹 (Optional) Allow Known Proxies
options.KnownProxies.Add(System.Net.IPAddress.Parse("192.168.1.100")); 

app.UseForwardedHeaders(options);

// Sample Endpoint to Check Headers
app.MapGet("/", (HttpContext context) =>
{
    var clientIP = context.Connection.RemoteIpAddress?.ToString();
    var originalIP = context.Request.Headers["X-Forwarded-For"].ToString();
    var originalScheme = context.Request.Headers["X-Forwarded-Proto"].ToString();

    return Results.Json(new
    {
        ClientIP = clientIP,
        ForwardedFor = originalIP,
        ForwardedProto = originalScheme
    });
});

app.Run();

🔍 Understanding the Code

🔹 ForwardedHeadersOptions → Specifies which headers to process (X-Forwarded-For, X-Forwarded-Proto).
🔹 KnownProxies → Lists trusted proxies (important for security).
🔹 UseForwardedHeaders(options) → Enables the middleware before other request-processing middleware.
🔹 HttpContext.Request.Headers → Reads the forwarded headers inside an API endpoint.


⚡ Testing Forwarded Headers in Postman or Curl

You can simulate forwarded headers using Postman or cURL:

curl -H "X-Forwarded-For: 203.0.113.42" -H "X-Forwarded-Proto: https" http://localhost:5000

Expected Response (Example Output)

{
    "ClientIP": "::1",
    "ForwardedFor": "203.0.113.42",
    "ForwardedProto": "https"
}

📌 Best Practices

1️⃣ Only trust known proxies → Use KnownProxies or KnownNetworks to avoid spoofing risks.
2️⃣ Enable forwarding at the right stage → Configure before authentication middleware.
3️⃣ Use middleware only behind a proxy → Avoid unnecessary header processing in development.


🎯 Conclusion

The Forwarded Headers Middleware is essential for handling reverse proxy headers in ASP.NET Core applications. It ensures that the application correctly identifies the client IP address and scheme, improving security and logging accuracy.

🔥 Key Takeaways:
✅ Enables handling of X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host.
✅ Necessary for reverse proxy setups (e.g., Nginx, Cloudflare, AWS).
✅ Always configure trusted proxies for security.

👉 Have any questions? Drop them in the comments below! 🚀

Kestrel Web Server in .NET Core

Kestrel Web Server in .NET Core

The **Kestrel Web Server** is a cross-platform, lightweight, and high-performance web server designed specifically for applications built with **.NET Core**. It acts as the default web server for ASP.NET Core applications and is ideal for both development and production environments.

What is Kestrel?

Kestrel is an open-source web server built on top of the **libuv** library (used for asynchronous I/O operations) in earlier versions, but now it leverages **transport abstractions** in .NET for enhanced flexibility and performance. It is optimized for handling both static and dynamic content efficiently.

Key Features of Kestrel

  • Cross-Platform: Runs seamlessly on Windows, macOS, and Linux.
  • High Performance: Designed to handle thousands of concurrent requests with low latency.
  • Asynchronous I/O: Uses async programming patterns for efficient resource utilization.
  • Lightweight: Ideal for microservices and containerized applications.
  • Integration Friendly: Can be used with a reverse proxy like IIS, Nginx, or Apache, or as a standalone server.

How to Configure Kestrel in .NET Core

Configuring Kestrel in a .NET Core application is straightforward. Here's an example of how to set it up in the Program.cs file:


using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseKestrel(); // Configuring Kestrel
                webBuilder.UseStartup<Startup>();
            });
}

    

When to Use Kestrel

  • As a Standalone Server: For lightweight, high-performance applications, especially in microservice architectures.
  • With a Reverse Proxy: Use Kestrel behind IIS, Nginx, or Apache for additional features like load balancing, SSL termination, and security hardening.

Advantages of Kestrel

  • **Performance:** Its lightweight and asynchronous architecture makes it one of the fastest web servers available.
  • **Ease of Use:** Configuration and integration into .NET Core projects are straightforward.
  • **Extensibility:** Kestrel can handle advanced scenarios with middleware components.
"Kestrel is the backbone of ASP.NET Core applications, ensuring high performance and scalability while keeping the server lightweight and efficient."

Conclusion

The Kestrel Web Server is a critical component of the .NET Core ecosystem. Its high performance, lightweight nature, and cross-platform capabilities make it ideal for modern web applications. Whether used as a standalone server or behind a reverse proxy, Kestrel ensures your ASP.NET Core applications are fast, reliable, and production-ready.

Know this difference HTTP/1.1 vs HTTP/2.0

HTTP/1.1 vs HTTP/2.0

HTTP/1.1 vs HTTP/2.0

The evolution of the HTTP protocol from HTTP/1.1 to HTTP/2.0 brought significant performance and efficiency improvements. Let’s explore the differences between these two versions:

Key Differences

  • Multiplexing: HTTP/2.0 allows multiple requests and responses over a single connection, whereas HTTP/1.1 processes them sequentially.
  • Header Compression: HTTP/2.0 uses HPACK compression to minimize header size, improving efficiency compared to the plaintext headers in HTTP/1.1.
  • Binary Protocol: HTTP/2.0 uses a binary protocol, which is faster and less error-prone than HTTP/1.1’s text-based protocol.
  • Server Push: HTTP/2.0 can proactively send resources to the client before they’re requested, a feature missing in HTTP/1.1.
  • Prioritization: HTTP/2.0 allows prioritization of critical resources for faster loading times.
  • Encryption: While optional in HTTP/1.1, HTTP/2.0 implementations often require encryption (TLS).

Comparison Table

Feature HTTP/1.1 HTTP/2.0
Protocol Type Text-based Binary
Multiplexing Not supported Supported
Header Compression No Yes (HPACK)
Server Push Not supported Supported
Prioritization Not supported Supported
Connection Multiple connections needed Single connection sufficient
Security Optional TLS TLS usually required
"HTTP/2.0 is faster, more efficient, and better suited for modern web demands compared to HTTP/1.1."

Summary

In conclusion, HTTP/2.0 introduces significant improvements over HTTP/1.1, such as multiplexing, server push, and header compression, making it faster and more efficient. These enhancements are crucial for delivering a better web experience, particularly for resource-intensive websites.

Mastering Chrome Developer tool Tips and tricks

Basic Console Navigation & Shortcuts

  • Open Console Quickly: Use Ctrl + Shift + J (Windows/Linux) or Cmd + Option + J (Mac) to open the Console directly.
  • Clear Console Output: Use Ctrl + L or type clear() in the Console to clean up clutter.
  • Command Palette: Open the Command Menu with Ctrl + Shift + P (or Cmd + Shift + P on Mac).

Debugging with Console

  • Logging Data: Use console.log() to print variables or messages. For structured output, use console.table():
    const users = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }];
    console.table(users);
                    
  • Inspect Objects: Use console.dir() to explore DOM elements or objects in detail.
  • Set Breakpoints: Right-click on the line number in the Sources tab to set breakpoints in your code.
  • Monitor Events: Use monitorEvents(element, 'event') to track events on an element:
    monitorEvents(document.body, 'click');
                    
  • Stop Monitoring Events: Use unmonitorEvents(element).

Using Fetch and Debugging Network Calls

  • Fetch Example:
    fetch('https://jsonplaceholder.typicode.com/posts/1')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error('Error:', error));
                    
  • Check Network Logs: View the Network tab to analyze request/response headers, status codes, and payloads.
  • Retry Fetches: Copy fetch() calls directly from the Network tab by right-clicking a request and choosing "Copy as Fetch."
  • Breakpoint on XHR or Fetch: In the Sources > Event Listener Breakpoints, check "XHR Breakpoints" to pause execution whenever a request is sent.

Debugging JavaScript

  • Live Edit Code: In the Sources tab, modify code directly and hit Ctrl + S (or Cmd + S) to save and run updated scripts.
  • Pause Execution: Use the debugger; statement to pause execution where it's placed:
    function myFunction() {
      debugger; // Execution will pause here
      console.log('Debugging...');
    }
    myFunction();
                    
  • Conditional Breakpoints: Right-click on a breakpoint in the Sources tab and set a condition (e.g., i === 5).
  • Stack Traces: Use console.trace() to log the current stack trace.

DOM Debugging

  • Select DOM Elements: Use $0, $1, etc., to reference elements selected in the Elements tab.
  • Find Elements: Use $('selector') or $$('selector') for querying single or multiple elements:
    const buttons = $$('button');
    console.log(buttons);
                    
  • Modify Elements: Select an element in the Elements tab, then modify it in the Console:
    $0.style.color = 'red';
                    

Find Performance Benchmark

  • Measure Performance: Use console.time() and console.timeEnd() to measure code execution time:
    console.time('fetch-time');
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(data => console.timeEnd('fetch-time'));
                    
  • Inspect JavaScript Functions: Type the function name in the Console to view its definition:
    console.log(myFunction.toString());
                    
  • Track Variable Changes: Use watch('variableName') in the Sources tab to monitor changes to specific variables.
  • Format JavaScript in Console: Use JSON.stringify(object, null, 2) to pretty-print objects:
    const data = { name: 'John', age: 25, city: 'New York' };
    console.log(JSON.stringify(data, null, 2));
                    

Find Unused Javascript

You can find unused JavaScript on your website by using the coverage tab in the Chrome DevTools. Press Ctrl/Cmd+Shift+p to open a command menu and type coverage to open the coverage tab. Now, click on the reload button within the coverage tab. The coverage tab tracks all the files and prepares a coverage list for you. Inside the list, you can see all the files have a usage visualisation graph. Click on a row to see the unused code in the sources tab.

Local File Override test changes before pushing to it production

  • Making changes to a production website is not ideal. If you break something, the whole website can go down. Is there a safe option to try out new things without actually changing the production code?
  • Local file overrides are a convenient feature for making tweaks to your website without changing the actual source code. Using local file overrides, you instruct Chrome to use your local modified files rather than using the files coming from the server.
  • To enable local file overrides, go to the sources tab of your Chrome DevTools and click on "enable local overrides". Now create a directory and give Chrome permission to save all the overrides in that directory.

Multiple Cursors One code many places

  • Ever have multiple lines you need to add something to? You can easily add multiple cursors by pressing Cmd + Click (Ctrl + Click) and entering information on multiple lines at the same time.

Capture Screenshots with dev tools

  • Capture a full-page screenshot.
  • Screenshot a node from the Elements panel.
  • Screenshot an area of a page.
  • Screenshot a node larger than the screen size.
  • Customize your screenshot.
  • Screenshot a mobile version of a website, and add a device frame.
  • Capture Screenshot videa

Make Readable Unminify JavaScript code

  • Code minifying is a build technique that is used to decrease the size of code files by removing indentations, spaces, and various other unnecessary things. Browsers can easily read and execute a minified file but for developers, reading a minified file is almost impossible.
  • Using Chrome DevTools, you can easily unminify a JavaScript file. Open the Chrome DevTools and go to the source tab. Then open a minified file from the left file explorer tab. Now click on the {} icon on the bottom of the file editor to unminify a file.

Record screen for automation

  • As a developer, you want to test how your website will react to different user flows. User flows are the journeys that users take on your website. It can be challenging to test a user flow manually, as you may need to repeat the same action again and again to mimic the user.
  • To record a user flow, open the Chrome DevTools and switch to the recorder tab. Now click on the red coloured recording button to start a new recording. Give your recording a unique name so that you can recognise it later. Now press the record button and perform the user flow that you want to record. All your actions, such as clicking buttons and navigating to other pages will be recorded. Once you've finished, click the end recording button, and your user flow is ready to replay. Now you can test your website with this flow automatically, without manual repetition.

© 2025 Don't waste your time on social media learn new things. All Rights Reserved.

Wednesday, January 22, 2025

Content Security Policy Report Only

Content Security Policy (CSP) and Reporting for Client Scripts

Content Security Policy (CSP) is a powerful browser feature that helps protect web applications from cross-site scripting (XSS) and other code injection attacks. By controlling which resources a browser can load, CSP enhances security and ensures that only trusted scripts are executed on your website.

What is Content Security Policy (CSP)?

CSP is a security standard that defines rules for loading content in web applications. These rules specify what types of content can be loaded and from which sources, thus reducing the risk of malicious attacks.

CSP for First-Party, Second-Party, Third-Party, and Fourth-Party Client Scripts

  • First-Party Scripts: These are scripts served directly from the same domain as your application. For example, if your website is https://example.com, any JavaScript file served from this domain, such as https://example.com/script.js, is considered first-party. These scripts are typically trusted, and CSP rules often allow them without restrictions.
  • Second-Party Scripts: These scripts come from trusted subdomains or partner domains. For instance, if you have a trusted analytics partner providing services from https://partner.example.com, their scripts would fall under second-party. CSP can be configured to allow such scripts explicitly:
    script-src 'self' https://partner.example.com;
  • Third-Party Scripts: These scripts originate from external sources such as ad networks, social media widgets, or analytics providers. For example, scripts from https://cdn.analytics.com or https://ads.provider.com would be classified as third-party. Allowing third-party scripts requires careful consideration to avoid introducing vulnerabilities. CSP rules can whitelist specific domains:
    script-src 'self' https://cdn.analytics.com https://ads.provider.com;
  • Fourth-Party Scripts: These are scripts loaded indirectly by third-party scripts. For example, if a script from https://cdn.analytics.com dynamically loads another script from https://another-provider.com, the latter is considered a fourth-party script. These scripts are the most challenging to control and pose significant security risks. CSP cannot directly specify these scripts unless they are explicitly loaded, making it essential to audit and monitor all third-party dependencies.

Using CSP with Report-Only Mode

Report-Only mode in CSP allows you to test policies without enforcing them. Violations are logged, enabling you to refine your rules before applying them. Here’s an example:

Content-Security-Policy-Report-Only: 
  default-src 'self'; 
  script-src 'self' https://trusted-partner.com; 
  report-uri /csp-violation-report-endpoint;

Full CSP Example for Client Scripts

The following is a complete example of a CSP header for managing first-party, second-party, and third-party scripts:

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self' https://trusted-partner.com https://analytics-provider.com; 
  style-src 'self' 'unsafe-inline'; 
  img-src 'self' https://images-provider.com; 
  connect-src 'self'; 
  report-uri /csp-violation-report-endpoint;

Benefits of Using CSP

  • Reduced Attack Surface: By specifying trusted sources, CSP minimizes the risk of malicious code execution.
  • Better Visibility: With report-only mode, you gain insights into potential violations and refine your policies.
  • Improved User Trust: A secure application boosts user confidence.

Conclusion

Implementing CSP is a critical step towards securing modern web applications. By carefully defining policies for first-party, second-party, third-party, and fourth-party client scripts, you can significantly reduce vulnerabilities and protect your users.

Why Swagger is Dead and .NET 9.0 Removed Swashbuckle

Why Swagger is Dead and .NET 9.0 Removed Swashbuckle

The software development landscape is constantly evolving, and tools that once seemed indispensable often fall by the wayside. Swagger, a popular API documentation tool, has recently been deemed outdated by many developers. This shift is reflected in .NET 9.0, which has officially removed support for Swashbuckle, the .NET implementation of Swagger.

Why Swagger is Considered Outdated

Swagger revolutionized API documentation by providing a user-friendly interface for exploring APIs. However, over time, several limitations became apparent:

  • Performance Issues: Swagger struggles with large-scale APIs, leading to slow rendering and navigation.
  • Limited Customization: While useful, Swagger’s UI offers limited flexibility for modern design requirements.
  • Emergence of Alternatives: Tools like OpenAPI and GraphQL provide more robust and flexible solutions.

What Replaces Swashbuckle in .NET 9.0?

.NET 9.0 introduces a shift towards better integration with OpenAPI specifications and native API documentation tools. Key replacements include:

  • Minimal APIs: Simplified API structures reduce the need for external documentation tools.
  • Native OpenAPI Support: Microsoft has improved OpenAPI integration for seamless API documentation.
  • Improved Developer Experience: Features like endpoint summaries and IntelliSense annotations make documentation easier.

Code Example: Using OpenAPI in .NET 9.0

// Enable OpenAPI in your ASP.NET Core application
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapGet("/api/hello", () => "Hello, World!")
    .WithName("GetHello")
    .WithOpenApi();

app.Run();

Advantages of Moving Away from Swagger

By phasing out Swashbuckle, .NET developers can benefit from:

  • Enhanced Performance: OpenAPI and other alternatives handle large APIs more efficiently.
  • Modern Features: Support for advanced configurations and integrations with CI/CD pipelines.
  • Better Developer Tools: Native solutions reduce dependency on external libraries.

Conclusion

While Swagger and Swashbuckle have served the developer community well, the move towards modern tools like OpenAPI signifies a natural progression in API development. .NET 9.0’s decision to remove Swashbuckle underscores the importance of embracing more efficient, flexible, and integrated solutions.

Azure AD B2C vs Microsoft Entra: Key Differences

Azure AD B2C vs Microsoft Entra: Key Differences

When building secure and scalable applications, choosing the right identity platform is crucial. Two popular offerings from Microsoft, Azure Active Directory B2C (Azure AD B2C) and Microsoft Entra, serve different purposes. Let’s dive into their differences to help you decide which one fits your needs.

What is Azure AD B2C?

Azure Active Directory B2C (Business-to-Consumer) is an identity management service tailored for customer-facing applications. It enables developers to authenticate users with social accounts or custom credentials, offering a seamless user experience.

Key Features of Azure AD B2C:

  • Customizable user flows for login, registration, and password reset.
  • Integration with social identity providers like Google, Facebook, and LinkedIn.
  • Support for multi-factor authentication (MFA).
  • Branding options for tailored user experiences.

What is Microsoft Entra?

Microsoft Entra is a suite of identity and access management solutions that includes Azure AD. It focuses on securing access to resources across enterprises, ensuring zero-trust principles, and managing identities for employees, partners, and systems.

Key Features of Microsoft Entra:

  • Enterprise-grade identity management for employees and partners.
  • Integration with hybrid cloud environments.
  • Advanced security features like conditional access and identity protection.
  • Support for seamless single sign-on (SSO).

Azure AD B2C vs Microsoft Entra: A Side-by-Side Comparison

Feature Azure AD B2C Microsoft Entra
Target Audience External customers Enterprise employees and partners
Authentication Options Social and local accounts Enterprise credentials
Use Case Customer-facing apps Enterprise resource access
Custom Branding Extensive support Limited

Which One Should You Choose?

If your primary focus is on creating customer-facing applications with customizable user experiences, Azure AD B2C is the right choice. However, if your goal is to manage enterprise identities and secure access to corporate resources, Microsoft Entra is more suitable.

© 2025 Cloud Identity Insights. All rights reserved.

Speeding Up ASP.NET Framework Unit Tests in Azure DevOp

Speeding Up ASP.NET Framework Unit Tests in Azure DevOps

Unit tests are critical for ensuring code quality, but their execution time can often slow down your CI/CD pipeline. In this article, we’ll explore strategies to accelerate unit test execution for ASP.NET Framework applications in Azure DevOps pipelines.

1. Optimize Test Parallelization

Parallelizing your tests can significantly reduce execution time. Ensure your tests are independent and can run in parallel without shared state conflicts. Use the RunSettings file to enable parallel test execution:


<!-- RunSettings file -->
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <RunConfiguration>
    <MaxCpuCount>4</MaxCpuCount>
  </RunConfiguration>
</RunSettings>
    

Include this file in your pipeline configuration.

2. Use Test Filters

Run only the necessary tests by using test filters. This is particularly useful when you’re working on a specific feature or bug fix. Update your pipeline YAML as follows:


- task: VSTest@2
  inputs:
    testSelector: 'testAssemblies'
    testAssemblyVer2: '**/*Tests.dll'
    testFiltercriteria: 'TestCategory=SmokeTest'
    runSettingsFile: '$(System.DefaultWorkingDirectory)/RunSettings.runsettings'
    diagnosticsEnabled: true
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'
    publishRunAttachments: true
    runInParallel: true
    codeCoverageEnabled: true
    testRunTitle: 'Smoke Test Execution'
    failOnMinCoverage: true
    runTestsInIsolation: true
    rerunFailedTests: true
    testRunParameters: >
      DatabaseConnectionString=$(DatabaseConnectionString);
    # Insert appropriate environment variables here.
      ServiceName=$(ServiceName);

    pipelineConfig:
      Use templates in jobs. Use mock dynamic variables to ensure business units are scoped contextually to their parent org structure