From cb8fc25fc8e7e211f58fa932caced75a9e060567 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 10 Dec 2020 22:51:35 +0100 Subject: [PATCH] Configure a zerotier-one network controller --- clients/zerotier-1.json | 4 + nodes/zerotier-1.json | 56 ++++ site-cookbooks/kosmos_zerotier/README.md | 3 +- .../kosmos_zerotier/files/zerotier-ctl.sh | 306 ++++++++++++++++++ .../kosmos_zerotier/recipes/controller.rb | 9 + .../kosmos_zerotier/recipes/default.rb | 21 -- .../kosmos_zerotier/recipes/firewall.rb | 23 +- 7 files changed, 377 insertions(+), 45 deletions(-) create mode 100644 clients/zerotier-1.json create mode 100644 nodes/zerotier-1.json create mode 100644 site-cookbooks/kosmos_zerotier/files/zerotier-ctl.sh create mode 100644 site-cookbooks/kosmos_zerotier/recipes/controller.rb diff --git a/clients/zerotier-1.json b/clients/zerotier-1.json new file mode 100644 index 0000000..f493753 --- /dev/null +++ b/clients/zerotier-1.json @@ -0,0 +1,4 @@ +{ + "name": "zerotier-1", + "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx59liuiEXuAykaiQhjvO\nMimzWH2MOE/GdfPdlGG0IupDtGbDgpsu6lHB/Tc8ct+SEsj55KuamEmUew3EzWRQ\ngVWAPjWtlk6gqVlpU+8eJjTAxT1vaEOvetzliPDNzRBk1AAzS0IkMQwPAIqOD2Vm\nz+QDrTiEFNnbKyBDQ54uY9jBtEgTHgzZyc9KHTjcodJu/oCmOuO0ieTtMS4CDWVl\no2auyABpXX6PzW3hFvH/GB0IlVC5IBa7XS6JrbIFbZCvoAYf/egcQUTToNiKH45e\n2tPZbFpOt955zwInKTioW+Ak3qVVEPvCZ9IBTN7jZkSQuP4Ob5SA4+IbDJcXGulG\nZQIDAQAB\n-----END PUBLIC KEY-----\n" +} \ No newline at end of file diff --git a/nodes/zerotier-1.json b/nodes/zerotier-1.json new file mode 100644 index 0000000..685171d --- /dev/null +++ b/nodes/zerotier-1.json @@ -0,0 +1,56 @@ +{ + "name": "zerotier-1", + "normal": { + "knife_zero": { + "host": "10.147.20.147" + } + }, + "automatic": { + "fqdn": "zerotier-1", + "os": "linux", + "os_version": "5.4.0-1028-kvm", + "hostname": "zerotier-1", + "ipaddress": "192.168.122.72", + "roles": [ + + ], + "recipes": [ + "kosmos-base", + "kosmos-base::default", + "kosmos_zerotier::controller", + "kosmos_zerotier::firewall", + "apt::default", + "timezone_iii::default", + "timezone_iii::debian", + "ntp::default", + "ntp::apparmor", + "kosmos-base::systemd_emails", + "apt::unattended-upgrades", + "kosmos-base::firewall", + "kosmos-postfix::default", + "postfix::default", + "postfix::_common", + "postfix::_attributes", + "postfix::sasl_auth", + "hostname::default" + ], + "platform": "ubuntu", + "platform_version": "20.04", + "cloud": null, + "chef_packages": { + "chef": { + "version": "15.14.0", + "chef_root": "/opt/chef/embedded/lib/ruby/gems/2.6.0/gems/chef-15.14.0/lib" + }, + "ohai": { + "version": "15.12.0", + "ohai_root": "/opt/chef/embedded/lib/ruby/gems/2.6.0/gems/ohai-15.12.0/lib/ohai" + } + } + }, + "run_list": [ + "recipe[kosmos-base]", + "recipe[kosmos_zerotier::controller]", + "recipe[kosmos_zerotier::firewall]" + ] +} \ No newline at end of file diff --git a/site-cookbooks/kosmos_zerotier/README.md b/site-cookbooks/kosmos_zerotier/README.md index 8645fb0..9ff88d7 100644 --- a/site-cookbooks/kosmos_zerotier/README.md +++ b/site-cookbooks/kosmos_zerotier/README.md @@ -1,4 +1,3 @@ # kosmos_zerotier -TODO: Enter the cookbook description here. - +Configures zerotier controllers and firewall rules. diff --git a/site-cookbooks/kosmos_zerotier/files/zerotier-ctl.sh b/site-cookbooks/kosmos_zerotier/files/zerotier-ctl.sh new file mode 100644 index 0000000..f95865c --- /dev/null +++ b/site-cookbooks/kosmos_zerotier/files/zerotier-ctl.sh @@ -0,0 +1,306 @@ +#!/bin/bash + +# +# team: devops/zerotier-ctl +# status: laboratory +# author: Makersphere Labs +# +VERSION=1.1.14 +# +# +# +ZT_AUTHFILE='/var/lib/zerotier-one/authtoken.secret' +ZT_PUBLICID='/var/lib/zerotier-one/identity.public' +ZT_NETWORK_PRIVATE=1 +ZT_NETWORK_BRIDGING=0 +ZT_NETWORK_V4_ASSIGN_MODE='zt' +ZT_NETWORK_V6_ASSIGN_MODE='none' +# +# Colors +# +RED='\033[0;31m' +ORANGE='\033[0;33m' +GREEN='\033[0;32m' +NC='\033[0m' +# +# Main Application +# +if [ "$1" != '' ]; then + # + # List all networks on this controller + # + if [ "$1" == 'listnetworks' ] || [ "$1" == 'list' ] || [ "$1" == '-l' ]; then + echo + echo -e "${ORANGE}=> List Networks${NC}"; + echo + # Check if authtoken.secret exists + if [ -f $ZT_AUTHFILE ]; then + echo -e "${ORANGE}> Loading networks...${NC}"; + echo + ZT_AUTHTOKEN=`cat $ZT_AUTHFILE` + # Make a GET request to the API + # Tested with ZeroTier One (1.1.4) API v1. + ZT_API_RESPONSE=$(curl -LsfSw '\n%{http_code}' \ + -X GET http://localhost:9993/controller/network?auth=${ZT_AUTHTOKEN}) + if [ "$(echo "$ZT_API_RESPONSE" | tail -n1 )" == '200' ]; then + echo -e "> $(echo "$ZT_API_RESPONSE" | head -n-1 )"; + echo + echo -e "${GREEN}==> Success${NC}"; + echo + exit 0; + else + echo -e "${RED}==> Failed to connect to Controller${NC}"; + exit 1; + fi + else + echo -e "${RED}==> The AuthFile is missing${NC}"; + exit 1; + fi + # + # Add a new network to this controller + # + elif [ "$1" == 'create' ] || [ "$1" == '-c' ]; then + echo + echo -e "${ORANGE}=> Create Network${NC}"; + echo + if [ "$2" != '' ]; then + # Check if authtoken.secret exists + if [ -f $ZT_AUTHFILE ]; then + ZT_NETWORK_NAME=$2 + ZT_NETWORK_SERVER_ID=`head -c 10 $ZT_PUBLICID`; + ZT_AUTHTOKEN=`cat $ZT_AUTHFILE` + echo "> Add a configuration for network '${2}'..." + read -p '> Enter a start IP address (e.g. 10.1.1.1): ' READ_IP + if [ "$READ_IP" != '' ]; then + ZT_NETWORK_IP_START=$READ_IP + read -p '> Enter the last IP address (e.g. 10.1.1.254): ' READ_IP2 + if [ "$READ_IP2" != '' ]; then + ZT_NETWORK_IP_END=$READ_IP2 + read -p '> Enter the network address (e.g. 10.1.1.0): ' READ_ROUTE + if [ "$READ_ROUTE" != '' ]; then + ZT_NETWORK_IP_LOCAL_ROUTE=$READ_ROUTE + read -p '> Enter the network submask (e.g. /24): /' READ_MASK + if [ "$READ_MASK" != '' ]; then + ZT_NETWORK_IP_LOCAL_ROUTE_MASK=$READ_MASK + else + echo -e "${RED}==> Please enter a vaild submask${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please enter a network address${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please enter the last IP address${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please enter a start IP address${NC}"; + exit 1; + fi + # Huge JSON file ahead + # Do not change this JSON string! + ZT_NETWORK_CONFIG="{\"auth\":\"${ZT_AUTHTOKEN}\",\"name\":\"${ZT_NETWORK_NAME}\",\"private\":${ZT_NETWORK_PRIVATE},\"allowPassiveBridging\":${ZT_NETWORK_BRIDGING},\"v4AssignMode\":\"${ZT_NETWORK_V4_ASSIGN_MODE}\",\"v6AssignMode\":\"${ZT_NETWORK_V6_ASSIGN_MODE}\",\"routes\":[{\"target\":\"${ZT_NETWORK_IP_LOCAL_ROUTE}/${ZT_NETWORK_IP_LOCAL_ROUTE_MASK}\",\"via\":null,\"flags\":0,\"metric\":0}],\"ipAssignmentPools\":[{\"ipRangeStart\":\"${ZT_NETWORK_IP_START}\",\"ipRangeEnd\":\"${ZT_NETWORK_IP_END}\"}],\"rules\":[{\"ruleNo\":10,\"action\":\"accept\"}]}" + echo '> Do you wish to add this network?' + select ZT_ADD_NET_YN in 'Yes' 'No'; do + case $ZT_ADD_NET_YN in + 'Yes' ) + # Make a POST request to the API + # Tested with ZeroTier One (1.1.4) API v1. + ZT_API_RESPONSE=$(curl -LsfSw '\n%{http_code}' \ + -X POST -d "$ZT_NETWORK_CONFIG" \ + http://localhost:9993/controller/network/${ZT_NETWORK_SERVER_ID}______?auth=${ZT_AUTHTOKEN}) + if [ "$(echo "$ZT_API_RESPONSE" | tail -n1 )" == '200' ]; then + ZT_NETWORK_NWID=$(echo "$(echo "$ZT_API_RESPONSE" | head -n-1 )" | grep -Po '(?<="nwid": ")[^"]*') + echo -e "${GREEN}==> Network '${ZT_NETWORK_NAME}' (ID ${ZT_NETWORK_NWID}) was successfully added to controller '${ZT_NETWORK_SERVER_ID}'${NC}"; + echo + exit 0; + else + echo -e "${RED}==> Failed to connect to Controller${NC}"; + exit 1; + fi + #DEBUG: echo $ZT_NETWORK_CONFIG + break;; + 'No' ) + echo -e "${ORANGE}==> Nothing was added${NC}"; + echo + exit 0; + exit;; + esac + done + else + echo -e "${RED}==> The AuthFile is missing${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please specify a network${NC}"; + exit 1; + fi + # + # Remove a new network from this controller + # + elif [ "$1" == 'delete' ] || [ "$1" == '-d' ]; then + echo + echo -e "${ORANGE}=> Delete Network${NC}"; + echo + if [ "$2" != '' ]; then + # Check if authtoken.secret exists + if [ -f $ZT_AUTHFILE ]; then + ZT_NETWORK_ID=$2 + ZT_AUTHTOKEN=`cat $ZT_AUTHFILE` + echo '> Do you wish to remove this network?' + select ZT_DEL_NET_YN in 'Yes' 'No'; do + case $ZT_DEL_NET_YN in + 'Yes' ) + # Make a DELETE request to the API + # Tested with ZeroTier One (1.1.4) API v1. + ZT_API_RESPONSE=$(curl -LsfSw '\n%{http_code}' \ + -X DELETE http://localhost:9993/controller/network/${ZT_NETWORK_ID}?auth=${ZT_AUTHTOKEN}) + if [ "$(echo "$ZT_API_RESPONSE" | tail -n1 )" == '200' ]; then + echo -e "${GREEN}==> Network '${ZT_NETWORK_ID}' was removed${NC}"; + echo + exit 0; + else + echo -e "${RED}==> Failed to connect to Controller${NC}"; + exit 1; + fi + break;; + 'No' ) + echo -e "${ORANGE}==> Nothing was removed${NC}"; + echo + exit 0; + exit;; + esac + done + + else + echo -e "${RED}==> The AuthFile is missing${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please specify a network${NC}"; + exit 1; + fi + # + # Authorize a new client to a network + # + elif [ "$1" == 'auth' ] || [ "$1" == '-a' ]; then + echo + echo -e "${ORANGE}=> Authorize Client${NC}"; + echo + if [ "$2" != '' ] && [ "$3" != '' ]; then + # Check if authtoken.secret exists + if [ -f $ZT_AUTHFILE ]; then + ZT_NETWORK=$2 + ZT_MEMBER=$3 + ZT_AUTHTOKEN=`cat $ZT_AUTHFILE` + echo "> Do you wish to authorize this client (${ZT_MEMBER})?" + select ZT_ADD_MEM_YN in 'Yes' 'No'; do + case $ZT_ADD_MEM_YN in + 'Yes' ) + # Make a POST request to the API + # Tested with ZeroTier One (1.1.4) API v1. + ZT_API_RESPONSE=$(curl -LsfSw '\n%{http_code}' \ + -X POST -d "{\"authorized\":true}" \ + http://localhost:9993/controller/network/${ZT_NETWORK}/member/${ZT_MEMBER}?auth=${ZT_AUTHTOKEN}) + if [ "$(echo "$ZT_API_RESPONSE" | tail -n1 )" == '200' ]; then + echo -e "${GREEN}==> Client '${3}' was authorized to network '${2}'${NC}"; + echo + exit 0; + else + echo -e "${RED}==> Failed to connect to Controller${NC}"; + exit 1; + fi + break;; + 'No' ) + echo -e "${ORANGE}==> Nothing was added${NC}"; + echo + exit 0; + exit;; + esac + done + else + echo -e "${RED}==> The AuthFile is missing${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please specify a network & client${NC}"; + exit 1; + fi + # + # Deauthorize a client + # + elif [ "$1" == 'deauth' ] || [ "$1" == '-da' ]; then + echo + echo -e "${ORANGE}=> Deauthorize Client${NC}"; + echo + if [ "$2" != '' ] && [ "$3" != '' ]; then + # Check if authtoken.secret exists + if [ -f $ZT_AUTHFILE ]; then + ZT_NETWORK=$2 + ZT_MEMBER=$3 + ZT_AUTHTOKEN=`cat $ZT_AUTHFILE` + echo "> Do you wish to deauthorize this client (${ZT_MEMBER})?" + select ZT_DEL_MEM_YN in 'Yes' 'No'; do + case $ZT_DEL_MEM_YN in + 'Yes' ) + # Make a DELETE request to the API + # Tested with ZeroTier One (1.1.4) API v1. + ZT_API_RESPONSE=$(curl -LsfSw '\n%{http_code}' \ + -X DELETE http://localhost:9993/controller/network/${ZT_NETWORK}/member/${ZT_MEMBER}?auth=${ZT_AUTHTOKEN}) + echo $ZT_API_RESPONSE + if [ "$(echo "$ZT_API_RESPONSE" | tail -n1 )" == '200' ]; then + echo -e "${GREEN}==> Client '${3}' was deauthorized${NC}"; + echo + exit 0; + else + echo -e "${RED}==> Failed to connect to Controller${NC}"; + exit 1; + fi + break;; + 'No' ) + echo -e "${ORANGE}==> Nothing was removed${NC}"; + echo + exit 0; + exit;; + esac + done + else + echo -e "${RED}==> The AuthFile is missing${NC}"; + exit 1; + fi + else + echo -e "${RED}==> Please specify a network & client${NC}"; + exit 1; + fi + # + # Display help + # + elif [ "$1" == 'help' ] || [ "$1" == '-h' ]; then + echo -e " +${ORANGE}+++ ZeroTier Controller CLI +++${NC} + +Version ${VERSION} + +Copyright © 2016 Makersphere Labs +Licensed under GNU GPL v3 + +Usage: zerotier-ctl [] + +Available commands: +help - Display this help +listnetworks - List all network IDs +create - Create a new network +delete - Delete a network +auth - Authorize a client +deauth - Deauthorize a client"; + echo + exit 0; + else + echo -e "${ORANGE}==> Use 'help' to get started${NC}"; + exit 1; + fi +else + echo -e "${ORANGE}==> Use 'help' to get started${NC}"; + exit 1; +fi diff --git a/site-cookbooks/kosmos_zerotier/recipes/controller.rb b/site-cookbooks/kosmos_zerotier/recipes/controller.rb new file mode 100644 index 0000000..a754868 --- /dev/null +++ b/site-cookbooks/kosmos_zerotier/recipes/controller.rb @@ -0,0 +1,9 @@ +# +# Cookbook:: kosmos_zerotier +# Recipe:: controller +# + +cookbook_file "/usr/local/sbin/zerotier-ctl" do + source "zerotier-ctl.sh" + mode "0750" +end diff --git a/site-cookbooks/kosmos_zerotier/recipes/default.rb b/site-cookbooks/kosmos_zerotier/recipes/default.rb index 1125c4a..12c2304 100644 --- a/site-cookbooks/kosmos_zerotier/recipes/default.rb +++ b/site-cookbooks/kosmos_zerotier/recipes/default.rb @@ -2,24 +2,3 @@ # Cookbook:: kosmos_zerotier # Recipe:: default # -# The MIT License (MIT) -# -# Copyright:: 2020, Kosmos Developers -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. diff --git a/site-cookbooks/kosmos_zerotier/recipes/firewall.rb b/site-cookbooks/kosmos_zerotier/recipes/firewall.rb index b179103..df99a7f 100644 --- a/site-cookbooks/kosmos_zerotier/recipes/firewall.rb +++ b/site-cookbooks/kosmos_zerotier/recipes/firewall.rb @@ -2,30 +2,9 @@ # Cookbook:: kosmos_zerotier # Recipe:: firewall # -# The MIT License (MIT) -# -# Copyright:: 2020, Kosmos Developers -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. firewall_rule "zerotier" do port node["kosmos_zerotier"]["server_port"] - protocol :tcp + protocol :none command :allow end