Skip to main content

Command Palette

Search for a command to run...

TechCart: Securing Azure Blob Storage Access with Terraform and DevSecOps

A LUIT Academy project - Upgrade

Updated
10 min read
TechCart: Securing Azure Blob Storage Access with Terraform and DevSecOps
M
Hello, my name is Malik W. Dixon. I am an internet marketer, designer, developer, DevOps practitioner, and DevSecOps advocate with a strong background in information technology, digital strategy, innovation, automation, and secure technology systems. I hold a Bachelor’s degree in Information Technology and a Master’s degree in Internet Marketing. I am also continuing to expand my expertise through advanced study and hands-on work in emerging technologies, AI, cloud computing, automation, DevOps, and DevSecOps. I am a disabled U.S. Army veteran, having served from 1982 to 1992. My military experience helped shape my discipline, resilience, problem-solving mindset, and commitment to lifelong learning. Today, I continue to build, create, secure, and improve technology with purpose. I enjoy learning the tools of my trade just as much as I enjoy working on personal tech projects, including flying, repairing, and programming quadcopter drones.

Introduction

As part of my LUIT Academy cloud and DevSecOps learning journey, I built TechCart, a secure asset management API for an e-commerce platform. The project focuses on solving a realistic cloud security problem: application assets stored in Azure Blob Storage were returning 403 Forbidden errors, and the previous access model relied on overly permissive storage account keys.

Instead of treating the issue as a simple permissions bug, I approached it as a full DevSecOps remediation project. The final solution combines secure application design, Azure Blob Storage hardening, Azure AD authentication, scoped User Delegation SAS tokens, Azure RBAC, Terraform infrastructure-as-code, and automated security checks in CI/CD.

This project demonstrates how a cloud or DevSecOps engineer can take a broken, risky storage access pattern and turn it into a secure, repeatable, production-ready solution.


Project Scenario

TechCart is an e-commerce platform that stores product images, documents, and other application assets in Azure Blob Storage. The application needed a secure way for users and services to upload and download files without exposing broad storage account keys or allowing anonymous public access.

The original environment had two major problems.

First, users were experiencing 403 Forbidden errors when attempting to access application assets.

Second, the previous design depended on storage account keys that were too powerful for normal application access. Storage account keys can provide broad access across the storage account, which creates a major security risk if they are leaked, copied, or misused.

The goal of the project was to fix the access issue while also redesigning the storage access model around least privilege, automation, and DevSecOps best practices.


Problem Statement

The TechCart application had an insecure and unreliable Azure Blob Storage access pattern.

The main problems were:

  • Application assets returned 403 Forbidden

  • Anonymous access controls were not consistently enforced

  • Previous access relied on overly permissive storage keys

  • Storage permissions were too broad

  • Upload and download permissions were not properly separated

  • Credential exposure would create a large blast radius

  • Infrastructure configuration was difficult to reproduce manually

  • Security checks were not fully integrated into the delivery pipeline

This created both an application reliability problem and a cloud security problem.


Project Objective

The objective of this LUIT Academy project was to design and implement a secure DevSecOps solution that:

  • Disables anonymous blob access

  • Removes storage account keys from the application access flow

  • Uses short-lived, scoped User Delegation SAS tokens

  • Enforces Azure RBAC based on identity and scope

  • Provisions Azure infrastructure with Terraform

  • Adds security scanning into CI/CD

  • Documents issues, fixes, and operational events

  • Demonstrates a production-style cloud security remediation workflow


Solution Overview

The final TechCart solution uses a Flask-based API as a secure gateway between users and Azure Blob Storage.

Users authenticate through Azure AD. The API validates the user’s JWT and checks the user’s application role. If the user is authorized, the API issues a short-lived SAS token for a specific blob operation.

The application no longer exposes storage account keys. Users do not receive direct Azure roles. Anonymous access is disabled. Blob containers are private. Uploads and downloads are controlled through scoped SAS tokens.

This design gives TechCart secure access without sacrificing usability.


