Terraform vSphere provider 1.x now supports deploying OVA files, makes using ovftool on ESXi hosts obsolete

You may currently have this pipe-line in your CI/CD process that involves running ovftool directly on your ESXi host so as to deploy an OVA appliance directly from it and with as less overhead as possible as in this tutorial on virtuallyGhetto or you could have picked up some tips about running ovftool on ESXi from this article that I wrote some time ago.

However, that is certainly not the best solution for many reasons. For example, if the input is not sanitized in some location(-s) then it becomes trivial to execute any command on the ESXi host. Thus, instead I recommend you to use a tool like Terraform to save your infrastructure as code in a Git repository, for example. With the 1.x version of the Terraform’s vSphere provider you can implement such pipe-line in Terraform as well.

It has its down-sides, though. For instance, it is impossible to explicitly express dependencies between module resources however I still think that tool is worth-while and future-proof. Even though it has its downsides, you should still move over to Terraform. I will show you how to do that.

Your pipe-line before might look something like this:

Instead, we will transform it to this:

The key idea is that instead of deploying the OVA via ovftool and specifying the properties up front, you should deploy it once without specifying anything and without turning the virtual machine on. Afterwards, convert it to a template and then you should clone that virtual machine and specify the properties. This way, after turning it on the first time, the fresh properties will be picked up. Also, because we will only deploy it once then there is no need to do it directly on the ESXi host every time. There are no time savings that we could win after the first import so let’s just ditch the idea of deploying directly from the ESXi host entirely. That’s the main change.

Deploying the OVA first time

To deploy the OVA the first time, you could use something like govc which is freely available instead of ovftool. Before downloading ovftool you are forced to accept certain terms and conditions, and create an VMware account which can become a nuisance so I recommend you to use other tools.

You could invoke govc like this:

GOVC_URL=user:pass@host govc import.ova -ds=datastore -folder=somefolder -host=host -name=template_from_ovf ./vmware-vcsa.ova

The -option parameter is not really useful in our case because we want to not specify any properties on purpose. Other parameter that you may find useful is -pool which specifies the resource pool to which the new virtual machine will be deployed to.

After deploying the OVA, convert it to a template as such:

GOVC_URL=user:pass@host govc vm.markastemplate template_from_ovf

Now it is ready for usage by the Terraform part of our pipe-line.

Terraform: provisioning the VMs

Since the 1.0.0 version of the vSphere Terraform provider, it supports specifying the vApp (OVA) properties. We will leverage this feature to specify them after cloning a new virtual machine from that template.  I’m not going to go over how to use Terraform in this article but I will provide an example of an resource vsphere_virtual_machine. It will do just what we need for this part of the pipe-line.

In main.tf (or whatever other file that ends in .tf. You could use different .tf files for different virtual machines) you need to have something more or less this:

data "vsphere_datacenter" "dc" {
  name = "dc1"
}

