outsource in library, rework jails env
This commit is contained in:
parent
de798d18cc
commit
b40eed619a
@ -1,5 +1,13 @@
|
||||
{
|
||||
"settings": {
|
||||
"soa": "ns1.higgsboson.tk.",
|
||||
"serial": 114,
|
||||
"refresh": "1H",
|
||||
"hostmaster": "hostmaster.higgsboson.tk",
|
||||
"domain": "eva.higgsboson.tk",
|
||||
"retry": "4H",
|
||||
"expire": "3W",
|
||||
"minimum": "1D",
|
||||
"ip4_subnet": "192.168.67.0/24",
|
||||
"ip6_subnet": "2a03:b0c0:2:d0:1::/80",
|
||||
"flavor": "default",
|
||||
|
181
scripts/jail
181
scripts/jail
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env ruby
|
||||
require "optparse"
|
||||
require "shellwords"
|
||||
require_relative "utils"
|
||||
require_relative "lib/utils.rb"
|
||||
require_relative "lib/jail.rb"
|
||||
|
||||
OPTION_PARSER = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: jails [options] [subcommand [options]]"
|
||||
@ -20,173 +19,6 @@ def usage
|
||||
exit(0)
|
||||
end
|
||||
|
||||
ROOT_PATH = Pathname.new(File.expand_path("../.." ,__FILE__))
|
||||
EZJAIL_CONFIG_PATH = Pathname.new("/usr/local/etc/ezjail/")
|
||||
|
||||
class Jail
|
||||
def initialize(name, properties={})
|
||||
@name = name
|
||||
@properties = properties
|
||||
end
|
||||
attr_accessor :name, :properties
|
||||
|
||||
def ip4
|
||||
extract_ip("ip4")
|
||||
end
|
||||
def ip6
|
||||
extract_ip("ip6")
|
||||
end
|
||||
|
||||
private
|
||||
def extract_ip(type)
|
||||
ips = @properties[type] || []
|
||||
ips.map do |addr|
|
||||
# example: em0|192.168.67.0 -> 192.168.67.0
|
||||
addr =~ /\|?([^|]+)$/
|
||||
$1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class JailRegistry < Registry
|
||||
def add(name)
|
||||
data["jails"] ||= {}
|
||||
data["settings"] ||= {}
|
||||
|
||||
ip4 = next_address("ip4")
|
||||
ip6 = next_address("ip6")
|
||||
data["jails"][name] = {
|
||||
"ip4" => [ip4],
|
||||
"ip6" => [ip6]
|
||||
}
|
||||
ipconfig = "#{ip4},#{ip6}"
|
||||
flavour = []
|
||||
if settings["flavour"]
|
||||
flavour = ["-f", settings["flavour"]]
|
||||
end
|
||||
sh("ezjail-admin", "create", *flavour, name, ipconfig)
|
||||
end
|
||||
|
||||
def env(name)
|
||||
jail_data = data["jails"][name] or die("no jail with name #{name} found")
|
||||
jail_data = default_jail_conf.merge(jail_data)
|
||||
templ = Template.new(ROOT_PATH.join("templates/jail_env.erb"))
|
||||
properties = jail_properties(name, jail_data)
|
||||
puts(templ.render(name: name, properties: properties))
|
||||
end
|
||||
|
||||
def update_pf_vars
|
||||
templ = Template.new(ROOT_PATH.join("templates/pf.erb"))
|
||||
path = ROOT_PATH.join("pf_vars.conf")
|
||||
|
||||
atomic_write(path, templ.render(jails: jails))
|
||||
end
|
||||
|
||||
def update_config_symlinks
|
||||
conf_path = ROOT_PATH.join("scripts/jail_conf")
|
||||
FileUtils.mkdir_p(EZJAIL_CONFIG_PATH)
|
||||
jails.each do |jail|
|
||||
FileUtils.ln_sf(conf_path, EZJAIL_CONFIG_PATH.join(jail.name))
|
||||
end
|
||||
end
|
||||
|
||||
def update_fstabs
|
||||
templ = Template.new(ROOT_PATH.join("templates/fstab.erb"))
|
||||
jails.each do |jail|
|
||||
fstab = settings["fstab"].dup
|
||||
fstab.concat(jail.properties["fstab"] || [])
|
||||
fstab.map! do |entry|
|
||||
entry % { name: jail.name }
|
||||
end
|
||||
|
||||
path = "/etc/fstab.#{jail.name}"
|
||||
atomic_write(path, templ.render(fstab: fstab))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def settings
|
||||
{
|
||||
"ip4_subnet" => "192.168.10.0/24",
|
||||
"ip6_subnet" => "fd7d:aed0:18aa::/48",
|
||||
"fstab" => [
|
||||
"/usr/jails/basejail /usr/jails/%{name}/basejail nullfs ro 0 0",
|
||||
],
|
||||
}.merge(data["settings"])
|
||||
end
|
||||
|
||||
def default_jail_conf
|
||||
{
|
||||
"exec_start" => "/bin/sh /etc/rc",
|
||||
"exec_stop" => nil,
|
||||
"hostname" => "%{name}",
|
||||
"rootdir" => "/usr/jails/%{name}",
|
||||
"mount_enable" => true,
|
||||
"devfs_ruleset" => "devfsrules_jails",
|
||||
"procfs_enable" => true,
|
||||
"fdescfs_enable" => true,
|
||||
"image" => nil,
|
||||
"imagetype" => nil,
|
||||
"attachparams" => nil,
|
||||
"attachblocking" => nil,
|
||||
"forceblocking" => nil,
|
||||
"zfs_datasets" => nil,
|
||||
"cpuset" => nil,
|
||||
"fib" => nil,
|
||||
"parentzfs" => nil,
|
||||
"parameters" => nil,
|
||||
"post_start_script" => nil,
|
||||
"retention_policy" => nil
|
||||
}.merge(data["default_jail_conf"])
|
||||
end
|
||||
|
||||
def jail_properties(name, properties)
|
||||
props = properties.dup
|
||||
|
||||
ips = props.delete("ip4") || []
|
||||
ips.concat(props.delete("ip6") || [])
|
||||
unless ips.empty?
|
||||
props["ip"] = ips.join(",")
|
||||
end
|
||||
props.each do |prop, value|
|
||||
props[prop] = serialize_property(name, value)
|
||||
end
|
||||
|
||||
props
|
||||
end
|
||||
|
||||
def serialize_property(name, value)
|
||||
str = case value
|
||||
when TrueClass
|
||||
return value ? "YES" : "NO"
|
||||
when String
|
||||
value % { name: name }
|
||||
else
|
||||
value
|
||||
end
|
||||
Shellwords.escape(str)
|
||||
end
|
||||
|
||||
def jails
|
||||
data["jails"].map do |name, properties|
|
||||
Jail.new(name, properties)
|
||||
end
|
||||
end
|
||||
|
||||
def next_address(type)
|
||||
subnets = []
|
||||
data["jails"].each do |k,v|
|
||||
if v[type].is_a? Array
|
||||
v[type].each do |subnet|
|
||||
subnets << NetAddr::CIDR.create(subnet)
|
||||
end
|
||||
end
|
||||
end
|
||||
subnet = settings["#{type}_subnet"]
|
||||
next_free_subnet(NetAddr::CIDR.create(subnet), subnets)
|
||||
end
|
||||
end
|
||||
|
||||
def main(args)
|
||||
OPTION_PARSER.order!(args)
|
||||
|
||||
@ -198,19 +30,18 @@ def main(args)
|
||||
when "add"
|
||||
name = args.first or die "name required"
|
||||
registry.add(name)
|
||||
registry.save
|
||||
when nil
|
||||
usage
|
||||
when "regenerate"
|
||||
when "env"
|
||||
name = args.first or die "name required"
|
||||
registry.env(name)
|
||||
else
|
||||
die "unknown subcommand #{command}"
|
||||
end
|
||||
registry.update_pf_vars
|
||||
registry.update_fstabs
|
||||
registry.update_config_symlinks
|
||||
registry.update_jail_config
|
||||
registry.update_zone
|
||||
registry.update_rzone
|
||||
registry.save
|
||||
end
|
||||
|
||||
main(ARGV)
|
||||
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "TODO"
|
||||
exit 1
|
183
scripts/lib/jail.rb
Normal file
183
scripts/lib/jail.rb
Normal file
@ -0,0 +1,183 @@
|
||||
require "optparse"
|
||||
require "shellwords"
|
||||
require_relative "utils.rb"
|
||||
|
||||
ROOT_PATH = Pathname.new(File.expand_path("../../.." ,__FILE__))
|
||||
EZJAIL_CONFIG_PATH = Pathname.new("/usr/local/etc/ezjail/")
|
||||
|
||||
class Jail
|
||||
def initialize(name, properties={})
|
||||
@name = name
|
||||
@properties = properties
|
||||
end
|
||||
attr_accessor :name, :properties
|
||||
|
||||
def ip4
|
||||
extract_ip("ip4")
|
||||
end
|
||||
def ip6
|
||||
extract_ip("ip6")
|
||||
end
|
||||
|
||||
private
|
||||
def extract_ip(type)
|
||||
ips = @properties[type] || []
|
||||
ips.map do |addr|
|
||||
# example: em0|192.168.67.0 -> 192.168.67.0
|
||||
addr =~ /\|?([^|]+)$/
|
||||
$1
|
||||
end
|
||||
end
|
||||
|
||||
def pointers(&block)
|
||||
subnet_arpa = subnet.arpa
|
||||
version = subnet.version
|
||||
|
||||
data["network"].each do |name, data|
|
||||
next unless data["ipv#{version}"]
|
||||
arpa = NetAddr::CIDR.create(data["ipv#{version}"]).arpa
|
||||
addr = arpa[0, arpa.size - subnet_arpa.size - 1]
|
||||
yield addr, name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class JailRegistry < Registry
|
||||
def add(name)
|
||||
data["jails"] ||= {}
|
||||
data["settings"] ||= {}
|
||||
|
||||
ip4 = next_address("ip4")
|
||||
ip6 = next_address("ip6")
|
||||
data["jails"][name] = {
|
||||
"ip4" => [ip4],
|
||||
"ip6" => [ip6]
|
||||
}
|
||||
ipconfig = "#{ip4},#{ip6}"
|
||||
flavour = []
|
||||
if settings["flavour"]
|
||||
flavour = ["-f", settings["flavour"]]
|
||||
end
|
||||
sh("ezjail-admin", "create", *flavour, name, ipconfig)
|
||||
end
|
||||
|
||||
def update_pf_vars
|
||||
templ = Template.new(ROOT_PATH.join("templates/pf.erb"))
|
||||
path = ROOT_PATH.join("pf_vars.conf")
|
||||
|
||||
atomic_write(path, templ.render(jails: jails))
|
||||
end
|
||||
|
||||
def update_jail_config
|
||||
jails.each do |jail|
|
||||
jail_data = default_jail_conf.merge(jail.properties)
|
||||
templ = Template.new(ROOT_PATH.join("templates/jail.erb"))
|
||||
properties = jail_properties(jail.name, jail_data)
|
||||
conf_path = EZJAIL_CONFIG_PATH.join(jail.name)
|
||||
atomic_write(conf_path, templ.render(name: jail.name, properties: properties))
|
||||
end
|
||||
end
|
||||
|
||||
def update_fstabs
|
||||
templ = Template.new(ROOT_PATH.join("templates/fstab.erb"))
|
||||
jails.each do |jail|
|
||||
fstab = settings["fstab"].dup
|
||||
fstab.concat(jail.properties["fstab"] || [])
|
||||
fstab.map! do |entry|
|
||||
entry % { name: jail.name }
|
||||
end
|
||||
|
||||
path = "/etc/fstab.#{jail.name}"
|
||||
atomic_write(path, templ.render(fstab: fstab))
|
||||
end
|
||||
end
|
||||
|
||||
def update_zone
|
||||
end
|
||||
|
||||
def update_rzone
|
||||
end
|
||||
|
||||
private
|
||||
def settings
|
||||
{
|
||||
"ip4_subnet" => "192.168.10.0/24",
|
||||
"ip6_subnet" => "fd7d:aed0:18aa::/48",
|
||||
"fstab" => [
|
||||
"/usr/jails/basejail /usr/jails/%{name}/basejail nullfs ro 0 0",
|
||||
],
|
||||
}.merge(data["settings"])
|
||||
end
|
||||
|
||||
def default_jail_conf
|
||||
{
|
||||
"exec_start" => "/bin/sh /etc/rc",
|
||||
"exec_stop" => nil,
|
||||
"hostname" => "%{name}",
|
||||
"rootdir" => "/usr/jails/%{name}",
|
||||
"mount_enable" => true,
|
||||
"devfs_ruleset" => "devfsrules_jails",
|
||||
"procfs_enable" => true,
|
||||
"fdescfs_enable" => true,
|
||||
"image" => nil,
|
||||
"imagetype" => nil,
|
||||
"attachparams" => nil,
|
||||
"attachblocking" => nil,
|
||||
"forceblocking" => nil,
|
||||
"zfs_datasets" => nil,
|
||||
"cpuset" => nil,
|
||||
"fib" => nil,
|
||||
"parentzfs" => nil,
|
||||
"parameters" => nil,
|
||||
"post_start_script" => nil,
|
||||
"retention_policy" => nil
|
||||
}.merge(data["default_jail_conf"])
|
||||
end
|
||||
|
||||
def jail_properties(name, properties)
|
||||
props = properties.dup
|
||||
|
||||
ips = []
|
||||
ips.concat(props.delete("ip4") || [])
|
||||
ips.concat(props.delete("ip6") || [])
|
||||
unless ips.empty?
|
||||
props["ip"] = ips.join(",")
|
||||
end
|
||||
props.each do |prop, value|
|
||||
props[prop] = serialize_property(name, value)
|
||||
end
|
||||
|
||||
props
|
||||
end
|
||||
|
||||
def serialize_property(name, value)
|
||||
str = case value
|
||||
when TrueClass
|
||||
return value ? "YES" : "NO"
|
||||
when String
|
||||
value % { name: name }
|
||||
else
|
||||
value
|
||||
end
|
||||
Shellwords.escape(str)
|
||||
end
|
||||
|
||||
def jails
|
||||
data["jails"].map do |name, properties|
|
||||
Jail.new(name, properties)
|
||||
end
|
||||
end
|
||||
|
||||
def next_address(type)
|
||||
subnets = []
|
||||
data["jails"].each do |k,v|
|
||||
if v[type].is_a? Array
|
||||
v[type].each do |subnet|
|
||||
subnets << NetAddr::CIDR.create(subnet)
|
||||
end
|
||||
end
|
||||
end
|
||||
subnet = settings["#{type}_subnet"]
|
||||
next_free_subnet(NetAddr::CIDR.create(subnet), subnets)
|
||||
end
|
||||
end
|
@ -7,7 +7,7 @@ require "pry"
|
||||
require "netaddr"
|
||||
|
||||
class Registry
|
||||
PATH = Pathname.new(File.expand_path("../../jails.json", __FILE__))
|
||||
PATH = Pathname.new(File.expand_path("../../../jails.json", __FILE__))
|
||||
def initialize
|
||||
@data = JSON.load(File.open(Registry::PATH))
|
||||
end
|
@ -1,3 +1,4 @@
|
||||
# THIS FILE WAS GENERATED, CHANGES WILL BE OVERWRITTEN
|
||||
<% properties.each do |property,value| -%>
|
||||
export jail_<%= name %>_<%= property %>=<%= value %>
|
||||
<% end -%>
|
26
templates/rzone.erb
Normal file
26
templates/rzone.erb
Normal file
@ -0,0 +1,26 @@
|
||||
@ IN SOA <%= data["zone"]["soa"] %> <%= data["zone"]["hostmaster"] %> (
|
||||
<%= data["zone"]["serial"] %> ; serial
|
||||
<%= data["zone"]["refresh"] %> ; refresh
|
||||
<%= data["zone"]["retry"] %> ; retry
|
||||
<%= data["zone"]["expire"] %> ; expire
|
||||
<%= data["zone"]["minimum"] %>) ; minimum
|
||||
<% data["jails"].each do |name, value| -%>
|
||||
<% if value["ns"] -%>
|
||||
IN NS <%= name %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
<% data["jails"].each do |name, value| -%>
|
||||
<% if value["ns"] -%>
|
||||
<% if value["ipv4"] -%>
|
||||
<%= name %> A <%= value["ipv4"] %>
|
||||
<% end -%>
|
||||
<% if value["ipv6"] -%>
|
||||
<%= name %> AAAA <%= value["ipv6"] %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
<% pointers do |addr, name| -%>
|
||||
<%= addr %> PTR <%= name %>.<%= data["zone"]["domain"] %>.
|
||||
<% end -%>
|
28
templates/zone.erb
Normal file
28
templates/zone.erb
Normal file
@ -0,0 +1,28 @@
|
||||
@ IN SOA <%= data["zone"]["soa"] %> <%= data["zone"]["hostmaster"] %> (
|
||||
<%= data["zone"]["serial"] %> ; serial
|
||||
<%= data["zone"]["refresh"] %> ; refresh
|
||||
<%= data["zone"]["retry"] %> ; retry
|
||||
<%= data["zone"]["expire"] %> ; expire
|
||||
<%= data["zone"]["minimum"] %>) ; minimum
|
||||
<% data["jails"].each do |name, value| -%>
|
||||
<% if value["ns"] -%>
|
||||
IN NS <%= name %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
<% jails.each do |jail| %>
|
||||
<% jail.cname -%>
|
||||
<%= name %> CNAME <%= jail.cname %>
|
||||
<% end -%>
|
||||
<% jail.srv.each do |srv| -%>
|
||||
<%= name %> SRV <%= srv %>
|
||||
<% end -%>
|
||||
<% jail.ip4.each do |ip| -%>
|
||||
<%= name %> A <%= ip %>
|
||||
ipv4.<%= name %> A <%= ip %>
|
||||
<% end -%>
|
||||
<% if value["ipv6"] -%>
|
||||
<%= name %> AAAA <%= ip(value["ipv6"]) %>
|
||||
ipv6.<%= name %> AAAA <%= ip(value["ipv6"]) %>
|
||||
<% end -%>
|
||||
<% end -%>
|
Loading…
Reference in New Issue
Block a user