Skip to content
This repository has been archived by the owner on Jun 22, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1 from tietoevry-infra-as-code/develop
Browse files Browse the repository at this point in the history
initial commit
  • Loading branch information
kumarvit authored Oct 1, 2020
2 parents b676425 + cc2ccf6 commit 9df216c
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 1 deletion.
95 changes: 94 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,94 @@
# terraform-azurerm-azure-bastion
# Azure Bastion Service Terraform module

The Azure Bastion service is a fully platform-managed PaaS service that provision inside the virtual network. It provides secure and seamless RDP/SSH connectivity to the virtual machines directly in the Azure portal over TLS. When connecting via Azure Bastion, the virtual machines do not need a public IP address.

Azure Bastion deployment is per virtual network, not per subscription/account or virtual machine. Once provisioned an Azure Bastion service in the virtual network, the RDP/SSH experience is available to all the VMs in the same virtual network.

## Module Usage

```hcl
module "azure-bastion" {
source = "kumarvna/azure-bastion/azurerm"
version = "1.0.0"
# Resource Group, location, VNet and Subnet details
resource_group_name = "rg-shared-westeurope-01"
virtual_network_name = "vnet-shared-hub-westeurope-001"
# Azure bastion server requireemnts
azure_bastion_service_name = "mybastion-service"
azure_bastion_subnet_address_prefix = ["10.5.0.0/26"]
# Adding TAG's to your Azure resources (Required)
tags = {
ProjectName = "demo-internal"
Env = "dev"
Owner = "user@example.com"
BusinessUnit = "CORP"
ServiceClass = "Gold"
}
}
```

## Pre-requisites

### Virtual network

You can create a new virtual network in the portal during this process, or use an existing virtual network to create Azure bastion service. If you are using an existing virtual network, make sure the existing virtual network has enough free address space to accommodate the Bastion subnet requirements.

### Subnet

The subnet will be dedicated to the Bastion host and must be named as `AzureBastionSubnet`. This subnet must be at least `/27` or larger. User-defined routing (UDR) is not supported on an Azure Bastion subnet. For scenarios that include both Azure Bastion and Azure Firewall/Network Virtual Appliance (NVA) in the same virtual network, you don’t need to force traffic from an Azure Bastion subnet to Azure Firewall because the communication between Azure Bastion and your VMs is private.

### Public IP address

The public IP of the Bastion resource on which RDP/SSH will be accessed (over port 443). Create a new public IP, or use an existing one. The public IP address must be in the same region as the Bastion resource you are creating. Public IP address SKU by default to `Standard` and Azure Bastion uses/supports only the Standard Public IP SKU with a static assignment.

## Requirements

Name | Version
-----|--------
terraform | >= 0.13
azurerm | ~> 2.27

## Providers

| Name | Version |
|------|---------|
azurerm | 2.27.0

## Inputs

Name | Description | Type | Default
---- | ----------- | ---- | -------
`resource_group_name` | The name of the resource group in which resources are created | string | `""`
`virtual_network_name`|The name of the virtual network|string|`""`
`public_ip_allocation_method`|Defines the allocation method for this IP address. Possible values are `Static` or `Dynamic`|static|`"Static"`
`public_ip_sku`|The SKU of the Public IP. Accepted values are `Basic` and `Standard`|string|`"Standard"`
`domain_name_label`|Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system|string|`null`
`azure_bastion_service_name`|Specifies the name of the Bastion Host|string|`""`
`azure_bastion_subnet_address_prefix`|The address prefix to use for the Azure Bastion subnet|list|`[]`
`tags`|A map of tags to add to all resources|map(string)|`{}`

## Outputs

Name | Description
---- | -----------
`azure_bastion_subnet_id`|The resource ID of Azure bastion subnet
`azure_bastion_public_ip`|The public IP of the virtual network gateway
`azure_bastion_public_ip_fqdn`|Fully qualified domain name of the virtual network gateway
`azure_bastion_host_id`|The resource ID of the Bastion Host
`azure_bastion_host_fqdn`|The FQDN of the Bastion Host

