{"id":28533771,"url":"https://github.com/epam/azurelz","last_synced_at":"2025-07-07T20:31:17.538Z","repository":{"id":197737156,"uuid":"691615483","full_name":"epam/azurelz","owner":"epam","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-23T11:23:10.000Z","size":2151,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-06-09T17:09:16.680Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/epam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-14T14:34:13.000Z","updated_at":"2025-01-23T11:10:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"ae64546d-65d1-4830-828e-ad646f4aca86","html_url":"https://github.com/epam/azurelz","commit_stats":null,"previous_names":["epam/azurelz"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/epam/azurelz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epam%2Fazurelz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epam%2Fazurelz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epam%2Fazurelz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epam%2Fazurelz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/epam","download_url":"https://codeload.github.com/epam/azurelz/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epam%2Fazurelz/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264142573,"owners_count":23563522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-09T17:08:37.257Z","updated_at":"2025-07-07T20:31:17.532Z","avatar_url":"https://github.com/epam.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Overview\n\nStarting Cloud Journey is a hard and challenging process for every company. Setting up an initial technical baseline is a crucial part of this process. Making mistakes on initial step brings not only security, reputational and financial risks, but also takes a great amount of time to fix them in the future.​\n\nEPAM experienced cloud engineering team enforced by unified approach, predefined templates and codified baseline architecture footprints can make this process fast, effective and highly adoptive to client’s business goals by utilizing **EPAM Azure Landing Zone offerings**. These Offerings are based on Cloud best practices and EPAM recommendations empowered by Infrastructure as a Code templates adopted to Customer’s cloud demand will reduce risks of mistakes in fundamental Cloud setup process or during the delivery of platform, business, and secure landing zones.\n\nThis **Demo** solution is a part of **EPAM Azure Landing Zone offerings** that delivers a demo environment for playground or sandboxes. The demo solutions follow the start small and expand approach that accounts for scale, security, governance, networking, and identity. The solution allows you to deploy an infrastructure to get acquainted with the capabilities of Azure Landing Zone Offerings/frameworks and IaC approach. \n\n\n# Architecture\n\nThe **Demo** solution is based on the Terraform and EPAM owned child modules for each Azure Resource. It is a complete standalone solution that allows you to build a fundament of your cloud infrastructure. The **Demo** solution consist of the following components:\n\n- Governance\n  - Management groups\n  - Policy Definitions\n  - Policy Initiative\n  - Resource group\n  - Diagnostic settings\n  - Automation account\n- Network\n  - Virtual Networks\n  - Virtual Network Peering\n  - Subnets\n  - Private endpoint\n  - Network Security Groups\n  - Application Security Groups\n  - Azure Firewall\n  - Bastion\n  - UDR\n  - Application Gateway\n  - Private DNS\n  - Virtual Network gateway\n  - Public IP\n- Storage\n  - Storage account\n  - Log Analytics workspace\n- Security\n  - Key vault\n  - Defender for Coud\n  - Managed Identity\n- Workload\n   - VM\n   - VNIC\n   - Disk\n\n\n\nThe **Demo** solution is based on the traditional hub-and-spoke network topology where hub virtual network acts as a central point of connectivity for other virtual networks. The hub can also be used as a connectivity point for on-premises networks. \n\nDuring deployment, passwords for virtual machines are transmitted by secrets located in Key Vault (they are also deployed in the solution). After the deployment, it is possible to connect to virtual machines using the Bastion service. Private Endpoint is used to access the Storage Account. NSG and Firewall rules are also configured.\n\nThe diagram below provides a high-level overview of the solution:\n\n![**Demo**](docs/.attachments/Solution-Management/Demo/Demo_solution_v1.1.png)\n\n## Organizational structure\n\n\nThe **Demo** solution leverages management groups for efficient access management, policies assignment, and subscription management. The management groups follow the layered approach with respective policy initiatives assignment on each level. The diagram below provides an overview:\n\n![**Demo**](docs/.attachments/Solution-Management/Demo/Demo_solution_MG.png)\n\nThe **Demo** solution leverage five subscriptions to split and isolated different workload types:\n\n- **Gateway** - Is the entry-point of the whole solution that provides access to the solution from the Internet or on-premise networks and provides communication between the other environments.\n- **Shared** - It contains shared resources that need to be accessed for the functioning of the solution elements in the rest of the environment.\n- **Identity** - designed for resources that store sensitive information and provide access control. This creates an opportunity to further protect our shared services like Domain Controllers, different authentication services, secure data management systems and etc..\n- **DMZ** - the spoke is designed to place resources open for Internet access, which need to be separated from the internal network. DMZs function as a buffer zone between the public Internet and the rest of the environments.\n- **Business** - Is an environment that is designed to deploy the resources that are used initially to achieve the goals and objectives of the business.\n\n\n## Azure Key Vault management\n\nThe solution deploys three types of the Azure Key Vault:\n\n- The prerequisite Key Vault - is one within the solution. Used to store sensitive data required for Terraform operation.\n- Infrastructure Key Vault - one for each environment, key/secret access based on access policies. It is used to store secret data used to create Azure resources, such as passwords for virtual machine user accounts.\n- Application Key Vault - one for each environment, key/secret access based on RBAC. It is used to store secret data used in the application, such as account passwords.\n\nFor Infrastructure Key Vault and Application Key Vault diagnostic settings are enabled, collected logs and metrics are stored in Log Analytics workspaces for each environment (subscription) and duplicated in the storage account for each environment (subscription)\n\n![**Demo_solution_KV**](docs/.attachments/Solution-Management/Demo/Demo_solution_KV.png)\n\n## Prerequisites\n\nTo deploy a **Demo** solution within your landscape, you will need:\n\n- Azure Cloud subscription.\n- Azure Cloud Service Principal with \"Management Group Contributor\" and \"Owner\" (at least \"Contributor\" and \"User Access Administrator\" if \"Owner\" is not available) permissions at the Root Management Group level.\n- Installed on the local machine tools: \n  - git\n  - Terraform\n  - PowerShell(pwsh)\n\nThe solution is designed for deployment in five subscriptions. You can create \n- a separate Azure Resource Manager service connection for each of them at Azure subscription level scope.\n- or use a single one at scope of Management Group (with Azure subscriptions inside). \n\n## Manual deploy instruction using PowerShell syntax\n1. Clone the repository and navigate on it\n```\ngit clone https://github.com/epam/azurelz.git\ncd azurelz\n\n```\n2. Set variables:\n```pwsh\n# Terraform connection variables\n$env:ARM_CLIENT_ID     = \"00000000-1111-2222-3333-444444444444\"\n$env:ARM_CLIENT_SECRET = '\u003csecret for ARM_CLIENT_ID\u003e'\n\n# Subscription variables\n$env:ARM_TENANT_ID = \"00000000-1111-2222-3333-444444444444\"\n$sub_business      = \"00000000-1111-2222-3333-444444444444\"\n$sub_dmz           = \"00000000-1111-2222-3333-444444444445\"\n$sub_gateway       = \"00000000-1111-2222-3333-444444444446\"\n$sub_identity      = \"00000000-1111-2222-3333-444444444447\"\n$sub_shared        = \"00000000-1111-2222-3333-444444444448\"\n\n# SP variables\n$sp_object_id = 'SERVICE_PRINCIPAL_OBJECT_ID'\n\n```\n3. replace tokens `#{ENV_AZURE_SUBSCRIPTION_ID}#` and `#{ENV_AZURE_SP_OBJECT_ID}#` in each config files:\n```pwsh\n### BASE_LAYER\n# business\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.business.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_business) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.business.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.business.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.business.env.demo.tfvars\n\n# dmz\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.dmz.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_dmz) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.dmz.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.dmz.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.dmz.env.demo.tfvars\n\n# gateway\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.gateway.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_gateway) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.gateway.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.gateway.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.gateway.env.demo.tfvars\n\n# identity\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_identity) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars\n\n# shared\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.shared.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_shared) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.shared.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.shared.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.shared.env.demo.tfvars\n\n\n\n### WORK_LAYER\n\n# business\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.business.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_business) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.business.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.business.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.business.env.demo.tfvars\n\n# dmz\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.dmz.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_dmz) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.dmz.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.dmz.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.dmz.env.demo.tfvars\n\n# gateway\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.gateway.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_gateway) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.gateway.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.gateway.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.gateway.env.demo.tfvars\n\n# identity\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.identity.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_identity) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.identity.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.identity.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.identity.env.demo.tfvars\n\n# shared\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.shared.env.demo.tfvars).replace(\n'#{ENV_AZURE_SUBSCRIPTION_ID}#', $sub_shared) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.shared.env.demo.tfvars\n\n(Get-Content .\\demo_solution\\configuration\\work_layer\\epam.shared.env.demo.tfvars).replace(\n'#{ENV_AZURE_SP_OBJECT_ID}#', $sp_object_id) |\nSet-Content  .\\demo_solution\\configuration\\work_layer\\epam.shared.env.demo.tfvars\n\n\n```\n\n4. replace token `#{ENV_AZURE_TENANT_ID}#` in     \"demo_solution/configuration/base_layer/epam.identity.env.demo.tfvars\" file.\n\n```pwsh\n(Get-Content .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars).replace(\n'#{ENV_AZURE_TENANT_ID}#', $env:ARM_TENANT_ID ) |\nSet-Content  .\\demo_solution\\configuration\\base_layer\\epam.identity.env.demo.tfvars\n```\n\n5. Deploy Base Layer to all environments\n```pwsh\ncd .\\demo_solution\\base_layer\\\nterraform init\nterraform validate\nterraform workspace new epam.business.env.demo\nterraform workspace new epam.dmz.env.demo\nterraform workspace new epam.gateway.env.demo\nterraform workspace new epam.identity.env.demo\nterraform workspace new epam.shared.env.demo\n\n$env:ARM_SUBSCRIPTION_ID = $sub_business\nterraform workspace select epam.business.env.demo\nterraform apply -var-file=\"../configuration/base_layer/epam.business.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_dmz\nterraform workspace select epam.dmz.env.demo\nterraform apply -var-file=\"../configuration/base_layer/epam.dmz.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_gateway\nterraform workspace select epam.gateway.env.demo\nterraform apply -var-file=\"../configuration/base_layer/epam.gateway.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_identity\nterraform workspace select epam.identity.env.demo\nterraform apply -var-file=\"../configuration/base_layer/epam.identity.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_shared\nterraform workspace select epam.shared.env.demo\nterraform apply -var-file=\"../configuration/base_layer/epam.shared.env.demo.tfvars\" -auto-approve\n\n```\n\n6. Deploy Work Layer to all environments\n```pwsh\ncd ..\\work_layer\nterraform init\nterraform validate\nterraform workspace new epam.business.env.demo\nterraform workspace new epam.dmz.env.demo\nterraform workspace new epam.gateway.env.demo\nterraform workspace new epam.identity.env.demo\nterraform workspace new epam.shared.env.demo\n\n$env:ARM_SUBSCRIPTION_ID = $sub_business\nterraform workspace select epam.business.env.demo\nterraform apply -var-file=\"../configuration/work_layer/epam.business.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_dmz\nterraform workspace select epam.dmz.env.demo\nterraform apply -var-file=\"../configuration/work_layer/epam.dmz.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_gateway\nterraform workspace select epam.gateway.env.demo\nterraform apply -var-file=\"../configuration/work_layer/epam.gateway.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_identity\nterraform workspace select epam.identity.env.demo\nterraform apply -var-file=\"../configuration/work_layer/epam.identity.env.demo.tfvars\" -auto-approve\n\n$env:ARM_SUBSCRIPTION_ID = $sub_shared\nterraform workspace select epam.shared.env.demo\nterraform apply -var-file=\"../configuration/work_layer/epam.shared.env.demo.tfvars\" -auto-approve\n\n```\n\n6. For destroy you need to start with Work layer, then destroy Base layer. Use terraform select \u003cworkspace\u003e for switching to target environment.\n\n\n# Documents\n- Some Terraform best practices you can found [here](./docs/Best-practices-for-using-Terraform.md)\n\n# Contributing\n\nPlease check out our [contributing guidelines](CONTRIBUTING.md).\n\n# License\n\nCopyright (C) 2025 EPAM Systems Inc.\nThe LICENSE file in the root of this project applies unless otherwise indicated. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepam%2Fazurelz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fepam%2Fazurelz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepam%2Fazurelz/lists"}