data "vsphere_datastore" "datastore" {
  name          = "datastore1"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_resource_pool" "pool" {
  name          = "cluster1/Resources"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
  name          = "public"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "tempate_from_ovf" {
  name          = "template_from_ovf"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

resource "vsphere_virtual_machine" "vm" {
  name             = "terraform-test"
  resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"

  num_cpus = 2
  memory   = 1024
  guest_id = "${data.vsphere_virtual_machine.template.guest_id}"

  scsi_type = "${data.vsphere_virtual_machine.template.scsi_type}"

  network_interface {
    network_id   = "${data.vsphere_network.network.id}"
    adapter_type = "${data.vsphere_virtual_machine.template.network_interface_types[0]}"
  }

  disk {
    name             = "disk0"
    size             = "${data.vsphere_virtual_machine.template.disks.0.size}"
    eagerly_scrub    = "${data.vsphere_virtual_machine.template.disks.0.eagerly_scrub}"
    thin_provisioned = "${data.vsphere_virtual_machine.template.disks.0.thin_provisioned}"
  }

  clone {
    template_uuid = "${data.vsphere_virtual_machine.template_from_ovf.id}"
  }

  vapp {
    properties {
      "guestinfo.hostname"                        = "terraform-test.foobar.local"
      "guestinfo.interface.0.name"                = "ens192"
      "guestinfo.interface.0.ip.0.address"        = "10.0.0.100/24"
      "guestinfo.interface.0.route.0.gateway"     = "10.0.0.1"
      "guestinfo.interface.0.route.0.destination" = "0.0.0.0/0"
      "guestinfo.dns.server.0"                    = "10.0.0.10"
    }
  }
}

(Copied verbatim from here. You can find much more information there)

I will go over each section:

  • At first information is gathered from various data sources: vsphere_datacenter, vsphere_datastore, and so on.
  • After that, a new resource vsphere_virtual_machine is created with name “vm”. The VM itself will have the name “terraform-test”. Some other options are specified that you can find in the example. Everything looks like the same except for the vapp section. In there, you should specify the OVA properties. You could list all of them by using this command:
ovftool /the/file.ova

Also, the vSphere client can help you out with this if you will go to the File > Deploy OVF Template. Another option is to check out the manifest file inside of the OVA file. Just open it with 7zip or some other program which can read archive files.

  • Gather the properties via your chosen method and specify them in the vapp section.

To understand what other options mean you should consult the vsphere provider documentation in terraform. I will not copy and paste it here for brevity.

Afterwards, run terraform apply with your custom options (if applicable) and watch how terraform will pick up everything and show you the details of the actions that will be performed if you will enter yes. So, finally, just enter yes and watch how the virtual machine will be created.

Conclusion

This concludes this tutorial. Now in case you need to create more virtual machines from the same template, duplicate the vsphere_virtual_machine resource declaration and others (if needed). Run terraform apply again and it will create the other virtual machines. You might want to provide -auto-approve to terraform apply in your CD pipe-line – that way you will not have to enter yes all the time. Check out the other options here.

By using this method, your deployment pipe-line just became less intrusive, faster, and more flexible because  you can actually specify the configuration of the resulting VM whereas with the old method you were forced to be stuck with the VM configuration specified in the OVA file unless you had some post-provisioning scripts in place. Have fun!

The State of Internet censorship in Lithuania (Beginning of 2018 Edition)

Unfortunately but the specter of Internet censorship has finally came to Lithuania a few years ago. It was rampant already in some European countries but I never thought that it would come to Lithuania as well. I thought that this country was different… nope, it started to slowly transform and become like others in terms of Internet censorship as well.

History

As far as I can tell everything was fine up until around 2008, 2009. It all began when on 2010 July 8th a court in Lithuania, Vilnius satisfied a lawsuit by which foreign gambling companies such as “bet365 Ltd.” and “Unibet International Ltd.” were blocked from doing their business in Lithuania. Accordingly, their websites must be blocked, the court said. The decision was appealed and the court case dragged further into the future.

Around 2011, LANVA (the Lithuanian anti-pirate association) sent a request to the IVPK (the committee of expansion of the information society) to block Linkomanija (as far as I know, it’s the biggest private torrent tracker in Lithuania). One of the responsibilities of that committee is to propose new laws to the parliament which are related to the Internet, author rights, and so on.  After a meeting, they decided not to go further with the request from LANVA however they said that they were available for more discussions about this topic in the future.

In 2012, global events affected Lithuania as well. During that year, the whole notorious ACTA crisis unfolded. Because people all over the world generated a lot of discussion around this topic, even the Lithuanian news media gave attention to it. What is more, local protests were organized where people were rallying for Lithuania to not sign the controversial act. As far as I know, it was never signed. After that, everyone quickly forgot about it. Thus, there were no changes with regards to Internet censorship in Lithuania.

In 2013, amendments to the law with regards to gambling were being considered. Numerous events were organised around discussions if Lithuania is going towards the censorship of the Internet. However, no decision was yet made because of a certain case that had been on-going in the European Court of Human Rights. It all culminated the following year.

In 2014, the European Court of Human Rights decided that EU countries can indeed block access to webpages which violated the rights of authors (the term “rights” has a very vague definition, obviously). That means that from that moment various institutions can go to courts to get certain websites blocked in their own country in the European Union. After this, the court decision to block various gambling companies went ahead in terms of blocking their pages online as well.

After some time, during 2015 some changes to the law were finally approved to implement a framework with which websites could be blocked. At that time it was clearly legal to do that in the European Union, and on 2016 January 11, betway.com became the first officially censored webpage in the Republic of Lithuania.

Implementation

The current censorship is implemented by modifying DNS records at the ISP level. The blocked websites’ A records are modified so that they would redirect to https://blokuojama.lpt.lt/. In there, the user is informed that the website that they tried to visit is “blocked” and it links to the court cases due to which those websites were “blocked”.

We could see how blocking works by using drill to send a few requests to DNS servers. First one up is my ISP’s one. Let’s see what response it gives:

giedrius@tyrael:~/ > drill betway.com @192.168.1.254
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 6156
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; betway.com.  IN      A

;; ANSWER SECTION:
betway.com.     10760   IN      A       194.135.95.243

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 2 msec
;; SERVER: 192.168.1.254
;; WHEN: Fri Mar 23 20:28:37 2018
;; MSG SIZE  rcvd: 44

As you can see, betway.com (the first website that was ever blocked in Lithuania) is apparently at 192.135.95.243.

To see if it is really there, let’s check the A records of the same domain at 8.8.8.8, Google’s relatively popular DNS server:

giedrius@tyrael:~/ > drill betway.com @8.8.8.8      
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 53085
;; flags: qr rd ra ; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; betway.com.  IN      A

;; ANSWER SECTION:
betway.com.     59      IN      A       45.60.87.104
betway.com.     59      IN      A       45.60.114.104

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 90 msec
;; SERVER: 8.8.8.8
;; WHEN: Fri Mar 23 20:30:51 2018
;; MSG SIZE  rcvd: 60

As you can see, the real results and the censored results differ. Indeed, if you would go to 192.135.95.243, it would redirect you to blokuojama.lpt.lt which is the title page for all censored websites.

Some people were talking that this is not enough and now they are pushing new laws which would make ISPs implement deep packet inspection. The ISPs themselves, on the other hand, argue about the effectiveness of that and who is going to give them money to buy expensive equipment which would let them to perform these functions. Plus, obviously, they are presenting many more valid arguments against Internet censorship. For example, many of them argue that they just provide an utility to customers and they don’t want to become the second police who would decide what content is “good” and what content is “bad”. This point of view of ISPs is briefly presented here at the end of the article.

Statistics

All of the data – relevant cases and URLs – about blocked websites is presented here. If we were to put all of that into a diagram (different domains count as different sites) we would get this:

As you can see, the number of blocked sites has been increasing a bit faster than linearly. If the current trend continues, around 500 sites will be blocked by the beginning of 2020. Hopefully, this will not be true. I guess that I will have to revisit this assertion again in two years.

How to circumvent this?

In general, you will have to change your settings so that your computer would use a different DNS server. There are plenty of options to choose from. The popular choices are 8.8.8.8 and 8.8.4.4 (Google DNS servers) however if you have any privacy concers with them then you can choose some other ones from, for example, here or here. Obviously, you should not choose a DNS server that is censored as well. So choose wisely.

Once you have done that, continue to the next two sub-sections depending on what you prefer. They do not cover all of the routers and operating systems but they give you a general gist of where to look for more information and give an example of how it looks like.

Router level

In general I would recommend you to search for something like “router model + admin panel” or “router model + DNS settings” and you should most certainly find something. I will present how to change the DNS settings on a router that is provided by the most popular ISP in Lithuania, Telia.

  1. Go to the admin panel which is usually at the same IP as the gateway. In my case, it is http://192.168.1.254. The default username and password is admin/admin. Enter your own username and password if you changed them. You will get into this:
  2. Go to Settings > Network Connections > WAN DSL > IPv4 (tab). There you can find a checkbox “Setup Static DNS Servers”. Click on “Yes”.  Then you should be able to input your preferred and an alternative DNS server. You should see something like this:
  3. After setting your DNS servers, click on “Apply”. You might have to restart your router to really apply the settings. Enjoy!

Operating system level

It seems that Windows 10 is still the most popular operating system on desktop computers so I will provide a way to change your DNS settings on it.

  1. First go to Control Panel > Network and Sharing Center:
  2. Click on Change adapter settings” and then click on “Properties” on the connection that you use to connect to the Internet:
  3. Go down to “Internet Protocol Version 4 (TCP/IPv4)” and click on “Properties”.  Inside there you can change the DNS settings. Choose “Use the following DNS server addresses” and enter the IP adresses of your choice:
  4. Once you are done click on “OK”. Et voilà!