Automate OpenStack Security Group with Terraform

Heat is the main project in the OpenStack Orchestration program. We can use heat to automate security group implementation. If you have NSXv plugin integrated with your OpenStack environment, you can use Heat template to automate your NSX DFW rules implementation as well. Here I will show you how to use Terraform to do the same magic: automate security group  deployment.

Below is my Terraform template of creating a security group and 5 rules within the newly created security group.

provider “openstack” {
user_name = “${var.openstack_user_name}”
password = “${var.openstack_password}”
tenant_name = “tenant1”
auth_url = “http://keystone.ops.com.au:5000/v3”
domain_name = “domain1”
}
resource “openstack_networking_secgroup_v2” “secgroup_2” {
name = “secgroup_2”
description = “Terraform security group”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
}
resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_1” {
direction = “egress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 22
port_range_max = 22
remote_ip_prefix = “10.41.129.12/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_2.id}”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
depends_on = [“openstack_networking_secgroup_v2.secgroup_2”]

}

resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_2” {
direction = “ingress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 443
port_range_max = 443
remote_ip_prefix = “10.41.129.12/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_2.id}”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
depends_on = [
“openstack_networking_secgroup_v2.secgroup_2”,
“openstack_networking_secgroup_rule_v2.secgroup_rule_1”
]
}

resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_3” {
direction = “ingress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 443
port_range_max = 443
remote_ip_prefix = “10.41.129.11/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_2.id}”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
depends_on = [
“openstack_networking_secgroup_v2.secgroup_2”,
“openstack_networking_secgroup_rule_v2.secgroup_rule_2”
]
}

resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_4” {
direction = “ingress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 8080
port_range_max = 8080
remote_ip_prefix = “10.41.129.11/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_2.id}”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
depends_on = [
“openstack_networking_secgroup_v2.secgroup_2”,
“openstack_networking_secgroup_rule_v2.secgroup_rule_3”
]
}

resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_5” {
direction = “ingress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 22
port_range_max = 22
remote_ip_prefix = “10.41.129.11/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_2.id}”
tenant_id =”2b8d09cb778346a4ae70c16ee65a5c69″
depends_on = [
“openstack_networking_secgroup_v2.secgroup_2”,
“openstack_networking_secgroup_rule_v2.secgroup_rule_4”
]
}

Please make sure that you added the resource dependency for each firewall rule via”depends_on”.

If not, you will see erros like the below when you try to “terraform apply”. You will be able only to  add 1 rule when you run “terraform apply” once.

2017/03/06 19:47:46 [TRACE] Preserving existing state lineage “607d13a8-c268-498a-bbb4-07f98f0dd6b4”
Error applying plan:

1 error(s) occurred:

2017/03/06 19:47:46 [DEBUG] plugin: waiting for all plugin processes to complete…
* openstack_networking_secgroup_rule_v2.secgroup2_rule_2: Internal Server Error

Terraform does not automatically rollback in the face of errors.

The above issue is known Issue (Issue ID 7519) with Terraform. (Refer the link: https://github.com/hashicorp/terraform/issues/7519).

Unfortunately, the issue is still in version 0.8.7. The current solution is adding specify explicit dependencies when creating firewall rules.

OpenStack CLI to create a VM

To create a VM in OpenStack, you can use a Nova CLI as the below:

nova boot –flavor SMALL4_2CPU_4GBRAM_80GBDISK –image rhel7 –nic net-id=eafea72a-c26e-4f73-826c-552da03cf532  myRHEL–availability-zone avz01

Except the name of the virtual machine, you need to find out all other requested parameters (flavor, image, net-id and availability-zone) so that you can use  “nova boot”. Please refer the CLI below to get what you need:

  • Get the flavor

nova flavor-list

  • Get the image

glance image-list

  • Get the net-id

neutron net-list

  • Get the availability zone

openstack availability zone list

Automate OpenStack with Terraform

Terraform can be used with Openstack for auto-provisioing.

Today, I will shows a working Terraform example in Openstack.

Firstly, define a Openstack provider for Terraform.

Provider:

provider “openstack” {
user_name = “${var.openstack_user_name}”
password = “${var.openstack_password}”
tenant_name = “project1”
auth_url = “http://keystone.openstack.com.au:5000/v3
domain_name = “DOMAINNAME”
}

Terraform currently support the following Openstack resource type: Compute, Network, Load Balancer, Firewall, Block Storage and Object Storage.

Here, we create a few of basic resources including Compute and Network (network (VXLAN here, but can be VLAN or any other kind of networks), subnet and security group)

Network:

Create a network named “tf-net2

resource “openstack_networking_network_v2” “tf-net2” {
region = “region1”
name = “tf-net2”
admin_state_up = “true”
}

create a subnet “tf_net_sub2” and associate with network tf-net2

resource “openstack_networking_subnet_v2” “tf_net_sub2” {
name = “tf_net_sub2”
region = “region1”
network_id = “${openstack_networking_network_v2.tf-net2.id}”
cidr = “172.16.50.0/24”
ip_version = 4
enable_dhcp = “false”
}

Security Group:

create a security group “secgroup_1” , then add 2 rules

resource “openstack_networking_secgroup_v2” “secgroup_1” {
name = “secgroup_1”
description = “Terraform security group”
}
resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_1” {
direction = “egress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 22
port_range_max = 22
remote_ip_prefix = “10.41.129.12/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_1.id}”
}

