Blame


1 1c2d62de 2021-12-21 jrmu #!/usr/bin/perl
2 1c2d62de 2021-12-21 jrmu
3 1c2d62de 2021-12-21 jrmu use strict;
4 1c2d62de 2021-12-21 jrmu use warnings;
5 1c2d62de 2021-12-21 jrmu use OpenBSD::Pledge;
6 1c2d62de 2021-12-21 jrmu use OpenBSD::Unveil;
7 1c2d62de 2021-12-21 jrmu use Data::Dumper;
8 1c2d62de 2021-12-21 jrmu use File::Copy qw(copy);
9 1c2d62de 2021-12-21 jrmu
10 1c2d62de 2021-12-21 jrmu my $vmconf = "/etc/vm.conf";
11 1c2d62de 2021-12-21 jrmu my $zonedir = "/var/nsd/zones/master/";
12 a4f32e6b 2023-06-01 jrmu my $hostname = "host.example.com";
13 a4f32e6b 2023-06-01 jrmu my $ipv4path = "/home/username/ipv4s";
14 a4f32e6b 2023-06-01 jrmu my $isopath = "/home/iso/install73.iso";
15 1c2d62de 2021-12-21 jrmu my @ipv4s;
16 1c2d62de 2021-12-21 jrmu if (!(-s "$ipv4path")) {
17 1c2d62de 2021-12-21 jrmu print "No IPv4 addresses in $ipv4path!\n";
18 1c2d62de 2021-12-21 jrmu die;
19 1c2d62de 2021-12-21 jrmu } else {
20 1c2d62de 2021-12-21 jrmu @ipv4s = readarray($ipv4path);
21 1c2d62de 2021-12-21 jrmu }
22 1c2d62de 2021-12-21 jrmu
23 1c2d62de 2021-12-21 jrmu `doas chmod -R g+w $zonedir`;
24 1c2d62de 2021-12-21 jrmu
25 1c2d62de 2021-12-21 jrmu # Read from filename and return array of lines without trailing newlines
26 1c2d62de 2021-12-21 jrmu sub readarray {
27 1c2d62de 2021-12-21 jrmu my ($filename) = @_;
28 1c2d62de 2021-12-21 jrmu open(my $fh, '<', $filename) or die "Could not read file '$filename' $!";
29 1c2d62de 2021-12-21 jrmu chomp(my @lines = <$fh>);
30 1c2d62de 2021-12-21 jrmu close $fh;
31 1c2d62de 2021-12-21 jrmu return @lines;
32 1c2d62de 2021-12-21 jrmu }
33 1c2d62de 2021-12-21 jrmu
34 1c2d62de 2021-12-21 jrmu # Read from filename and return as string
35 1c2d62de 2021-12-21 jrmu sub readstr {
36 1c2d62de 2021-12-21 jrmu my ($filename) = @_;
37 1c2d62de 2021-12-21 jrmu open my $fh, '<', $filename or die "Could not read file '$filename' $!";
38 1c2d62de 2021-12-21 jrmu my $str = do { local $/; <$fh> };
39 1c2d62de 2021-12-21 jrmu close $fh;
40 1c2d62de 2021-12-21 jrmu return $str;
41 1c2d62de 2021-12-21 jrmu }
42 1c2d62de 2021-12-21 jrmu
43 1c2d62de 2021-12-21 jrmu # Write str to filename
44 1c2d62de 2021-12-21 jrmu sub writefile {
45 1c2d62de 2021-12-21 jrmu my ($filename, $str) = @_;
46 1c2d62de 2021-12-21 jrmu open(my $fh, '>', "$filename") or die "Could not write to $filename";
47 1c2d62de 2021-12-21 jrmu print $fh $str;
48 1c2d62de 2021-12-21 jrmu close $fh;
49 1c2d62de 2021-12-21 jrmu }
50 1c2d62de 2021-12-21 jrmu
51 1c2d62de 2021-12-21 jrmu # Append str to filename
52 1c2d62de 2021-12-21 jrmu sub appendfile {
53 1c2d62de 2021-12-21 jrmu my ($filename, $str) = @_;
54 1c2d62de 2021-12-21 jrmu open(my $fh, '>>', "$filename") or die "Could not append to $filename";
55 1c2d62de 2021-12-21 jrmu print $fh $str;
56 1c2d62de 2021-12-21 jrmu close $fh;
57 1c2d62de 2021-12-21 jrmu }
58 1c2d62de 2021-12-21 jrmu
59 1c2d62de 2021-12-21 jrmu sub date {
60 1c2d62de 2021-12-21 jrmu my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
61 1c2d62de 2021-12-21 jrmu my $localtime = sprintf("%04d%02d%02d", $year+1900, $mon+1, $mday);
62 1c2d62de 2021-12-21 jrmu return $localtime;
63 1c2d62de 2021-12-21 jrmu }
64 1c2d62de 2021-12-21 jrmu
65 1c2d62de 2021-12-21 jrmu sub setdns {
66 1c2d62de 2021-12-21 jrmu my ($domain, $ip) = @_;
67 1c2d62de 2021-12-21 jrmu my $filename = "$zonedir/$hostname";
68 1c2d62de 2021-12-21 jrmu my $subdomain;
69 1c2d62de 2021-12-21 jrmu if ($domain =~ /^([a-zA-Z][-\.a-zA-Z0-9]+)\.$hostname$/) {
70 1c2d62de 2021-12-21 jrmu $subdomain = $1;
71 1c2d62de 2021-12-21 jrmu } else {
72 1c2d62de 2021-12-21 jrmu return 0;
73 1c2d62de 2021-12-21 jrmu }
74 1c2d62de 2021-12-21 jrmu my @lines = readarray($filename);
75 1c2d62de 2021-12-21 jrmu foreach my $line (@lines) {
76 1c2d62de 2021-12-21 jrmu # increment the zone's serial number
77 1c2d62de 2021-12-21 jrmu if ($line =~ /(\d{8})(\d{2})((\s+\d+){4}\s*\))/) {
78 1c2d62de 2021-12-21 jrmu my $date = date();
79 1c2d62de 2021-12-21 jrmu my $serial = 0;
80 1c2d62de 2021-12-21 jrmu if ($date <= $1) { $serial = $2+1; }
81 1c2d62de 2021-12-21 jrmu $line = $`.$date.sprintf("%02d",$serial).$3.$';
82 1c2d62de 2021-12-21 jrmu }
83 1c2d62de 2021-12-21 jrmu }
84 1c2d62de 2021-12-21 jrmu if ($ip =~ /^([0-9\.]+)$/) { # if IPv4
85 1c2d62de 2021-12-21 jrmu push(@lines, "$subdomain 3600 IN A $ip");
86 1c2d62de 2021-12-21 jrmu } elsif ($ip =~ /:/) { # if IPv6
87 1c2d62de 2021-12-21 jrmu push(@lines, "$subdomain 3600 IN AAAA $ip");
88 1c2d62de 2021-12-21 jrmu } elsif (!defined($ip)) { # delete records
89 1c2d62de 2021-12-21 jrmu @lines = grep !/\b$subdomain\s*3600\s*IN/, @lines;
90 1c2d62de 2021-12-21 jrmu }
91 1c2d62de 2021-12-21 jrmu # trailing newline necessary
92 1c2d62de 2021-12-21 jrmu writefile("$filename.bak", join("\n", @lines)."\n");
93 1c2d62de 2021-12-21 jrmu copy "$filename.bak", $filename;
94 1c2d62de 2021-12-21 jrmu if (system("doas -u _nsd nsd-control reload")) {
95 1c2d62de 2021-12-21 jrmu return 0;
96 1c2d62de 2021-12-21 jrmu } else {
97 1c2d62de 2021-12-21 jrmu return 1;
98 1c2d62de 2021-12-21 jrmu }
99 1c2d62de 2021-12-21 jrmu }
100 1c2d62de 2021-12-21 jrmu
101 1c2d62de 2021-12-21 jrmu # create A and AAAA records for subdomain, set the rDNS,
102 1c2d62de 2021-12-21 jrmu # and return the new ipv6 address
103 1c2d62de 2021-12-21 jrmu sub nextdns {
104 1c2d62de 2021-12-21 jrmu my ($subdomain) = @_;
105 1c2d62de 2021-12-21 jrmu my $ipv4 = shift(@ipv4s);
106 1c2d62de 2021-12-21 jrmu my $ipv6;
107 1c2d62de 2021-12-21 jrmu my $fqdn = "$subdomain.$hostname";
108 1c2d62de 2021-12-21 jrmu if ($ipv4 =~ /^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+)$/) {
109 1c2d62de 2021-12-21 jrmu $ipv6 = "2602:fccf:1:1".sprintf("%03d",$1)."::";
110 1c2d62de 2021-12-21 jrmu }
111 1c2d62de 2021-12-21 jrmu writefile($ipv4path, join("\n", @ipv4s));
112 1c2d62de 2021-12-21 jrmu my $success = setdns($fqdn, $ipv4) && setdns($fqdn, $ipv6) && setdns("ns1.$fqdn", $ipv4) && setdns("ns2.$fqdn", $ipv4);
113 a4f32e6b 2023-06-01 jrmu print "IP: $ipv4 $ipv6\n";
114 1c2d62de 2021-12-21 jrmu return $success;
115 1c2d62de 2021-12-21 jrmu }
116 1c2d62de 2021-12-21 jrmu
117 1c2d62de 2021-12-21 jrmu sub createshell {
118 1c2d62de 2021-12-21 jrmu my ($username, $password) = @_;
119 1c2d62de 2021-12-21 jrmu print "Username: $username\n";
120 1c2d62de 2021-12-21 jrmu print "Password: $password\n";
121 1c2d62de 2021-12-21 jrmu system "doas groupadd $username";
122 1c2d62de 2021-12-21 jrmu system "doas adduser -batch $username $username $username `encrypt $password`";
123 1c2d62de 2021-12-21 jrmu system "doas usermod -G vmdusers $username";
124 1c2d62de 2021-12-21 jrmu system "doas chmod -R o-rwx /home/$username";
125 1c2d62de 2021-12-21 jrmu system "doas su -l $username -c \"vmctl create -s 20G $username.qcow2\"";
126 1c2d62de 2021-12-21 jrmu print "VM created for $username!\n";
127 1c2d62de 2021-12-21 jrmu my @vmconf = readarray($vmconf);
128 1c2d62de 2021-12-21 jrmu my $lladdr;
129 1c2d62de 2021-12-21 jrmu foreach my $line (@vmconf) {
130 1c2d62de 2021-12-21 jrmu if ($line =~ /lladdr (.*)/) {
131 1c2d62de 2021-12-21 jrmu $lladdr = $1;
132 1c2d62de 2021-12-21 jrmu }
133 1c2d62de 2021-12-21 jrmu }
134 1c2d62de 2021-12-21 jrmu if (defined($lladdr) && $lladdr =~ /([0-9a-fA-F]{2})$/) {
135 1c2d62de 2021-12-21 jrmu $lladdr = $`.($1+1);
136 1c2d62de 2021-12-21 jrmu }
137 1c2d62de 2021-12-21 jrmu my $block = <<"EOF";
138 1c2d62de 2021-12-21 jrmu vm "$username" {
139 1c2d62de 2021-12-21 jrmu owner $username
140 a4f32e6b 2023-06-01 jrmu memory 2048M
141 a4f32e6b 2023-06-01 jrmu cdrom "$isopath"
142 1c2d62de 2021-12-21 jrmu disk /home/$username/$username.qcow2
143 1c2d62de 2021-12-21 jrmu interface {
144 1c2d62de 2021-12-21 jrmu locked lladdr $lladdr
145 1c2d62de 2021-12-21 jrmu switch "switch0"
146 1c2d62de 2021-12-21 jrmu }
147 1c2d62de 2021-12-21 jrmu }
148 1c2d62de 2021-12-21 jrmu EOF
149 1c2d62de 2021-12-21 jrmu appendfile($vmconf, $block);
150 1c2d62de 2021-12-21 jrmu `doas vmctl reload`;
151 1c2d62de 2021-12-21 jrmu }
152 1c2d62de 2021-12-21 jrmu
153 1c2d62de 2021-12-21 jrmu my $nargs = $#ARGV + 1;
154 1c2d62de 2021-12-21 jrmu if ($nargs != 1) {
155 1c2d62de 2021-12-21 jrmu print "\nUsage: install.pl username\n";
156 1c2d62de 2021-12-21 jrmu exit;
157 1c2d62de 2021-12-21 jrmu }
158 1c2d62de 2021-12-21 jrmu my $username = $ARGV[0];
159 1c2d62de 2021-12-21 jrmu my $password = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..12;
160 1c2d62de 2021-12-21 jrmu
161 1c2d62de 2021-12-21 jrmu createshell($username, $password);
162 1c2d62de 2021-12-21 jrmu nextdns($username);