|
1 | | -# Configure Storage Account for Terraform State File |
| 1 | +# 🗄️ Configure Storage Account for Terraform State File |
2 | 2 |
|
3 | | -## 🎯 Purpose |
4 | | -In this lab, you'll create a secure location to store the remote Terraform State file. This is crucial for maintaining consistency and collaboration in your infrastructure-as-code projects. |
| 3 | +> **Difficulty Level:** 🟢 **Beginner** | **Estimated Time:** ⏱️ **10-15 minutes** |
5 | 4 |
|
6 | | -## 🛠️ Create Blob Storage for Terraform State File |
| 5 | +## 🎯 **Learning Objectives** |
7 | 6 |
|
8 | | -### Prerequisites |
9 | | -- [ ] Azure CLI installed and configured (`az login` executed) |
10 | | -- [ ] Contributor permissions on your Azure subscription |
11 | | -- [ ] Basic understanding of Azure Storage concepts |
| 7 | +By the end of this tutorial, you will: |
| 8 | +- [ ] **Understand Terraform state management** and remote storage benefits |
| 9 | +- [ ] **Create Azure Storage Account** with security best practices |
| 10 | +- [ ] **Configure blob container** for Terraform state files |
| 11 | +- [ ] **Implement security measures** for production-ready storage |
| 12 | +- [ ] **Validate storage setup** through Azure Portal and CLI |
12 | 13 |
|
13 | | -### Steps |
| 14 | +## 📋 **Prerequisites** |
14 | 15 |
|
15 | | -1. **Customise Variables** |
16 | | - - Open the [create-terraform-storage.sh](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/1-Azure/scripts/create-terraform-storage.sh) script. |
17 | | - - Locate the following lines: |
| 16 | +**✅ Required Knowledge:** |
| 17 | +- [ ] Basic understanding of Terraform fundamentals |
| 18 | +- [ ] Familiarity with Azure Resource Groups and Storage Accounts |
| 19 | +- [ ] Command-line interface operations |
| 20 | + |
| 21 | +**🔧 Required Tools:** |
| 22 | +- [ ] Azure CLI installed and configured |
| 23 | +- [ ] Azure subscription with Contributor permissions |
| 24 | +- [ ] Terminal/command line access |
| 25 | +- [ ] Text editor for script customization |
| 26 | + |
| 27 | +**🏗️ Infrastructure Dependencies:** |
| 28 | +- [ ] Active Azure subscription |
| 29 | +- [ ] Azure CLI authenticated (`az login` completed) |
| 30 | +- [ ] Sufficient permissions to create resources |
| 31 | + |
| 32 | +## � **Step-by-Step Implementation** |
| 33 | + |
| 34 | +### **Step 1: Understand Remote State Benefits** ⏱️ *3 minutes* |
| 35 | + |
| 36 | +1. **📚 Why Remote State Storage?** |
| 37 | + |
| 38 | + **🎯 Benefits of Remote State:** |
| 39 | + - [ ] **Team Collaboration** - Multiple developers can share state |
| 40 | + - [ ] **State Locking** - Prevents concurrent modifications |
| 41 | + - [ ] **Security** - Centralized, encrypted storage |
| 42 | + - [ ] **Backup & Recovery** - Automatic versioning and backup |
| 43 | + - [ ] **Consistency** - Single source of truth for infrastructure state |
| 44 | + |
| 45 | +2. **🔒 Azure Blob Storage Advantages** |
| 46 | + - [ ] **Encryption at rest** - Data automatically encrypted |
| 47 | + - [ ] **Access control** - Fine-grained permissions with Azure RBAC |
| 48 | + - [ ] **Versioning** - Built-in state file versioning |
| 49 | + - [ ] **Geo-redundancy** - High availability across regions |
| 50 | + - [ ] **Cost-effective** - Pay-as-you-use storage model |
| 51 | + |
| 52 | +### **Step 2: Customize Configuration Script** ⏱️ *5 minutes* |
| 53 | + |
| 54 | +3. **📂 Navigate to Azure Scripts Directory** |
| 55 | + ```bash |
| 56 | + cd 1-Azure/scripts |
| 57 | + ls -la |
| 58 | + ``` |
| 59 | + **✅ Expected Files:** |
| 60 | + - `1-create-terraform-storage.sh` |
| 61 | + - `2-create-azure-ad-group.sh` |
| 62 | + |
| 63 | +4. **📝 Review and Customize Storage Script** |
| 64 | + ```bash |
| 65 | + # View the script content |
| 66 | + cat 1-create-terraform-storage.sh |
| 67 | + ``` |
| 68 | + |
| 69 | +5. **⚙️ Update Configuration Variables** |
| 70 | + ```bash |
| 71 | + # Edit the script with your preferred editor |
| 72 | + nano 1-create-terraform-storage.sh |
| 73 | + # or |
| 74 | + code 1-create-terraform-storage.sh |
| 75 | + ``` |
| 76 | + |
| 77 | + **🎯 Key Variables to Customize:** |
| 78 | + ```bash |
| 79 | + # Find and update these lines: |
| 80 | + RESOURCE_GROUP_NAME="devopsthehardway-rg" |
| 81 | + STORAGE_ACCOUNT_NAME="devopsthehardwaysa" |
| 82 | + CONTAINER_NAME="tfstate" |
| 83 | + LOCATION="uksouth" |
| 84 | + ``` |
| 85 | + |
| 86 | + **💡 Naming Guidelines:** |
| 87 | + - **Storage Account:** 3-24 characters, lowercase letters and numbers only |
| 88 | + - **Resource Group:** Descriptive name for your project |
| 89 | + - **Location:** Choose region closest to your development team |
| 90 | + |
| 91 | +6. **🔍 Understand Script Operations** |
| 92 | + |
| 93 | + **📋 Script Workflow:** |
| 94 | + ```bash |
| 95 | + # The script will: |
| 96 | + # 1. Create Resource Group |
| 97 | + az group create --name $RESOURCE_GROUP_NAME --location $LOCATION |
18 | 98 |
|
19 | | - ```bash |
20 | | - RESOURCE_GROUP_NAME="devopshardway-rg" |
21 | | - STORAGE_ACCOUNT_NAME="devopshardwaysa" |
22 | | - ``` |
23 | | - |
24 | | - - Replace the placeholders with your desired names. |
25 | | - |
26 | | -2. **Run the Script** |
27 | | - |
28 | | - - Run the following command in your terminal: |
29 | | - |
30 | | - ```bash |
31 | | - ./scripts/1-create-terraform-storage.sh |
32 | | - ``` |
33 | | - |
34 | | -3. **What's Happening Behind the Scenes?** |
35 | | - The script performs these actions: |
36 | | - - [ ] Creates an Azure Resource Group with appropriate tags |
37 | | - - [ ] Sets up an Azure Storage Account with enhanced security settings: |
38 | | - - Encryption enabled for blob storage |
39 | | - - TLS 1.2 enforced |
40 | | - - Public access to blobs disabled |
41 | | - - [ ] Establishes an Azure Blob storage container |
42 | | - - [ ] Outputs configuration for your Terraform backend |
| 99 | + # 2. Create Storage Account with security settings |
| 100 | + az storage account create \ |
| 101 | + --name $STORAGE_ACCOUNT_NAME \ |
| 102 | + --resource-group $RESOURCE_GROUP_NAME \ |
| 103 | + --location $LOCATION \ |
| 104 | + --sku Standard_LRS \ |
| 105 | + --encryption-services blob \ |
| 106 | + --https-only true \ |
| 107 | + --allow-blob-public-access false |
| 108 | + |
| 109 | + # 3. Create Blob Container |
| 110 | + az storage container create \ |
| 111 | + --name $CONTAINER_NAME \ |
| 112 | + --account-name $STORAGE_ACCOUNT_NAME |
| 113 | + ``` |
| 114 | + |
| 115 | +### **Step 3: Execute Storage Setup** ⏱️ *5 minutes* |
| 116 | + |
| 117 | +7. **🚀 Run the Storage Creation Script** |
| 118 | + ```bash |
| 119 | + # Make script executable |
| 120 | + chmod +x 1-create-terraform-storage.sh |
| 121 | + |
| 122 | + # Execute the script |
| 123 | + ./1-create-terraform-storage.sh |
| 124 | + ``` |
| 125 | + **⏱️ Execution Time:** 2-3 minutes |
| 126 | + |
| 127 | + **✅ Expected Output:** |
| 128 | + ```json |
| 129 | + { |
| 130 | + "id": "/subscriptions/.../resourceGroups/devopsthehardway-rg", |
| 131 | + "location": "uksouth", |
| 132 | + "name": "devopsthehardway-rg", |
| 133 | + "properties": { |
| 134 | + "provisioningState": "Succeeded" |
| 135 | + } |
| 136 | + } |
| 137 | + ``` |
| 138 | + |
| 139 | +8. **📋 Capture Backend Configuration** |
| 140 | + ```bash |
| 141 | + # The script should output Terraform backend configuration |
| 142 | + # Save this for use in your Terraform configurations: |
| 143 | + |
| 144 | + # Example output: |
| 145 | + # terraform { |
| 146 | + # backend "azurerm" { |
| 147 | + # resource_group_name = "devopsthehardway-rg" |
| 148 | + # storage_account_name = "devopsthehardwaysa" |
| 149 | + # container_name = "tfstate" |
| 150 | + # key = "terraform.tfstate" |
| 151 | + # } |
| 152 | + # } |
| 153 | + ``` |
| 154 | + |
| 155 | +### **Step 4: Verify and Secure Setup** ⏱️ *4 minutes* |
| 156 | + |
| 157 | +9. **🔍 Verify Through Azure Portal** |
| 158 | + - Navigate to [Azure Portal](https://portal.azure.com) |
| 159 | + - Search for your resource group |
| 160 | + - Verify storage account creation |
| 161 | + - Check blob container exists |
| 162 | + |
| 163 | +10. **📋 Verify Using Azure CLI** |
| 164 | + ```bash |
| 165 | + # Check resource group |
| 166 | + az group show --name devopsthehardway-rg --output table |
| 167 | + |
| 168 | + # Verify storage account |
| 169 | + az storage account show --name devopsthehardwaysa --resource-group devopsthehardway-rg --output table |
| 170 | + |
| 171 | + # List containers |
| 172 | + az storage container list --account-name devopsthehardwaysa --output table |
| 173 | + ``` |
| 174 | + |
| 175 | +11. **🔒 Implement Additional Security (Recommended)** |
| 176 | + ```bash |
| 177 | + # Add resource lock to prevent accidental deletion |
| 178 | + az lock create \ |
| 179 | + --name "TerraformStorageLock" \ |
| 180 | + --lock-type CanNotDelete \ |
| 181 | + --resource-group devopsthehardway-rg \ |
| 182 | + --resource-name devopsthehardwaysa \ |
| 183 | + --resource-type Microsoft.Storage/storageAccounts |
| 184 | + |
| 185 | + # Enable soft delete for blobs |
| 186 | + az storage blob service-properties delete-policy update \ |
| 187 | + --account-name devopsthehardwaysa \ |
| 188 | + --enable true \ |
| 189 | + --days-retained 7 |
| 190 | + ``` |
| 191 | + |
| 192 | +## ✅ **Validation Steps** |
| 193 | + |
| 194 | +**🔍 Infrastructure Validation:** |
| 195 | +- [ ] Resource group created successfully |
| 196 | +- [ ] Storage account deployed with correct configuration |
| 197 | +- [ ] Blob container accessible and properly configured |
| 198 | +- [ ] Security settings applied (HTTPS-only, encryption enabled) |
| 199 | +- [ ] Access permissions properly configured |
| 200 | + |
| 201 | +**🔧 Technical Validation:** |
| 202 | +```bash |
| 203 | +# Comprehensive validation script |
| 204 | +echo "🗄️ Validating Terraform storage setup..." |
| 205 | +
|
| 206 | +# Check if resource group exists |
| 207 | +RG_NAME="devopsthehardway-rg" |
| 208 | +SA_NAME="devopsthehardwaysa" |
| 209 | +
|
| 210 | +if az group show --name $RG_NAME &>/dev/null; then |
| 211 | + echo "✅ Resource group exists" |
| 212 | + |
| 213 | + # Check storage account |
| 214 | + if az storage account show --name $SA_NAME --resource-group $RG_NAME &>/dev/null; then |
| 215 | + echo "✅ Storage account exists" |
| 216 | + |
| 217 | + # Check encryption settings |
| 218 | + ENCRYPTION=$(az storage account show --name $SA_NAME --resource-group $RG_NAME --query "encryption.services.blob.enabled" -o tsv) |
| 219 | + echo "🔒 Blob encryption enabled: $ENCRYPTION" |
| 220 | + |
| 221 | + # Check HTTPS enforcement |
| 222 | + HTTPS_ONLY=$(az storage account show --name $SA_NAME --resource-group $RG_NAME --query "enableHttpsTrafficOnly" -o tsv) |
| 223 | + echo "🔐 HTTPS-only enabled: $HTTPS_ONLY" |
| 224 | + |
| 225 | + # Check container |
| 226 | + CONTAINER_COUNT=$(az storage container list --account-name $SA_NAME --output tsv | wc -l) |
| 227 | + echo "📦 Containers created: $CONTAINER_COUNT" |
| 228 | + |
| 229 | + echo "✅ Terraform storage validation complete!" |
| 230 | + else |
| 231 | + echo "❌ Storage account not found" |
| 232 | + exit 1 |
| 233 | + fi |
| 234 | +else |
| 235 | + echo "❌ Resource group not found" |
| 236 | + exit 1 |
| 237 | +fi |
| 238 | +``` |
| 239 | + |
| 240 | +**📊 Security Checklist:** |
| 241 | +- [ ] **Encryption** - Blob storage encryption enabled |
| 242 | +- [ ] **HTTPS** - Secure transport enforced |
| 243 | +- [ ] **Public Access** - Blob public access disabled |
| 244 | +- [ ] **Access Control** - Proper RBAC permissions |
| 245 | +- [ ] **Resource Lock** - Protection against accidental deletion |
| 246 | + |
| 247 | +## 🚨 **Troubleshooting Guide** |
| 248 | + |
| 249 | +**❌ Common Setup Issues:** |
| 250 | +```bash |
| 251 | +# Problem: Storage account name already exists globally |
| 252 | +# Solution: Storage account names must be globally unique |
| 253 | +az storage account check-name --name $STORAGE_ACCOUNT_NAME |
| 254 | +
|
| 255 | +# Problem: Insufficient permissions |
| 256 | +# Solution: Verify your Azure CLI permissions |
| 257 | +az role assignment list --assignee $(az account show --query user.name -o tsv) |
| 258 | +
|
| 259 | +# Problem: Region not available |
| 260 | +# Solution: Check available locations |
| 261 | +az account list-locations --output table |
| 262 | +``` |
| 263 | + |
| 264 | +**🔧 Configuration Issues:** |
| 265 | +```bash |
| 266 | +# Problem: Container creation fails |
| 267 | +# Solution: Verify storage account exists and permissions |
| 268 | +az storage account show --name $SA_NAME --resource-group $RG_NAME |
| 269 | +
|
| 270 | +# Problem: Script execution fails |
| 271 | +# Solution: Check script permissions and syntax |
| 272 | +chmod +x 1-create-terraform-storage.sh |
| 273 | +bash -n 1-create-terraform-storage.sh # Syntax check |
| 274 | +
|
| 275 | +# Problem: Backend configuration not working |
| 276 | +# Solution: Verify storage account key access |
| 277 | +az storage account keys list --resource-group $RG_NAME --account-name $SA_NAME |
| 278 | +``` |
| 279 | + |
| 280 | +**🧹 Cleanup Commands:** |
| 281 | +```bash |
| 282 | +# Remove resource lock before deletion |
| 283 | +az lock delete --name "TerraformStorageLock" --resource-group $RG_NAME |
| 284 | +
|
| 285 | +# Delete storage account (careful!) |
| 286 | +az storage account delete --name $SA_NAME --resource-group $RG_NAME --yes |
| 287 | +
|
| 288 | +# Delete resource group (removes everything) |
| 289 | +az group delete --name $RG_NAME --yes --no-wait |
| 290 | +``` |
| 291 | + |
| 292 | +## 💡 **Knowledge Check** |
| 293 | + |
| 294 | +**🎯 Terraform State Concepts:** |
| 295 | +1. What happens if multiple people run Terraform simultaneously without remote state? |
| 296 | +2. How does Terraform state locking prevent conflicts? |
| 297 | +3. What information is stored in the Terraform state file? |
| 298 | +4. How does remote state improve team collaboration? |
| 299 | + |
| 300 | +**📝 Answers:** |
| 301 | +1. **Concurrent execution** can cause state corruption and conflicting infrastructure changes |
| 302 | +2. **State locking** uses blob leases to ensure only one Terraform operation runs at a time |
| 303 | +3. **State file** contains resource mappings, metadata, dependencies, and current configuration |
| 304 | +4. **Remote state** provides shared access, consistency, security, and automated backup |
| 305 | + |
| 306 | +**🔍 Advanced Concepts:** |
| 307 | +- **State Encryption:** How is sensitive data protected in state files? |
| 308 | +- **Versioning:** How can you roll back to previous state versions? |
| 309 | +- **Migration:** How would you migrate from local to remote state? |
| 310 | + |
| 311 | +## 🎯 **Next Steps** |
| 312 | + |
| 313 | +**✅ Upon Completion:** |
| 314 | +- [ ] Secure Azure Storage Account created for Terraform state |
| 315 | +- [ ] Blob container configured with proper permissions |
| 316 | +- [ ] Security best practices implemented |
| 317 | +- [ ] Backend configuration ready for Terraform projects |
| 318 | +- [ ] Understanding of remote state management benefits |
| 319 | + |
| 320 | +**➡️ Continue to:** [Create Azure AD Group for AKS Admins](./2-Create-Azure-AD-Group-AKS-Admins.md) |
| 321 | + |
| 322 | +--- |
| 323 | + |
| 324 | +## 📚 **Additional Resources** |
| 325 | + |
| 326 | +- 🔗 [Terraform Backend Configuration](https://www.terraform.io/language/settings/backends/azurerm) |
| 327 | +- 🔗 [Azure Storage Security Guide](https://docs.microsoft.com/en-us/azure/storage/common/storage-security-guide) |
| 328 | +- 🔗 [Terraform State Best Practices](https://www.terraform.io/language/state) |
| 329 | +- 🔗 [Azure CLI Storage Commands](https://docs.microsoft.com/en-us/cli/azure/storage) |
| 330 | + |
| 331 | +**🎯 Pro Tips:** |
| 332 | +- Use **separate storage accounts** for different environments (dev/staging/prod) |
| 333 | +- Enable **soft delete and versioning** for production workloads |
| 334 | +- Implement **network restrictions** to limit storage account access |
| 335 | +- Consider **customer-managed keys** for additional encryption control |
43 | 336 |
|
44 | 337 | ## 🔍 Verification |
45 | 338 | To ensure everything was set up correctly: |
|
0 commit comments