Pascal Dreissen
2016-07-08 f1193b43f4c9fd132741d30f03f0b35841011989
commit | author | age
0ae8da 1 <?php
F 2
3 class nginx_reverseproxy_plugin {
4
5     var $plugin_name = 'nginx_reverseproxy_plugin';
6     var $class_name = 'nginx_reverseproxy_plugin';
7
8     // private variables
9     var $action = '';
10
11     //* This function is called during ispconfig installation to determine
12     //  if a symlink shall be created for this plugin.
13     function onInstall() {
14         global $conf;
15
c91bdc 16         if(isset($conf['services']['proxy']) && $conf['services']['proxy'] == true && isset($conf['nginx']['installed']) && $conf['nginx']['installed'] == true) {
0ae8da 17             return true;
F 18         } else {
19             return false;
20         }
21
22     }
23
24
25     /*
26          This function is called when the plugin is loaded
27     */
28
29     function onLoad() {
30         global $app;
31
32         /*
33         Register for the events
34         */
35
b1a6a5 36         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'ssl');
MC 37         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'ssl');
38         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'ssl');
39
40         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'insert');
41         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'update');
42         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'delete');
43
44         // $app->plugins->registerEvent('proxy_reverse_insert',$this->plugin_name,'rewrite_insert');
45         // $app->plugins->registerEvent('proxy_reverse_update',$this->plugin_name,'rewrite_update');
46         // $app->plugins->registerEvent('proxy_reverse_delete',$this->plugin_name,'rewrite_delete');
47
0ae8da 48
F 49
50     }
b1a6a5 51
MC 52
53     function insert($event_name, $data) {
0ae8da 54         global $app, $conf;
b1a6a5 55
0ae8da 56         // just run the update function
b1a6a5 57         $this->update($event_name, $data);
0ae8da 58     }
b1a6a5 59
MC 60
61     function update($event_name, $data) {
0ae8da 62         global $app, $conf;
F 63
64         if($this->action != 'insert') $this->action = 'update';
65
511ba5 66         if($data['new']['type'] != 'vhost' && $data['new']['type'] != 'vhostsubdomain' && $data['new']['type'] != 'vhostalias' && $data['new']['parent_domain_id'] > 0) {
0ae8da 67
F 68             $old_parent_domain_id = intval($data['old']['parent_domain_id']);
69             $new_parent_domain_id = intval($data['new']['parent_domain_id']);
70
71             // If the parent_domain_id has been chenged, we will have to update the old site as well.
72             if($this->action == 'update' && $data['new']['parent_domain_id'] != $data['old']['parent_domain_id']) {
cc7a82 73                 $tmp = $app->dbmaster->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $old_parent_domain_id);
0ae8da 74                 $data['new'] = $tmp;
F 75                 $data['old'] = $tmp;
76                 $this->action = 'update';
b1a6a5 77                 $this->update($event_name, $data);
0ae8da 78             }
F 79
80             // This is not a vhost, so we need to update the parent record instead.
cc7a82 81             $tmp = $app->dbmaster->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $new_parent_domain_id);
0ae8da 82             $data['new'] = $tmp;
F 83             $data['old'] = $tmp;
84             $this->action = 'update';
85         }
b1a6a5 86
MC 87
88
89
0ae8da 90         // load the server configuration options
F 91         $app->uses('getconf');
4ffb51 92         $nginx_config = $app->getconf->get_server_config($conf['server_id'], 'web');
0ae8da 93
F 94         // Create group and user, if not exist
95         $app->uses('system');
96
97         //* Create the vhost config file
98         $app->load('tpl');
99
100         $tpl = new tpl();
101         $tpl->newTemplate('nginx_reverseproxy_vhost.conf.master');
102
103         $vhost_data = $data['new'];
104         $vhost_data['config_dir'] = $config['nginx']['config_dir'];
b1a6a5 105
0ae8da 106         $vhost_data['ssl_domain'] = $data['new']['ssl_domain'];
F 107         // Check if a SSL cert exists
108         $ssl_dir = $config['nginx']['config_dir'].'/ssl';
109         $domain = $data['new']['ssl_domain'];
110         $key_file = $ssl_dir.'/'.$domain.'.key';
111         $crt_file = $ssl_dir.'/'.$domain.'.crt';
112         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
113
b1a6a5 114         $vhost_data['nginx_directives'] = preg_replace("/\[IP\]/", $vhost_data['ip_address'], $vhost_data['nginx_directives']);
0ae8da 115
F 116
117         if($data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file)) {
118             $vhost_data['ssl_enabled'] = 1;
b1a6a5 119             $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG);
0ae8da 120         } else {
F 121             $vhost_data['ssl_enabled'] = 0;
b1a6a5 122             $app->log('Disable SSL for: '.$domain, LOGLEVEL_DEBUG);
0ae8da 123         }
F 124
125         if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
126
127
128         $tpl->setVar($vhost_data);
129
b1a6a5 130
0ae8da 131
F 132         // get alias domains (co-domains and subdomains)
cc7a82 133         $aliases = $app->dbmaster->queryAllRecords("SELECT * FROM web_domain WHERE parent_domain_id = ? AND (type != 'vhostsubdomain' OR type != 'vhostalias') AND active = 'y'", $data['new']['domain_id']);
0ae8da 134         $server_alias = array();
F 135         switch($data['new']['subdomain']) {
b1a6a5 136         case 'www':
MC 137             $server_alias[] .= 'www.'.$data['new']['domain'].' ';
138             break;
139         case '*':
140             $server_alias[] .= '*.'.$data['new']['domain'].' ';
141             break;
0ae8da 142         }
F 143         if(is_array($aliases)) {
144             foreach($aliases as $alias) {
145                 switch($alias['subdomain']) {
b1a6a5 146                 case 'www':
MC 147                     $server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
148                     break;
149                 case '*':
150                     $server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
151                     break;
152                 default:
153                     $server_alias[] .= $alias['domain'].' ';
154                     break;
0ae8da 155                 }
b1a6a5 156                 $app->log('Add server alias: '.$alias['domain'], LOGLEVEL_DEBUG);
MC 157
0ae8da 158             }
F 159         }
160
161         //* If we have some alias records
162         if(count($server_alias) > 0) {
163             $server_alias_str = '';
164             $n = 0;
165
166             // begin a new ServerAlias line after 30 alias domains
167             foreach($server_alias as $tmp_alias) {
168                 if($n % 30 == 0) $server_alias_str .= " ";
169                 $server_alias_str .= $tmp_alias;
170             }
171             unset($tmp_alias);
172
b1a6a5 173             $tpl->setVar('alias', trim($server_alias_str));
0ae8da 174         } else {
b1a6a5 175             $tpl->setVar('alias', '');
0ae8da 176         }
b1a6a5 177
0ae8da 178
4ffb51 179         $vhost_file = escapeshellcmd($nginx_config['nginx_vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
0ae8da 180         //* Make a backup copy of vhost file
b1a6a5 181         copy($vhost_file, $vhost_file.'~');
MC 182
0ae8da 183         //* Write vhost file
b1a6a5 184         file_put_contents($vhost_file, $tpl->grab());
MC 185         $app->log('Writing the vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
0ae8da 186         unset($tpl);
F 187
188
189         // Set the symlink to enable the vhost
4ffb51 190         $vhost_symlink = escapeshellcmd($nginx_config['nginx_vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
0ae8da 191         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
b1a6a5 192             symlink($vhost_file, $vhost_symlink);
MC 193             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
0ae8da 194         }
F 195
196         // Remove the symlink, if site is inactive
197         if($data['new']['active'] == 'n' && is_link($vhost_symlink)) {
198             unlink($vhost_symlink);
b1a6a5 199             $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
0ae8da 200         }
b1a6a5 201
0ae8da 202         if(!is_dir('/var/log/ispconfig/nginx/'.$data['new']['domain'])) exec('mkdir -p /var/log/ispconfig/nginx/'.$data['new']['domain']);
F 203
204         // remove old symlink and vhost file, if domain name of the site has changed
205         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
4ffb51 206             $vhost_symlink = escapeshellcmd($nginx_config['nginx_vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
0ae8da 207             unlink($vhost_symlink);
b1a6a5 208             $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
4ffb51 209             $vhost_file = escapeshellcmd($nginx_config['nginx_vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
0ae8da 210             unlink($vhost_file);
b1a6a5 211             $app->log('Removing file: '.$vhost_file, LOGLEVEL_DEBUG);
MC 212
0ae8da 213             if(is_dir('/var/log/ispconfig/nginx/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/nginx/'.$data['old']['domain']);
F 214         }
b1a6a5 215
0ae8da 216         // request a httpd reload when all records have been processed
b1a6a5 217         $app->services->restartServiceDelayed('nginx', 'restart');
MC 218
0ae8da 219         // Remove the backup copy of the config file.
F 220         if(@is_file($vhost_file.'~')) unlink($vhost_file.'~');
b1a6a5 221
0ae8da 222
F 223         //* Unset action to clean it for next processed vhost.
224         $this->action = '';
225
226     }
b1a6a5 227
MC 228
229
0ae8da 230
F 231     // Handle the creation of SSL certificates
b1a6a5 232     function ssl($event_name, $data) {
0ae8da 233         global $app, $conf;
F 234
235         if(!is_dir($conf['nginx']['config_dir'].'/ssl')) exec('mkdir -p '.$conf['nginx']['config_dir'].'/ssl');
236         $ssl_dir = $conf['nginx']['config_dir'].'/ssl';
237         $domain = $data['new']['ssl_domain'];
238         $key_file = $ssl_dir.'/'.$domain.'.key.org';
239         $key_file2 = $ssl_dir.'/'.$domain.'.key';
240         $csr_file = $ssl_dir.'/'.$domain.'.csr';
241         $crt_file = $ssl_dir.'/'.$domain.'.crt';
242
b1a6a5 243
0ae8da 244         //* Save a SSL certificate to disk
F 245         if($data["new"]["ssl_action"] == 'save') {
cc7a82 246             $web = $app->masterdb->queryOneRecord("select wd.document_root, sp.ip_address from web_domain wd INNER JOIN server_ip sp USING(server_id) WHERE domain = ?", $data['new']['domain']);
b1a6a5 247
0ae8da 248             $src_ssl_dir = $web["document_root"]."/ssl";
F 249             //$domain = $data["new"]["ssl_domain"];
250             //$csr_file = $ssl_dir.'/'.$domain.".csr";
251             //$crt_file = $ssl_dir.'/'.$domain.".crt";
252             //$bundle_file = $ssl_dir.'/'.$domain.".bundle";
253             $this->_exec('rsync -v -e ssh root@'.$web['ip_address'].':~/$src_ssl_dir '.$ssl_dir);
b1a6a5 254
MC 255             $app->log('Syncing SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
0ae8da 256         }
F 257
258         //* Delete a SSL certificate
259         if($data['new']['ssl_action'] == 'del') {
260             //$ssl_dir = $data['new']['document_root'].'/ssl';
261             $domain = $data['new']['ssl_domain'];
262             $csr_file = $ssl_dir.'/'.$domain.'.csr';
263             $crt_file = $ssl_dir.'/'.$domain.'.crt';
264             $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
265             unlink($csr_file);
266             unlink($crt_file);
267             unlink($bundle_file);
b1a6a5 268             $app->log('Deleting SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
0ae8da 269         }
F 270
271
272     }
273
274
b1a6a5 275     function delete($event_name, $data) {
0ae8da 276         global $app, $conf;
F 277
278         // load the server configuration options
279         $app->uses('getconf');
4ffb51 280         $nginx_config = $app->getconf->get_server_config($conf['server_id'], 'web');
0ae8da 281
F 282
511ba5 283         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
0ae8da 284
F 285             //* This is a website
286             // Deleting the vhost file, symlink and the data directory
4ffb51 287             $vhost_symlink = escapeshellcmd($nginx_config['nginx_vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
0ae8da 288             unlink($vhost_symlink);
b1a6a5 289             $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
0ae8da 290
4ffb51 291             $vhost_file = escapeshellcmd($nginx_config['nginx_vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
0ae8da 292             unlink($vhost_file);
b1a6a5 293             $app->log('Removing vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
MC 294
295
0ae8da 296
F 297             // Delete the log file directory
298             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/nginx/'.$data['old']['domain']);
b1a6a5 299             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir, '..')) exec('rm -rf '.$vhost_logfile_dir);
MC 300             $app->log('Removing website logfile directory: '.$vhost_logfile_dir, LOGLEVEL_DEBUG);
0ae8da 301
F 302         }
303     }
b1a6a5 304
0ae8da 305     //* Wrapper for exec function for easier debugging
F 306     private function _exec($command) {
307         global $app;
b1a6a5 308         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
0ae8da 309         exec($command);
F 310     }
b1a6a5 311
MC 312     function rewrite_insert($event_name, $data) {
0ae8da 313         global $app, $conf;
F 314
315         // just run the update function
b1a6a5 316         $this->update($event_name, $data);
0ae8da 317     }
b1a6a5 318
MC 319     function rewrite_update($event_name, $data) {
0ae8da 320         global $app, $conf;
b1a6a5 321
0ae8da 322         $rules = $this->_getRewriteRules($app);
b1a6a5 323
0ae8da 324         $app->uses('getconf');
4ffb51 325         $nginx_config = $app->getconf->get_server_config($conf['server_id'], 'web');
b1a6a5 326
0ae8da 327         $app->load('tpl');
F 328         $tpl = new tpl();
329         $tpl->newTemplate("nginx_reverseproxy_rewrites.conf.master");
b1a6a5 330         if (!empty($rules))$tpl->setLoop('nginx_rewrite_rules', $rules);
MC 331
4ffb51 332         $rewrites_file = escapeshellcmd($nginx_config['nginx_vhost_conf_dir'].'/default.rewrites.conf');
0ae8da 333         //* Make a backup copy of vhost file
b1a6a5 334         copy($rewrites_file, $rewrites_file.'~');
MC 335
0ae8da 336         //* Write vhost file
b1a6a5 337         file_put_contents($rewrites_file, $tpl->grab());
MC 338         $app->log('Writing the nginx rewrites file: '.$rewrites_file, LOGLEVEL_DEBUG);
0ae8da 339         unset($tpl);
F 340
341
342         // Set the symlink to enable the vhost
4ffb51 343         $rewrite_symlink = escapeshellcmd($nginx_config['nginx_vhost_conf_enabled_dir'].'/default.rewrites.conf');
b1a6a5 344
0ae8da 345         if(!is_link($rewrite_symlink)) {
b1a6a5 346             symlink($rewrites_file, $rewrite_symlink);
MC 347             $app->log('Creating symlink for nginx rewrites: '.$rewrite_symlink.'->'.$rewrites_file, LOGLEVEL_DEBUG);
348         }
0ae8da 349     }
b1a6a5 350
MC 351     function rewrite_delete($event_name, $data) {
0ae8da 352         global $app, $conf;
b1a6a5 353
0ae8da 354         // just run the update function
b1a6a5 355         $this->rewrite_update($event_name, $data);
0ae8da 356     }
b1a6a5 357
0ae8da 358
F 359     function _getRewriteRules($app)
360     {
361         $rules = array();
b1a6a5 362         $rules = $app->db->queryAllRecords("SELECT rewrite_url_src, rewrite_url_dst FROM proxy_reverse ORDER BY rewrite_id ASC");
0ae8da 363         return $rules;
F 364     }
365
366 } // end class
367
368 ?>