Can I assign a firewall while creating a droplet via API?

March 21, 2018 489 views
API DigitalOcean Cloud Firewalls CentOS

I would like to provision droplets for my clients via the API and everything works great except I don't see anything in the documentation for assigning a cloud firewall while creating a droplet.

Is there any way to automatically do this at the same time? An example of the code I am currently using:


// Setup droplet details
$data = array(
"name" => "$hostname",
"region" => "$location",
"size" => "s-1vcpu-1gb",
"monitoring" => "true",
"image" => "centos-7-x64",
"user_data" => "$user_data",
);

# Convert droplet details into JSON
$data_string = json_encode($data);

// Setup actually sending to API
$ch = curl_init('https://api.digitalocean.com/v2/droplets');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "Authorization: Bearer $TOKEN",
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string))
);

$result = curl_exec($ch);

// Actually send to API and show result
print_r($result);

}    
?>

6 Answers

I would suggest taking a look at something like terraform to do your droplet provisioning.

resource "digitalocean_droplet" "web" {
  name      = "web-1"
  size      = "512mb"
  image     = "centos-7-x64"
  region    = "nyc3"
}

resource "digitalocean_firewall" "web" {
  name = "only-22-80-and-443"

  droplet_ids = ["${digitalocean_droplet.web.id}"]

  inbound_rule = [
    {
      protocol           = "tcp"
      port_range         = "22"
      source_addresses   = ["192.168.1.0/24", "2002:1:2::/48"]
    },
    {
      protocol           = "tcp"
      port_range         = "80"
      source_addresses   = ["0.0.0.0/0", "::/0"]
    },
    {
      protocol           = "tcp"
      port_range         = "443"
      source_addresses   = ["0.0.0.0/0", "::/0"]
    },
  ]

  outbound_rule = [
    {
      protocol                = "tcp"
      port_range              = "53"
      destination_addresses   = ["0.0.0.0/0", "::/0"]
    },
    {
      protocol                = "udp"
      port_range              = "53"
      destination_addresses   = ["0.0.0.0/0", "::/0"]
    },
  ]
}

https://www.terraform.io/docs/providers/do/index.html

What I am hoping to be able to do is something similar to this:

// Setup droplet details
$data = array(
"name" => "$hostname",
"region" => "$location",
"size" => "s-1vcpu-1gb",
"monitoring" => "true",
"image" => "centos-7-x64",
"user_data" => "$user_data",
"firewall_id" => "firewall-ID-here",
);

I honestly really want to do this from my main droplet to make things easier, the way I have it setup everything is automated to create droplets, set the droplets up, alert the clients, etc.

My alternative to automatically assigning the firewall is basically something like this as a daily cron job (work in progress) if Digital Ocean doesn't support assigning a firewall during droplet creation..

Although I will be working on the logic to prevent unnecessary API calls and I do see a logic flaw in the code as it stands right now.

#!/bin/bash
TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
FIREWALLID='xxxxxxxxxxxxxxxxxxxxxx';
# ITERATE THROUGH ALL DROPLETS 1 AT A TIME FOR EASIER PARSING
for i in {1..1000}; do
    if ! (curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer 00567194053b404e749f72a3f409d7af595e34517436ae303f411cfa1f1cdeeb" "https://api.digitalocean.com/v2/droplets?page=$i&per_page=1" | grep -qviE "droplets|to|exclude"); then
        DROPLETID=$(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer 00567194053b404e749f72a3f409d7af595e34517436ae303f411cfa1f1cdeeb" "https://api.digitalocean.com/v2/droplets?page=1&per_page=1" | awk -F"," '{print $1}' | awk -F'"id":' '{print $2}');
        echo "$DROPLETID" > /tmp/lastdroplet.txt;


            if ( "$(cat /tmp/lastdroplet.txt)" != "$DROPLETID" ); then
                if !(grep -q $DROPLETID /root/firewalled-droplets.txt); then
                    curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"droplet_ids":['"$DROPLETID"']}' "https://api.digitalocean.com/v2/firewalls/$FIREWALLID/droplets";
                    echo $DROPLETID >> /root/firewalled-droplets.txt;
                fi;
            else
                echo "All droplets have been added to firewall, exiting.";
                exit 0;
            fi;



    fi;
done;

My end goal is enter in an email address and a location when I get an order, the automation/API will handle everything else.

One of possible solutions is to use tags. You can create a firewall and assign it a tag, and then use that tag on Droplet creation.
That way, all rules defined in the firewall will be applied to all Droplets with the assigned tag.

I don't see anyway to add a tag to firewalls in the web interface, is this maybe something that can only be done by API?

Have another answer? Share your knowledge.