resource “openstack_networking_secgroup_rule_v2” “secgroup_rule_2” {
direction = “ingress”
ethertype = “IPv4”
protocol = “tcp”
port_range_min = 22
port_range_max = 22
remote_ip_prefix = “10.41.129.12/32”
security_group_id = “${openstack_networking_secgroup_v2.secgroup_1.id}”
}

Compute:

create 1 virtual instance using network tf-net2 and security group secgroup_1 which just created.

resource “openstack_compute_instance_v2” “vm_terraform” {

region = “region1”
availability_zone = “az1”
name = “nsx_terraform”
image_id = “b5d00e5c-ab30-4fb4-9ed0-1d99c7ff864b”
flavor_id = “10”
security_groups = [“${openstack_networking_secgroup_v2.secgroup_1.id}”]

metadata {
this = “that”
}

network {
name = “tf-net2”
}
stop_before_destroy = “true”
}

Result:

Openstack Network:

openstack-network

Security Group:

securitygroup

VM:

vm

Heat stack operation CLI

  • List all heat stacks in one Openstack project

heat stack-list

  • create a new heat stacks

heat stack-create stackname -f template.yml

  • update a existing heat stacks

heat stack-update stackname -f template.yml

  • update a existing heat stacks

heat stack-delete stackname

  • check stack create/update/delete progress

heat event-list stackname

  • display stack information

heat stack-show stackname

  • display resource information for a stack

heat resource-list stackname

  • display all VM in all tenants/projects

nova list –all-tenants

How to quickly find which project one VM belongs to

In multi-tenants OpenStack environment, you possibly need to quickly find which project one VM belongs to.

From CLI, I just found out a quick way.

Step 1:

[root@openstack RC]# nova list –all-tenants | grep 10.42.130.174
| 1c1c1051-2b28-47a6-9019-9ac2e3670587 | lnxau2004-001 | bc1dff54cfc841dfb8cc5b56e75d10e9 | ACTIVE | – | Running | sls1-dev-isd-waz001=10.42.130.174

From the output of Step 1, we can the project ID bc1dff54cfc841dfb8cc5b56e75d10e9

Step 2:

[root@openstack RC]# openstack project show bc1dff54cfc841dfb8cc5b56e75d10e9

…..

| id | bc1dff54cfc841dfb8cc5b56e75d10e9 |
| name | TST1 |

OpenStack Neutron CLI for NSXv

  • Create a new shared network

neutron net-create network1 –name network1 –shared

  • Create a new exclusive network

neutron net-create network1 –name network1

  • Create a VLAN network

neutron net-create net-vlan –provider:segmentation_id VLAN-ID –provider:network_type vlan –provider:physical_network DVS-Switch-ID

  • Create a subnet

neutron subnet-create network1 172.16.31.0/24 –name subnet01 –allocation-pool start=172.16.31.2,end=172.16.31.254 –disable-dhcp –gateway 172.16.31.1

  • Create a DLR

neutron router-create dlr01 –distributed True

  • Create a Edge

neutron router-create –distributed false edg01 –router-type exclusive

  • Add interface to DLR or Edge

neutron router-interface-add dlr01 subnet01

  • Update the routing for Edge or DLR

neutron router-update edg01 –routes type=dict list=true destination=0.0.0.0/0,nexthop=172.16.32.1 destination=10.0.0.0/8,nexthop=10.1.1.1