### ### Copyright 2000-2007 University of Illinois Board of Trustees ### All rights reserved. ### ### Apache.pm - apache module for psgconf ### ### Campus Information Technologies and Educational Services ### University of Illinois at Urbana-Champaign ### package PSGConf::Control::Apache; use strict; use PSGConf::Action::CopyFile; use PSGConf::Action::ChGrp; use PSGConf::Action::ChMod; use PSGConf::Action::ChOwn; use PSGConf::Action::CreateFile; use PSGConf::Action::GenerateFile::httpd_conf; use PSGConf::Action::GenerateFile::mime_types; use PSGConf::Action::GenerateFile::EnvFile; use PSGConf::Action::MkDir; use PSGConf::Action::svcs::addpg; use PSGConf::Action::svcs::import; use PSGConf::Action::svcs::setprop; use PSGConf::Action::RestartDaemon; use PSGConf::Action::RunCommand; use PSGConf::Data::Boolean; use PSGConf::Data::List; use PSGConf::Data::Hash; use PSGConf::Data::String; use PSGConf::Data::Table; use PSGConf::Control::Packages qw(_add_pkgs); use PSGConf::Util; ############################################################################### ### utility functions ############################################################################### ### canonify Apache host:port strings ### (server_name arg is used for default IP address if specified; ### otherwise, use hostname) sub _canonify_www_addrs { my ($addr, $server_name, $psgconf) = @_; my ($host, $port, @addrs); ($host, $port) = split(/:/, $addr); if ($host =~ m/^([0-9\.]{1,3}\.){3}[0-9\.]{1,3}$/) { ### don't modify if specified by IP address @addrs = ($host); } else { ### convert hostname to IP addresses @addrs = get_addrs($psgconf, $host) if ($host ne ''); ### if DNS lookup fails or if no host is specified @addrs = get_addrs($psgconf, $server_name) if (!@addrs && $server_name ne ''); ### if no server_name is specified or DNS lookup fails @addrs = get_addrs($psgconf, $psgconf->data_obj('hostname')->get()) if (!@addrs); } ### add port $port = '80' if (!defined($port)); @addrs = map { "$_:$port" } @addrs; return @addrs; } ############################################################################### ### policy methods ############################################################################### ### check stuff that depends on www_enable sub _policy_check_enable { my ($self, $psgconf) = @_; if ($psgconf->data_obj('www_enable')->equals('false')) { $psgconf->data_obj('www_vh_ssl')->unset(); $psgconf->data_obj('www_auto_start')->set('false'); } } ### check stuff that depends on www_vh_ssl sub _policy_check_ssl { my ($self, $psgconf) = @_; if (!$psgconf->data_obj('www_vh_ssl')->count()) { $psgconf->data_obj('www_ssl_start_reminder')->set('false'); ### Remove the ssl module as well $psgconf->data_obj('www_modules')->delete_row({0 => 'ssl'}); } } ### initialize default server names sub _policy_default_server_names { my ($self, $psgconf) = @_; return if ($psgconf->data_obj('www_enable')->equals('false')); $psgconf->data_obj('www_ssl_server_name')->set( $psgconf->data_obj('hostname')->get() ) if ($psgconf->data_obj('www_vh_ssl')->count() && ! defined $psgconf->data_obj('www_ssl_server_name')->get()); } ### initialize default vhosts sub _policy_default_vhosts { my ($self, $psgconf) = @_; return if ($psgconf->data_obj('www_enable')->equals('false')); if (defined $psgconf->data_obj('www_server_name')->get() && !defined $psgconf->data_obj('www_virtual_hosts')->find('http')) { $psgconf->data_obj('www_virtual_hosts')->insert( { 'http' => [ $psgconf->data_obj('www_server_name')->get() ] } ); } if (defined $psgconf->data_obj('www_ssl_server_name')->get() && !defined $psgconf->data_obj('www_virtual_hosts')->find('https')) { $psgconf->data_obj('www_virtual_hosts')->insert( { 'https' => [ $psgconf->data_obj('www_ssl_server_name')->get(), ':443' ] } ); $psgconf->data_obj('www_vh_ssl')->insert( { 'https' => undef } ); } } sub _policy_canonify_www_log_dir { my ($self, $psgconf) = @_; my ($syslog); return if ($psgconf->data_obj('www_enable')->equals('false')); ### set logfile location $psgconf->data_obj('www_log_dir')->set('httpd') if (!defined $psgconf->data_obj('www_log_dir')->get()); $psgconf->data_obj('www_log_dir')->prepend( $psgconf->data_obj('log_dir')->get() . '/' ) if (! $psgconf->data_obj('www_log_dir')->match('^/')); ### If we are logging to syslog, then add the ### appropiate syslog.conf entry if ( $psgconf->data_obj('www_log_syslog')->equals('true') ) { if ( $psgconf->data_obj('syslog_enable')->equals('true') ) { ### If we have the format syslog:NAME, grab name to ### put into the syslog.conf file. By default Apache ### uses local7, so assume that if :NAME is missing. $psgconf->data_obj('syslog')->insert( { $psgconf->data_obj('www_log_dir')->get() . '/error_log' => $psgconf->data_obj('www_log_fac')->get() . '.' . $psgconf->data_obj('www_log_level')->get() } ); } } } ### set default pidfile location sub _policy_default_pidfile { my ($self, $psgconf) = @_; return if ($psgconf->data_obj('www_enable')->equals('false')); $psgconf->data_obj('www_global_options')->insert( { 'PidFile' => $psgconf->data_obj('pidfile_dir')->get() . '/httpd.pid' } ) if (!defined $psgconf->data_obj('www_global_options')->find('PidFile')); } ### convert vhost addresses to IP-addr:port sub _policy_default_vhost_addrs { my ($self, $psgconf) = @_; my ($www_virtual_hosts); my ($vhost, $lref, $idx, @addrs); return if ($psgconf->data_obj('www_enable')->equals('false')); $www_virtual_hosts = $psgconf->data_obj('www_virtual_hosts')->get(); foreach $vhost (keys %$www_virtual_hosts) { $www_virtual_hosts->{$vhost} = [ $psgconf->data_obj('hostname')->get() ] if (! defined($www_virtual_hosts->{$vhost})); $lref = $www_virtual_hosts->{$vhost}; if (@$lref < 2) { push(@$lref, _canonify_www_addrs(undef, $lref->[0], $psgconf)); } else { for ($idx = 1; $idx < @$lref; $idx++) { @addrs = _canonify_www_addrs($lref->[$idx], $lref->[0], $psgconf); splice(@$lref, $idx, 1, @addrs); } } } } ### set default listen addresses based on vhost addrs sub _policy_default_listen_addrs { my ($self, $psgconf) = @_; my ($www_listen_addrs, $www_virtual_hosts); my ($vhost, $lref); return if ($psgconf->data_obj('www_enable')->equals('false')); $www_virtual_hosts = $psgconf->data_obj('www_virtual_hosts')->get(); $www_listen_addrs = $psgconf->data_obj('www_listen_addrs')->get(); if (! %$www_listen_addrs) { foreach $vhost (keys %$www_virtual_hosts) { $lref = $www_virtual_hosts->{$vhost}; map { $www_listen_addrs->{$_} = undef; } @$lref[1..$#$lref]; } } } sub _policy_canonify_modules { my ($self, $psgconf) = @_; my ($mod); return if ($psgconf->data_obj('www_enable')->equals('false')); foreach $mod (@{$psgconf->data_obj('www_modules')->get()}) { next if ($mod->[0] eq ''); ### set default module path $mod->[1] = 'mod_' . $mod->[0] . '.so' if (!defined($mod->[1]) || $mod->[1] eq ''); $mod->[1] = $psgconf->data_obj('www_module_dir')->get() . '/' . $mod->[1] if (substr($mod->[1], 0, 1) ne '/'); ### verify that module exists warn "\n\t!!!Apache module $mod->[1] does not exist\n" if (! -e $mod->[1]); ### set default add name $mod->[2] = 'mod_' . $mod->[0] . '.c' if (!defined($mod->[2]) || $mod->[2] eq ''); } } ### determine absolute paths for vhost access logs sub _policy_canonify_vhost_access_logs { my ($self, $psgconf) = @_; my ($www_log_dir, $www_virtual_hosts, $access_logs, $vhost); return if ($psgconf->data_obj('www_enable')->equals('false')); $www_virtual_hosts = $psgconf->data_obj('www_virtual_hosts')->get(); $www_log_dir = $psgconf->data_obj('www_log_dir')->get(); $access_logs = $psgconf->data_obj('www_vh_access_log')->get(); foreach $vhost (keys %$access_logs) { $access_logs->{$vhost} = $www_log_dir . '/' . $access_logs->{$vhost} if (substr($access_logs->{$vhost}, 0, 1) ne '/'); } } ### determine absolute path for document root locations sub _policy_canonify_vhost_doc_roots { my ($self, $psgconf) = @_; my ($www_server_dir, $www_virtual_hosts, $doc_roots, $vhost); return if ($psgconf->data_obj('www_enable')->equals('false')); $www_server_dir = $psgconf->data_obj('www_server_dir')->get(); $www_virtual_hosts = $psgconf->data_obj('www_virtual_hosts')->get(); $doc_roots = $psgconf->data_obj('www_vh_document_root')->get(); foreach $vhost (keys %$doc_roots) { $doc_roots->{$vhost} = $www_server_dir . '/' . $doc_roots->{$vhost} if (substr($doc_roots->{$vhost}, 0, 1) ne '/'); } } ### remove non-existant vhosts from www_vh_* data objs sub _policy_validate_vhost_data { my ($self, $psgconf) = @_; my ($vhost, $directive); return if ($psgconf->data_obj('www_enable')->equals('false')); foreach $directive ( 'www_vh_document_root', 'www_vh_access_log', 'www_vh_ssl', 'www_vh_config' ) { foreach $vhost (keys %{$psgconf->data_obj($directive)->get()}) { $psgconf->data_obj($directive)->delete($vhost) if (!$psgconf->data_obj('www_virtual_hosts')->exists($vhost)); } } } ### set up RC script sub _policy_add_rc_scripts { my ($self, $psgconf) = @_; my ($start_cmd, $sendmail_path); return if ($psgconf->data_obj('www_enable')->equals('false')); if ($psgconf->data_obj('www_ssl_start_reminder')->equals('true')) { $sendmail_path = $psgconf->data_obj('sendmail_path')->get(); $start_cmd = <data_obj('www_apachectl_path')->get() . ' start'; $start_cmd .= 'ssl' if ($psgconf->data_obj('www_vh_ssl')->count()); } if ($psgconf->data_obj('platform')->match('solaris10')) { if ($psgconf->data_obj('www_use_apache2')->equals('true')) { $psgconf->data_obj('rc_scripts')->insert( {'apache2' => { 'state' => 'enable' }} ); } else { $psgconf->data_obj('rc_scripts')->insert( {'apache' => { 'state' => 'enable' }} ); } } else { $psgconf->data_obj('rc_scripts')->insert( {'httpd' => { 'state' => 'enable', 'start_cmd' => $start_cmd, 'stop_cmd' => $psgconf->data_obj('www_apachectl_path')->get() . ' stop' } } ); } } ### create httpd user sub _policy_add_user { my ($self, $psgconf) = @_; return if ($psgconf->data_obj('www_enable')->equals('false')); $psgconf->data_obj('group_info')->insert( { $psgconf->data_obj('www_group_name')->get() => {} } ) if (!defined $psgconf->data_obj('group_info')->find( $psgconf->data_obj('www_group_name')->get())); $psgconf->data_obj('user_info')->insert( { $psgconf->data_obj('www_user_name')->get() => { 'group' => $psgconf->data_obj('www_group_name')->get(), 'passwd' => $psgconf->data_obj('passwd_token')->get(), 'home' => $psgconf->data_obj('www_config_dir')->get(), 'gecos' => 'Apache Webserver', 'shell' => '/bin/false' } } ) if (!defined $psgconf->data_obj('user_info')->find($psgconf->data_obj('www_user_name')->get())); } ### setup webmaster aliases sub _policy_add_sendmail_aliases { my ($self, $psgconf) = @_; return if ($psgconf->data_obj('www_enable')->equals('false')); $psgconf->data_obj('sendmail_aliases')->insert( { $psgconf->data_obj('www_user_name')->get() => 'root' } ) if (!defined $psgconf->data_obj('sendmail_aliases')->find($psgconf->data_obj('www_user_name')->get())); $psgconf->data_obj('sendmail_aliases')->insert( { $psgconf->data_obj('www_admin_alias')->get() => 'root' } ) if (!defined $psgconf->data_obj('sendmail_aliases')->find($psgconf->data_obj('www_admin_alias')->get())); } ### request apache and openssl packages sub _policy_add_packages { my ($self, $psgconf) = @_; $self->_add_pkgs($psgconf); $self->{enable} = 'www_vh_ssl'; $self->{packages} = 'openssl_packages'; $self->_add_pkgs($psgconf); } ### set default www_name_vhost_addrs sub _policy_default_name_vhost_addrs { my ($self, $psgconf) = @_; my ($www_virtual_hosts, $lref, $vhost, $name_vhost_addrs, %addrs); return if ($psgconf->data_obj('www_enable')->equals('false')); $name_vhost_addrs = $psgconf->data_obj('www_name_vhost_addrs')->get(); $www_virtual_hosts = $psgconf->data_obj('www_virtual_hosts')->get(); return if (%$name_vhost_addrs); ### add addresses of all virtual hosts foreach $vhost (keys %$www_virtual_hosts) { $lref = $www_virtual_hosts->{$vhost}; map { $addrs{$_}++; } @$lref[1..$#$lref]; } ### warn if trying to use name-based vhosting for SSL vhost foreach $vhost (keys %$www_virtual_hosts) { $lref = $www_virtual_hosts->{$vhost}; map { warn "\n\t!!!SSL virtual host " . "\"$vhost\" cannot share listen " . "address \"$_\"\n" if ( $psgconf->data_obj('www_vh_ssl')->exists($vhost) && ($addrs{$_} > 1)); } @$lref[1..$#$lref]; } ### those addresses serving more than one vhost are name-based map { $name_vhost_addrs->{$_} = undef if ($addrs{$_} > 1); } keys %addrs; } # # Check to see if svc.confd needs to be stopped & restarted before # importing the apache2 .xml config. # sub _kill_svc_configd { my ($psgconf) = @_; my ($ret); # a return of 1 means that the FMRI doesn't exist, so svc.configd needs # to be killed so we can import the http-apache2 xml file $ret = PSGConf::Util::RunCommand('/usr/bin/svcs http > /dev/null', 1); return $ret; } ############################################################################### ### decide() method ############################################################################### sub decide { my ($self, $psgconf) = @_; my ($www_config_dir, $www_server_dir, @logs, $uid, $gid); return if ($psgconf->data_obj('www_enable')->equals('false')); $www_config_dir = $psgconf->data_obj('www_config_dir')->get(); $www_server_dir = $psgconf->data_obj('www_server_dir')->get(); $uid = ( defined $psgconf->data_obj('user_info')->find($psgconf->data_obj('www_user_name')->get()))? $psgconf->data_obj('user_info')->find($psgconf->data_obj('www_user_name')->get())->{'uid'}: -1; $gid = ( defined $psgconf->data_obj('user_info')->find($psgconf->data_obj('www_user_name')->get()))? $psgconf->data_obj('user_info')->find($psgconf->data_obj('www_user_name')->get())->{'gid'}: -1; $psgconf->data_obj('www_mime_dir')->set($www_config_dir) if ( ! defined $psgconf->data_obj('www_mime_dir')->get() ); @logs = ( $psgconf->data_obj('www_log_dir')->get() . '/access_log' ); push @logs, $psgconf->data_obj('www_log_dir')->get() . '/error_log' if ($psgconf->data_obj('www_log_syslog')->equals('false')); push @logs, $psgconf->data_obj('www_log_dir')->get() . '/suexec' if ( -f $psgconf->data_obj('www_log_dir')->get() . '/suexec' ); map { push @logs, $_; } values %{$psgconf->data_obj('www_vh_access_log')->get()}; push @logs, $psgconf->data_obj('www_log_dir')->get() . '/ssl_engine_log' if ( $psgconf->data_obj('www_vh_ssl')->count() ); push @logs, $psgconf->data_obj('www_jk_logfile')->get() if ( $psgconf->data_obj('www_jk_enable')->equals('true') ); ### set up config and content trees $psgconf->register_actions( PSGConf::Action::MkDir->new( name => $www_server_dir ), PSGConf::Action::MkDir->new( name => $psgconf->data_obj('www_document_dir')->get() ), (map { PSGConf::Action::MkDir->new( name => $_ ) } (sort values %{$psgconf->data_obj('www_vh_document_root')->get()})), PSGConf::Action::MkDir->new( name => $psgconf->data_obj('www_log_dir')->get(), uid => $uid, gid => $gid, mode => 0755 ), (map { if ( ! -f $_ ) { PSGConf::Action::CreateFile->new( name => $_, mode => 0644, uid => $uid, gid => $gid ); } else { PSGConf::Action::ChMod->new( name => $_, mode => 0644 ), PSGConf::Action::ChOwn->new( name => $_, uid => $uid ), PSGConf::Action::ChGrp->new( name => $_, gid => $gid ); } } @logs), PSGConf::Action::MkDir->new( name => $www_config_dir, uid => $uid, gid => $gid, mode => 0755 ), ($psgconf->data_obj('www_vh_ssl')->count() ? (PSGConf::Action::MkDir->new( name => $www_config_dir . '/ssl.key', mode => 0700 ), PSGConf::Action::MkDir->new( name => $www_config_dir . '/ssl.csr' ), PSGConf::Action::MkDir->new( name => $www_config_dir . '/ssl.crt' ) ) : () ), PSGConf::Action::GenerateFile::httpd_conf->new( name => "$www_config_dir/httpd.conf", description => 'Apache httpd configuration', use_apache2 => $psgconf->data_obj('www_use_apache2')->equals('true'), pidfile_dir => $psgconf->data_obj('pidfile_dir')->get(), icons_dir => $psgconf->data_obj('www_icons_dir')->get(), server_dir => $psgconf->data_obj('www_server_dir')->get(), document_dir => $psgconf->data_obj('www_document_dir')->get(), default_allowoverride => $psgconf->data_obj('www_default_allowoverride')->get(), config_dir => $psgconf->data_obj('www_config_dir')->get(), mime_dir => $psgconf->data_obj('www_mime_dir')->get(), user_name => $psgconf->data_obj('www_user_name')->get(), group_name => $psgconf->data_obj('www_group_name')->get(), log_level => $psgconf->data_obj('www_log_level')->get(), ssl_log_level => $psgconf->data_obj('www_ssl_log_level')->get(), ssl_cipher_suite => $psgconf->data_obj('www_ssl_cipher_suite')->get(), log_dir => $psgconf->data_obj('www_log_dir')->get(), log_syslog => $psgconf->data_obj('www_log_syslog')->get(), log_fac => $psgconf->data_obj('www_log_fac')->get(), global_options => $psgconf->data_obj('www_global_options')->get(), listen_addrs => $psgconf->data_obj('www_listen_addrs')->get(), virtual_hosts => $psgconf->data_obj('www_virtual_hosts')->get(), vh_ssl => $psgconf->data_obj('www_vh_ssl')->get(), global_config => $psgconf->data_obj('www_global_config')->get(), modules => $psgconf->data_obj('www_modules')->get(), module_dir => $psgconf->data_obj('www_module_dir')->get(), main_server_name => $psgconf->data_obj('hostname')->get(), main_server_options => $psgconf->data_obj('www_main_server_options')->get(), main_server_config => $psgconf->data_obj('www_main_server_config')->get(), main_admin_alias => $psgconf->data_obj('www_admin_alias')->get(), vh_document_root => $psgconf->data_obj('www_vh_document_root')->get(), vh_access_log => $psgconf->data_obj('www_vh_access_log')->get(), vh_config => $psgconf->data_obj('www_vh_config')->get(), name_vhost_addrs => $psgconf->data_obj('www_name_vhost_addrs')->get() ), PSGConf::Action::CopyFile->new( name => "$www_config_dir/magic", copy_from => 'magic' ), PSGConf::Action::GenerateFile::mime_types->new( name => $psgconf->data_obj('www_mime_dir')->get() . '/mime.types', description => 'Apache MIME types file', types => $psgconf->data_obj('www_mime_types')->get() ) ); ### ### Since the apache2 import does not work correctly, ### it was recommended to HUP svc.configd instead. ### $psgconf->register_actions( PSGConf::Action::RunCommand->new( name => 'Kill svc.configd', command => '/usr/bin/pkill svc.configd', check_func => \&_kill_svc_configd ), PSGConf::Action::RunCommand->new( name => 'sleep for 10 seconds', command => '/usr/bin/sleep 10', check_func => \&_kill_svc_configd ), PSGConf::Action::svcs::import->new( name => 'Import Apache2 SMF configurations', FMRI => 'svc:/network/http:apache2', manifest => '/var/svc/manifest/network/http-apache2.xml' ), ### FIXME: The following is a hack to fix the problem ### (Sun Bug ID #6270245) where apache2 starts before ### the filesystem is mounted RW when you are using SVM ### to mirror the boot disks. PSGConf::Action::svcs::addpg->new( name => 'Adding filesystem-local dependency', FMRI => 'svc:/network/http:apache2', group => 'filesystem-local', type => 'dependency', refresh => 0 ), PSGConf::Action::svcs::setprop->new( name => 'set entities property', FMRI => 'svc:/network/http:apache2', property => 'filesystem-local/entities', value => 'fmri: svc:/system/filesystem/local:default', refresh => 0 ), PSGConf::Action::svcs::setprop->new( name => 'set grouping property', FMRI => 'svc:/network/http:apache2', property => 'filesystem-local/grouping', value => 'astring: require_all', refresh => 0 ), PSGConf::Action::svcs::setprop->new( name => 'set restart_on property', FMRI => 'svc:/network/http:apache2', property => 'filesystem-local/restart_on', value => 'astring: none', refresh => 0 ), PSGConf::Action::svcs::setprop->new( name => 'set type property', FMRI => 'svc:/network/http:apache2', property => 'filesystem-local/type', value => 'astring: service', refresh => 1 ) ) if ( $psgconf->data_obj('www_use_apache2')->equals('true') && $psgconf->data_obj('platform')->match('solaris10') ); $psgconf->register_actions( PSGConf::Action::svcs::setprop->new( name => 'enable Apache2 SSL', FMRI => 'svc:/network/http:apache2', property => 'httpd/ssl', value => 'true', refresh => 0 ) ) if (defined $psgconf->data_obj('www_ssl_server_name')->get() && $psgconf->data_obj('www_use_apache2')->equals('true') && $psgconf->data_obj('platform')->match('solaris10') ); $psgconf->register_actions( PSGConf::Action::RunCommand->new( name => 'Restart Apache', command => $psgconf->data_obj('www_apachectl_path')->get() . ' graceful', filename => [ "$www_config_dir/httpd.conf" ] ) ) if ($psgconf->{'restart_daemons'}); $psgconf->register_actions( PSGConf::Action::GenerateFile::EnvFile->new( name => '/etc/sysconfig/httpd', description => 'Apache startup options', quote_values => 1, vars => { OPTIONS => ($psgconf->data_obj('www_vh_ssl')->count())? '-DSSL': '' } ) ) if ($psgconf->data_obj('platform')->match('(-rhel-)|(-rhl-)|(-fc-)')); } ############################################################################### ### Constructor ############################################################################### sub new { my ($class, $psgconf) = @_; my ($self); $self = {}; bless($self, $class); ### So that _add_pkgs knows which directives to look at $self->{name} = 'www'; $self->{enable} = $self->{name} . '_enable'; $self->{packages} = $self->{name} . '_packages'; $psgconf->register_data( 'www_apachectl_path' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/usr/local/sbin/apachectl' ), 'www_auto_start' => PSGConf::Data::Boolean->new( value => 'false' ), 'www_packages' => PSGConf::Data::List->new(), 'openssl_packages' => PSGConf::Data::List->new(), 'www_config_dir' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/usr/local/etc/apache' ), 'www_mime_dir' => PSGConf::Data::String->new( 'value_abspath' => 1 ), 'www_enable' => PSGConf::Data::Boolean->new( value => 'false' ), 'www_use_apache2' => PSGConf::Data::Boolean->new( value => 'false' ), 'www_default_allowoverride' => PSGConf::Data::String->new( value => 'None' ), 'www_global_config' => PSGConf::Data::String->new(), 'www_global_options' => PSGConf::Data::Hash->new(), 'www_icons_dir' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/usr/local/share/apache/icons' ), 'www_listen_addrs' => PSGConf::Data::Hash->new( value_optional => 1 ), 'www_name_vhost_addrs' => PSGConf::Data::Hash->new( value_optional => 1 ), 'www_log_dir' => PSGConf::Data::String->new(), 'www_log_syslog' => PSGConf::Data::Boolean->new( value => 'false' ), 'www_log_fac' => PSGConf::Data::String->new( value => 'local7' ), 'www_log_level' => PSGConf::Data::String->new( value => 'warn' ), 'www_ssl_log_level' => PSGConf::Data::String->new( value => 'info' ), 'www_user_name' => PSGConf::Data::String->new( value => 'httpd' ), 'www_group_name' => PSGConf::Data::String->new( value => 'httpd' ), 'www_admin_alias' => PSGConf::Data::String->new( value => 'webmaster' ), 'www_main_server_config' => PSGConf::Data::String->new(), 'www_main_server_options' => PSGConf::Data::Hash->new(), 'www_mime_types' => PSGConf::Data::Hash->new( value_optional => 1, value_type => 'HASH' ), 'www_modules' => PSGConf::Data::Table->new(), 'www_module_dir' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/usr/local/libexec' ), 'www_server_name' => PSGConf::Data::String->new(), 'www_server_dir' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/services/www' ), 'www_document_dir' => PSGConf::Data::String->new( 'value_abspath' => 1, value => '/services/www/htdocs' ), 'www_ssl_server_name' => PSGConf::Data::String->new(), 'www_ssl_cipher_suite' => PSGConf::Data::String->new( value => 'ALL:!ADH:!EXP56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL' ), 'www_ssl_start_reminder' => PSGConf::Data::Boolean->new( value => 'false' ), 'www_virtual_hosts' => PSGConf::Data::Hash->new( value_type => 'ARRAY', value_optional => 1 ), 'www_vh_config' => PSGConf::Data::Hash->new(), 'www_vh_document_root' => PSGConf::Data::Hash->new(), 'www_vh_access_log' => PSGConf::Data::Hash->new(), 'www_vh_ssl' => PSGConf::Data::Hash->new( value_optional => 1 ) ); $psgconf->register_policy($self, apache_check_enable => '_policy_check_enable', apache_check_ssl => '_policy_check_ssl', apache_canonify_modules => '_policy_canonify_modules', apache_default_server_names => '_policy_default_server_names', apache_default_vhosts => '_policy_default_vhosts', apache_default_vhost_addrs => '_policy_default_vhost_addrs', apache_default_listen_addrs => '_policy_default_listen_addrs', apache_default_pidfile => '_policy_default_pidfile', apache_validate_vhost_data => '_policy_validate_vhost_data', apache_default_name_vhost_addrs => '_policy_default_name_vhost_addrs', apache_canonify_www_log_dir => '_policy_canonify_www_log_dir', apache_canonify_vhost_access_logs => '_policy_canonify_vhost_access_logs', apache_canonify_vhost_doc_roots => '_policy_canonify_vhost_doc_roots', apache_add_rc_scripts => '_policy_add_rc_scripts', apache_add_user => '_policy_add_user', apache_add_sendmail_aliases => '_policy_add_sendmail_aliases', apache_add_packages => '_policy_add_packages' ); return $self; } ############################################################################### ### documentation ############################################################################### 1; __END__ =head1 NAME PSGConf::Control::Apache - psgconf control class for Apache =head1 SYNOPSIS In F: Control PSGConf::Control::Apache =head1 DESCRIPTION The B module provides a B control object for configuring the Apache webserver. It supports the following methods: =over 4 =item new() The constructor. Its parameter is a reference to the B object. It registers the following data objects: =over 4 =item I A B object containing the absolute path to the I command. The default is F. =item I A B object indicating whether Apache should be started automatically at boot time. =item I A B object listing what apache packages to install. =item I A B object listing what openssl packages to install. =item I A B object containing the absolute path to the Apache configuration directory. The default is F. =item I A B object containing the absolute path to the directory the mime.types file resides in. The default is I directive value. =item I A B object indicating whether Apache should be configured. =item I A B object indicating whether Apache2 syntax should be used in the config file. =item I A B object containing the default value for AllowOverride that gets put into the virtual host DocumentRoot as well as the global DocumentRoot sections. Defaults to C. =item I A B object containing global configuration directives for F. =item I A B object containing global configuration options (and the corresponding values) for F. =item I A B object containing the absolute path to the Apache icons directory. The default is F. =item I A B object whose keys are the addresses and ports to bind to. Each key is a string of the form C, C
, C, or C. If C<:port> is not specified, it defaults to port 80. =item I A B object containing the name of the login to run the httpd process as. The default is B. =item I A B object containing the name of the group to run the httpd process as. The default is B. =item I A B object containing the path to the Apache log directory. If not an absolute path, it will be located under the directory specified by the I data object (which is provided by the B module). =item I A B object telling apache to use the C facility to do the logging. The default is no to. =item I A B object containing the syslog facility to log to. Defaults to I. =item I A B object containing the verbosity of the logs. The default is B. =item I A B object containing the verbosity of the logs. The default is B. =item I A B object containing configuration directives for the main virtual host. =item I A B object containing configuration options (and the corresponding values) for the main virtual host. =item I A B object containing the name of the email alias to send problems to. The default is B. =item I A B object containing MIME types (e.g., C) to an anonymous hash whose keys are the list of file extensions used for that MIME type. =item I A B object containing the list of Apache modules to load. Each row in the table consists of the following fields: module name, filename (if different from F), argument to C directive (if different from F), and conditional value (i.e., set to C to wrap the C and C directives in a CIfModule SSLE> block). =item I A B object that contains the absolute path to the Apache modules. The default is F. =item I A B object whose keys are the address/port pairs for which name-based virtual hosting should be used. =item I A B object containing the server name of the C virtual host. (This is the same as creating an C entry in the I object.) =item I A B object that contains the absolute path to the Apache content tree. The default is F. =item I A B object that contains the absolute path to the Apache DocumentRoot tree. The default is F. =item I A B object containing the server name of the C virtual host. (This is the same as creating an C entry in the I and I objects.) =item I A B object containing the codes for the C directive I. Defaults to I =item I A B object that indicates whether the boot script should print and email a reminder that Apache needs to be started manually. =item I A B object that contains virtual host definitions. The hash key is the label for the virtual host, and the value is a reference to a list containing the server name followed by zero or more addresses. The addresses are strings of the form C, C
, C, C, or just C<:port>. If C<:port> is not specified, it defaults to port 80. If no hostname or address is specified, it defaults to the IP address of the server name. =item I A B object that contains a configuration directives for each virtual host. The hash key is the name of the virtual host, and the value is the text that should be placed within the virtual host block. =item I A B object that contains the document root for each virtual host. The hash key is the name of the virtual host, and the value is the document root directory. If not an absolute path, the directory will be located in the directory specified by the I data object. =item I A B object that contains the access log name for each virtual host. The hash key is the name of the virtual host, and the value is the name of the log file. If not an absolute path, the file will be placed in the directory specified by the I data object. =item I A B object whose keys are the names of virtual hosts which serve HTTPS requests. =back In addition, the constructor registers the following policy methods: =over 4 =item I If I is not set, unsets I and I. =item I If I is not set, unset I. =item I If I is set, updates I and I from I if they are not set. =item I If I is set, updates I and I based on I and I. =item I If the value of the I data object is not an absolute path, prepends the value of the I data object (supplied by the B module). =item I If the I object does not have an entry for C, set it to F/httpd.pid>. (The I data object is provided by the B module.) =item I Canonifies information for each entry in I. If no server name is specified, set it to I. If no addresses are specified, add the IP address of our primary network interface; if no port is specified, set it to 80. =item I If I is not set, add the addresses of every virtual host. =item I For each entry in I, if the module path is not set, set it to F. If the module add name is not set, set it to C. =item I For each value in I that is not an absolute path, prepends the value of the I data object. =item I For each value in I that is not an absolute path, prepends the value of the I data object. =item I Deletes entries in I, I, I, and I for virtual hosts that are not listed in I. =item I Requests an RC script for Apache using the I data object, which is supplied by the B module. =item I Adds a user and group named C to the I and I data objects, supplied by the B module. =item I If mail aliases for C and C do not exist, make them point to C. This is done using the I data object, which is provided by the B module. =item I Request the C package be installed. If I is set, also request the C package. Packages are requested using the B data object, which is provided by the B module. =item I If I is not set, add all addresses/port pairs that are used by more than one virtual host. =back =item decide() Instantiates and registers action objects, as follows: =over 4 =item * Registers a B action object to create the I directory. =item * Registers a B action object to create the F/htdocs> directory, which is the document root for the main server. =item * Registers a B action object to create the document root for each virtual host. =item * Registers a B action object to create the I directory. This directory will be owned by user and group I. =item * Registers a B action object to create the I directory. =item * If the I object has any entries, registers a B action object to create the F/ssl.key> directory. =item * If the I object has any entries, registers a B action object to create the F/ssl.csr> directory. =item * If the I object has any entries, registers a B action object to create the F/ssl.crt> directory. =item * Registers a B object to generate the F/httpd.conf> file. =item * Registers a B object to generate the F/mime.types> file. =item * Registers a B action object to install the F file in I. =back =back =head1 BUGS Instead of distributing canned versions of the F file, it should be generated dynamically from config data. Some F data is still hard-coded. This should be made more flexible. =head1 SEE ALSO L httpd(8) apachectl(8) L L L L L L L L L L L L L L L L L L L L L L L L =cut