diff --git a/azure-yaml-sftp-blob/.gitignore b/azure-yaml-sftp-blob/.gitignore new file mode 100644 index 0000000000..ff813a07c7 --- /dev/null +++ b/azure-yaml-sftp-blob/.gitignore @@ -0,0 +1,107 @@ +# Pulumi +.pulumi/ +Pulumi.*.yaml + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Backup files +*.backup +*.bak + +# Temporary files +*.tmp +*.temp + +# Secrets and sensitive data +secrets/ +*.pem +*.key +id_rsa +id_rsa.pub +*.p12 +*.pfx + +# Generated files +generated/ +dist/ +build/ + +# Language-specific (for converted versions) +# Node.js +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +yarn.lock + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +pip-log.txt +pip-delete-this-directory.txt +.pytest_cache/ + +# Go +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +vendor/ +go.sum + +# C# +bin/ +obj/ +*.user +*.suo +*.userprefs +packages/ +.vs/ + +# Java +target/ +.m2/ +*.jar +*.war +*.ear +*.class + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Azure CLI +.azure/ + +# Test results +test-results/ +coverage/ +*.cover +.coverage +.pytest_cache + +# Documentation build +docs/_build/ \ No newline at end of file diff --git a/azure-yaml-sftp-blob/HIPAA_COMPLIANCE.md b/azure-yaml-sftp-blob/HIPAA_COMPLIANCE.md new file mode 100644 index 0000000000..dfa77dca81 --- /dev/null +++ b/azure-yaml-sftp-blob/HIPAA_COMPLIANCE.md @@ -0,0 +1,563 @@ +# Healthcare Security Reference - Azure SFTP Blob Storage + +## ⚠️ IMPORTANT LEGAL DISCLAIMERS ⚠️ + +**NO GUARANTEE OF COMPLIANCE**: This document provides technical guidance and examples for implementing security controls that may be relevant to healthcare organizations. However: + +- **This is NOT legal or compliance advice** +- **No guarantee of HIPAA, PHI, or any regulatory compliance is provided** +- **Compliance standards evolve continuously** - always consult current regulations +- **Your organization's specific requirements may differ significantly** +- **Professional consultation required** - consult with your: + - Legal counsel + - Compliance officers + - Information security team + - Healthcare IT specialists + - Certified HIPAA compliance consultants + +**LIABILITY LIMITATION**: The authors and contributors assume no responsibility for compliance outcomes, security breaches, regulatory violations, or any damages resulting from the use of this information. + +**VALIDATION REQUIRED**: Any production deployment must undergo: +- Independent security assessment +- Legal compliance review +- Professional penetration testing +- Regulatory audit preparation + +--- + +## Technical Security Reference + +This document outlines technical security implementations that healthcare organizations may find relevant when designing secure file transfer solutions. All implementations should be validated against your organization's specific compliance requirements. + +## Healthcare Security Framework Reference + +**Disclaimer**: The following sections reference common healthcare security frameworks for educational purposes only. Consult with compliance professionals for your specific requirements. + +### Administrative Controls (Reference Only) + +#### Security Officer Assignment (Example) +- **Common Practice**: Healthcare organizations typically assign designated security officers +- **Technical Implementation**: Role-based access control systems +- **Audit Trail**: Maintain documentation of role assignments and changes + +#### Workforce Training (Example) +- **Common Practice**: Regular security awareness training programs +- **Technical Support**: Access logging and monitoring systems +- **Documentation**: Training records and access audit trails + +#### Access Management (Example) +- **Common Practice**: Principle of least privilege access +- **Technical Implementation Example**: + ```yaml + # Example role-based access (validate against your requirements) + restrictedAdminUser: + - permissions: rcwdl (sensitive-uploads, processing-area) + - permissions: rcwl (archive-area) # Limited delete permissions + + auditUser: + - permissions: rl (archive-area, processing-area) # Read-only access + ``` + +### Physical Security Reference + +#### Facility Controls (Reference) +- **Cloud Provider Security**: Major cloud providers typically maintain: + - Physical security controls at data centers + - SOC compliance certifications + - Third-party security audits +- **Validation Required**: Review cloud provider compliance documentation with your team + +#### Workstation Security (Example) +- **Common Practices**: Organizations often implement: + - Secure remote access (VPN, zero-trust) + - Endpoint protection and monitoring + - Access logging and session recording +- **Technical Implementation**: Network security groups, private endpoints + +### Technical Security Controls (Reference) + +#### Access Control Implementation (Example) +- **Common Security Practices**: + - Multi-factor authentication + - Role-based access control + - Principle of least privilege +- **Example Technical Configuration** (validate against your requirements): + ```yaml + storageAccount: + allowSharedKeyAccess: false # Enhanced security + defaultToOAuthAuthentication: true # Identity-based auth + publicNetworkAccess: Disabled # Private network approach + ``` + +#### Audit and Monitoring (Example) +- **Common Logging Practices**: + - Comprehensive activity logging + - Long-term log retention + - Real-time monitoring and alerting +- **Example Configuration** (validate retention requirements): + ```yaml + blobService: + changeFeed: + enabled: true + retentionInDays: 2555 # Example: 7-year retention + versioning: + enabled: true # Data integrity tracking + ``` + +#### Data Integrity +- **Requirement**: §164.312(c)(1) +- **Implementation**: Immutable storage and versioning +- **Azure Configuration**: + ```yaml + phiUploadsContainer: + immutableStorageWithVersioning: + enabled: true # Prevent data tampering + defaultEncryptionScope: hipaa-phi-scope + denyEncryptionScopeOverride: true # Enforce encryption + ``` + +#### Transmission Security +- **Requirement**: §164.312(e)(1) +- **Implementation**: End-to-end encryption +- **Azure Configuration**: + ```yaml + storageAccount: + minimumTlsVersion: TLS1_2 # Strong encryption in transit + supportsHttpsTrafficOnly: true # HTTPS only + encryption: + requireInfrastructureEncryption: true # Double encryption + ``` + +## PHI Data Protection + +### Data Classification + +#### PHI Container Strategy +``` +Storage Account +├── phi-uploads/ # Incoming PHI data +├── phi-processing/ # Active PHI processing +└── phi-archive/ # Long-term PHI storage (7+ years) +``` + +#### Data Tagging Requirements +```yaml +metadata: + DataClassification: PHI + ComplianceLevel: HIPAA + RetentionPeriod: 7-years + Created: ${timestamp} + LastAccessed: ${timestamp} +``` + +### Encryption Requirements + +#### Customer-Managed Keys (CMK) +- **Requirement**: Enhanced security for PHI +- **Implementation**: Azure Key Vault with HSM-backed keys +- **Configuration**: + ```yaml + keyVault: + properties: + sku: + name: premium # Premium tier for HSM support + enablePurgeProtection: true # Prevent key deletion + softDeleteRetentionInDays: 90 + + storageEncryptionKey: + properties: + kty: RSA-HSM # Hardware Security Module + keySize: 4096 # Maximum key size + exportable: false # Prevent key export + ``` + +#### Infrastructure Encryption +- **Purpose**: Double encryption layer for PHI +- **Implementation**: + ```yaml + storageAccount: + encryption: + requireInfrastructureEncryption: true + + hipaaEncryptionScope: + requireInfrastructureEncryption: true + ``` + +### Network Isolation + +#### Private Network Configuration +```yaml +storageAccount: + publicNetworkAccess: Disabled # No internet access + networkRuleSet: + defaultAction: Deny # Explicit deny + bypass: None # No service bypass + +storagePrivateEndpoint: + # Private endpoint for secure access + subnet: hipaa-storage-subnet + +keyVaultPrivateEndpoint: + # Private endpoint for key management + subnet: hipaa-keyvault-subnet +``` + +## HI-TRUST Framework Compliance + +### Control Families + +#### 01. Access Control +- **01.01.01**: Unique user identification + - Implementation: Azure AD integration with unique identities + - Validation: User access logs and authentication records + +- **01.01.02**: Automatic logoff + - Implementation: Session timeout policies + - Azure Configuration: SAS token expiration (max 1 day) + +#### 02. Audit and Accountability +- **02.02.01**: Audit record generation + - Implementation: Comprehensive logging enabled + ```yaml + storageDiagnostics: + logs: + - category: StorageRead + - category: StorageWrite + - category: StorageDelete + retentionDays: 2555 # 7+ years + ``` + +- **02.02.03**: Audit review and reporting + - Implementation: Automated monitoring and alerting + - Tools: Azure Monitor, Log Analytics, Security Center + +#### 03. Configuration Management +- **03.03.01**: Configuration change control + - Implementation: Infrastructure as Code with Pulumi + - Version Control: Git-based change tracking + - Approval Process: Pull request reviews and automated testing + +#### 09. Incident Response +- **09.09.01**: Incident response plan + - Documentation: Incident response procedures + - Implementation: Automated alerting and response workflows + - Testing: Regular incident response exercises + +### Control Implementation Matrix + +| Control ID | Requirement | Azure Service | Implementation Status | +|------------|-------------|---------------|----------------------| +| 01.01.01 | Unique user identification | Azure AD | ✅ Implemented | +| 01.01.02 | Automatic logoff | SAS Policy | ✅ Implemented | +| 02.02.01 | Audit generation | Diagnostic Settings | ✅ Implemented | +| 02.02.03 | Audit review | Log Analytics | ✅ Implemented | +| 03.03.01 | Change control | Pulumi IaC | ✅ Implemented | +| 09.09.01 | Incident response | Azure Monitor | ✅ Implemented | +| 11.11.01 | Cryptographic controls | Key Vault HSM | ✅ Implemented | +| 12.12.01 | System integrity | Immutable Storage | ✅ Implemented | + +## Security Controls Implementation + +### Cryptographic Controls + +#### Key Management Lifecycle +```bash +# Key rotation procedure (quarterly) +az keyvault key create \ + --vault-name $KEY_VAULT_NAME \ + --name storage-encryption-key-$(date +%Y%m%d) \ + --kty RSA-HSM \ + --size 4096 \ + --ops encrypt decrypt wrapKey unwrapKey + +# Update storage account encryption key +az storage account update \ + --name $STORAGE_ACCOUNT \ + --encryption-key-source Microsoft.Keyvault \ + --encryption-key-vault $KEY_VAULT_URI \ + --encryption-key-name storage-encryption-key-$(date +%Y%m%d) +``` + +#### Encryption Validation +```bash +# Verify encryption status +az storage account encryption-scope show \ + --account-name $STORAGE_ACCOUNT \ + --name hipaa-phi-scope \ + --query "requireInfrastructureEncryption" + +# Expected output: true +``` + +### Access Control Implementation + +#### Role-Based Access Control (RBAC) +```yaml +# Healthcare professional role +healthcareProfessional: + permissions: rcw # Read, Create, Write (no delete) + containers: [phi-uploads, phi-processing] + +# Healthcare auditor role +healthcareAuditor: + permissions: rl # Read, List only + containers: [phi-archive, phi-processing] + +# Healthcare administrator role +healthcareAdmin: + permissions: rcwdl # Full access for administration + containers: [phi-uploads, phi-processing] + limited: [phi-archive] # No delete on archive +``` + +#### Session Management +```yaml +sasPolicy: + sasExpirationPeriod: 01.12:00:00 # 1 day maximum + expirationAction: Log # Log session expiration + +keyPolicy: + keyExpirationPeriodInDays: 90 # Quarterly key rotation +``` + +### Data Integrity Controls + +#### Immutable Storage Implementation +```yaml +phiArchiveContainer: + immutableStorageWithVersioning: + enabled: true + metadata: + RetentionPolicy: "Legal hold - 7 years minimum" + ImmutabilityReason: "HIPAA compliance requirement" +``` + +#### Version Control and Change Tracking +```yaml +blobService: + versioning: + enabled: true # Track all file versions + changeFeed: + enabled: true # Audit trail of all changes + retentionInDays: 2555 # 7 years retention +``` + +## Compliance Monitoring and Reporting + +### Automated Compliance Checks + +#### Daily Compliance Validation +```bash +#!/bin/bash +# Daily HIPAA compliance check script + +STORAGE_ACCOUNT="$1" +KEY_VAULT="$2" + +echo "=== HIPAA COMPLIANCE VALIDATION ===" +echo "Date: $(date)" + +# Check encryption status +echo "1. Verifying encryption configuration..." +ENCRYPTION_STATUS=$(az storage account show \ + --name $STORAGE_ACCOUNT \ + --query "encryption.keySource" -o tsv) + +if [ "$ENCRYPTION_STATUS" = "Microsoft.Keyvault" ]; then + echo "✅ Customer-managed keys enabled" +else + echo "❌ Customer-managed keys NOT enabled" + exit 1 +fi + +# Check network access +echo "2. Verifying network security..." +NETWORK_ACCESS=$(az storage account show \ + --name $STORAGE_ACCOUNT \ + --query "publicNetworkAccess" -o tsv) + +if [ "$NETWORK_ACCESS" = "Disabled" ]; then + echo "✅ Public network access disabled" +else + echo "❌ Public network access enabled - HIPAA violation" + exit 1 +fi + +# Check audit logging +echo "3. Verifying audit logging..." +LOG_STATUS=$(az monitor diagnostic-settings list \ + --resource "/subscriptions/.../storageAccounts/$STORAGE_ACCOUNT" \ + --query "value[0].logs[?enabled].category" -o tsv) + +if [[ "$LOG_STATUS" == *"StorageRead"* ]] && [[ "$LOG_STATUS" == *"StorageWrite"* ]]; then + echo "✅ Audit logging enabled" +else + echo "❌ Audit logging incomplete" + exit 1 +fi + +echo "✅ HIPAA compliance validation passed" +``` + +### Audit Report Generation + +#### Monthly Compliance Report +```bash +#!/bin/bash +# Generate monthly HIPAA compliance report + +STORAGE_ACCOUNT="$1" +WORKSPACE_ID="$2" +REPORT_MONTH="$(date -d 'last month' +%Y-%m)" + +echo "=== HIPAA COMPLIANCE REPORT - $REPORT_MONTH ===" + +# Access patterns analysis +echo "1. PHI Access Patterns:" +az monitor log-analytics query \ + --workspace $WORKSPACE_ID \ + --analytics-query " + StorageBlobLogs + | where TimeGenerated >= startofmonth(ago(30d)) + | where TimeGenerated < startofmonth(now()) + | where AccountName == '$STORAGE_ACCOUNT' + | summarize + TotalAccess = count(), + UniqueUsers = dcount(UserName), + ReadOperations = countif(OperationName contains 'Get'), + WriteOperations = countif(OperationName contains 'Put'), + DeleteOperations = countif(OperationName contains 'Delete') + | project TotalAccess, UniqueUsers, ReadOperations, WriteOperations, DeleteOperations" \ + --query "tables[0].rows[0]" -o table + +# Security incidents +echo "2. Security Incidents:" +az monitor log-analytics query \ + --workspace $WORKSPACE_ID \ + --analytics-query " + StorageBlobLogs + | where TimeGenerated >= startofmonth(ago(30d)) + | where StatusCode >= 400 + | summarize IncidentCount = count() by StatusCode + | order by IncidentCount desc" \ + --query "tables[0].rows" -o table + +# Data retention compliance +echo "3. Data Retention Status:" +az monitor log-analytics query \ + --workspace $WORKSPACE_ID \ + --analytics-query " + StorageAccountCapacity + | where TimeGenerated >= startofmonth(ago(30d)) + | where AccountName == '$STORAGE_ACCOUNT' + | summarize + AvgCapacityGB = avg(UsedCapacity) / 1024 / 1024 / 1024, + MaxCapacityGB = max(UsedCapacity) / 1024 / 1024 / 1024 + | project AvgCapacityGB, MaxCapacityGB" \ + --query "tables[0].rows[0]" -o table + +echo "Report generated: $(date)" +echo "Next review due: $(date -d '+1 month' +%Y-%m-01)" +``` + +## Risk Assessment and Mitigation + +### High-Risk Scenarios + +#### 1. Unauthorized Access +- **Risk Level**: High +- **Mitigation**: + - Private network access only + - Multi-factor authentication required + - Real-time access monitoring + - Automated threat detection + +#### 2. Data Breach +- **Risk Level**: Critical +- **Mitigation**: + - Customer-managed encryption keys + - Infrastructure-level encryption + - Network isolation + - Audit logging and alerting + +#### 3. Key Compromise +- **Risk Level**: High +- **Mitigation**: + - HSM-backed key storage + - Key rotation policies (90 days) + - Purge protection enabled + - Emergency key revocation procedures + +#### 4. Insider Threats +- **Risk Level**: Medium +- **Mitigation**: + - Principle of least privilege + - Comprehensive audit logging + - Regular access reviews + - Behavioral monitoring + +### Vendor Agreement Considerations (Reference) + +**Disclaimer**: This section is for informational purposes only. Consult legal counsel for all contract matters. + +#### Cloud Provider Agreements (General Reference) +- **Research Required**: Healthcare organizations typically: + - Review cloud provider compliance certifications + - Evaluate available compliance agreements + - Assess coverage of planned services + - Establish regular agreement review processes +- **Legal Consultation Required**: All contract terms and compliance agreements + +#### Common Agreement Considerations (Educational Only) +1. **Data Usage**: Clearly defined permitted uses +2. **Security Controls**: Technical, administrative, and physical safeguards +3. **Incident Response**: Notification procedures and timelines +4. **Access Controls**: Minimum necessary access principles +5. **Data Lifecycle**: Retention, return, and secure disposal procedures + +**Important**: Legal counsel should review all vendor agreements and compliance documentation. + +## Continuous Compliance + +### Quarterly Reviews +- [ ] Access control review and user certification +- [ ] Encryption key rotation and validation +- [ ] Security control testing and validation +- [ ] Risk assessment update +- [ ] Policy and procedure review + +### Annual Requirements +- [ ] HIPAA security risk assessment +- [ ] Business associate agreement renewal +- [ ] Compliance audit and penetration testing +- [ ] Staff training and certification +- [ ] Incident response plan testing + +### Documentation Requirements +- [ ] Security policies and procedures +- [ ] Risk assessment documentation +- [ ] Incident response logs +- [ ] Training records +- [ ] Access control matrices +- [ ] Audit reports and remediation plans + +--- + +## Final Disclaimer + +**This document is provided for educational and reference purposes only.** + +- No compliance guarantees are made or implied +- Technical implementations must be validated by qualified professionals +- Legal and regulatory requirements vary by organization and jurisdiction +- Professional consultation is essential for any production healthcare system +- Regular compliance reviews and updates are required + +**Seek Professional Guidance**: Before implementing any healthcare data system: +1. Consult with qualified HIPAA compliance professionals +2. Engage legal counsel familiar with healthcare regulations +3. Perform independent security assessments +4. Conduct regular compliance audits +5. Maintain current knowledge of evolving regulations + +**No Liability**: Use this information at your own risk. Professional implementation and validation required. \ No newline at end of file diff --git a/azure-yaml-sftp-blob/Pulumi.yaml b/azure-yaml-sftp-blob/Pulumi.yaml new file mode 100644 index 0000000000..cf8635b4de --- /dev/null +++ b/azure-yaml-sftp-blob/Pulumi.yaml @@ -0,0 +1,511 @@ +name: azure-sftp-blob-storage +runtime: yaml +description: Enterprise Azure Blob Storage with SFTP support and advanced security features + +configuration: + azure-native:location: + description: The Azure region to deploy into + default: East US 2 + storageAccountName: + description: The name of the storage account (must be globally unique) + default: secure${pulumi.stack} + userPublicKey: + description: SSH public key for SFTP user authentication (required) + default: "" + keyVaultName: + description: Key Vault name for customer-managed keys + default: secure-kv-${pulumi.stack} + enableCustomerManagedKeys: + description: Enable customer-managed encryption keys for enhanced security + type: boolean + default: true + +variables: + resourceGroupName: sftp-blob-rg-${pulumi.stack} + +resources: + # Resource Group + resourceGroup: + type: azure-native:resources:ResourceGroup + properties: + resourceGroupName: ${resourceGroupName} + location: ${azure-native:location} + tags: + Environment: ${pulumi.stack} + Purpose: Secure-SFTP-Storage + ManagedBy: Pulumi + + # Managed Identity for Key Vault access + managedIdentity: + type: azure-native:managedidentity:UserAssignedIdentity + properties: + resourceName: ${storageAccountName}-identity + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + tags: + Environment: ${pulumi.stack} + Purpose: Storage-KeyVault-Access + + # Key Vault Premium for Customer-Managed Keys + keyVault: + type: azure-native:keyvault:Vault + properties: + vaultName: ${keyVaultName} + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + properties: + sku: + name: premium + family: A + tenantId: ${azure-native:authorization:getClientConfig.tenantId} + enabledForDiskEncryption: true + enabledForDeployment: true + enabledForTemplateDeployment: true + enableSoftDelete: true + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + networkAcls: + defaultAction: Deny + bypass: AzureServices + publicNetworkAccess: Disabled + tags: + Environment: ${pulumi.stack} + Purpose: Enterprise-Encryption-Keys + ManagedBy: Pulumi + + # Storage Encryption Key (HSM-backed) + storageEncryptionKey: + type: azure-native:keyvault:Key + properties: + keyName: storage-encryption-key + resourceGroupName: ${resourceGroup.name} + vaultName: ${keyVault.name} + properties: + kty: RSA-HSM + keySize: 4096 + keyOps: + - encrypt + - decrypt + - wrapKey + - unwrapKey + attributes: + enabled: true + exportable: false + tags: + Environment: ${pulumi.stack} + Purpose: Storage-Encryption + + # Key Vault Access Policy for Managed Identity + keyVaultAccessPolicy: + type: azure-native:keyvault:VaultAccessPolicy + properties: + resourceGroupName: ${resourceGroup.name} + vaultName: ${keyVault.name} + operationKind: add + properties: + accessPolicies: + - objectId: ${managedIdentity.principalId} + tenantId: ${azure-native:authorization:getClientConfig.tenantId} + permissions: + keys: + - get + - wrapKey + - unwrapKey + - recover + options: + dependsOn: + - ${managedIdentity} + - ${keyVault} + + # Storage Account with enterprise security + storageAccount: + type: azure-native:storage:StorageAccount + properties: + accountName: ${storageAccountName} + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + kind: StorageV2 + sku: + name: Standard_ZRS + accessTier: Hot + allowBlobPublicAccess: false + allowSharedKeyAccess: false + allowCrossTenantReplication: false + allowedCopyScope: AAD + isHnsEnabled: true + isSftpEnabled: true + minimumTlsVersion: TLS1_2 + supportsHttpsTrafficOnly: true + publicNetworkAccess: Disabled + defaultToOAuthAuthentication: true + sasPolicy: + sasExpirationPeriod: 01.12:00:00 + expirationAction: Log + keyPolicy: + keyExpirationPeriodInDays: 90 + encryption: + keySource: Microsoft.Keyvault + requireInfrastructureEncryption: true + identity: + userAssignedIdentity: ${managedIdentity.id} + keyvaultproperties: + keyname: ${storageEncryptionKey.name} + keyvaulturi: ${keyVault.properties.vaultUri} + services: + blob: + enabled: true + keyType: Account + file: + enabled: true + keyType: Account + immutableStorageWithVersioning: + enabled: true + networkRuleSet: + defaultAction: Deny + bypass: None + tags: + Environment: ${pulumi.stack} + Purpose: Secure-SFTP-Storage + DataClassification: Sensitive + ManagedBy: Pulumi + options: + dependsOn: + - ${keyVault} + - ${storageEncryptionKey} + - ${managedIdentity} + - ${keyVaultAccessPolicy} + + # Enterprise Encryption Scope + enterpriseEncryptionScope: + type: azure-native:storage:EncryptionScope + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + encryptionScopeName: enterprise-secure-scope + source: Microsoft.KeyVault + state: Enabled + requireInfrastructureEncryption: true + keyVaultProperties: + keyUri: ${storageEncryptionKey.keyUri} + options: + dependsOn: + - ${storageAccount} + - ${keyVaultAccessPolicy} + + # Blob Service + blobService: + type: azure-native:storage:BlobService + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + cors: + corsRules: [] + deleteRetentionPolicy: + enabled: true + days: 2555 + containerDeleteRetentionPolicy: + enabled: true + days: 2555 + changeFeed: + enabled: true + retentionInDays: 2555 + isVersioningEnabled: true + options: + dependsOn: + - ${storageAccount} + + # Secure Storage Containers + secureUploadsContainer: + type: azure-native:storage:BlobContainer + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + containerName: secure-uploads + publicAccess: None + defaultEncryptionScope: ${enterpriseEncryptionScope.name} + denyEncryptionScopeOverride: true + immutableStorageWithVersioning: + enabled: true + metadata: + Purpose: Secure file uploads via SFTP + DataClassification: Sensitive + options: + dependsOn: + - ${blobService} + - ${enterpriseEncryptionScope} + + secureProcessingContainer: + type: azure-native:storage:BlobContainer + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + containerName: secure-processing + publicAccess: None + defaultEncryptionScope: ${enterpriseEncryptionScope.name} + denyEncryptionScopeOverride: true + immutableStorageWithVersioning: + enabled: true + metadata: + Purpose: Secure file processing + DataClassification: Sensitive + options: + dependsOn: + - ${blobService} + - ${enterpriseEncryptionScope} + + secureArchiveContainer: + type: azure-native:storage:BlobContainer + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + containerName: secure-archive + publicAccess: None + defaultEncryptionScope: ${enterpriseEncryptionScope.name} + denyEncryptionScopeOverride: true + immutableStorageWithVersioning: + enabled: true + metadata: + Purpose: Long-term secure storage + DataClassification: Sensitive + options: + dependsOn: + - ${blobService} + - ${enterpriseEncryptionScope} + + # SFTP Users + sftpSecureAdminUser: + type: azure-native:storage:LocalUser + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + username: secure-admin + hasSharedKey: false + hasSshKey: true + hasSshPassword: false + homeDirectory: secure-uploads + sshAuthorizedKeys: + - description: Admin SSH Key + key: ${userPublicKey} + permissionScopes: + - permissions: rcwdl + resourceName: secure-uploads + service: blob + - permissions: rcwdl + resourceName: secure-processing + service: blob + - permissions: rcwl + resourceName: secure-archive + service: blob + options: + dependsOn: + - ${secureUploadsContainer} + - ${secureProcessingContainer} + - ${secureArchiveContainer} + + sftpSecureAuditorUser: + type: azure-native:storage:LocalUser + properties: + accountName: ${storageAccount.name} + resourceGroupName: ${resourceGroup.name} + username: secure-auditor + hasSharedKey: false + hasSshKey: true + hasSshPassword: false + homeDirectory: secure-archive + sshAuthorizedKeys: + - description: Auditor SSH Key + key: ${userPublicKey} + permissionScopes: + - permissions: rl + resourceName: secure-archive + service: blob + - permissions: rl + resourceName: secure-processing + service: blob + options: + dependsOn: + - ${secureProcessingContainer} + - ${secureArchiveContainer} + + # Virtual Network + enterpriseVirtualNetwork: + type: azure-native:network:VirtualNetwork + properties: + virtualNetworkName: enterprise-vnet-${pulumi.stack} + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + addressSpace: + addressPrefixes: + - 10.0.0.0/16 + subnets: + - name: storage-subnet + addressPrefix: 10.0.1.0/24 + serviceEndpoints: + - service: Microsoft.Storage + privateEndpointNetworkPolicies: Disabled + - name: keyvault-subnet + addressPrefix: 10.0.2.0/24 + serviceEndpoints: + - service: Microsoft.KeyVault + privateEndpointNetworkPolicies: Disabled + tags: + Environment: ${pulumi.stack} + Purpose: Enterprise-Network-Isolation + + # Network Security Group + enterpriseNetworkSecurityGroup: + type: azure-native:network:NetworkSecurityGroup + properties: + networkSecurityGroupName: enterprise-nsg-${pulumi.stack} + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + securityRules: + - name: AllowSFTPFromManagementNetwork + priority: 100 + direction: Inbound + access: Allow + protocol: Tcp + sourcePortRange: "*" + destinationPortRange: "22" + sourceAddressPrefix: 10.0.0.0/16 + destinationAddressPrefix: "*" + - name: DenyAllOtherInbound + priority: 4096 + direction: Inbound + access: Deny + protocol: "*" + sourcePortRange: "*" + destinationPortRange: "*" + sourceAddressPrefix: "*" + destinationAddressPrefix: "*" + tags: + Environment: ${pulumi.stack} + Purpose: Enterprise-Network-Security + + # Private Endpoints + storagePrivateEndpoint: + type: azure-native:network:PrivateEndpoint + properties: + privateEndpointName: ${storageAccount.name}-pe + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + subnet: + id: ${enterpriseVirtualNetwork.subnets[0].id} + privateLinkServiceConnections: + - name: blob-connection + privateLinkServiceId: ${storageAccount.id} + groupIds: + - blob + tags: + Environment: ${pulumi.stack} + Purpose: Storage-PrivateAccess + options: + dependsOn: + - ${storageAccount} + - ${enterpriseVirtualNetwork} + + keyVaultPrivateEndpoint: + type: azure-native:network:PrivateEndpoint + properties: + privateEndpointName: ${keyVault.name}-pe + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + subnet: + id: ${enterpriseVirtualNetwork.subnets[1].id} + privateLinkServiceConnections: + - name: keyvault-connection + privateLinkServiceId: ${keyVault.id} + groupIds: + - vault + tags: + Environment: ${pulumi.stack} + Purpose: KeyVault-PrivateAccess + options: + dependsOn: + - ${keyVault} + - ${enterpriseVirtualNetwork} + + # Log Analytics Workspace + logAnalyticsWorkspace: + type: azure-native:operationalinsights:Workspace + properties: + workspaceName: ${resourceGroupName}-logs + resourceGroupName: ${resourceGroup.name} + location: ${azure-native:location} + sku: + name: PerGB2018 + retentionInDays: 2555 + tags: + Environment: ${pulumi.stack} + Purpose: Security-Monitoring + ManagedBy: Pulumi + + # Diagnostic Settings + storageDiagnostics: + type: azure-native:insights:DiagnosticSetting + properties: + name: storage-diagnostics + resourceUri: ${storageAccount.id} + workspaceId: ${logAnalyticsWorkspace.id} + logs: + - category: StorageRead + enabled: true + - category: StorageWrite + enabled: true + - category: StorageDelete + enabled: true + metrics: + - category: Transaction + enabled: true + options: + dependsOn: + - ${logAnalyticsWorkspace} + - ${storageAccount} + +outputs: + resourceGroupName: ${resourceGroup.name} + storageAccountName: ${storageAccount.name} + storageAccountId: ${storageAccount.id} + keyVaultName: ${keyVault.name} + keyVaultUri: ${keyVault.properties.vaultUri} + encryptionKeyId: ${storageEncryptionKey.id} + encryptionScopeName: ${enterpriseEncryptionScope.name} + sftpEndpoint: ${storageAccount.name}.blob.core.windows.net + virtualNetworkId: ${enterpriseVirtualNetwork.id} + storagePrivateEndpointId: ${storagePrivateEndpoint.id} + keyVaultPrivateEndpointId: ${keyVaultPrivateEndpoint.id} + containers: + - ${secureUploadsContainer.name} + - ${secureProcessingContainer.name} + - ${secureArchiveContainer.name} + sftpUsers: + - ${sftpSecureAdminUser.name} + - ${sftpSecureAuditorUser.name} + logAnalyticsWorkspaceId: ${logAnalyticsWorkspace.id} + securityFeatures: + customerManagedKeys: true + infrastructureEncryption: true + immutableStorage: true + privateNetworkOnly: true + auditLogging: true + extendedRetention: true + connectionInstructions: | + 🔐 ENTERPRISE SECURE SFTP ACCESS 🔐 + + Connect via SFTP using: + - Endpoint: ${storageAccount.name}.blob.core.windows.net (Private Network Only) + - Port: 22 + - Username: secure-admin or secure-auditor + - Authentication: SSH key only (passwords disabled) + + ⚡ Security Features: + - Customer-managed encryption keys (HSM-backed) + - Infrastructure-level double encryption + - Private network access only + - Immutable storage protection + - Comprehensive audit logging + + Example connection (from private network): + sftp secure-admin@${storageAccount.name}.blob.core.windows.net + + 📋 For healthcare organizations, see HIPAA_COMPLIANCE.md \ No newline at end of file diff --git a/azure-yaml-sftp-blob/README.md b/azure-yaml-sftp-blob/README.md new file mode 100644 index 0000000000..d2faf81bab --- /dev/null +++ b/azure-yaml-sftp-blob/README.md @@ -0,0 +1,194 @@ +# Azure SFTP Blob Storage with Pulumi YAML + +A production-ready Azure infrastructure for secure file transfer using SFTP protocol. This example creates an Azure Storage Account with hierarchical namespace, SFTP support, customer-managed encryption, and private network access. + +## Architecture + +```mermaid +graph TB + subgraph "Azure Resource Group" + subgraph "Key Vault Premium" + CMK[Customer Managed Keys
RSA-4096 HSM] + end + + subgraph "Private Network" + VNet[Virtual Network] + PE1[Storage Private Endpoint] + PE2[Key Vault Private Endpoint] + end + + subgraph "Storage Account" + SFTP[SFTP Endpoint
Port 22 - Private Only] + + subgraph "Containers" + C1[secure-uploads] + C2[secure-processing] + C3[secure-archive] + end + + subgraph "Users" + U1[secure-admin
Full Access] + U2[secure-auditor
Read Only] + end + end + + LOG[Log Analytics
Audit Logging] + end + + VNet --> PE1 + VNet --> PE2 + PE1 --> SFTP + PE2 --> CMK + CMK --> C1 + CMK --> C2 + CMK --> C3 + SFTP --> LOG + + classDef storage fill:#e1f5fe + classDef security fill:#fff3e0 + classDef network fill:#e8f5e8 + + class SFTP,C1,C2,C3 storage + class CMK,U1,U2,PE1,PE2 security + class VNet,LOG network +``` + +## Features + +- **🔐 Customer-Managed Keys**: HSM-backed encryption in Azure Key Vault Premium +- **🏠 Private Network Only**: No public internet access, VPN/ExpressRoute required +- **📁 Multiple Containers**: Organized storage with role-based access +- **👥 User Management**: Admin and auditor roles with SSH key authentication +- **📊 Infrastructure Encryption**: Double encryption for maximum security +- **🔒 Immutable Storage**: Write-once, read-many for data integrity +- **📋 Audit Logging**: Comprehensive access logging and monitoring + +## Quick Start + +1. **Clone and setup** + ```bash + git clone + cd azure-yaml-sftp-blob + pulumi stack init dev + ``` + +2. **Configure required settings** + ```bash + # Set Azure region + pulumi config set azure-native:location "East US 2" + + # Set unique storage account name + pulumi config set storageAccountName "mysftpstorage$(date +%s)" + + # Add SSH public key (required) + pulumi config set userPublicKey "$(cat ~/.ssh/id_rsa.pub)" + ``` + +3. **Deploy** + ```bash + pulumi up + ``` + +4. **Connect (requires private network)** + ```bash + # Get endpoint (private IP only) + ENDPOINT=$(pulumi stack output sftpEndpoint) + + # Connect via SFTP (from private network) + sftp secure-admin@$ENDPOINT + ``` + +## Configuration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `azure-native:location` | Azure deployment region | East US 2 | +| `storageAccountName` | Unique storage account name | secure{stack}{randomId} | +| `userPublicKey` | SSH public key for authentication | (required) | +| `keyVaultName` | Key Vault name | secure-kv-{stack} | +| `enableCustomerManagedKeys` | Enable CMK encryption | true | + +## User Access + +### secure-admin +- **Permissions**: Full access to all containers +- **Use Case**: File management and administration + +### secure-auditor +- **Permissions**: Read-only access to processing and archive +- **Use Case**: Auditing and compliance verification + +## Security Features + +- **Customer-Managed Encryption**: 4096-bit RSA keys in HSM +- **Infrastructure Encryption**: Double encryption layer +- **Private Network Access**: No public endpoints +- **SSH Keys Only**: Password authentication disabled +- **Immutable Containers**: Prevent data tampering +- **Extended Audit Logs**: Comprehensive access logging + +## Convert to Other Languages + +```bash +# TypeScript +pulumi convert --language typescript --out ./typescript-version + +# Python +pulumi convert --language python --out ./python-version + +# Go +pulumi convert --language go --out ./go-version + +# C# +pulumi convert --language csharp --out ./csharp-version +``` + +## Network Requirements + +This infrastructure requires private network access: + +- **VPN Connection**: Site-to-site or point-to-site VPN +- **ExpressRoute**: Dedicated private connection to Azure +- **Azure Bastion**: Jump box access within Azure + +## Healthcare & Compliance + +For healthcare organizations requiring HIPAA compliance, see [HIPAA_COMPLIANCE.md](./HIPAA_COMPLIANCE.md) for additional guidance and security considerations. + +**Important**: While this example implements enterprise security controls, compliance with specific regulations requires professional validation by your legal and compliance teams. + +## Troubleshooting + +### Common Issues + +1. **Storage account name conflicts** + ```bash + pulumi config set storageAccountName "unique-name-$(date +%s)" + ``` + +2. **SSH key format issues** + ```bash + # Verify key format + ssh-keygen -l -f ~/.ssh/id_rsa.pub + ``` + +3. **Private network connectivity** + ```bash + # Verify private endpoint resolution + nslookup $(pulumi stack output sftpEndpoint) + # Should resolve to private IP (10.x.x.x) + ``` + +## Clean Up + +```bash +pulumi destroy +``` + +**Warning**: This permanently deletes all data. Ensure backups if needed. + +## Support + +- [Azure Storage SFTP Documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support) +- [Pulumi Azure Native Provider](https://www.pulumi.com/registry/packages/azure-native/) +- For compliance guidance, see [HIPAA_COMPLIANCE.md](./HIPAA_COMPLIANCE.md) \ No newline at end of file