DevSecOps Architecture

The solution includes four major layers:

1. Application Security Layer

The Flask API validates every request using Azure AD JWT authentication. Middleware checks the user’s role before allowing upload or download operations.

Application roles include:

  • asset_reader

  • asset_uploader

  • asset_manager

Only users with the correct role can request a SAS token for the corresponding blob action.


2. Azure Storage Security Layer

Azure Blob Storage is hardened with several security controls:

  • Anonymous access disabled

  • Containers set to private

  • Shared key access disabled

  • Public network access disabled

  • Minimum TLS version enforced

  • Blob soft delete enabled

  • Blob versioning enabled

  • Change feed enabled

  • Diagnostics sent to Log Analytics

  • Access restricted through private endpoints

This protects the storage account from public exposure and reduces the risk of unauthorized access.


3. Infrastructure as Code Layer

Terraform is used to provision and manage the Azure infrastructure.

The project uses modular Terraform for:

  • Networking

  • Storage

  • Managed identities

  • RBAC

  • Key Vault

  • Monitoring

This allows the infrastructure to be version-controlled, reviewed through pull requests, and deployed consistently across environments.

The Terraform design supports both development and production environments with different settings for replication, retention, and state management.


4. DevSecOps Pipeline Layer

GitHub Actions is used to automate CI/CD and security validation.

The pipeline includes:

  • Code linting

  • Formatting checks

  • Unit testing

  • Coverage reporting

  • Static application security testing

  • Dependency vulnerability scanning

  • Secret detection

  • Infrastructure-as-code scanning

  • Terraform validation and planning

Security is not treated as a final step. It is built directly into the development workflow.


Secure Upload Flow

The upload workflow uses a two-step pattern.

  1. The client sends an upload request to the Flask API.

  2. The API validates the Azure AD JWT.

  3. The API checks whether the user has the correct role.

  4. The API issues a short-lived write-only SAS URL.

  5. The client uploads the file directly to Azure Blob Storage.

  6. The client notifies the API that the upload is complete.

  7. The API verifies that the blob exists.

This design keeps large file uploads out of the API server while still allowing the API to control authorization and verification.


Secure Download Flow

The download workflow follows a similar least-privilege model.

  1. The client requests access to an asset.

  2. The API validates the user’s JWT.

  3. The API checks the user’s role.

  4. The API issues a short-lived read-only SAS URL.

  5. The client downloads the asset from Azure Blob Storage.

The user receives access only to the specific asset for a limited period.

GitHub Actions are all green. This is due to checking for every error, repairing it, and rerunning.


Azure RBAC Design

The project uses Azure RBAC to separate responsibilities across identities.

Identity Azure Role Scope
API server Storage Blob Delegator Storage account
Upload worker Storage Blob Data Contributor Uploads container
CDN service Storage Blob Data Reader Assets container
End users No Azure role Controlled through application JWT and role claims

This design follows the principle of least privilege. Each identity receives only the access required to perform its job.

The API server can issue SAS tokens, but it does not become a broad privileged data conduit.


Terraform Implementation

The Terraform infrastructure is organized under an infra/ directory.

The project includes modules for:

Network Module

Creates virtual networks, subnets, network security groups, private DNS zones, and private endpoint connectivity.

Storage Module

Creates the hardened Azure Storage account, private blob containers, private endpoints, and diagnostic settings.

Identity Module

Creates user-assigned managed identities for the API server, upload worker, and CDN reader.

RBAC Module

Assigns least-privilege Azure roles to the correct identities at the correct scopes.

Key Vault Module

Creates a secure Azure Key Vault using RBAC mode, purge protection, private endpoint access, and diagnostic logging.

Monitoring Module

Creates Log Analytics and diagnostic settings for visibility across the environment.

This modular structure makes the project easier to maintain, test, and expand.

First verification of Terraform apply in GitHub Actions


Dev and Prod Environment Strategy

The project supports separate development and production environments.

