Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennizz committed Sep 2, 2024
1 parent 915ef4c commit 74bbb1d
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 70 deletions.
104 changes: 36 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,9 @@
# terraform-aviatrix-module-template

This repository provides standardized instructions and conventions for creating Aviatrix modules.

#### Instructions
1. Create a new repository from this template, by clicking the green "Use this template" button. Make sure to use the [module naming convention](#module-naming-convention)
2. Clone the repository to your system with ```git clone <repository>```
5. Edit the repository and commit and update the new repository:
- Commit changes: ```git commit -am "Description of changes"```
- Push to repository: ```git push origin master```
6. Update the readme.md file
- Remove all content above [the line](#delete-everything-above-and-including-this-line).
- Fill out the rest of file based on the provided template.
7. When ready for release, create a [tag](#tagging).

#### Conventions

###### Repositories
- For each module, a new reposity shall be created. This is for the purpose of:
- Version control per module
- Issue handling/feature requests per module
- Easier consumption of the module in projects and publication in registers like Terraform Cloud

###### Module Naming convention
We will use the following convention for naming repositories:

**terraform-aviatrix-\<cloudname or mc for multi-cloud>-\<function>**

Function can be a single word, or more if required to accurately describe the module function. These should be seperated by hyphens. Example:

**terraform-aviatrix-aws-transit-firenet**

###### Resource Naming convention
```A naming convention for objects created through our modules needs to be decided upon and inserted here.```

###### Tagging
In order to use modules, it is best practice to tag versions when they are ready for consumption. The format to be used for this is "vx.x.x" e.g. v0.0.1. This can be done on Github by clicking "Create a new release". It is also possible to do this from your system. Make sure you committed your changes to the master branch. After that, create a new tag with ```git tag vx.x.x``` and push the tagged version to the tagged branch with ```git push origin vx.x.x```.

As soon as a module is ready for publishing publicly, the tag release should move up to the first major release. A tag v1.0.0 should be created and the repository can now be altered from a private to a public.

###### Module layout
The repository contains the default file layout that is recommended to use.
file | use
:---|:---
main.tf | This should contain the resources to be created
variables.tf | This should contain all expected input variables
output.tf | This should contain all output objects

Diagram images used in the readme.md should be stored on a publicly available environment. E.g. a public s3 bucket. The reason for that is, when publishing these modules at some point (e.g. Terraform Registry), the image source should always be publicly accessible, even though the repository itself might not be.


#### Delete everything above and including this line
***

# Repository Name
# terraform-aviatrix-azure-sse

### Description
\<Provide a description of the module>
This module facilitates easy integration between Aviatrix and Microsoft Azure's Security Service Edge.

As Azure's Terraform provider currently does not yet support the creation of the Security Services Edge resources, this module depends on directly calling the Azure API.

### Diagram
\<Provide a diagram of the high level constructs thet will be created by this module>
Expand All @@ -64,19 +12,30 @@ Diagram images used in the readme.md should be stored on a publicly available en
### Compatibility
Module version | Terraform version | Controller version | Terraform provider version
:--- | :--- | :--- | :---
v1.0.2 | 0.12 | 6.1 | 0.2.16
v1.0.1 | | |
v1.0.0 | | |
v0.0.1 | >= 1.0 | 7.0 | >= 3.0.0

### Usage Example
```
module "transit_aws_1" {
source = "terraform-aviatrix-modules/aws-transit/aviatrix"
version = "1.0.0"
```hcl
module "transit" {
source = "terraform-aviatrix-modules/mc-transit/aviatrix"
version = "2.5.3"
cloud = "azure"
region = "West Europe"
cidr = "10.1.0.0/23"
account = "Azure"
ha_gw = false
local_as_number = 65001
}
module "sse" {
source = "/mnt/c/Users/Dennis/repositories/Modules/terraform-aviatrix-azure-sse"
azure_tenant_id = "xxxxx"
azure_client_id = "xxxxx"
azure_client_secret = "xxxxx"
cidr = "10.1.0.0/20"
region = "eu-west-1"
aws_account_name = "AWS"
transit_gateway = module.transit.transit_gateway
}
```

Expand All @@ -85,17 +44,26 @@ The following variables are required:

key | value
:--- | :---
\<keyname> | \<description of value that should be provided in this variable>
| \<description of value that should be provided in this variable>
azure_tenant_id | Azure tenant id
azure_client_id | Azure client id
azure_client_secret | Azure client secret
transit_gateway | The Aviatrix transit gateway object

The following variables are optional:

key | default | value
:---|:---|:---
\<keyname> | \<default value> | \<description of value that should be provided in this variable>
sse_forwarding_profiles | ["m365"] | Selects the forwarding profiles.
sse_bandwidth | 250 | Sets the bandwidth per tunnel.
tunnel_subnets | ["169.254.0.0/30","169.254.0.4/30"] | Determines which tunnel addresses are used.

### Outputs
This module will return the following outputs:

key | description
:---|:---
\<keyname> | \<description of object that will be returned in this output>



70 changes: 70 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
locals {

azure_region_names = {
"East US" = "eastUS"
"East US 2" = "eastUS2"
"West US" = "westUS"
"West US 2" = "westUS2"
"West US 3" = "westUS3"
"Central US" = "centralUS"
"North Central US" = "northCentralUS"
"South Central US" = "southCentralUS"
"West Central US" = "westCentralUS"
"North Europe" = "northEurope"
"West Europe" = "westEurope"
"France Central" = "franceCentral"
"Germany West Central" = "germanyWestCentral"
"Switzerland North" = "switzerlandNorth"
"UK South" = "ukSouth"
"Canada East" = "canadaEast"
"Canada Central" = "canadaCentral"
"South Africa West" = "southAfricaWest"
"South Africa North" = "southAfricaNorth"
"UAE North" = "uaeNorth"
"Australia East" = "australiaEast"
"Central India" = "centralIndia"
"Southeast Asia" = "southEastAsia"
"Sweden Central" = "swedenCentral"
"South India" = "southIndia"
"Australia Southeast" = "australiaSouthEast"
"Korea Central" = "koreaCentral"
"Poland Central" = "polandCentral"
"Brazil South" = "brazilSouth"
"Japan East" = "japanEast"
"Japan West" = "japanWest"
"Korea South" = "koreaSouth"
"Italy North" = "italyNorth"
"France South" = "franceSouth"
"Israel Central" = "israelCentral"
"East Asia" = "eastAsia"
"Central US EUAP" = "centralUSEUAP"
"East US 2 EUAP" = "eastUS2EUAP"
"West India" = "westIndia"
"Germany North" = "germanyNorth"
"Norway East" = "norwayEast"
"Norway West" = "norwayWest"
"UAE Central" = "uaeCentral"
"Brazil Southeast" = "brazilSoutheast"
"Qatar Central" = "qatarCentral"
"China North" = "chinaNorth"
"China East" = "chinaEast"
"China North 2" = "chinaNorth2"
"China East 2" = "chinaEast2"
"Germany Central" = "germanyCentral"
"Germany Northeast" = "germanyNortheast"
"India South" = "indiaSouth"
"US DoD East" = "usDoDEast"
"US DoD Central" = "usDoDCentral"
"US Gov Virginia" = "usGovVirginia"
"US Gov Iowa" = "usGovIowa"
"US Gov Arizona" = "usGovArizona"
"US Gov Texas" = "usGovTexas"
}

profiles = [for i in var.sse_forwarding_profiles :
one([for profile in jsondecode(data.http.forwarding_profiles.response_body).value : { id = lookup(profile, "id", null) } if profile.trafficForwardingType == i])
]

bearer_token = jsondecode(data.http.azure_bearer_token.response_body).access_token
sse_endpoint_config = jsondecode(data.http.device_config.response_body)
}
109 changes: 109 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#Obtain Azure API bearer token
data "http" "azure_bearer_token" {
url = "https://login.microsoftonline.com/${var.azure_tenant_id}/oauth2/token"
method = "POST"

request_headers = {
Accept = "application/x-www-form-urlencoded"
}

request_body = format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=https://graph.microsoft.com/", var.azure_client_id, var.azure_client_secret)
}

#Fetch forwarding profiles
data "http" "forwarding_profiles" {
url = "https://graph.microsoft.com/beta/networkAccess/forwardingProfiles"
request_headers = {
Authorization = "Bearer ${local.bearer_token}"
Accept = "application/json"
}
}

#Create random PSK
resource "random_password" "psk" {
length = 16
special = true
override_special = "!#$%&*()-_=+[]{}<>:?"
}

#Create remote network
resource "restapi_object" "remote_network" {
provider = restapi
path = "/"
data = jsonencode({
name = format("Aviatrix SSE Hub - %s", var.transit_gateway.vpc_reg)
region = "centralUS" #Hardcoded for beta
# region = lookup(local.azure_region_names, var.transit_gateway.vpc_reg)
forwardingProfiles = local.profiles
devicelinks = [
{
name = "AVX-Transit"
ipAddress = var.transit_gateway.public_ip
bandwidthCapacityInMbps = format("mbps%s", var.sse_bandwidth)
deviceVendor = "other"
bgpConfiguration = {
localIpAddress = cidrhost(var.tunnel_subnets[0], 1)
peerIpAddress = cidrhost(var.tunnel_subnets[0], 2)
asn = var.transit_gateway.local_as_number
}
redundancyConfiguration = {
zoneLocalIpAddress = null
redundancyTier = "noRedundancy"
}
tunnelConfiguration = {
"@odata.type" = "#microsoft.graph.networkaccess.tunnelConfigurationIKEv2Custom"
preSharedKey = random_password.psk.result
zoneRedundancyPreSharedKey = null
saLifeTimeSeconds = 300
ipSecEncryption = "none"
ipSecIntegrity = "sha256"
ikeEncryption = "aes128"
ikeIntegrity = "sha256"
dhGroup = "dhGroup14"
pfsGroup = "pfs14"
}
}
]
})
}

data "http" "device_config" {
url = "https://graph.microsoft.com/beta/networkAccess/connectivity/remoteNetworks/${restapi_object.remote_network.id}/connectivityConfiguration"
request_headers = {
Authorization = "Bearer ${local.bearer_token}"
Accept = "application/json"
}
depends_on = [time_sleep.wait_for_sse_endpoint]
}

resource "time_sleep" "wait_for_sse_endpoint" {
depends_on = [restapi_object.remote_network]
create_duration = "90s"
}

output "test" {
value = local.profiles
}

resource "aviatrix_transit_external_device_conn" "sse_connection" {
vpc_id = var.transit_gateway.vpc_id
connection_name = format("avx-sse-%s", lower(replace(var.transit_gateway.vpc_reg, " ", "-")))
gw_name = var.transit_gateway.gw_name
remote_gateway_ip = local.sse_endpoint_config["links"][0]["localConfigurations"][0]["endpoint"]
connection_type = "bgp"
bgp_local_as_num = var.transit_gateway.local_as_number
bgp_remote_as_num = local.sse_endpoint_config["links"][0]["localConfigurations"][0]["asn"]
ha_enabled = false
local_tunnel_cidr = format("%s/30", cidrhost(var.tunnel_subnets[0], 2))
remote_tunnel_cidr = format("%s/30", cidrhost(var.tunnel_subnets[0], 1))
custom_algorithms = true
pre_shared_key = random_password.psk.result
phase_1_authentication = "SHA-256"
phase_2_authentication = "HMAC-SHA-256"
phase_1_dh_groups = "14"
phase_2_dh_groups = "14"
phase_1_encryption = "AES-128-CBC"
phase_2_encryption = "NULL-ENCR"
phase1_local_identifier = null
enable_ikev2 = true
}
14 changes: 14 additions & 0 deletions provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
provider "restapi" {
uri = "https://graph.microsoft.com/beta/networkAccess/connectivity/remoteNetworks"
write_returns_object = true
debug = true

headers = {
Authorization = "Bearer ${local.bearer_token}"
Content-Type = "application/json"
}

create_method = "POST"
update_method = "PUT"
destroy_method = "DELETE"
}
54 changes: 54 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
variable "azure_tenant_id" {
description = "Azure Tenant ID"
}

variable "azure_client_id" {
description = "Azure Client ID"
}

variable "azure_client_secret" {
description = "Azure Client Secret"
}

variable "sse_forwarding_profiles" {
description = "List of the desired forwarding profiles"
default = ["m365"]

validation {
condition = alltrue([for i in var.sse_forwarding_profiles : contains(["m365", ], i)]) #Add "internet" to the list once that is supported.
error_message = "Currently only m365 is supported."
}
}

variable "sse_bandwidth" {
description = "The desired bandwidth in Mbps."
default = 250

validation {
condition = contains([250, 500, 750, 1000], tonumber(var.sse_bandwidth))
error_message = "The sse_bandwidth variable must be one of the following values: 250, 500, 750, or 1000."
}
}

variable "tunnel_subnets" {
default = [
"169.254.0.0/30",
"169.254.0.4/30",
]
}

variable "transit_gateway" {
description = "The Aviatix transit gateway object"

#Check that transit gatway is passed as the complete object.
validation {
condition = alltrue([for key in ["id", "vpc_id", "account_name"] : contains(keys(var.transit_gateway), key)])
error_message = "It looks like you did not provide the entire Aviatrix transit gateway object."
}

#Check that transit gatway has an AS number configured.
validation {
condition = var.transit_gateway.local_as_number != ""
error_message = "The Aviatrix transit gateway must have a local_as_number configured."
}
}
Loading

0 comments on commit 74bbb1d

Please sign in to comment.