## Resource Graph

![Resource Graph](graph.png)

## Authors

Originally created by [Kumaraswamy Vithanala](mailto:kumaraswamy.vithanala@tieto.com)

## Other resources

* [Azure Bastion Service](https://docs.microsoft.com/en-us/azure/bastion/bastion-overview#next-steps)
* [Terraform AzureRM Provider Documentation](https://www.terraform.io/docs/providers/azurerm/index.html)
52 changes: 52 additions & 0 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Azure Bastion Service Terraform module

Terraform module to create fully platform-managed Azure bastion PaaS service.

## Module Usage

```hcl
module "azure-bastion" {
source = "kumarvna/azure-bastion/azurerm"
version = "1.0.0"
# Resource Group, location, VNet and Subnet details
resource_group_name = "rg-shared-westeurope-01"
virtual_network_name = "vnet-shared-hub-westeurope-001"
# Azure bastion server requireemnts
azure_bastion_service_name = "mybastion-service"
azure_bastion_subnet_address_prefix = ["10.5.0.0/26"]
# Adding TAG's to your Azure resources (Required)
tags = {
ProjectName = "demo-internal"
Env = "dev"
Owner = "user@example.com"
BusinessUnit = "CORP"
ServiceClass = "Gold"
}
}
```

## Terraform Usage

To run this example you need to execute following Terraform commands

```hcl
terraform init
terraform plan
terraform apply
```

Run `terraform destroy` when you don't need these resources.

## Outputs

Name | Description
---- | -----------
`azure_bastion_subnet_id`|The resource ID of Azure bastion subnet
`azure_bastion_public_ip`|The public IP of the virtual network gateway
`azure_bastion_public_ip_fqdn`|Fully qualified domain name of the virtual network gateway
`azure_bastion_host_id`|The resource ID of the Bastion Host
`azure_bastion_host_fqdn`|The FQDN of the Bastion Host
21 changes: 21 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module "azure-bastion" {
source = "kumarvna/azure-bastion/azurerm"
version = "1.0.0"

# Resource Group, location, VNet and Subnet details
resource_group_name = "rg-shared-westeurope-01"
virtual_network_name = "vnet-shared-hub-westeurope-001"

# Azure bastion server requireemnts
azure_bastion_service_name = "mybastion-service"
azure_bastion_subnet_address_prefix = ["10.5.0.0/26"]

# Adding TAG's to your Azure resources (Required)
tags = {
ProjectName = "demo-internal"
Env = "dev"
Owner = "user@example.com"
BusinessUnit = "CORP"
ServiceClass = "Gold"
}
}
24 changes: 24 additions & 0 deletions examples/complete/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
output "azure_bastion_subnet_id" {
description = "List of IDs of subnets"
value = module.azure-bastion.azure_bastion_subnet_id
}

output "azure_bastion_public_ip" {
description = "The public IP of the virtual network gateway"
value = module.azure-bastion.azure_bastion_public_ip
}

output "azure_bastion_public_ip_fqdn" {
description = "Fully qualified domain name of the virtual network gateway"
value = module.azure-bastion.azure_bastion_public_ip_fqdn
}

output "azure_bastion_host_id" {
description = "The resource ID of the Bastion Host"
value = module.azure-bastion.azure_bastion_host_id
}

output "azure_bastion_host_fqdn" {
description = "The fqdn of the Bastion Host"
value = module.azure-bastion.azure_bastion_host_fqdn
}
Binary file added graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#----------------------------------------------------------
# Resource Group, VNet, Subnet selection & Random Resources
#----------------------------------------------------------
data "azurerm_resource_group" "rg" {
name = var.resource_group_name
}

data "azurerm_virtual_network" "vnet" {
name = var.virtual_network_name
resource_group_name = data.azurerm_resource_group.rg.name
}

resource "random_string" "str" {
length = 6
special = false
upper = false
keepers = {
domain_name_label = var.azure_bastion_service_name
}
}

#-----------------------------------------------------------------------
# Subnets Creation for Azure Bastion Service - at least /27 or larger.
#-----------------------------------------------------------------------
resource "azurerm_subnet" "abs_snet" {
count = var.azure_bastion_subnet_address_prefix != null ? 1 : 0
name = "AzureBastionSubnet"
resource_group_name = data.azurerm_resource_group.rg.name
virtual_network_name = data.azurerm_virtual_network.vnet.name
address_prefixes = var.azure_bastion_subnet_address_prefix
}

#---------------------------------------------
# Public IP for Azure Bastion Service
#---------------------------------------------
resource "azurerm_public_ip" "pip" {
name = lower("${var.azure_bastion_service_name}-${data.azurerm_resource_group.rg.location}-pip")
location = data.azurerm_resource_group.rg.location
resource_group_name = data.azurerm_resource_group.rg.name
allocation_method = var.public_ip_allocation_method
sku = var.public_ip_sku
domain_name_label = var.domain_name_label != null ? var.domain_name_label : format("gw%s%s", lower(replace(var.azure_bastion_service_name, "/[[:^alnum:]]/", "")), random_string.str.result)
tags = merge({ "ResourceName" = lower("${var.azure_bastion_service_name}-${data.azurerm_resource_group.rg.location}-pip") }, var.tags, )
}

#---------------------------------------------
# Azure Bastion Service host
#---------------------------------------------
resource "azurerm_bastion_host" "main" {
name = var.azure_bastion_service_name
location = data.azurerm_resource_group.rg.location
resource_group_name = data.azurerm_resource_group.rg.name

ip_configuration {
name = "${var.azure_bastion_service_name}-network"
subnet_id = azurerm_subnet.abs_snet.0.id
public_ip_address_id = azurerm_public_ip.pip.id
}
}

24 changes: 24 additions & 0 deletions output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
output "azure_bastion_subnet_id" {
description = "The resource ID of Azure bastion subnet"
value = element(concat([azurerm_subnet.abs_snet.0.id], [""]), 0)
}

output "azure_bastion_public_ip" {
description = "The public IP of the virtual network gateway"
value = element(concat([azurerm_public_ip.pip.ip_address], [""]), 0)
}

output "azure_bastion_public_ip_fqdn" {
description = "Fully qualified domain name of the virtual network gateway"
value = element(concat([azurerm_public_ip.pip.fqdn], [""]), 0)
}

output "azure_bastion_host_id" {
description = "The resource ID of the Bastion Host"
value = azurerm_bastion_host.main.id
}

output "azure_bastion_host_fqdn" {
description = "The fqdn of the Bastion Host"
value = azurerm_bastion_host.main.dns_name
}
40 changes: 40 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
variable "resource_group_name" {
description = "A container that holds related resources for an Azure solution"
default = ""
}

variable "virtual_network_name" {
description = "The name of the virtual network"
default = ""
}

variable "public_ip_allocation_method" {
description = "Defines the allocation method for this IP address. Possible values are Static or Dynamic"
default = "Static"
}

variable "public_ip_sku" {
description = "The SKU of the Public IP. Accepted values are Basic and Standard. Defaults to Basic"
default = "Standard"
}

variable "domain_name_label" {
description = "Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system"
default = null
}

variable "azure_bastion_service_name" {
description = "Specifies the name of the Bastion Host"
default = ""
}

variable "azure_bastion_subnet_address_prefix" {
description = "The address prefix to use for the Azure Bastion subnet"
default = []
}

variable "tags" {
description = "A map of tags to add to all resources"
type = map(string)
default = {}
}
13 changes: 13 additions & 0 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>2.27.0"
}
}
required_version = ">= 0.13"
}

provider "azurerm" {
features {}
}

0 comments on commit 9df216c

Please sign in to comment.