Environment Replication Blob Soft Delete Key Vault Retention
Dev LRS 7 days 7 days
Prod GZRS 30 days 90 days

This reflects a real-world environment strategy in which development remains lightweight, while production uses stronger durability and retention controls.


CI/CD and Security Tooling

The DevSecOps pipeline uses GitHub Actions.

CI Tools

  • Ruff for linting

  • Ruff format check

  • Pytest for unit testing

  • Coverage reporting

Security Tools

  • Bandit for Python security linting

  • Semgrep for secure code analysis

  • CodeQL for deeper static analysis

  • pip-audit for dependency vulnerability scanning

  • Trivy for filesystem, secrets, IaC, and container scanning

  • Gitleaks for secret detection

  • Checkov for Terraform and cloud misconfiguration scanning

Shift-Left Controls

The project also includes pre-commit hooks to catch common issues before code is pushed.

These include:

  • Ruff

  • Bandit

  • Gitleaks

  • Private key detection

  • Large file checks

  • Trailing whitespace checks

  • End-of-file fixes

This gives the project a practical DevSecOps workflow from local development through deployment.

The workflow discovered errors that had to be repaired before running Terraform apply


Issues Resolved During the Project

This project also included real troubleshooting and remediation work.

Examples of resolved or mitigated issues include:

  • Terraform backend initialization failure

  • Azure login failure in GitHub Actions

  • Ruff formatting failures

  • GitHub Actions Node version deprecation warnings

  • Bandit SARIF formatting issue

  • SARIF upload limitations in a private repository

  • Checkov Terraform policy findings

  • Trivy SARIF exit-code behavior

  • Semgrep authentication limitations

  • CodeQL limitations without GitHub Advanced Security

  • Azure resources remaining after the environment destroy

These issues helped make the project more realistic because DevSecOps work is not only about writing code. It also involves diagnosing pipeline failures, understanding tooling limitations, documenting fixes, and improving the delivery process.


Final Outcome

The TechCart project successfully transformed an insecure blob access pattern into a secure, automated, DevSecOps-driven solution.

The final outcome included:

  • Anonymous blob access disabled

  • Storage account keys removed from the application flow

  • Private containers enforced

  • User Delegation SAS tokens implemented

  • Azure RBAC applied using least privilege

  • Upload and download permissions separated

  • Terraform used for repeatable infrastructure deployment

  • Dev and prod environments defined

  • CI/CD pipeline implemented

  • Security scans integrated into the software delivery process

  • Operational issues documented and resolved

The project demonstrates how cloud security, infrastructure automation, and DevSecOps practices work together in a realistic Azure environment.

Verification of Azure resources created with Terraform

techart-dev-app-nsg verification

Verification of Terraform destroy. However, there were issues in Terraform destroy that did not remove all of the resources on the first run in the Terraform destroy. The Azure resources were destroyed on the second run.


Skills Demonstrated

This LUIT Academy project demonstrates hands-on experience with:

  • Azure Blob Storage

  • Azure AD authentication

  • Azure RBAC

  • User Delegation SAS tokens

  • Terraform

  • Infrastructure as Code

  • GitHub Actions

  • DevSecOps pipelines

  • Secret scanning

  • SAST and SCA tooling

  • IaC security scanning

  • Private endpoints

  • Managed identities

  • Key Vault

  • Log Analytics

  • Cloud security troubleshooting

  • Least-privilege access design


Conclusion

TechCart is a strong LUIT Academy project because it shows more than basic cloud deployment. It demonstrates how to identify an insecure access pattern, redesign the architecture, automate infrastructure, enforce least privilege, and integrate security into the software delivery lifecycle.

The project started with a common production issue: 403 Forbidden errors and risky storage key usage. It ended with a secure Azure Blob Storage access model backed by Terraform and DevSecOps automation.

This is the kind of project that shows practical readiness for cloud engineering, DevSecOps engineering, and cloud security roles. The repo can be found here: https://github.com/mdixon47/azure-techcart