├── .fixtures.yml ├── .gitignore ├── .pmtignore ├── .rspec ├── .rubocop.yml ├── .travis.yml ├── Gemfile ├── README.md ├── Rakefile ├── lib └── puppet │ ├── provider │ ├── directadmin.rb │ ├── directadmin_admin │ │ └── directadmin.rb │ ├── directadmin_reseller │ │ └── directadmin.rb │ ├── directadmin_reseller_package │ │ └── directadmin.rb │ └── directadmin_user_package │ │ └── directadmin.rb │ └── type │ ├── directadmin_admin.rb │ ├── directadmin_reseller.rb │ ├── directadmin_reseller_package.rb │ └── directadmin_user_package.rb ├── manifests ├── config │ └── set.pp ├── custombuild.pp ├── custombuild │ └── set.pp ├── directories.pp ├── init.pp ├── install.pp ├── mail.pp ├── mail │ ├── exim │ │ ├── config.pp │ │ └── virtual.pp │ └── spamassassin │ │ ├── config.pp │ │ └── score.pp ├── modsecurity.pp ├── params.pp ├── resources.pp ├── services.pp ├── services │ └── named.pp ├── update.pp └── user_ssl.pp ├── metadata.json ├── spec ├── acceptance │ ├── class_spec.rb │ └── nodesets │ │ ├── centos6.yml │ │ ├── centos7.yml │ │ ├── debian7.yml │ │ ├── debian8.yml │ │ ├── default.yml │ │ ├── ubuntu1404.yml │ │ └── ubuntu1604.yml ├── classes │ ├── coverage_spec.rb │ ├── directadmin_custombuild_spec.rb │ ├── directadmin_directories_spec.rb │ ├── directadmin_init_spec.rb │ ├── directadmin_install_spec.rb │ ├── directadmin_mail_spec.rb │ ├── directadmin_modsecurity_spec.rb │ ├── directadmin_resources_spec.rb │ ├── directadmin_service_named_spec.rb │ └── directadmin_services_spec.rb ├── defines │ ├── directadmin_config_set_spec.rb │ ├── directadmin_custombuild_set_spec.rb │ ├── directadmin_mail_exim_config_spec.rb │ ├── directadmin_mail_exim_virtual_spec.rb │ ├── directadmin_mail_spamassassin_config_spec.rb │ ├── directadmin_mail_spamassassin_score_spec.rb │ └── directadmin_user_ssl_spec.rb ├── spec_helper.rb └── spec_helper_acceptance.rb └── templates └── modsecurity └── modsec-wordpress.conf.erb /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | forge_modules: 3 | stdlib: 4 | repo: "puppetlabs/stdlib" 5 | ref: "4.6.0" 6 | symlinks: 7 | directadmin: "#{source_dir}" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.sw? 2 | /pkg 3 | /spec/fixtures/manifests 4 | /spec/fixtures/modules 5 | /.rspec_system 6 | /.vagrant 7 | /.bundle 8 | /vendor 9 | /Gemfile.lock 10 | /junit 11 | /log 12 | .yardoc 13 | coverage 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /.pmtignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | Exclude: 3 | - '**/*.erb' 4 | - 'vendor/**/*' 5 | - 'spec/fixtures/**/*' 6 | 7 | # Bug: https://github.com/bbatsov/rubocop/issues/3752 8 | # This is only added in rubocop 0.46 9 | Bundler/DuplicatedGem: 10 | Enabled: false 11 | 12 | # Support for 1.9.3 13 | # https://github.com/bbatsov/ruby-style-guide#percent-i 14 | Style/SymbolArray: 15 | Enabled: false 16 | 17 | # This fails on older Puppet versions for some reason 18 | Style/WordArray: 19 | Enabled: false 20 | 21 | # This isn't really necessary as they limit us in how 22 | # long text can be when describing a test 23 | Metrics/BlockLength: 24 | Enabled: false 25 | 26 | # There is no real reason to check for line length 27 | Metrics/LineLength: 28 | Enabled: false 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | sudo: false 3 | language: ruby 4 | bundler_args: --without development system_tests 5 | before_install: rm Gemfile.lock || true 6 | rvm: 7 | - 2.1.0 8 | - 2.3.0 9 | script: bundle exec rake test 10 | env: 11 | - PUPPET_VERSION="~> 4.7.0" 12 | - PUPPET_VERSION="~> 4.8.0" 13 | - PUPPET_VERSION="~> 4.9.0" 14 | - PUPPET_VERSION="~> 5.0.0" 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source ENV['GEM_SOURCE'] || 'https://rubygems.org' 2 | 3 | puppetversion = ENV.key?('PUPPET_VERSION') ? ENV['PUPPET_VERSION'] : ['~> 4.7.0'] 4 | gem 'facter', '>= 1.7.0' 5 | gem 'metadata-json-lint', '< 2.0.0' 6 | gem 'puppet', puppetversion 7 | gem 'puppet-lint', '>= 1.0.0' 8 | gem 'puppetlabs_spec_helper', '>= 1.0.0' 9 | gem 'rspec-puppet', '~> 2.6.0' 10 | gem 'rspec-puppet-facts', '~> 1.9.0' 11 | gem 'rubocop', '>= 0.48.1' 12 | gem 'safe_yaml', '~> 1.0.4' 13 | gem 'simplecov', require: false 14 | gem 'simplecov-console', require: false 15 | 16 | group :system_tests do 17 | gem 'beaker', '<= 2.51.0' if RUBY_VERSION < '2.2.5' 18 | gem 'beaker-puppet_install_helper' 19 | gem 'beaker-rspec' 20 | gem 'nokogiri', '< 1.7.0' if RUBY_VERSION < '2.1.0' 21 | gem 'public_suffix', '<= 1.4.6' if RUBY_VERSION < '2.0.0' 22 | end 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # directadmin 2 | 3 | [![Build Status](https://travis-ci.org/sensson/puppet-directadmin.svg?branch=master)](https://travis-ci.org/sensson/puppet-directadmin) [![Puppet Forge](https://img.shields.io/puppetforge/v/sensson/directadmin.svg?maxAge=2592000?style=plastic)](https://forge.puppet.com/sensson/directadmin) 4 | 5 | This module is used to configure DirectAdmin. 6 | 7 | It can manage the installation of DirectAdmin, admin and reseller users and their 8 | packages. It is not meant to replace the API or other functionality from DirectAdmin. 9 | 10 | Pull requests and bug reports are always appreciated. 11 | 12 | ## Examples 13 | 14 | ### Installation and configuration 15 | 16 | This will install DirectAdmin if it has not been installed yet. You will need 17 | to specify the client and license id here. Keep in mind that when you enable 18 | this module on an existing server, certain options may be overwritten. 19 | 20 | If you don't specify an `interface` it will default to venet0:0 on OpenVZ containers 21 | and eth0 on other systems. You can override this setting or not set it at all. 22 | 23 | Set `lan` to true when using [DirectAdmin behind a NAT](http://www.directadmin.com/lan.shtml). 24 | 25 | ``` 26 | class { 'directadmin': 27 | clientid => '1000', 28 | licenseid => '10000', 29 | interface => 'eth0', 30 | admin_password => '$1$xyz$4SuXM/NcNyHdr1j2DppL5/', 31 | lan => false, 32 | } 33 | ``` 34 | 35 | ## Reference 36 | 37 | ### Parameters 38 | 39 | #### directadmin 40 | 41 | We provide a number of configuration options to change particular settings 42 | or to override our defaults when required. 43 | 44 | ##### `clientid` 45 | 46 | This is the client id for your DirectAdmin license. Required. Defaults to undef. 47 | 48 | ##### `licenseid` 49 | 50 | This is the licence id for your DirectAdmin license. Required. Defaults to undef. 51 | 52 | ##### `interface` 53 | 54 | Change the interface for your license. Defaults to eth0 or venet0:0 on OpenVZ. 55 | 56 | ##### `auto_update` 57 | 58 | Set this to true if you want Puppet to check for custombuild updates. Defaults to false. 59 | 60 | ##### `admin_password` 61 | 62 | Manage the admin user password. Recommended if you want to manage admin users, reseller 63 | packages and resellers. This needs to be a hash. Defaults to undef. 64 | 65 | ##### `lan` 66 | 67 | Set `lan` to true when using [DirectAdmin behind a NAT](http://www.directadmin.com/lan.shtml). 68 | 69 | ##### `mail_limit` 70 | 71 | Set a maximum outgoing mail limit per user account. Defaults to 200. 72 | 73 | ##### `mail_limit_per_address` 74 | 75 | Set a maximum outgoing mail limit per e-mail address. Defaults to 0 (no limit). 76 | 77 | ##### `sa_updates` 78 | 79 | Set this to true if you want to enable daily SpamAssassin updates. Defaults to false. 80 | 81 | ##### `php_imap` 82 | 83 | Set this to true if you want to enable the imap extension in PHP. Defaults to false. 84 | 85 | ##### `default_webmail` 86 | 87 | Set the default webmail client. Defaults to roundcube. 88 | 89 | ##### `default_rbl` 90 | 91 | This creates a symlink that makes sure all e-mail domains are checked agains the RBL's 92 | in Exim. Defaults to false. 93 | 94 | ##### `installer_location` 95 | 96 | Override the DirectAdmin installer location. Defaults to http://www.directadmin.com/setup.sh. 97 | 98 | ##### `modsecurity` 99 | 100 | Enable ModSecurity. Defaults to false. 101 | 102 | ##### `modsecurity_ruleset` 103 | 104 | Enable a ModSecurity ruleset. Valid options comodo/owasp/false. Defaults to false. 105 | 106 | ##### `modsecurity_wordpress` 107 | 108 | Enable a WordPress brute force prevention ruleset. Defaults to false. 109 | 110 | #### directadmin::services::named 111 | 112 | We currently only support managing small portions of named. We have implemented two features: 113 | 114 | * Managing also-notify, allow-transfer and notify settings 115 | * Managing named rewrites (in case you are managing custom DNS templates) 116 | 117 | You can enable `also-notify` and `allow-transfer` by passing the relevant parameters to this class. 118 | 119 | ``` 120 | class directadmin::services::named { also-notify => '1.2.3.4', allow-transfer => '1.2.3.4' } 121 | ``` 122 | 123 | Aside from that this module allows you to rewrite named, e.g. what's described here: 124 | http://help.directadmin.com/item.php?id=141 125 | 126 | You can do this with: 127 | 128 | ``` 129 | notify => Exec['rewrite-named-config'], 130 | ``` 131 | 132 | ##### `allow_transfer` 133 | 134 | Set up an IP address to allow zone transfers. Defaults to ''. 135 | 136 | ##### `also_notify` 137 | 138 | Also notify this IP address when zone changes occur. Defaults to ''. 139 | 140 | ##### `ensure_transfer` 141 | 142 | Make sure this configuration exists or not. Defaults to 'present'. 143 | 144 | ##### `ensure_notify` 145 | 146 | Make sure this configuration exists or not. Defaults to 'present.' 147 | 148 | ### Defines 149 | 150 | #### directadmin::config::set 151 | 152 | This module allows you to configure DirectAdmin. We support all DirectAdmin 153 | configuration settings. Be careful though, we don't check if the settings are 154 | actually valid. It will set it to whatever value you have specified. 155 | 156 | ``` 157 | directadmin::config::set { 'brute_force_log_scanner': value => '0', } 158 | ``` 159 | 160 | It also supports Hiera. If you want, you can specify a number of settings by simply 161 | adding something similar to the following to your node's configuration files: 162 | 163 | ``` 164 | directadmin::config::options: 165 | brute_force_log_scanner: 166 | value: 0 167 | timeout: 168 | value: 30 169 | enable_ssl_sni: 170 | value: 1 171 | ``` 172 | 173 | ##### `value` 174 | 175 | Set the value of the configuration item you want to change. Defaults to '' 176 | 177 | #### directadmin::custombuild::set 178 | 179 | Custombuild plays an important role in DirectAdmin's configurations and settings of 180 | the software it uses to provide its services. Custombuild can be managed with this 181 | module in a similar fashion as you would expect the command line to work. It is 182 | automatically installed when you use this module. 183 | 184 | We support all options Custombuild supports out of the box. There will never be any 185 | addtional configuration required. If you want to change an option you can use the 186 | following function: 187 | 188 | ``` 189 | directadmin::custombuild::set { 'php1_release': value => '5.5', } 190 | ``` 191 | 192 | It also supports Hiera. If you want, you can specify a number of settings by simply 193 | adding something similar to the following to your node's configuration files: 194 | 195 | ``` 196 | directadmin::custombuild::options: 197 | php1_release: 198 | value: '5.5' 199 | mysql: 200 | value: '5.5' 201 | apache_ver: 202 | value: '2.4' 203 | spamassassin: 204 | value: 'yes' 205 | ``` 206 | 207 | All settings can be set before the installation runs. 208 | 209 | When you make any changes to a setting in the custombuild options class it will 210 | automatically update the setting in /usr/local/directadmin/custombuild/options.conf but 211 | it will not trigger a reinstallation of a particular feature in custombuild. If you do 212 | want to do this, you can. For example by using something similar as the code below. 213 | 214 | ``` 215 | exec { 'rebuild-php': 216 | command => '/usr/local/directadmin/custombuild/build php n', 217 | subscribe => Directadmin::Custombuild::Set['php1_release'], 218 | require => Class['directadmin::install'], 219 | refreshonly => true, 220 | } 221 | ``` 222 | 223 | ##### `value` 224 | 225 | Set the value of the configuration item you want to change. Defaults to '' 226 | 227 | #### directadmin::mail::spamassassin::score 228 | 229 | If you need to set custom rules for SpamAssassin you can do so with the following function: 230 | 231 | ``` 232 | directadmin::mail::spamassassin::score { 'URIBL_BLOCKED': score => 3, } 233 | ``` 234 | 235 | ##### `score` 236 | 237 | Set the score for a specific SpamAssassin check. Defaults to 1. 238 | 239 | #### directadmin::mail::spamassassin::config 240 | 241 | This allows you to create larger configuration files with specific settings. These configuration 242 | files will be created in /etc/mail/spamassassin. It is possible to specify a prefix with the 243 | `order` parameter as SpamAssassin reads these files in alphabetical order. 244 | 245 | The filename will be `$order-$title.cf` and cannot be changed. 246 | 247 | ##### `ensure` 248 | 249 | Valid values: present, absent. Defaults to 'present'. 250 | 251 | ##### `content` 252 | 253 | Set the content of the configuration file. Defaults to ''. 254 | 255 | ##### `order` 256 | 257 | Set the order in which the files should be read. Numeric values are recommended. Defaults to '99'. 258 | 259 | #### directadmin::mail::exim::config 260 | 261 | This allows you to set override custom configurations such as in exim.strings.conf.custom. It takes 262 | title as its setting. It will automatically notify Exim to reload. 263 | 264 | ##### `file` 265 | 266 | Valid values are e.g. 'exim.strings.conf.custom'. Do not specify a path. Defaults to 'undef'. 267 | 268 | ##### `value` 269 | 270 | Set the value for the setting you're changing. Defaults to 'undef'. 271 | 272 | #### directadmin::mail::exim::virtual 273 | 274 | This allows you to set values in /etc/virtual. You can manage 'skip_rbl_hosts_ip' for example. 275 | 276 | ##### `file` 277 | 278 | Valid values are e.g. 'skip_rbl_hosts_ip'. Do not specify a path. Defaults to 'undef'. 279 | 280 | ##### `value` 281 | 282 | Set the value. Defaults to 'undef'. 283 | 284 | ### Resources 285 | 286 | DirectAdmin provides an API to automate certain actions. This module implements a few resources 287 | to simplify the initial set up of a server with DirectAdmin. It's not going to replace the existing 288 | web interface as it is simply not meant for that. Please keep in mind that this is a very basic 289 | implementation of resources for Puppet, not all features are supported. They are considered helper 290 | functions. They will add or remove resources only. 291 | 292 | You may want to have a look at the DirectAdmin API docs to see what certain settings do or require. 293 | Resources will in most cases follow the directions in http://www.directadmin.com/api.html. 294 | 295 | Every resource will have the following settings: 296 | 297 | * `api_username` needs to be set to the user with access to the API. 298 | * `api_password` is the password for the user mentioned before. 299 | * `api_hostname` you need to change this if your API is not accessible on localhost. 300 | * `api_port` if you run DirectAdmin on a different port than 2222 this allows you to change that. 301 | 302 | NOTE: As the installer will not return a username or password to Puppet and we have not and will not 303 | implement a feature that reads passwords from setup.txt for example, we recommend that you set up 304 | a resource to manage the admin user before running any custom resources, e.g. just after the installer 305 | has finished. 306 | 307 | #### Set up a new admin user 308 | 309 | It only manages the `email` and `password` property. Changing them will update the user. 310 | 311 | ``` 312 | directadmin_admin { "username": 313 | ensure => present, 314 | password => "password", 315 | email => "your@email.address" 316 | notifications => "no", 317 | api_username => "admin", 318 | api_password => "api_password", 319 | api_hostname => "localhost (default)", 320 | api_port => "2222 (default)", 321 | api_ssl => false (default), 322 | } 323 | ``` 324 | 325 | #### Set up a new reseller package 326 | 327 | You will need to set up a reseller package before you can create a reseller. All values 328 | are manageable, as in, you can change them after a package has been created. Renaming 329 | packages is not supported though. 330 | 331 | ``` 332 | directadmin_reseller_package { "newpackage2": 333 | ensure => present, 334 | aftp => on, 335 | bandwidth => 1000, 336 | catchall => on, 337 | cgi => on, 338 | cron => on, 339 | dns => off/two/three, 340 | dnscontrol => on, 341 | domainptr => 2000, 342 | domains => 3000, 343 | ftp => 4000, 344 | inodes => 5000, 345 | ips => 1, 346 | login_keys => on, 347 | mysql => 6000, 348 | nemailf => 7000, 349 | nemails => 8000, 350 | nemailml => 9000, 351 | nemailr => 10000, 352 | nsubdomains => 11000, 353 | quota => 12000, 354 | php => on, 355 | spamassassin => on, 356 | ssl => on, 357 | ssh => on, 358 | userssh => on, 359 | oversell => on, 360 | sysinfo => on, 361 | serverip => on, 362 | api_username => "admin", 363 | api_password => "api_password", 364 | api_hostname => "localhost (default)", 365 | api_port => "2222 (default)", 366 | api_ssl => false (default), 367 | } 368 | ``` 369 | 370 | #### Set up a new reseller 371 | 372 | It only manages the `email` and `password` property. Changing them will update the user. 373 | 374 | ``` 375 | directadmin_reseller { "resellername": 376 | ensure => present, 377 | password => "password", 378 | email => "your@email.address", 379 | domain => "yourdomain.com", 380 | ip_address => "shared", 381 | user_package => "an_existing_package", 382 | notifications => "no", 383 | api_username => "admin", 384 | api_password => "api_password", 385 | api_hostname => "localhost (default)", 386 | api_port => "2222 (default)", 387 | api_ssl => false (default), 388 | } 389 | ``` 390 | 391 | #### Set up a new user package 392 | 393 | All values are manageable, as in, you can change them after a package has been created. 394 | Renaming packages is not supported though. 395 | 396 | ``` 397 | directadmin_user_package { "bronze": 398 | ensure => present, 399 | aftp => off, 400 | bandwidth => 25000, 401 | catchall => on, 402 | cgi => on, 403 | cron => on, 404 | dnscontrol => on, 405 | domainptr => 1001, 406 | domains => 1, 407 | ftp => 2001, 408 | inodes => 3001, 409 | language => 'en', 410 | login_keys => on, 411 | mysql => 4001, 412 | nemailf => 5001, 413 | nemails => 6001, 414 | nemailml => 7001, 415 | nemailr => 8001, 416 | nsubdomains => unlimited, 417 | quota => 1000, 418 | php => on, 419 | spamassassin => on, 420 | ssl => on, 421 | sysinfo => on, 422 | suspend_at_limit => on, 423 | skin => 'enhanced', 424 | api_username => "reseller", 425 | api_password => "api_password", 426 | api_hostname => "localhost (default)", 427 | api_port => "2222 (default)", 428 | api_ssl => false (default), 429 | } 430 | ``` 431 | 432 | ## Limitations 433 | 434 | This module has been tested on: 435 | 436 | * CentOS 6 437 | * CentOS 7 438 | * Debian 7 439 | 440 | ## Development 441 | 442 | We strongly believe in the power of open source. This module is our way 443 | of saying thanks. 444 | 445 | This module is tested against the Ruby versions from Puppet's support 446 | matrix. Please make sure you have a supported version of Ruby installed. 447 | 448 | If you want to contribute please: 449 | 450 | 1. Fork the repository. 451 | 2. Run tests. It's always good to know that you can start with a clean slate. 452 | 3. Add a test for your change. 453 | 4. Make sure it passes. 454 | 5. Push to your fork and submit a pull request. 455 | 456 | We can only accept pull requests with passing tests. 457 | 458 | To install all of its dependencies please run: 459 | 460 | ``` 461 | bundle install --path vendor/bundle --without development 462 | ``` 463 | 464 | ### Running unit tests 465 | 466 | ``` 467 | bundle exec rake test 468 | ``` 469 | 470 | ### Running acceptance tests 471 | 472 | The unit tests only verify if the code runs, not if it does exactly 473 | what we want on a real machine. For this we use Beaker. Beaker will 474 | start a new virtual machine (using Vagrant) and runs a series of 475 | simple tests. 476 | 477 | Beaker is currently not supported due to licensing constraints. 478 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'puppetlabs_spec_helper/rake_tasks' 2 | require 'puppet-lint/tasks/puppet-lint' 3 | require 'metadata-json-lint/rake_task' 4 | 5 | if RUBY_VERSION >= '1.9' 6 | require 'rubocop/rake_task' 7 | RuboCop::RakeTask.new 8 | end 9 | 10 | PuppetLint.configuration.send('disable_80chars') 11 | PuppetLint.configuration.relative = true 12 | PuppetLint.configuration.ignore_paths = [ 13 | 'spec/**/*.pp', 14 | 'pkg/**/*.pp', 15 | 'vendor/**/*.pp', 16 | 'fixtures/**/*.pp', 17 | 'spec/fixtures/modules/**/*' 18 | ] 19 | 20 | # Sort of support for 1.9.3 21 | PuppetSyntax.fail_on_deprecation_notices = false 22 | 23 | desc 'Validate manifests, templates, and ruby files' 24 | task :validate do 25 | Dir['manifests/**/*.pp'].each do |manifest| 26 | sh "puppet parser validate --noop #{manifest}" 27 | end 28 | Dir['spec/**/*.rb', 'lib/**/*.rb'].each do |ruby_file| 29 | sh "ruby -c #{ruby_file}" unless ruby_file =~ %r{spec/fixtures} 30 | end 31 | Dir['templates/**/*.erb'].each do |template| 32 | sh "erb -P -x -T '-' #{template} | ruby -c" 33 | end 34 | end 35 | 36 | desc 'Run metadata_lint, lint, validate, and spec tests.' 37 | task :test do 38 | # This should be changed once we drop support for 1.9.3 to 39 | # %i[metadata_lint lint validate rubocop spec].each 40 | [:metadata_lint, :lint, :validate, :spec].each do |test| 41 | Rake::Task[test].invoke 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/puppet/provider/directadmin.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'uri' 3 | 4 | # This class currently has some duplicate code in it, this needs cleaning up. 5 | class Puppet::Provider::DirectAdmin < Puppet::Provider 6 | initvars 7 | 8 | class Error < ::StandardError 9 | end 10 | 11 | def self.connect(username, password, hostname, port, ssl = false) 12 | @auth_username = username 13 | @auth_password = password 14 | @http = Net::HTTP.new(hostname, port) 15 | 16 | if ssl == true 17 | @http.use_ssl = true 18 | if hostname == 'localhost' 19 | @http.verify_mode = OpenSSL::SSL::VERIFY_NONE 20 | end 21 | end 22 | end 23 | 24 | # We need to allow post requests to the API for certain actions such as removing accounts. 25 | def self.post(uri, *args) 26 | options = args.first || {} 27 | uri = "/#{uri}" 28 | resp = "" 29 | 30 | @http.start() { |http| 31 | req = Net::HTTP::Post.new(uri) 32 | req.set_form_data(options) 33 | req.basic_auth @auth_username, @auth_password 34 | response = http.request(req) 35 | # URI.unescape misses a lot, for some reason. 36 | resp = URI.unescape(response.body).gsub("-","-").gsub("@", "@").gsub("_", "_").gsub(":", ":") 37 | } 38 | 39 | # Create a hash of the response. We need some additional magic to make sure lists are parsed properly. 40 | resp_hash = {} 41 | response = resp.split('&') 42 | i = 0 43 | response.each do |var| 44 | key,value = var.split("=") 45 | if key == "list[]" 46 | key = i 47 | i += 1 48 | end 49 | resp_hash[key] = value 50 | end 51 | 52 | if resp_hash["error"] == "1" 53 | text = resp_hash["text"] 54 | details = resp_hash["details"] 55 | raise(Puppet::Error, "#{text}. #{details}.") 56 | elsif resp =~ /DirectAdmin\ Login/ 57 | raise(Puppet::Error, "Login failed. The specified username and/or password is not correct.") 58 | elsif resp =~ /authority\ level/ 59 | raise(Puppet::Error, "The request you've made cannot be executed because it does not exist in your authority level.") 60 | else 61 | return resp_hash 62 | end 63 | end 64 | 65 | # In most cases we can send a GET request to DirectAdmin to do what we want. 66 | def self.query(uri, *args) 67 | options = args.first || {} 68 | params = "" 69 | options.each do |o| 70 | params << "#{o[0]}=#{o[1]}&" 71 | end 72 | uri = "/#{uri}?#{params}api=yes" 73 | resp = "" 74 | 75 | @http.start() { |http| 76 | req = Net::HTTP::Get.new(uri) 77 | req.basic_auth @auth_username, @auth_password 78 | response = http.request(req) 79 | # URI.unescape misses a lot, for some reason. 80 | resp = URI.unescape(response.body).gsub("-","-").gsub("@", "@").gsub("_", "_").gsub(":", ":") 81 | } 82 | 83 | # Create a hash of the response. We need some additional magic to make sure lists are parsed properly. 84 | resp_hash = {} 85 | response = resp.split('&') 86 | i = 0 87 | response.each do |var| 88 | key,value = var.split("=") 89 | if key == "list[]" 90 | key = i 91 | i += 1 92 | end 93 | resp_hash[key] = value 94 | end 95 | 96 | if resp_hash["error"] == "1" 97 | text = resp_hash["text"] 98 | details = resp_hash["details"] 99 | raise(Puppet::Error, "#{text}. #{details}.") 100 | elsif resp =~ /DirectAdmin\ Login/ 101 | raise(Puppet::Error, "Login failed. The specified username and/or password is not correct.") 102 | elsif resp =~ /authority\ level/ 103 | raise(Puppet::Error, "The request you've made cannot be executed because it does not exist in your authority level.") 104 | else 105 | return resp_hash 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /lib/puppet/provider/directadmin_admin/directadmin.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'directadmin')) 2 | Puppet::Type.type(:directadmin_admin).provide(:directadmin, :parent => Puppet::Provider::DirectAdmin) do 3 | def create 4 | connect 5 | self.class.query('CMD_API_ACCOUNT_ADMIN', 6 | :action => "create", 7 | :add => "Submit", 8 | :username => resource[:username], 9 | :email => resource[:email], 10 | :passwd => resource[:password], 11 | :passwd2 => resource[:password], 12 | :notify => resource[:notifications] 13 | ) 14 | end 15 | 16 | def destroy 17 | connect 18 | self.class.post('CMD_API_SELECT_USERS', 19 | :confirmed => "Confirmed", 20 | :delete => "yes", 21 | :select0 => resource[:username] 22 | ) 23 | end 24 | 25 | def exists? 26 | connect 27 | admins = self.class.query('CMD_API_SHOW_ADMINS') 28 | if admins.has_value?(resource[:username]) 29 | return true 30 | else 31 | return false 32 | end 33 | end 34 | 35 | # ----- 36 | # Custom functions 37 | # ----- 38 | 39 | def connect 40 | self.class.connect(resource[:api_username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 41 | end 42 | 43 | def connect_as_user 44 | self.class.connect(resource[:api_username] + "|" + resource[:username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 45 | end 46 | 47 | # ----- 48 | # Changing properties for this resource 49 | # ----- 50 | 51 | # Change the e-mail address for a particular user. 52 | def email 53 | connect 54 | user = self.class.query('CMD_API_SHOW_USER_CONFIG', 55 | :user => resource[:username] 56 | ) 57 | return user["email"] 58 | end 59 | 60 | def email=(value) 61 | connect 62 | info = self.class.post('CMD_API_MODIFY_USER', 63 | :action => "single", 64 | :user => resource[:username], 65 | :evalue => resource[:email], 66 | :email => "Save" 67 | ) 68 | return true 69 | end 70 | 71 | # Change the password for the admin user. 72 | def password 73 | connect 74 | password = self.class.query('CMD_API_VERIFY_PASSWORD', 75 | :user => resource[:username], 76 | :passwd => resource[:password] 77 | ) 78 | if password["valid"] == "1" 79 | return resource[:password] 80 | else 81 | return "********" 82 | end 83 | end 84 | 85 | def password=(value) 86 | connect 87 | self.class.post('CMD_API_USER_PASSWD', 88 | :username => resource[:username], 89 | :passwd => resource[:password], 90 | :passwd2 => resource[:password] 91 | ) 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /lib/puppet/provider/directadmin_reseller/directadmin.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'directadmin')) 2 | Puppet::Type.type(:directadmin_reseller).provide(:directadmin, :parent => Puppet::Provider::DirectAdmin) do 3 | def create 4 | connect 5 | self.class.query('CMD_API_ACCOUNT_RESELLER', 6 | :action => "create", 7 | :add => "Submit", 8 | :username => resource[:username], 9 | :email => resource[:email], 10 | :passwd => resource[:password], 11 | :passwd2 => resource[:password], 12 | :domain => resource[:domain], 13 | :package => resource[:user_package], 14 | :ip => resource[:ip_address], 15 | :notify => resource[:notifications] 16 | ) 17 | end 18 | 19 | def destroy 20 | connect 21 | self.class.post('CMD_API_SELECT_USERS', 22 | :confirmed => "Confirmed", 23 | :delete => "yes", 24 | :select0 => resource[:username] 25 | ) 26 | end 27 | 28 | def exists? 29 | connect 30 | resellers = self.class.query('CMD_API_SHOW_RESELLERS') 31 | if resellers.has_value?(resource[:username]) 32 | return true 33 | else 34 | return false 35 | end 36 | end 37 | 38 | # ----- 39 | # Custom functions 40 | # ----- 41 | 42 | def connect 43 | self.class.connect(resource[:api_username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 44 | end 45 | 46 | # ----- 47 | # Changing properties for this resource 48 | # ----- 49 | 50 | # Change the e-mail address for a particular user. 51 | def email 52 | connect 53 | user = self.class.query('CMD_API_SHOW_USER_CONFIG', 54 | :user => resource[:username] 55 | ) 56 | return user["email"] 57 | end 58 | 59 | def email=(value) 60 | connect 61 | info = self.class.post('CMD_API_MODIFY_USER', 62 | :action => "single", 63 | :user => resource[:username], 64 | :evalue => resource[:email], 65 | :email => "Save" 66 | ) 67 | return true 68 | end 69 | 70 | # Change the password for the admin user. 71 | def password 72 | connect 73 | current_password = self.class.query('CMD_API_VERIFY_PASSWORD', 74 | :user => resource[:username], 75 | :passwd => resource[:password] 76 | ) 77 | 78 | if current_password["valid"] == "1" 79 | return resource[:password] 80 | else 81 | return "password" 82 | end 83 | end 84 | 85 | def password=(value) 86 | connect 87 | self.class.post('CMD_API_USER_PASSWD', 88 | :username => resource[:username], 89 | :passwd => resource[:password], 90 | :passwd2 => resource[:password] 91 | ) 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /lib/puppet/provider/directadmin_reseller_package/directadmin.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'directadmin')) 2 | Puppet::Type.type(:directadmin_reseller_package).provide(:directadmin, :parent => Puppet::Provider::DirectAdmin) do 3 | def convert_package 4 | # We don't have support for personal DNS yet. 5 | package = {} 6 | package[:add] = "Save" 7 | package[:packagename] = resource[:package_name] 8 | 9 | # Configurable resources 10 | package[:bandwidth] = resource[:bandwidth] if resource[:bandwidth] != :unlimited 11 | package[:ubandwidth] = "ON" if resource[:bandwidth] == :unlimited 12 | package[:domainptr] = resource[:domainptr] if resource[:domainptr] != :unlimited 13 | package[:udomainptr] = "ON" if resource[:domainptr] == :unlimited 14 | package[:ftp] = resource[:ftp] if resource[:ftp] != :unlimited 15 | package[:uftp] = "ON" if resource[:ftp] == :unlimited 16 | package[:inode] = resource[:inodes] if resource[:inodes] != :unlimited 17 | package[:uinode] = "ON" if resource[:inodes] == :unlimited 18 | package[:ips] = resource[:ips] 19 | package[:mysql] = resource[:mysql] if resource[:mysql] != :unlimited 20 | package[:umysql] = "ON" if resource[:mysql] == :unlimited 21 | package[:nemailf] = resource[:nemailf] if resource[:nemailf] != :unlimited 22 | package[:unemailf] = "ON" if resource[:nemailf] == :unlimited 23 | package[:nemails] = resource[:nemails] if resource[:nemails] != :unlimited 24 | package[:unemails] = "ON" if resource[:nemails] == :unlimited 25 | package[:nemailml] = resource[:nemailml] if resource[:nemailml] != :unlimited 26 | package[:unemailml] = "ON" if resource[:nemailml] == :unlimited 27 | package[:nemailr] = resource[:nemailr] if resource[:nemailr] != :unlimited 28 | package[:unemailr] = "ON" if resource[:nemailr] == :unlimited 29 | package[:nsubdomains] = resource[:nsubdomains] if resource[:nsubdomains] != :unlimited 30 | package[:unsubdomains] = "ON" if resource[:nsubdomains] == :unlimited 31 | package[:quota] = resource[:quota] if resource[:quota] != :unlimited 32 | package[:uquota] = "ON" if resource[:quota] == :unlimited 33 | package[:vdomains] = resource[:domains] if resource[:domains] != :unlimited 34 | package[:uvdomains] = "ON" if resource[:domains] == :unlimited 35 | 36 | # Resources that can be turned on or off 37 | resource[:aftp] == :on ? (package[:aftp] = "ON") : (package[:aftp] = "OFF") 38 | resource[:catchall] == :on ? (package[:catchall] = "ON") : (package[:catchall] = "OFF") 39 | resource[:cgi] == :on ? (package[:cgi] = "ON") : (package[:cgi] = "OFF") 40 | resource[:cron] == :on ? (package[:cron] = "ON") : (package[:cron] = "OFF") 41 | resource[:dnscontrol] == :on ? (package[:dnscontrol] = "ON") : (package[:dnscontrol] = "OFF") 42 | resource[:login_keys] == :on ? (package[:login_keys] = "ON") : (package[:login_keys] = "OFF") 43 | resource[:php] == :on ? (package[:php] = "ON") : (package[:php] = "OFF") 44 | resource[:spamassassin] == :on ? (package[:spam] = "ON") : (package[:spam] = "OFF") 45 | resource[:ssl] == :on ? (package[:ssl] = "ON") : (package[:ssl] = "OFF") 46 | resource[:ssh] == :on ? (package[:ssh] = "ON") : (package[:ssh] = "OFF") 47 | resource[:userssh] == :on ? (package[:userssh] = "ON") : (package[:userssh] = "OFF") 48 | resource[:oversell] == :on ? (package[:oversell] = "ON") : (package[:oversell] = "OFF") 49 | resource[:sysinfo] == :on ? (package[:sysinfo] = "ON") : (package[:sysinfo] = "OFF") 50 | resource[:serverip] == :on ? (package[:serverip] = "ON") : (package[:serverip] = "OFF") 51 | 52 | # Other resources 53 | package[:dns] = "OFF" if resource[:dns] == :off 54 | package[:dns] = "TWO" if resource[:dns] == :two 55 | package[:dns] = "THREE" if resource[:dns] == :three 56 | 57 | @package_details = package 58 | end 59 | 60 | def create 61 | connect 62 | convert_package 63 | set_package = self.class.post('CMD_API_MANAGE_RESELLER_PACKAGES', @package_details) 64 | end 65 | 66 | def destroy 67 | connect 68 | self.class.post('CMD_API_MANAGE_RESELLER_PACKAGES', 69 | :delete => "Delete", 70 | :delete0 => resource[:package_name] 71 | ) 72 | end 73 | 74 | def exists? 75 | connect 76 | packages = self.class.query('CMD_API_PACKAGES_RESELLER') 77 | if packages.has_value?(resource[:package_name]) 78 | @package_values = get_package_values 79 | @package_values["packagename"] = resource[:package_name] 80 | return true 81 | else 82 | return false 83 | end 84 | end 85 | 86 | # ----- 87 | # Custom functions 88 | # ----- 89 | 90 | def connect 91 | self.class.connect(resource[:api_username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 92 | end 93 | 94 | def connect_as_user 95 | self.class.connect(resource[:api_username] + "|" + resource[:username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 96 | end 97 | 98 | def get_package_values 99 | connect 100 | package = self.class.query('CMD_API_PACKAGES_RESELLER', 101 | :package => resource[:package_name] 102 | ) 103 | return package 104 | end 105 | 106 | def set_package_values 107 | connect 108 | convert_package 109 | set_package = self.class.post('CMD_API_MANAGE_RESELLER_PACKAGES', @package_details) 110 | return true 111 | end 112 | 113 | # ----- 114 | # Changing properties for this resource 115 | # ----- 116 | 117 | def bandwidth 118 | package = @package_values 119 | return package["bandwidth"] 120 | end 121 | 122 | def bandwidth=(value) 123 | return set_package_values 124 | end 125 | 126 | def aftp 127 | package = @package_values 128 | return package["aftp"].downcase 129 | end 130 | 131 | def aftp=(value) 132 | return set_package_values 133 | end 134 | 135 | def catchall 136 | package = @package_values 137 | return package["catchall"].downcase 138 | end 139 | 140 | def catchall=(value) 141 | return set_package_values 142 | end 143 | 144 | def cgi 145 | package = @package_values 146 | return package["cgi"].downcase 147 | end 148 | 149 | def cgi=(value) 150 | return set_package_values 151 | end 152 | 153 | def cron 154 | package = @package_values 155 | return package["cron"].downcase 156 | end 157 | 158 | def cron=(value) 159 | return set_package_values 160 | end 161 | 162 | def dns 163 | package = @package_values 164 | return package["dns"].downcase 165 | end 166 | 167 | def dns=(value) 168 | return set_package_values 169 | end 170 | 171 | def dnscontrol 172 | package = @package_values 173 | return package["dnscontrol"].downcase 174 | end 175 | 176 | def dnscontrol=(value) 177 | return set_package_values 178 | end 179 | 180 | def domains 181 | package = @package_values 182 | return package["vdomains"] 183 | end 184 | 185 | def domains=(value) 186 | return set_package_values 187 | end 188 | 189 | def domainptr 190 | package = @package_values 191 | return package["domainptr"] 192 | end 193 | 194 | def domainptr=(value) 195 | return set_package_values 196 | end 197 | 198 | def ftp 199 | package = @package_values 200 | return package["ftp"] 201 | end 202 | 203 | def ftp=(value) 204 | return set_package_values 205 | end 206 | 207 | def inodes 208 | package = @package_values 209 | return package["inode"] 210 | end 211 | 212 | def inodes=(value) 213 | return set_package_values 214 | end 215 | 216 | def ips 217 | package = @package_values 218 | return package["ips"] 219 | end 220 | 221 | def ips=(value) 222 | return set_package_values 223 | end 224 | 225 | def login_keys 226 | package = @package_values 227 | return package["login_keys"].downcase 228 | end 229 | 230 | def login_keys=(value) 231 | return set_package_values 232 | end 233 | 234 | def language 235 | package = @package_values 236 | return package["language"] 237 | end 238 | 239 | def language=(value) 240 | return set_package_values 241 | end 242 | 243 | def mysql 244 | package = @package_values 245 | return package["mysql"] 246 | end 247 | 248 | def mysql=(value) 249 | return set_package_values 250 | end 251 | 252 | def nemailf 253 | package = @package_values 254 | return package["nemailf"] 255 | end 256 | 257 | def nemailf=(value) 258 | return set_package_values 259 | end 260 | 261 | def nemails 262 | package = @package_values 263 | return package["nemails"] 264 | end 265 | 266 | def nemails=(value) 267 | return set_package_values 268 | end 269 | 270 | def nemailml 271 | package = @package_values 272 | return package["nemailml"] 273 | end 274 | 275 | def nemailml=(value) 276 | return set_package_values 277 | end 278 | 279 | def nemailr 280 | package = @package_values 281 | return package["nemailr"] 282 | end 283 | 284 | def nemailr=(value) 285 | return set_package_values 286 | end 287 | 288 | def nsubdomains 289 | package = @package_values 290 | return package["nsubdomains"] 291 | end 292 | 293 | def nsubdomains=(value) 294 | return set_package_values 295 | end 296 | 297 | def oversell 298 | package = @package_values 299 | return package["oversell"].downcase 300 | end 301 | 302 | def oversell=(value) 303 | return set_package_values 304 | end 305 | 306 | def php 307 | package = @package_values 308 | return package["php"].downcase 309 | end 310 | 311 | def php=(value) 312 | return set_package_values 313 | end 314 | 315 | def serverip 316 | package = @package_values 317 | return package["serverip"].downcase 318 | end 319 | 320 | def serverip=(value) 321 | return set_package_values 322 | end 323 | 324 | def spamassassin 325 | package = @package_values 326 | return package["spam"].downcase 327 | end 328 | 329 | def spamassassin=(value) 330 | return set_package_values 331 | end 332 | 333 | def ssl 334 | package = @package_values 335 | return package["ssl"].downcase 336 | end 337 | 338 | def ssl=(value) 339 | return set_package_values 340 | end 341 | 342 | def ssh 343 | package = @package_values 344 | return package["ssh"].downcase 345 | end 346 | 347 | def ssh=(value) 348 | return set_package_values 349 | end 350 | 351 | def sysinfo 352 | package = @package_values 353 | return package["sysinfo"].downcase 354 | end 355 | 356 | def sysinfo=(value) 357 | return set_package_values 358 | end 359 | 360 | def quota 361 | package = @package_values 362 | return package["quota"] 363 | end 364 | 365 | def quota=(value) 366 | return set_package_values 367 | end 368 | 369 | def userssh 370 | package = @package_values 371 | return package["userssh"].downcase 372 | end 373 | 374 | def userssh=(value) 375 | return set_package_values 376 | end 377 | end 378 | -------------------------------------------------------------------------------- /lib/puppet/provider/directadmin_user_package/directadmin.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'directadmin')) 2 | Puppet::Type.type(:directadmin_user_package).provide(:directadmin, :parent => Puppet::Provider::DirectAdmin) do 3 | def convert_package 4 | # We don't have support for personal DNS yet. 5 | package = {} 6 | package[:add] = "Save" 7 | package[:packagename] = resource[:package_name] 8 | package[:skin] = resource[:skin] 9 | package[:language] = resource[:language] 10 | 11 | # Configurable resources 12 | package[:bandwidth] = resource[:bandwidth] if resource[:bandwidth] != :unlimited 13 | package[:ubandwidth] = "ON" if resource[:bandwidth] == :unlimited 14 | package[:domainptr] = resource[:domainptr] if resource[:domainptr] != :unlimited 15 | package[:udomainptr] = "ON" if resource[:domainptr] == :unlimited 16 | package[:ftp] = resource[:ftp] if resource[:ftp] != :unlimited 17 | package[:uftp] = "ON" if resource[:ftp] == :unlimited 18 | package[:inode] = resource[:inodes] if resource[:inodes] != :unlimited 19 | package[:uinode] = "ON" if resource[:inodes] == :unlimited 20 | package[:mysql] = resource[:mysql] if resource[:mysql] != :unlimited 21 | package[:umysql] = "ON" if resource[:mysql] == :unlimited 22 | package[:nemailf] = resource[:nemailf] if resource[:nemailf] != :unlimited 23 | package[:unemailf] = "ON" if resource[:nemailf] == :unlimited 24 | package[:nemails] = resource[:nemails] if resource[:nemails] != :unlimited 25 | package[:unemails] = "ON" if resource[:nemails] == :unlimited 26 | package[:nemailml] = resource[:nemailml] if resource[:nemailml] != :unlimited 27 | package[:unemailml] = "ON" if resource[:nemailml] == :unlimited 28 | package[:nemailr] = resource[:nemailr] if resource[:nemailr] != :unlimited 29 | package[:unemailr] = "ON" if resource[:nemailr] == :unlimited 30 | package[:nsubdomains] = resource[:nsubdomains] if resource[:nsubdomains] != :unlimited 31 | package[:unsubdomains] = "ON" if resource[:nsubdomains] == :unlimited 32 | package[:quota] = resource[:quota] if resource[:quota] != :unlimited 33 | package[:uquota] = "ON" if resource[:quota] == :unlimited 34 | package[:vdomains] = resource[:domains] if resource[:domains] != :unlimited 35 | package[:uvdomains] = "ON" if resource[:domains] == :unlimited 36 | 37 | # Resources that can be turned on or off 38 | resource[:aftp] == :on ? (package[:aftp] = "ON") : (package[:aftp] = "OFF") 39 | resource[:catchall] == :on ? (package[:catchall] = "ON") : (package[:catchall] = "OFF") 40 | resource[:cgi] == :on ? (package[:cgi] = "ON") : (package[:cgi] = "OFF") 41 | resource[:cron] == :on ? (package[:cron] = "ON") : (package[:cron] = "OFF") 42 | resource[:dnscontrol] == :on ? (package[:dnscontrol] = "ON") : (package[:dnscontrol] = "OFF") 43 | resource[:login_keys] == :on ? (package[:login_keys] = "ON") : (package[:login_keys] = "OFF") 44 | resource[:php] == :on ? (package[:php] = "ON") : (package[:php] = "OFF") 45 | resource[:spamassassin] == :on ? (package[:spam] = "ON") : (package[:spam] = "OFF") 46 | resource[:ssl] == :on ? (package[:ssl] = "ON") : (package[:ssl] = "OFF") 47 | resource[:ssh] == :on ? (package[:ssh] = "ON") : (package[:ssh] = "OFF") 48 | resource[:sysinfo] == :on ? (package[:sysinfo] = "ON") : (package[:sysinfo] = "OFF") 49 | resource[:suspend_at_limit] == :on ? (package[:suspend_at_limit] = "ON") : (package[:suspend_at_limit] = "OFF") 50 | 51 | @package_details = package 52 | end 53 | 54 | def create 55 | connect 56 | convert_package 57 | set_package = self.class.post('CMD_API_MANAGE_USER_PACKAGES', @package_details) 58 | end 59 | 60 | def destroy 61 | connect 62 | self.class.post('CMD_API_MANAGE_USER_PACKAGES', 63 | :delete => "Delete", 64 | :delete0 => resource[:package_name] 65 | ) 66 | end 67 | 68 | def exists? 69 | connect 70 | packages = self.class.query('CMD_API_PACKAGES_USER') 71 | if packages.has_value?(resource[:package_name]) 72 | @package_values = get_package_values 73 | @package_values["packagename"] = resource[:package_name] 74 | return true 75 | else 76 | return false 77 | end 78 | end 79 | 80 | # ----- 81 | # Custom functions 82 | # ----- 83 | 84 | def connect 85 | self.class.connect(resource[:api_username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 86 | end 87 | 88 | def connect_as_user 89 | self.class.connect(resource[:api_username] + "|" + resource[:username], resource[:api_password], resource[:api_hostname], resource[:api_port], resource[:api_ssl]) 90 | end 91 | 92 | def get_package_values 93 | connect 94 | package = self.class.query('CMD_API_PACKAGES_USER', 95 | :package => resource[:package_name] 96 | ) 97 | return package 98 | end 99 | 100 | def set_package_values 101 | connect 102 | convert_package 103 | set_package = self.class.post('CMD_API_MANAGE_USER_PACKAGES', @package_details) 104 | return true 105 | end 106 | 107 | # ----- 108 | # Changing properties for this resource 109 | # ----- 110 | 111 | def bandwidth 112 | package = @package_values 113 | return package["bandwidth"] 114 | end 115 | 116 | def bandwidth=(value) 117 | return set_package_values 118 | end 119 | 120 | def aftp 121 | package = @package_values 122 | return package["aftp"].downcase 123 | end 124 | 125 | def aftp=(value) 126 | return set_package_values 127 | end 128 | 129 | def catchall 130 | package = @package_values 131 | return package["catchall"].downcase 132 | end 133 | 134 | def catchall=(value) 135 | return set_package_values 136 | end 137 | 138 | def cgi 139 | package = @package_values 140 | return package["cgi"].downcase 141 | end 142 | 143 | def cgi=(value) 144 | return set_package_values 145 | end 146 | 147 | def cron 148 | package = @package_values 149 | return package["cron"].downcase 150 | end 151 | 152 | def cron=(value) 153 | return set_package_values 154 | end 155 | 156 | def domains 157 | package = @package_values 158 | return package["vdomains"] 159 | end 160 | 161 | def domains=(value) 162 | return set_package_values 163 | end 164 | 165 | def domainptr 166 | package = @package_values 167 | return package["domainptr"] 168 | end 169 | 170 | def domainptr=(value) 171 | return set_package_values 172 | end 173 | 174 | def dnscontrol 175 | package = @package_values 176 | return package["dnscontrol"].downcase 177 | end 178 | 179 | def dnscontrol=(value) 180 | return set_package_values 181 | end 182 | 183 | def ftp 184 | package = @package_values 185 | return package["ftp"] 186 | end 187 | 188 | def ftp=(value) 189 | return set_package_values 190 | end 191 | 192 | def inodes 193 | package = @package_values 194 | return package["inode"] 195 | end 196 | 197 | def inodes=(value) 198 | return set_package_values 199 | end 200 | 201 | def ips 202 | package = @package_values 203 | return package["ips"] 204 | end 205 | 206 | def ips=(value) 207 | return set_package_values 208 | end 209 | 210 | def login_keys 211 | package = @package_values 212 | return package["login_keys"].downcase 213 | end 214 | 215 | def login_keys=(value) 216 | return set_package_values 217 | end 218 | 219 | def language 220 | package = @package_values 221 | return package["language"] 222 | end 223 | 224 | def language=(value) 225 | return set_package_values 226 | end 227 | 228 | def mysql 229 | package = @package_values 230 | return package["mysql"] 231 | end 232 | 233 | def mysql=(value) 234 | return set_package_values 235 | end 236 | 237 | def nemailf 238 | package = @package_values 239 | return package["nemailf"] 240 | end 241 | 242 | def nemailf=(value) 243 | return set_package_values 244 | end 245 | 246 | def nemails 247 | package = @package_values 248 | return package["nemails"] 249 | end 250 | 251 | def nemails=(value) 252 | return set_package_values 253 | end 254 | 255 | def nemailml 256 | package = @package_values 257 | return package["nemailml"] 258 | end 259 | 260 | def nemailml=(value) 261 | return set_package_values 262 | end 263 | 264 | def nemailr 265 | package = @package_values 266 | return package["nemailr"] 267 | end 268 | 269 | def nemailr=(value) 270 | return set_package_values 271 | end 272 | 273 | def nsubdomains 274 | package = @package_values 275 | return package["nsubdomains"] 276 | end 277 | 278 | def nsubdomains=(value) 279 | return set_package_values 280 | end 281 | 282 | def php 283 | package = @package_values 284 | return package["php"].downcase 285 | end 286 | 287 | def php=(value) 288 | return set_package_values 289 | end 290 | 291 | def spamassassin 292 | package = @package_values 293 | return package["spam"].downcase 294 | end 295 | 296 | def spamassassin=(value) 297 | return set_package_values 298 | end 299 | 300 | def ssl 301 | package = @package_values 302 | return package["ssl"].downcase 303 | end 304 | 305 | def ssl=(value) 306 | return set_package_values 307 | end 308 | 309 | def ssh 310 | package = @package_values 311 | return package["ssh"].downcase 312 | end 313 | 314 | def ssh=(value) 315 | return set_package_values 316 | end 317 | 318 | def sysinfo 319 | package = @package_values 320 | return package["sysinfo"].downcase 321 | end 322 | 323 | def sysinfo=(value) 324 | return set_package_values 325 | end 326 | 327 | def suspend_at_limit 328 | package = @package_values 329 | return package["suspend_at_limit"].downcase 330 | end 331 | 332 | def suspend_at_limit=(value) 333 | return set_package_values 334 | end 335 | 336 | def skin 337 | package = @package_values 338 | return package["skin"] 339 | end 340 | 341 | def skin=(value) 342 | return set_package_values 343 | end 344 | 345 | def quota 346 | package = @package_values 347 | return package["quota"] 348 | end 349 | 350 | def quota=(value) 351 | return set_package_values 352 | end 353 | 354 | end 355 | -------------------------------------------------------------------------------- /lib/puppet/type/directadmin_admin.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:directadmin_admin) do 2 | @doc = "Manage DirectAdmin admin users." 3 | 4 | ensurable 5 | 6 | # The following parameters are required. 7 | validate do 8 | fail('password parameter is required.') if self[:ensure] == :present and self[:password].nil? 9 | fail('email property is required.') if self[:ensure] == :present and self[:email].nil? 10 | fail('api_username parameter is required.') if self[:api_username].nil? 11 | fail('api_password parameter is required.') if self[:api_password].nil? 12 | end 13 | 14 | newparam(:username, :namevar => true) do 15 | desc 'The admin\'s name.' 16 | validate do |value| 17 | raise Puppet::Error, "username is #{value.length} characters long; must be of length 4 or greater" if value.length < 4 18 | end 19 | end 20 | 21 | newproperty(:password) do 22 | desc 'The admin\'s password.' 23 | isrequired 24 | validate do |value| 25 | raise Puppet::Error, "password is #{value.length} characters long; must be of length 6 or greater" if value.length < 6 26 | end 27 | end 28 | 29 | newproperty(:email) do 30 | desc 'The admin\'s e-mail address.' 31 | isrequired 32 | validate do |value| 33 | unless (value =~ /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/) 34 | raise(Puppet::Error, "The e-mail address '#{value}' is invalid.") 35 | end 36 | end 37 | end 38 | 39 | newparam(:notifications) do 40 | desc "Send a notification e-mail, or not." 41 | newvalues(:no, :yes) 42 | defaultto :no 43 | end 44 | 45 | newparam(:api_username) do 46 | desc 'The username to connect to the API.' 47 | isrequired 48 | validate do |value| 49 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 50 | end 51 | end 52 | 53 | newparam(:api_password) do 54 | desc 'The api_username\'s password to connect to the API.' 55 | isrequired 56 | validate do |value| 57 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 58 | end 59 | end 60 | 61 | newparam(:api_hostname) do 62 | desc 'The API\'s endpoint. Do not specify the port here.' 63 | defaultto "localhost" 64 | end 65 | 66 | newparam(:api_port) do 67 | desc 'The API\'s endpoint\'s port.' 68 | defaultto "2222" 69 | end 70 | 71 | newparam(:api_ssl) do 72 | desc 'Connect to the API over SSL.' 73 | defaultto :false 74 | end 75 | 76 | end 77 | -------------------------------------------------------------------------------- /lib/puppet/type/directadmin_reseller.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:directadmin_reseller) do 2 | @doc = "Manage DirectAdmin resellers." 3 | 4 | ensurable 5 | 6 | # The following parameters are required. 7 | validate do 8 | fail('password parameter is required.') if self[:ensure] == :present and self[:password].nil? 9 | fail('email parameter is required.') if self[:ensure] == :present and self[:email].nil? 10 | fail('domain parameter is required.') if self[:ensure] == :present and self[:domain].nil? 11 | fail('user_package parameter is required.') if self[:ensure] == :present and self[:user_package].nil? 12 | fail('api_username parameter is required.') if self[:api_username].nil? 13 | fail('api_password parameter is required.') if self[:api_password].nil? 14 | end 15 | 16 | newparam(:username, :namevar => true) do 17 | desc 'The reseller\'s name.' 18 | validate do |value| 19 | raise Puppet::Error, "username is #{value.length} characters long; must be of length 4 or greater" if value.length < 4 20 | end 21 | end 22 | 23 | newproperty(:password) do 24 | desc 'The reseller\'s password.' 25 | isrequired 26 | validate do |value| 27 | raise Puppet::Error, "password is #{value.length} characters long; must be of length 6 or greater" if value.length < 6 28 | end 29 | end 30 | 31 | newproperty(:email) do 32 | desc 'The reseller\'s e-mail address.' 33 | isrequired 34 | validate do |value| 35 | unless (value =~ /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/) 36 | raise(Puppet::Error, "The e-mail address '#{value}' is invalid.") 37 | end 38 | end 39 | end 40 | 41 | newparam(:domain) do 42 | desc "The reseller's domain name." 43 | isrequired 44 | validate do |value| 45 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 46 | end 47 | end 48 | 49 | newparam(:ip_address) do 50 | desc "Set the type of IP address." 51 | newvalues(:shared, :sharedreseller, :assign) 52 | defaultto :shared 53 | end 54 | 55 | newparam(:notifications) do 56 | desc "Send a notification e-mail, or not." 57 | newvalues(:no, :yes) 58 | defaultto :no 59 | end 60 | 61 | newparam(:user_package) do 62 | desc 'The package that will be used for the reseller.' 63 | isrequired 64 | validate do |value| 65 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 66 | end 67 | end 68 | 69 | newparam(:api_username) do 70 | desc 'The username to connect to the API.' 71 | isrequired 72 | validate do |value| 73 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 74 | end 75 | end 76 | 77 | newparam(:api_password) do 78 | desc 'The api_username\'s password to connect to the API.' 79 | isrequired 80 | validate do |value| 81 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 82 | end 83 | end 84 | 85 | newparam(:api_hostname) do 86 | desc 'The API\'s endpoint. Do not specify the port here.' 87 | defaultto "localhost" 88 | end 89 | 90 | newparam(:api_port) do 91 | desc 'The API\'s endpoint\'s port.' 92 | defaultto "2222" 93 | end 94 | 95 | newparam(:api_ssl) do 96 | desc 'Connect to the API over SSL.' 97 | defaultto :false 98 | end 99 | 100 | end 101 | -------------------------------------------------------------------------------- /lib/puppet/type/directadmin_reseller_package.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:directadmin_reseller_package) do 2 | @doc = "Manage DirectAdmin packages for resellers." 3 | 4 | ensurable 5 | 6 | # The following parameters are required. 7 | validate do 8 | fail('api_username parameter is required.') if self[:api_username].nil? 9 | fail('api_password parameter is required.') if self[:api_password].nil? 10 | 11 | # Additional verification. 12 | end 13 | 14 | newparam(:package_name, :namevar => true) do 15 | desc 'The package\'s name.' 16 | validate do |value| 17 | raise Puppet::Error, "package_name is #{value.length} characters long; must be of length 4 or greater" if value.length < 4 18 | end 19 | end 20 | 21 | newproperty(:aftp) do 22 | desc 'Allow anonymous FTP access.' 23 | newvalues(:on, :off) 24 | defaultto :off 25 | end 26 | 27 | newproperty(:bandwidth) do 28 | desc 'Bandwidth limit in MB.' 29 | newvalues(:unlimited, /\d+/) 30 | defaultto 0 31 | end 32 | 33 | newproperty(:catchall) do 34 | desc 'Allow catch all e-mail.' 35 | newvalues(:on, :off) 36 | defaultto :off 37 | end 38 | 39 | newproperty(:cgi) do 40 | desc 'Allow CGI access.' 41 | newvalues(:on, :off) 42 | defaultto :off 43 | end 44 | 45 | newproperty(:cron) do 46 | desc 'Allow cronjobs.' 47 | newvalues(:on, :off) 48 | defaultto :on 49 | end 50 | 51 | newproperty(:dns) do 52 | desc 'Personal DNS servers' 53 | newvalues(:two, :three, :off) 54 | defaultto :off 55 | end 56 | 57 | newproperty(:dnscontrol) do 58 | desc 'Allow DNS control.' 59 | newvalues(:on, :off) 60 | defaultto :on 61 | end 62 | 63 | newproperty(:domains) do 64 | desc 'Virtual domains allowed.' 65 | newvalues(:unlimited, /\d+/) 66 | defaultto :unlimited 67 | end 68 | 69 | newproperty(:domainptr) do 70 | desc 'Domain pointers.' 71 | newvalues(:unlimited, /\d+/) 72 | defaultto 0 73 | end 74 | 75 | newproperty(:ftp) do 76 | desc 'FTP accounts.' 77 | newvalues(:unlimited, /\d+/) 78 | defaultto 0 79 | end 80 | 81 | newproperty(:inodes) do 82 | desc 'Inodes.' 83 | newvalues(:unlimited, /\d+/) 84 | defaultto :unlimited 85 | end 86 | 87 | newproperty(:ips) do 88 | desc 'IP addresses.' 89 | newvalues(/\d+/) 90 | defaultto 0 91 | end 92 | 93 | newproperty(:login_keys) do 94 | desc 'Allow login keys.' 95 | newvalues(:on, :off) 96 | defaultto :off 97 | end 98 | 99 | newproperty(:mysql) do 100 | desc 'MySQL databases.' 101 | newvalues(:unlimited, /\d+/) 102 | defaultto 0 103 | end 104 | 105 | newproperty(:nemailf) do 106 | desc 'E-mail forwarders.' 107 | newvalues(:unlimited, /\d+/) 108 | defaultto 0 109 | end 110 | 111 | newproperty(:nemails) do 112 | desc 'E-mail forwarders.' 113 | newvalues(:unlimited, /\d+/) 114 | defaultto 0 115 | end 116 | 117 | newproperty(:nemailml) do 118 | desc 'E-mail mailing lists.' 119 | newvalues(:unlimited, /\d+/) 120 | defaultto :unlimited 121 | end 122 | 123 | newproperty(:nemailr) do 124 | desc 'E-mail auto responders.' 125 | newvalues(:unlimited, /\d+/) 126 | defaultto :unlimited 127 | end 128 | 129 | newproperty(:nsubdomains) do 130 | desc 'Subdomains.' 131 | newvalues(:unlimited, /\d+/) 132 | defaultto 0 133 | end 134 | 135 | newproperty(:oversell) do 136 | desc 'Allow overselling' 137 | newvalues(:on, :off) 138 | defaultto :off 139 | end 140 | 141 | newproperty(:php) do 142 | desc 'PHP access' 143 | newvalues(:on, :off) 144 | defaultto :off 145 | end 146 | 147 | newproperty(:serverip) do 148 | desc 'Share server IP' 149 | newvalues(:on, :off) 150 | defaultto :off 151 | end 152 | 153 | newproperty(:spamassassin) do 154 | desc 'SpamAssassin' 155 | newvalues(:on, :off) 156 | defaultto :off 157 | end 158 | 159 | newproperty(:ssl) do 160 | desc 'SSL access' 161 | newvalues(:on, :off) 162 | defaultto :off 163 | end 164 | 165 | newproperty(:ssh) do 166 | desc 'SSH access' 167 | newvalues(:on, :off) 168 | defaultto :off 169 | end 170 | 171 | newproperty(:sysinfo) do 172 | desc 'System Info' 173 | newvalues(:on, :off) 174 | defaultto :off 175 | end 176 | 177 | newproperty(:quota) do 178 | desc 'Disk space.' 179 | newvalues(:unlimited, /\d+/) 180 | defaultto :unlimited 181 | end 182 | 183 | newproperty(:userssh) do 184 | desc 'SSH access for users' 185 | newvalues(:on, :off) 186 | defaultto :off 187 | end 188 | 189 | newparam(:api_username) do 190 | desc 'The username to connect to the API.' 191 | isrequired 192 | validate do |value| 193 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 194 | end 195 | end 196 | 197 | newparam(:api_password) do 198 | desc 'The api_username\'s password to connect to the API.' 199 | isrequired 200 | validate do |value| 201 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 202 | end 203 | end 204 | 205 | newparam(:api_hostname) do 206 | desc 'The API\'s endpoint. Do not specify the port here.' 207 | defaultto "localhost" 208 | end 209 | 210 | newparam(:api_port) do 211 | desc 'The API\'s endpoint\'s port.' 212 | defaultto "2222" 213 | end 214 | 215 | newparam(:api_ssl) do 216 | desc 'Connect to the API over SSL.' 217 | defaultto :false 218 | end 219 | 220 | end 221 | -------------------------------------------------------------------------------- /lib/puppet/type/directadmin_user_package.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:directadmin_user_package) do 2 | @doc = "Manage DirectAdmin packages for users." 3 | 4 | ensurable 5 | 6 | # The following parameters are required. 7 | validate do 8 | fail('api_username parameter is required.') if self[:api_username].nil? 9 | fail('api_password parameter is required.') if self[:api_password].nil? 10 | 11 | # Additional verification. 12 | end 13 | 14 | newparam(:package_name, :namevar => true) do 15 | desc 'The package\'s name.' 16 | validate do |value| 17 | raise Puppet::Error, "package_name is #{value.length} characters long; must be of length 4 or greater" if value.length < 4 18 | end 19 | end 20 | 21 | newproperty(:aftp) do 22 | desc 'Allow anonymous FTP access.' 23 | newvalues(:on, :off) 24 | defaultto :off 25 | end 26 | 27 | newproperty(:bandwidth) do 28 | desc 'Bandwidth limit in MB.' 29 | newvalues(:unlimited, /\d+/) 30 | defaultto 0 31 | end 32 | 33 | newproperty(:catchall) do 34 | desc 'Allow catch all e-mail.' 35 | newvalues(:on, :off) 36 | defaultto :off 37 | end 38 | 39 | newproperty(:cgi) do 40 | desc 'Allow CGI access.' 41 | newvalues(:on, :off) 42 | defaultto :off 43 | end 44 | 45 | newproperty(:cron) do 46 | desc 'Allow cronjobs.' 47 | newvalues(:on, :off) 48 | defaultto :on 49 | end 50 | 51 | newproperty(:dnscontrol) do 52 | desc 'Allow DNS control.' 53 | newvalues(:on, :off) 54 | defaultto :on 55 | end 56 | 57 | newproperty(:domains) do 58 | desc 'Virtual domains allowed.' 59 | newvalues(:unlimited, /\d+/) 60 | defaultto :unlimited 61 | end 62 | 63 | newproperty(:domainptr) do 64 | desc 'Domain pointers.' 65 | newvalues(:unlimited, /\d+/) 66 | defaultto 0 67 | end 68 | 69 | newproperty(:ftp) do 70 | desc 'FTP accounts.' 71 | newvalues(:unlimited, /\d+/) 72 | defaultto 0 73 | end 74 | 75 | newproperty(:inodes) do 76 | desc 'Inodes.' 77 | newvalues(:unlimited, /\d+/) 78 | defaultto :unlimited 79 | end 80 | 81 | newproperty(:language) do 82 | desc 'The language.' 83 | validate do |value| 84 | raise Puppet::Error, "langue is #{value.length} characters long; must be of length 2 or greater" if value.length < 2 85 | end 86 | end 87 | 88 | newproperty(:login_keys) do 89 | desc 'Allow login keys.' 90 | newvalues(:on, :off) 91 | defaultto :off 92 | end 93 | 94 | newproperty(:mysql) do 95 | desc 'MySQL databases.' 96 | newvalues(:unlimited, /\d+/) 97 | defaultto 0 98 | end 99 | 100 | newproperty(:nemailf) do 101 | desc 'E-mail forwarders.' 102 | newvalues(:unlimited, /\d+/) 103 | defaultto 0 104 | end 105 | 106 | newproperty(:nemails) do 107 | desc 'E-mail forwarders.' 108 | newvalues(:unlimited, /\d+/) 109 | defaultto 0 110 | end 111 | 112 | newproperty(:nemailml) do 113 | desc 'E-mail mailing lists.' 114 | newvalues(:unlimited, /\d+/) 115 | defaultto :unlimited 116 | end 117 | 118 | newproperty(:nemailr) do 119 | desc 'E-mail auto responders.' 120 | newvalues(:unlimited, /\d+/) 121 | defaultto :unlimited 122 | end 123 | 124 | newproperty(:nsubdomains) do 125 | desc 'Subdomains.' 126 | newvalues(:unlimited, /\d+/) 127 | defaultto 0 128 | end 129 | 130 | newproperty(:php) do 131 | desc 'PHP access' 132 | newvalues(:on, :off) 133 | defaultto :off 134 | end 135 | 136 | newproperty(:spamassassin) do 137 | desc 'SpamAssassin' 138 | newvalues(:on, :off) 139 | defaultto :off 140 | end 141 | 142 | newproperty(:ssl) do 143 | desc 'SSL access' 144 | newvalues(:on, :off) 145 | defaultto :off 146 | end 147 | 148 | newproperty(:ssh) do 149 | desc 'SSH access' 150 | newvalues(:on, :off) 151 | defaultto :off 152 | end 153 | 154 | newproperty(:sysinfo) do 155 | desc 'System Info' 156 | newvalues(:on, :off) 157 | defaultto :off 158 | end 159 | 160 | newproperty(:suspend_at_limit) do 161 | desc 'Suspend at limit' 162 | newvalues(:on, :off) 163 | defaultto :off 164 | end 165 | 166 | newproperty(:skin) do 167 | desc 'The skin\'s name.' 168 | validate do |value| 169 | raise Puppet::Error, "skin is #{value.length} characters long; must be of length 4 or greater" if value.length < 4 170 | end 171 | end 172 | 173 | newproperty(:quota) do 174 | desc 'Disk space.' 175 | newvalues(:unlimited, /\d+/) 176 | defaultto :unlimited 177 | end 178 | 179 | newparam(:api_username) do 180 | desc 'The username to connect to the API.' 181 | isrequired 182 | validate do |value| 183 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 184 | end 185 | end 186 | 187 | newparam(:api_password) do 188 | desc 'The api_username\'s password to connect to the API.' 189 | isrequired 190 | validate do |value| 191 | raise(Puppet::Error, "Empty values are not allowed") if value == "" 192 | end 193 | end 194 | 195 | newparam(:api_hostname) do 196 | desc 'The API\'s endpoint. Do not specify the port here.' 197 | defaultto "localhost" 198 | end 199 | 200 | newparam(:api_port) do 201 | desc 'The API\'s endpoint\'s port.' 202 | defaultto "2222" 203 | end 204 | 205 | newparam(:api_ssl) do 206 | desc 'Connect to the API over SSL.' 207 | defaultto :false 208 | end 209 | 210 | end 211 | -------------------------------------------------------------------------------- /manifests/config/set.pp: -------------------------------------------------------------------------------- 1 | # directadmin::config::set 2 | define directadmin::config::set($value = '') { 3 | if $value == '' { fail("Value can't be empty.") } 4 | 5 | # File_line: set a config setting in DirectAdmin and notify the service. 6 | file_line { "config-set-${title}-${value}": 7 | path => '/usr/local/directadmin/conf/directadmin.conf', 8 | line => "${title}=${value}", 9 | match => "^${title}=", 10 | require => Class['directadmin::install'], 11 | notify => Service['directadmin'], 12 | } 13 | 14 | # Special settings: nameservers workaround for the 'admin' user. 15 | # - This makes sure that new resellers will get the right values. 16 | if $title =~ /^ns\d+/ { 17 | # File_line: set a nameserver value in admin/user.conf 18 | file_line { "config-set-admin-user-${title}-${value}": 19 | path => '/usr/local/directadmin/data/users/admin/user.conf', 20 | line => "${title}=${value}", 21 | match => "^${title}=", 22 | require => Class['directadmin::install'], 23 | } 24 | 25 | # File_line: set a nameserver value in admin/reseller.conf 26 | file_line { "config-set-admin-reseller-${title}-${value}": 27 | path => '/usr/local/directadmin/data/users/admin/reseller.conf', 28 | line => "${title}=${value}", 29 | match => "^${title}=", 30 | require => Class['directadmin::install'], 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /manifests/custombuild.pp: -------------------------------------------------------------------------------- 1 | # directadmin::custombuild 2 | class directadmin::custombuild inherits directadmin { 3 | # Exec: download the latest custombuild version 4 | exec { 'install-custombuild': 5 | cwd => '/usr/local/directadmin', 6 | command => "rm -rf custombuild* && wget --no-check-certificate -O custombuild.tar.gz ${::directadmin::params::custombuild_installer_location} && tar xvzf custombuild.tar.gz", 7 | creates => '/usr/local/directadmin/custombuild/options.conf', 8 | require => File['/usr/local/directadmin'], 9 | path => '/bin:/usr/bin', 10 | } 11 | 12 | # Set up a custom directory that can be used by other modules 13 | file { [ '/usr/local/directadmin/custombuild/custom/' ]: 14 | ensure => directory, 15 | require => [ Exec['install-custombuild'], ], 16 | before => [ Exec['directadmin-installer'], ], 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /manifests/custombuild/set.pp: -------------------------------------------------------------------------------- 1 | # This function sets custombuild settings. 2 | # More information on all the available options: 3 | # ./build opt_help full 4 | define directadmin::custombuild::set($value = '') { 5 | if $value == '' { fail("Value can't be empty.") } 6 | 7 | # Exec: ./build set setting value, this sets a configuration setting in custombuild 8 | # It needs to run before the installation so we can pre-set things before it runs. 9 | exec { "custombuild-set-${title}-${value}": 10 | command => "/usr/local/directadmin/custombuild/build set ${title} ${value}", 11 | unless => "grep /usr/local/directadmin/custombuild/options.conf -e '^${title}=${value}'", 12 | require => Class['directadmin::custombuild'], 13 | before => Class['directadmin::install'], 14 | path => '/bin:/usr/bin', 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manifests/directories.pp: -------------------------------------------------------------------------------- 1 | # directadmin::directories 2 | class directadmin::directories { 3 | # File: set up the required directories, we need to ensure they exist 4 | file { [ '/usr/local/directadmin', '/usr/local/directadmin/plugins' ]: 5 | ensure => directory, 6 | before => Class['directadmin::install'], 7 | } 8 | } -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # directadmin 2 | class directadmin( 3 | $clientid = undef, 4 | $licenseid = undef, 5 | $interface = undef, 6 | $auto_update = false, 7 | $admin_password = undef, 8 | $lan = false, 9 | $mail_limit = $::directadmin::params::mail_limit, 10 | $mail_limit_per_address = $::directadmin::params::mail_limit_per_address, 11 | $sa_updates = false, 12 | $php_imap = false, 13 | $default_webmail = $::directadmin::params::default_webmail, 14 | $default_rbl = false, 15 | $installer_location = $::directadmin::params::installer_location, 16 | $modsecurity = $::directadmin::params::modsecurity, 17 | $modsecurity_ruleset = $::directadmin::params::modsecurity_ruleset, 18 | $modsecurity_wordpress = $::directadmin::params::modsecurity_wordpress, 19 | ) inherits directadmin::params { 20 | # Run some sanity checks 21 | if !is_numeric($directadmin::clientid) { fail("The client ID ${directadmin::clientid} is not a number.") } 22 | if !is_numeric($directadmin::licenseid) { fail("The license ID ${directadmin::licenseid} is not a number.") } 23 | 24 | class { '::directadmin::directories': } 25 | -> class { '::directadmin::custombuild': } 26 | -> class { '::directadmin::install': } 27 | -> class { '::directadmin::update': } 28 | class { '::directadmin::services': } 29 | class { '::directadmin::resources': } 30 | class { '::directadmin::mail': } 31 | class { '::directadmin::modsecurity': } 32 | 33 | # Set all required options for custombuild 34 | $custombuild_options = lookup('directadmin::custombuild::options', Hash, 'deep', {}) 35 | create_resources(directadmin::custombuild::set, $custombuild_options) 36 | 37 | # Set all required configuration settings 38 | $directadmin_config = lookup('directadmin::config::options', Hash, 'deep', {}) 39 | create_resources(directadmin::config::set, $directadmin_config) 40 | 41 | # Set up the chain that defines when to run which resources in order to support Hiera. This is done in two steps: 42 | # - The first chain doesn't include the directadmin_admin resouce on purpose, you may not use it. 43 | # - The second chain makes sure that should you include a different admin, it's running before the reseller package resource. 44 | # - The third and fourth chain make sure that our workaround for nameservers in directadmin::config::set works. 45 | Class['directadmin::services'] -> User <| title == 'admin' |> -> Directadmin_reseller_package <| |> -> Directadmin_reseller <| |> -> Directadmin_user_package <| |> 46 | User <| title == 'admin' |> -> Directadmin_admin <| |> -> Directadmin_reseller_package <| |> 47 | File_line <| path == '/usr/local/directadmin/data/users/admin/user.conf' |> -> Directadmin_reseller_package <| |> 48 | File_line <| path == '/usr/local/directadmin/data/users/admin/reseller.conf' |> -> Directadmin_reseller_package <| |> 49 | } 50 | -------------------------------------------------------------------------------- /manifests/install.pp: -------------------------------------------------------------------------------- 1 | # directadmin::install 2 | class directadmin::install inherits directadmin { 3 | # Decide which interface to use 4 | if $directadmin::interface == undef { 5 | if has_interface_with('venet0') { $directadmin_interface = 'venet0:0' } 6 | else { $directadmin_interface = 'eth0'} 7 | } else { 8 | $directadmin_interface = $directadmin::interface 9 | } 10 | 11 | # The following will install all required packages for SpamAssassin on CentOS servers. 12 | if $::osfamily == 'RedHat' { 13 | if versioncmp($::operatingsystemmajrelease, '6') >= 0 { 14 | $directadmin_packages = [ 15 | 'perl-ExtUtils-MakeMaker', 'perl-Digest-SHA', 'perl-Net-DNS', 'perl-NetAddr-IP', 16 | 'perl-Archive-Tar', 'perl-IO-Zlib', 'perl-Mail-SPF', 'perl-IO-Socket-INET6', 17 | 'perl-IO-Socket-SSL', 'perl-Mail-DKIM', 'perl-DBI', 'perl-Encode-Detect', 18 | 'perl-HTML-Parser', 'perl-HTML-Tagset', 'perl-Time-HiRes', 'perl-libwww-perl', 19 | 'perl-ExtUtils-Embed', 20 | ] 21 | } 22 | if versioncmp($::operatingsystemmajrelease, '7') >= 0 { 23 | $additional_packages = [ 24 | 'perl-Sys-Syslog', 'perl-DB_File', 25 | ] 26 | 27 | # Package: required packages for SpamAssassin on CentOS 7+ 28 | package { $additional_packages: 29 | ensure => installed, 30 | before => Exec['directadmin-download-installer'], 31 | } 32 | } 33 | } 34 | 35 | # The following will install all required packages for SpamAssassin on Debian servers. 36 | if $::osfamily == 'Debian' { 37 | $directadmin_packages = [ 38 | 'libarchive-any-perl', 'libhtml-parser-perl', 'libnet-dns-perl', 'libnetaddr-ip-perl', 39 | 'libhttp-date-perl', 40 | ] 41 | } 42 | 43 | # Package: required packages for SpamAssassin etc. 44 | package { $directadmin_packages: 45 | ensure => installed, 46 | before => Exec['directadmin-download-installer'], 47 | } 48 | 49 | # Using DirectAdmin on a server behind NAT (example: 192.168.0.x)? Touch /root/.lan. 50 | # When this file contains '1', setup.sh will skip --bind-address in wget. 51 | # For more information about running DirectAdmin behind NAT: http://www.directadmin.com/lan.shtml 52 | if $directadmin::lan { 53 | file { '/root/.lan': 54 | ensure => file, 55 | content => '1', 56 | before => Exec['directadmin-installer'], 57 | } 58 | } 59 | 60 | # Exec: make sure the required packages are installed automatically. This provides support for all operating systems. 61 | exec { 'directadmin-set-pre-install': 62 | cwd => '/root', 63 | command => 'echo 1 > /root/.preinstall', 64 | creates => '/root/.preinstall', 65 | before => Exec['directadmin-installer'], 66 | path => '/bin:/usr/bin', 67 | } 68 | 69 | # Exec: set up the installation files 70 | exec { 'directadmin-download-installer': 71 | cwd => '/root', 72 | command => "wget -O setup.sh --no-check-certificate ${::directadmin::installer_location} && chmod +x /root/setup.sh", 73 | creates => '/root/setup.sh', 74 | path => '/bin:/usr/bin', 75 | } 76 | 77 | # Exec: install DirectAdmin 78 | exec { 'directadmin-installer': 79 | cwd => '/root', 80 | command => "echo 2.0 > /root/.custombuild && /root/setup.sh ${::directadmin::clientid} ${::directadmin::licenseid} ${::fqdn} ${directadmin_interface}", 81 | require => [ Exec['directadmin-download-installer'], Class['directadmin::custombuild'], ], 82 | creates => '/usr/local/directadmin/conf/directadmin.conf', 83 | timeout => 0, 84 | path => '/sbin:/usr/sbin:/bin:/usr/bin', 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /manifests/mail.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mail 2 | class directadmin::mail { 3 | 4 | # File change: set up our e-mail limit 5 | file { '/etc/virtual/limit': 6 | ensure => present, 7 | owner => mail, 8 | group => mail, 9 | mode => '0644', 10 | 11 | # maximum e-mails per day, it needs quotes to ensure it gets 12 | # read correctly, Hiera will set it as an integer for example 13 | content => sprintf('%s', $::directadmin::mail_limit), 14 | 15 | # restart on change 16 | notify => Service['exim'], 17 | require => Exec['directadmin-installer'], 18 | } 19 | # File change: /etc/virtual/limit_unknown 20 | -> file { '/etc/virtual/limit_unknown': 21 | ensure => present, 22 | owner => mail, 23 | group => mail, 24 | mode => '0644', 25 | content => sprintf('%s', '0'), 26 | notify => Service['exim'], 27 | require => Exec['directadmin-installer'], 28 | } 29 | # File change: /etc/virtual/user_limit 30 | -> file { '/etc/virtual/user_limit': 31 | ensure => present, 32 | owner => mail, 33 | group => mail, 34 | 35 | # this file is set to 755 by directadmin by default 36 | mode => '0755', 37 | 38 | # maximum e-mails per day, per e-mail address. 39 | # it needs quotes to ensure it gets read correctly, Hiera will 40 | # set it as an integer for example 41 | content => sprintf('%s', $::directadmin::mail_limit_per_address), 42 | notify => Service['exim'], 43 | require => Exec['directadmin-installer'], 44 | } 45 | 46 | # File: set the default webmail client 47 | file { '/var/www/html/webmail': 48 | ensure => link, 49 | target => "/var/www/html/${::directadmin::default_webmail}", 50 | require => Exec['directadmin-installer'], 51 | } 52 | # File_line: set the default /webmail alias 53 | file_line { 'httpd-alias-default-webmail': 54 | ensure => present, 55 | path => '/etc/httpd/conf/extra/httpd-alias.conf', 56 | line => "Alias /webmail /var/www/html/${::directadmin::default_webmail}", 57 | match => 'Alias \/webmail', 58 | notify => Service['httpd'], 59 | require => Exec['directadmin-installer'], 60 | } 61 | directadmin::config::set { 'webmail_link': value => $::directadmin::default_webmail, } 62 | 63 | # Install support for imap in php if required 64 | if $::directadmin::php_imap == true { 65 | # Make sure libc-client2007e-dev is installed on Debian and Ubuntu 66 | if $::operatingsystem =~ /^(Debian|Ubuntu)$/ { 67 | if versioncmp($::operatingsystemmajrelease, '7') >= 0 { 68 | if versioncmp($::puppetversion, '3.6.0') >= 0 { 69 | # There is a really weird bug in puppet-lint that errors out when 70 | # a space is added between Package and {. 71 | Package{ 72 | allow_virtual => true, 73 | } 74 | } 75 | 76 | package { 'libc-client2007e-dev': 77 | ensure => installed, 78 | before => Exec['directadmin-download-php-imap'], 79 | } 80 | } 81 | } 82 | exec { 'directadmin-download-php-imap': 83 | cwd => '/root', 84 | command => 'wget -O /root/imap_php.sh files.directadmin.com/services/all/imap_php.sh && chmod +x /root/imap_php.sh', 85 | creates => '/root/imap_php.sh', 86 | require => Exec['directadmin-installer'], 87 | path => '/bin:/usr/bin', 88 | } 89 | exec { 'directadmin-install-php-imap': 90 | cwd => '/root', 91 | command => '/root/imap_php.sh', 92 | unless => 'php -i | grep -i c-client | wc -l | grep -c 1', 93 | require => [ Exec['directadmin-installer'], Exec['directadmin-download-php-imap'] ], 94 | timeout => 0, 95 | path => '/bin:/usr/bin', 96 | notify => Service['httpd'], 97 | } 98 | } 99 | 100 | # File_line: make sure the primary hostname is set in exim.conf 101 | # as we have seen some issues with CentOS 7 here. 102 | file_line { 'exim-set-primary-hostname': 103 | path => '/etc/exim.conf', 104 | line => "primary_hostname = ${::fqdn}", 105 | match => '^(# )?primary_hostname =', 106 | notify => Service['exim'], 107 | require => Exec['directadmin-installer'], 108 | } 109 | 110 | # SpamAssassin cron jobs 111 | if $::directadmin::sa_updates == true { 112 | $sa_cron = 'present' 113 | } else { 114 | $sa_cron = 'absent' 115 | } 116 | 117 | # Cron: daily update of SpamAssassin rules 118 | cron { 'exim-sa-update': 119 | ensure => $sa_cron, 120 | command => '/usr/bin/sa-update && /sbin/service exim restart >/dev/null 2>&1', 121 | user => root, 122 | hour => 7, 123 | minute => 5, 124 | require => Exec['directadmin-installer'], 125 | } 126 | 127 | # Set up RBL checks by default 128 | if $::directadmin::default_rbl == true { 129 | file { '/etc/virtual/use_rbl_domains': 130 | ensure => 'link', 131 | target => '/etc/virtual/domains', 132 | require => Exec['directadmin-installer'], 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /manifests/mail/exim/config.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mail::exim::config 2 | define directadmin::mail::exim::config( 3 | $value = undef, 4 | $file = undef, 5 | ) { 6 | # Check the $file parameter 7 | if $file == undef { fail('file must be set.') } 8 | if $file =~ /\/etc/ { fail('file should be specified without /etc') } 9 | 10 | # Check $value parameter - we don't do consistency checks! 11 | if $value == undef { fail('value must be set.') } 12 | 13 | # Manage /etc/${file} 14 | ensure_resource('file', "/etc/${file}", { 'ensure' => 'present', 'mode' => '0644'} ) 15 | 16 | file_line { "exim-set-${file}-${title}-${value}": 17 | path => "/etc/${file}", 18 | line => "${title}==${value}", 19 | match => "^${title}==", 20 | require => File["/etc/${file}"], 21 | notify => Service['exim'], 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /manifests/mail/exim/virtual.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mail::exim::virtual 2 | define directadmin::mail::exim::virtual( 3 | $value = undef, 4 | $file = undef, 5 | ) { 6 | # Check the $file parameter 7 | if $file == undef { fail('file must be set.') } 8 | if $file =~ /\/etc\/virtual/ { fail('file should be specified without /etc/virtual/') } 9 | 10 | # Check $value parameter - we don't do consistency checks! 11 | if $value == undef { fail('value must be set.') } 12 | 13 | # Manage /etc/virtual/${file} 14 | ensure_resource('file', "/etc/virtual/${file}", { 15 | 'ensure' => 'present', 16 | 'mode' => '0755', 17 | 'owner' => 'mail', 18 | 'group' => 'mail', 19 | 'require' => 'Exec[directadmin-installer]', 20 | }) 21 | 22 | file_line { "exim-set-${file}-${value}": 23 | path => "/etc/virtual/${file}", 24 | line => $value, 25 | require => File["/etc/virtual/${file}"], 26 | notify => Service['exim'], 27 | } 28 | } -------------------------------------------------------------------------------- /manifests/mail/spamassassin/config.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mail::spamassassin::config 2 | # Use this if you want to create bigger configuration blocks 3 | define directadmin::mail::spamassassin::config( 4 | $ensure = 'present', 5 | $content = '', 6 | $order = 99, 7 | ) { 8 | file { "${order}-${title}": 9 | ensure => $ensure, 10 | path => "/etc/mail/spamassassin/${order}-${title}.cf", 11 | content => $content, 12 | require => Exec['directadmin-installer'], 13 | notify => Service['exim'], 14 | } 15 | } -------------------------------------------------------------------------------- /manifests/mail/spamassassin/score.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mail::spamassassin::score 2 | define directadmin::mail::spamassassin::score($score = 1) { 3 | file_line { "enable-${title}-${score}": 4 | ensure => present, 5 | path => '/etc/mail/spamassassin/local.cf', 6 | line => "score ${title} ${score}", 7 | match => "^score ${title}.*", 8 | notify => Service['exim'], 9 | require => Exec['directadmin-installer'], 10 | } 11 | } -------------------------------------------------------------------------------- /manifests/modsecurity.pp: -------------------------------------------------------------------------------- 1 | # directadmin::mod_security 2 | class directadmin::modsecurity inherits directadmin { 3 | if $::directadmin::modsecurity { 4 | directadmin::custombuild::set { 'modsecurity': value => 'yes' } 5 | 6 | # This enables the modsecurity ruleset from DirectAdmin, it's disabled by us by default 7 | if $::directadmin::modsecurity_ruleset { 8 | directadmin::custombuild::set { 'modsecurity_ruleset': value => $::directadmin::modsecurity_ruleset } 9 | } else { 10 | directadmin::custombuild::set { 'modsecurity_ruleset': value => 'no' } 11 | } 12 | 13 | # This enables our custom wordpress ruleset 14 | if $::directadmin::modsecurity_wordpress { 15 | file { [ '/usr/local/directadmin/custombuild/custom/modsecurity/', '/usr/local/directadmin/custombuild/custom/modsecurity/conf/' ]: 16 | ensure => directory, 17 | require => File['/usr/local/directadmin/custombuild/custom/'], 18 | before => File['/usr/local/directadmin/custombuild/custom/modsecurity/conf/wordpress.conf'], 19 | } 20 | file { '/usr/local/directadmin/custombuild/custom/modsecurity/conf/wordpress.conf': 21 | ensure => present, 22 | content => template('directadmin/modsecurity/modsec-wordpress.conf.erb'), 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # params 2 | class directadmin::params { 3 | # The installation URL and a set of base packages that we need to install 4 | $installer_location = 'http://www.directadmin.com/setup.sh' 5 | $custombuild_installer_location = 'http://files.directadmin.com/services/custombuild/2.0/custombuild.tar.gz' 6 | 7 | # Mail settings 8 | $default_webmail = 'roundcube' 9 | $mail_limit = 200 10 | $mail_limit_per_address = 0 11 | 12 | # ModSecurity 13 | $modsecurity = false 14 | $modsecurity_ruleset = false 15 | $modsecurity_wordpress = false 16 | } -------------------------------------------------------------------------------- /manifests/resources.pp: -------------------------------------------------------------------------------- 1 | # directadmin::resources 2 | class directadmin::resources { 3 | # Create additional admin users and manage the primary one 4 | if $directadmin::admin_password != undef { 5 | user { 'admin': password => $directadmin::admin_password, } 6 | } 7 | $directadmin_admins = lookup('directadmin::admins', Hash, 'deep', {}) 8 | create_resources(directadmin_admin, $directadmin_admins) 9 | 10 | # Create reseller packages 11 | $directadmin_reseller_packages = lookup('directadmin::reseller::packages', Hash, 'deep', {}) 12 | create_resources(directadmin_reseller_package, $directadmin_reseller_packages) 13 | 14 | # Create resellers 15 | $directadmin_resellers = lookup('directadmin::resellers', Hash, 'deep', {}) 16 | create_resources(directadmin_reseller, $directadmin_resellers) 17 | 18 | # Create user packages 19 | $directadmin_user_packages = lookup('directadmin::user::packages', Hash, 'deep', {}) 20 | create_resources(directadmin_user_package, $directadmin_user_packages) 21 | } 22 | -------------------------------------------------------------------------------- /manifests/services.pp: -------------------------------------------------------------------------------- 1 | # directadmin::services 2 | class directadmin::services { 3 | case $::operatingsystem { 4 | 'RedHat', 'CentOS': { $has_status = true } 5 | /^(Debian|Ubuntu)$/: { $has_status = false } 6 | default: { $has_status = true } 7 | } 8 | 9 | # Service: exim, our e-mail server 10 | service { 'exim': 11 | ensure => running, 12 | enable => true, 13 | hasrestart => true, 14 | hasstatus => $has_status, 15 | require => Exec['directadmin-installer'], 16 | } 17 | 18 | # Service: dovecot, our POP/IMAP server 19 | service { 'dovecot': 20 | ensure => running, 21 | enable => true, 22 | hasrestart => true, 23 | hasstatus => $has_status, 24 | require => Exec['directadmin-installer'], 25 | } 26 | 27 | # Service: apache, our web server 28 | service { 'httpd': 29 | ensure => running, 30 | enable => true, 31 | hasrestart => true, 32 | hasstatus => $has_status, 33 | require => Exec['directadmin-installer'], 34 | } 35 | 36 | # Service: directadmin, our control panel 37 | service { 'directadmin': 38 | ensure => running, 39 | enable => true, 40 | hasrestart => true, 41 | hasstatus => $has_status, 42 | require => Exec['directadmin-installer'], 43 | } 44 | 45 | # Service: named, our dns server 46 | service { 'named': 47 | ensure => running, 48 | enable => true, 49 | hasrestart => true, 50 | hasstatus => $has_status, 51 | require => Exec['directadmin-installer'], 52 | } 53 | 54 | # Service: mysqld, our database server 55 | service { 'mysqld': 56 | ensure => running, 57 | enable => true, 58 | hasrestart => true, 59 | hasstatus => $has_status, 60 | require => Exec['directadmin-installer'], 61 | } 62 | } -------------------------------------------------------------------------------- /manifests/services/named.pp: -------------------------------------------------------------------------------- 1 | # directadmin::named 2 | class directadmin::services::named( 3 | $allow_transfer = '', 4 | $also_notify = '', 5 | $ensure_transfer = 'present', 6 | $ensure_notify = 'present', 7 | ) { 8 | case $::operatingsystem { 9 | 'RedHat', 'CentOS': { $named_path = '/etc/named.conf' } 10 | /^(Debian|Ubuntu)$/: { $named_path = '/etc/bind/named.conf.options' } 11 | default: { $named_path = '/etc/named.conf' } 12 | } 13 | 14 | # Exec: rewrite named configurations when required 15 | exec { 'rewrite-named-config': 16 | command => 'echo "action=rewrite&value=named" >> /usr/local/directadmin/data/task.queue', 17 | require => Exec['directadmin-installer'], 18 | refreshonly => true, 19 | unless => 'grep -c named /usr/local/directadmin/data/task.queue', 20 | path => '/bin:/usr/bin', 21 | } 22 | 23 | if $allow_transfer != '' { 24 | # File_line: enable allow transfers 25 | file_line { 'named-enable-allow-transfer': 26 | ensure => $ensure_transfer, 27 | path => $named_path, 28 | line => "\tallow-transfer { ${allow_transfer}; };", 29 | match => "^\tallow-transfer", 30 | after => '^options \{', 31 | notify => Service['named'], 32 | require => Exec['directadmin-installer'], 33 | } 34 | } 35 | 36 | if $also_notify != '' { 37 | # File_line: also notify 38 | file_line { 'named-enable-also-notify': 39 | ensure => $ensure_notify, 40 | path => $named_path, 41 | line => "\talso-notify { ${also_notify}; };", 42 | match => "^\talso-notify", 43 | after => '^options \{', 44 | notify => Service['named'], 45 | require => Exec['directadmin-installer'], 46 | } 47 | 48 | # File_line: also notify 49 | file_line { 'named-enable-notify-setting': 50 | ensure => $ensure_notify, 51 | path => $named_path, 52 | line => "\tnotify yes;", 53 | match => "^\tnotify", 54 | after => '^options \{', 55 | notify => Service['named'], 56 | require => Exec['directadmin-installer'], 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /manifests/update.pp: -------------------------------------------------------------------------------- 1 | # directadmin::update 2 | class directadmin::update inherits directadmin { 3 | if $::directadmin::auto_update == true { 4 | exec { 'update-versions': 5 | cwd => '/usr/local/directadmin/custombuild', 6 | command => '/usr/local/directadmin/custombuild/build update_versions', 7 | unless => '/usr/local/directadmin/custombuild/build update && /usr/local/directadmin/custombuild/build versions', 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /manifests/user_ssl.pp: -------------------------------------------------------------------------------- 1 | # directadmin::user_ssl 2 | define directadmin::user_ssl($domain = $title, $user = '', $sslcert = '', $sslkey = '', $sslca = '', $sslpem = '') { 3 | if $user == '' { fail("user can't be empty") } 4 | if $sslcert == '' { fail("sslcert can't be empty") } 5 | if $sslkey == '' { fail("sslkey can't be empty") } 6 | 7 | # This is our certificate 8 | file { "/usr/local/directadmin/data/users/${user}/domains/${domain}.cert": 9 | content => $sslcert, 10 | notify => Service['httpd'], 11 | require => Exec['directadmin-installer'], 12 | } 13 | 14 | # Our key 15 | file { "/usr/local/directadmin/data/users/${user}/domains/${domain}.key": 16 | content => $sslkey, 17 | notify => Service['httpd'], 18 | require => Exec['directadmin-installer'], 19 | owner => 'diradmin', 20 | group => 'mail', 21 | } 22 | 23 | if $sslca != '' { 24 | # Our CA 25 | file { "/usr/local/directadmin/data/users/${user}/domains/${domain}.cacert": 26 | content => $sslca, 27 | notify => Service['httpd'], 28 | require => Exec['directadmin-installer'], 29 | } 30 | } 31 | 32 | if $sslpem != '' { 33 | # A PEM file to be used by SNI (e.g. Exim) 34 | file { "/usr/local/directadmin/data/users/${user}/domains/${domain}.cert.combined": 35 | content => $sslpem, 36 | notify => Service['httpd'], 37 | require => Exec['directadmin-installer'], 38 | owner => 'diradmin', 39 | group => 'mail', 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sensson-directadmin", 3 | "version": "2.0.0", 4 | "author": "sensson", 5 | "license": "Apache-2.0", 6 | "summary": "A module to install and configure DirectAdmin", 7 | "source": "https://github.com/sensson/puppet-directadmin", 8 | "project_page": "https://github.com/sensson/puppet-directadmin", 9 | "issues_url": "https://github.com/sensson/puppet-directadmin/issues", 10 | "tags": [ "directadmin" ], 11 | "operatingsystem_support": [ 12 | { "operatingsystem":"CentOS", "operatingsystemrelease":[ "6.0", "7.0" ] }, 13 | { "operatingsystem":"RedHat", "operatingsystemrelease":[ "6.0", "7.0" ] }, 14 | { "operatingsystem":"Ubuntu", "operatingsystemrelease":[ "14.04" ] }, 15 | { "operatingsystem":"Debian", "operatingsystemrelease":[ "7.0" ] } 16 | ], 17 | "requirements": [ 18 | { "name": "puppet", "version_requirement": ">= 4.7.0 < 6.0.0" } 19 | ], 20 | "dependencies": [ 21 | { "name": "puppetlabs/stdlib", "version_requirement": ">=4.3.2 < 5.0.0" } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /spec/acceptance/class_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper_acceptance' 2 | 3 | describe 'directadmin class' do 4 | context 'authorative server' do 5 | # Using puppet_apply as a helper 6 | it 'should work idempotently with no errors' do 7 | pp = <<-EOS 8 | class { 'directadmin': } 9 | EOS 10 | 11 | # Run it twice and test for idempotency 12 | apply_manifest(pp, :catch_failures => true) 13 | apply_manifest(pp, :catch_changes => true) 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /spec/acceptance/nodesets/centos6.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | centos-66-x64: 3 | roles: 4 | - master 5 | platform: el-6-x86_64 6 | box: puppetlabs/centos-6.6-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/centos-6.6-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/centos7.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | centos-72-x64: 3 | roles: 4 | - master 5 | platform: el-7-x86_64 6 | box: puppetlabs/centos-7.2-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/centos-7.2-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/debian7.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | debian-78-x64: 3 | roles: 4 | - master 5 | platform: debian-7-amd64 6 | box: puppetlabs/debian-7.8-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/debian-7.8-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/debian8.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | debian-82-x64: 3 | roles: 4 | - master 5 | platform: debian-8-amd64 6 | box: debian/jessie64 7 | box_url: https://vagrantcloud.com/debian/boxes/jessie64 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/default.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | centos-72-x64: 3 | roles: 4 | - master 5 | platform: el-7-x86_64 6 | box: puppetlabs/centos-7.2-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/centos-7.2-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/ubuntu1404.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-1404-x64: 3 | roles: 4 | - master 5 | platform: ubuntu-1404-amd64 6 | box: puppetlabs/ubuntu-14.04-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/ubuntu-14.04-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/acceptance/nodesets/ubuntu1604.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-1604-x64: 3 | roles: 4 | - master 5 | platform: ubuntu-1604-amd64 6 | box: puppetlabs/ubuntu-16.04-64-nocm 7 | box_url: https://vagrantcloud.com/puppetlabs/boxes/ubuntu-16.04-64-nocm 8 | hypervisor: vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss -------------------------------------------------------------------------------- /spec/classes/coverage_spec.rb: -------------------------------------------------------------------------------- 1 | at_exit { RSpec::Puppet::Coverage.report! } -------------------------------------------------------------------------------- /spec/classes/directadmin_custombuild_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::custombuild', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::custombuild class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | custombuild_installer = 'http://files.directadmin.com/services/custombuild/2.0/custombuild.tar.gz' 16 | it { is_expected.to compile.with_all_deps } 17 | it { is_expected.to contain_exec('install-custombuild').with_command('rm -rf custombuild* && wget --no-check-certificate -O custombuild.tar.gz %s && tar xvzf custombuild.tar.gz' % [ custombuild_installer ])} 18 | it { is_expected.to contain_exec('install-custombuild').with_require('File[/usr/local/directadmin]') } 19 | it { is_expected.to contain_file('/usr/local/directadmin/custombuild/custom/').with_ensure('directory') } 20 | end 21 | end 22 | end 23 | end 24 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_directories_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::directories', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::directories class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | it { is_expected.to compile.with_all_deps } 16 | it { is_expected.to contain_file('/usr/local/directadmin').with_ensure('directory') } 17 | it { is_expected.to contain_file('/usr/local/directadmin/plugins').with_ensure('directory') } 18 | end 19 | end 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_init_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin class with parameters" do 11 | let(:params) {{ 12 | :clientid => '1234', 13 | :licenseid => '123456' 14 | }} 15 | 16 | it { is_expected.to compile.with_all_deps } 17 | it { is_expected.to contain_class('directadmin') } 18 | it { is_expected.to contain_class('directadmin::directories') } 19 | it { is_expected.to contain_class('directadmin::custombuild') } 20 | it { is_expected.to contain_class('directadmin::install') } 21 | it { is_expected.to contain_class('directadmin::update') } 22 | it { is_expected.to contain_class('directadmin::services') } 23 | it { is_expected.to contain_class('directadmin::resources') } 24 | it { is_expected.to contain_class('directadmin::mail') } 25 | it { is_expected.to contain_class('directadmin::params') } 26 | it { is_expected.to contain_class('directadmin::modsecurity') } 27 | 28 | # Directories. Referenced in directadmin::directories 29 | # Filename: directadmin_custombuild_directories.rb 30 | it { is_expected.to contain_file('/usr/local/directadmin').with_ensure('directory') } 31 | it { is_expected.to contain_file('/usr/local/directadmin/plugins').with_ensure('directory') } 32 | end 33 | 34 | context "directadmin class without parameters" do 35 | it 'fails' do 36 | expect { subject.call } .to raise_error(/The client ID/) 37 | end 38 | end 39 | 40 | end 41 | end 42 | end 43 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_install_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::install', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::install class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | it { is_expected.to compile.with_all_deps } 16 | it { is_expected.to contain_exec('directadmin-set-pre-install').with('cwd' => '/root') } 17 | it { is_expected.to contain_exec('directadmin-set-pre-install').with('command' => 'echo 1 > /root/.preinstall') } 18 | it { is_expected.to contain_exec('directadmin-set-pre-install').with('creates' => '/root/.preinstall') } 19 | it { is_expected.to contain_exec('directadmin-set-pre-install').that_comes_before('Exec[directadmin-installer]') } 20 | it { is_expected.to contain_exec('directadmin-download-installer').with('cwd' => '/root') } 21 | it { is_expected.to contain_exec('directadmin-download-installer').with('command' => 'wget -O setup.sh --no-check-certificate http://www.directadmin.com/setup.sh && chmod +x /root/setup.sh') } 22 | it { is_expected.to contain_exec('directadmin-download-installer').with('creates' => '/root/setup.sh') } 23 | it { is_expected.to contain_exec('directadmin-download-installer').with('cwd' => '/root') } 24 | it { is_expected.to contain_exec('directadmin-installer').with('cwd' => '/root') } 25 | it { is_expected.to contain_exec('directadmin-installer').with_command('echo 2.0 > /root/.custombuild && /root/setup.sh %i %i %s %s' % [ 1234, 123456, facts[:fqdn], 'eth0' ]) } 26 | 27 | case facts[:osfamily] 28 | when 'RedHat' 29 | if facts[:operatingsystemmajrelease].to_i >= 6 30 | it { is_expected.to contain_package('perl-ExtUtils-MakeMaker') } 31 | it { is_expected.to contain_package('perl-Digest-SHA') } 32 | it { is_expected.to contain_package('perl-Net-DNS') } 33 | it { is_expected.to contain_package('perl-NetAddr-IP') } 34 | it { is_expected.to contain_package('perl-Archive-Tar') } 35 | it { is_expected.to contain_package('perl-IO-Zlib') } 36 | it { is_expected.to contain_package('perl-Mail-SPF') } 37 | it { is_expected.to contain_package('perl-IO-Socket-INET6') } 38 | it { is_expected.to contain_package('perl-IO-Socket-SSL') } 39 | it { is_expected.to contain_package('perl-Mail-DKIM') } 40 | it { is_expected.to contain_package('perl-DBI') } 41 | it { is_expected.to contain_package('perl-Encode-Detect') } 42 | it { is_expected.to contain_package('perl-HTML-Parser') } 43 | it { is_expected.to contain_package('perl-HTML-Tagset') } 44 | it { is_expected.to contain_package('perl-Time-HiRes') } 45 | it { is_expected.to contain_package('perl-libwww-perl') } 46 | it { is_expected.to contain_package('perl-ExtUtils-Embed') } 47 | end 48 | if facts[:operatingsystemmajrelease].to_i >= 7 49 | it { is_expected.to contain_package('perl-Sys-Syslog') } 50 | it { is_expected.to contain_package('perl-DB_File') } 51 | end 52 | when 'Debian' 53 | it { is_expected.to contain_package('libarchive-any-perl') } 54 | it { is_expected.to contain_package('libhtml-parser-perl') } 55 | it { is_expected.to contain_package('libnet-dns-perl') } 56 | it { is_expected.to contain_package('libnetaddr-ip-perl') } 57 | it { is_expected.to contain_package('libhttp-date-perl') } 58 | end 59 | end 60 | 61 | context "directadmin::install class with lan enabled" do 62 | let(:pre_condition) do 63 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, lan => true }' 64 | end 65 | 66 | it { is_expected.to compile.with_all_deps } 67 | it { is_expected.to contain_file('/root/.lan').with_content('1') } 68 | it { is_expected.to contain_file('/root/.lan').with_ensure('file') } 69 | it { is_expected.to contain_file('/root/.lan').that_comes_before('Exec[directadmin-installer]') } 70 | end 71 | 72 | end 73 | end 74 | end 75 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_mail_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::mail', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::mail class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | it { is_expected.to compile.with_all_deps } 16 | it { is_expected.to contain_class('directadmin::mail') } 17 | 18 | it { is_expected.to contain_file('/etc/virtual/limit').with_content('200') } 19 | it { is_expected.to contain_file('/etc/virtual/limit').that_requires('Exec[directadmin-installer]') } 20 | it { is_expected.to contain_file('/etc/virtual/limit_unknown').with_content('0') } 21 | it { is_expected.to contain_file('/etc/virtual/limit_unknown').that_requires('Exec[directadmin-installer]') } 22 | it { is_expected.to contain_file('/etc/virtual/user_limit').with_content('0') } 23 | it { is_expected.to contain_file('/etc/virtual/user_limit').that_requires('Exec[directadmin-installer]') } 24 | 25 | it { is_expected.to contain_file('/var/www/html/webmail').with_target('/var/www/html/roundcube') } 26 | it { is_expected.to contain_file('/var/www/html/webmail').that_requires('Exec[directadmin-installer]') } 27 | it { is_expected.to contain_file_line('httpd-alias-default-webmail').with_line('Alias /webmail /var/www/html/roundcube') } 28 | it { is_expected.to contain_file_line('httpd-alias-default-webmail').that_requires('Exec[directadmin-installer]') } 29 | it { is_expected.to contain_directadmin__config__set('webmail_link') } 30 | it { is_expected.to contain_file_line('config-set-webmail_link-roundcube') } 31 | 32 | it { is_expected.to contain_cron('exim-sa-update').with_ensure('absent') } 33 | it { is_expected.to contain_file_line('exim-set-primary-hostname').with_line('primary_hostname = %s' % [facts[:fqdn]]) } 34 | 35 | # By default we don't manage rbls 36 | it { is_expected.not_to contain_file('/etc/virtual/use_rbl_domains') } 37 | 38 | # By default we don't install php-imap 39 | it { is_expected.not_to contain_exec('directadmin-download-php-imap') } 40 | it { is_expected.not_to contain_exec('directadmin-install-php-imap') } 41 | it { is_expected.not_to contain_exec('libc-client2007e-dev') } 42 | end 43 | 44 | context "directadmin::mail class with php imap" do 45 | let(:pre_condition) do 46 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, php_imap => true, }' 47 | end 48 | 49 | 50 | it { is_expected.to contain_exec('directadmin-download-php-imap') } 51 | it { is_expected.to contain_exec('directadmin-install-php-imap') } 52 | 53 | if facts[:operatingsystem] =~ /^(Debian|Ubuntu)$/ 54 | if facts[:operatingsystemmajrelease].to_i >= 7 55 | it { is_expected.to contain_package('libc-client2007e-dev') } 56 | end 57 | end 58 | end 59 | 60 | context "directadmin::mail class with spamassassin updates" do 61 | let(:pre_condition) do 62 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, sa_updates => true, }' 63 | end 64 | 65 | it { is_expected.to contain_cron('exim-sa-update').with_ensure('present') } 66 | end 67 | 68 | context "directadmin::mail class with rbl management" do 69 | let(:pre_condition) do 70 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, default_rbl => true, }' 71 | end 72 | 73 | it { is_expected.to contain_file('/etc/virtual/use_rbl_domains').with_ensure('link') } 74 | it { is_expected.to contain_file('/etc/virtual/use_rbl_domains').with_require('Exec[directadmin-installer]') } 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/classes/directadmin_modsecurity_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::modsecurity', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::modsecurity class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | it { is_expected.to compile.with_all_deps } 16 | it { is_expected.not_to contain_directadmin__custombuild__set('modsecurity') } 17 | it { is_expected.not_to contain_directadmin__custombuild__set('modsecurity_ruleset') } 18 | end 19 | 20 | context "directadmin::modsecurity class with modsecurity enabled" do 21 | let(:pre_condition) do 22 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, modsecurity => true }' 23 | end 24 | 25 | it { is_expected.to compile.with_all_deps } 26 | it { is_expected.to contain_directadmin__custombuild__set('modsecurity') } 27 | it { is_expected.to contain_exec('custombuild-set-modsecurity-yes') } 28 | it { is_expected.to contain_exec('custombuild-set-modsecurity_ruleset-no') } 29 | end 30 | 31 | context "directadmin::modsecurity class with modsecurity and modsecurity ruleset enabled" do 32 | let(:pre_condition) do 33 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, modsecurity => true, modsecurity_ruleset => comodo }' 34 | end 35 | 36 | it { is_expected.to compile.with_all_deps } 37 | it { is_expected.to contain_directadmin__custombuild__set('modsecurity_ruleset') } 38 | it { is_expected.to contain_exec('custombuild-set-modsecurity_ruleset-comodo') } 39 | end 40 | 41 | context "directadmin::modsecurity class with modsecurity and modsecurity wordpress enabled" do 42 | let(:pre_condition) do 43 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, modsecurity => true, modsecurity_wordpress => true }' 44 | end 45 | 46 | it { is_expected.to compile.with_all_deps } 47 | it { is_expected.to contain_file('/usr/local/directadmin/custombuild/custom/modsecurity/').with_ensure('directory') } 48 | it { is_expected.to contain_file('/usr/local/directadmin/custombuild/custom/modsecurity/conf/').with_ensure('directory') } 49 | it { is_expected.to contain_file('/usr/local/directadmin/custombuild/custom/modsecurity/conf/wordpress.conf') } 50 | end 51 | 52 | end 53 | end 54 | end 55 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_resources_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::resources', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::resources class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | case facts[:operatingsystem] 16 | when 'RedHat', 'CentOS' 17 | hasstatus = 'true' 18 | when 'Debian', 'Ubuntu' 19 | hasstatus = 'false' 20 | end 21 | 22 | it { is_expected.to compile.with_all_deps } 23 | it { is_expected.not_to contain_user('admin') } 24 | end 25 | 26 | context "directadmin::resources class with the admin password specified" do 27 | let(:pre_condition) do 28 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, admin_password => \'hashed\' }' 29 | end 30 | 31 | case facts[:operatingsystem] 32 | when 'RedHat', 'CentOS' 33 | hasstatus = 'true' 34 | when 'Debian', 'Ubuntu' 35 | hasstatus = 'false' 36 | end 37 | 38 | it { is_expected.to compile.with_all_deps } 39 | it { is_expected.to contain_user('admin').with_password('hashed') } 40 | end 41 | 42 | end 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_service_named_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::services::named', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:pre_condition) do 11 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 12 | end 13 | 14 | case facts[:operatingsystem] 15 | when 'RedHat', 'CentOS' 16 | named_path = '/etc/named.conf' 17 | when 'Debian', 'Ubuntu' 18 | named_path = '/etc/bind/named.conf.options' 19 | end 20 | 21 | context "directadmin::services::named class without parameters" do 22 | it { is_expected.to compile.with_all_deps } 23 | it { is_expected.to contain_class('directadmin::services::named') } 24 | it { is_expected.to contain_exec('rewrite-named-config').with_refreshonly('true') } 25 | it { is_expected.to contain_exec('rewrite-named-config').with_unless('grep -c named /usr/local/directadmin/data/task.queue') } 26 | end 27 | 28 | context "directadmin::services::named class with allow transfer" do 29 | let(:params) {{ 30 | :allow_transfer => '192.168.0.1' 31 | }} 32 | 33 | it { is_expected.to compile.with_all_deps } 34 | it { is_expected.to contain_file_line('named-enable-allow-transfer').with_ensure('present') } 35 | it { is_expected.to contain_file_line('named-enable-allow-transfer').with_path(named_path) } 36 | it { is_expected.to contain_file_line('named-enable-allow-transfer').with_line(/allow-transfer { 192.168.0.1; };/) } 37 | end 38 | 39 | context "directadmin::services::named class with also notify" do 40 | let(:params) {{ 41 | :also_notify => '192.168.0.1' 42 | }} 43 | 44 | it { is_expected.to compile.with_all_deps } 45 | it { is_expected.to contain_file_line('named-enable-also-notify').with_ensure('present') } 46 | it { is_expected.to contain_file_line('named-enable-also-notify').with_path(named_path) } 47 | it { is_expected.to contain_file_line('named-enable-also-notify').with_line(/also-notify { 192.168.0.1; };/) } 48 | 49 | it { is_expected.to contain_file_line('named-enable-notify-setting').with_ensure('present') } 50 | it { is_expected.to contain_file_line('named-enable-notify-setting').with_path(named_path) } 51 | it { is_expected.to contain_file_line('named-enable-notify-setting').with_line(/notify yes;/) } 52 | end 53 | 54 | end 55 | end 56 | end 57 | end -------------------------------------------------------------------------------- /spec/classes/directadmin_services_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::services', :type => :class do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | context "directadmin::services class without parameters" do 11 | let(:pre_condition) do 12 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 13 | end 14 | 15 | case facts[:operatingsystem] 16 | when 'RedHat', 'CentOS' 17 | hasstatus = 'true' 18 | when 'Debian', 'Ubuntu' 19 | hasstatus = 'false' 20 | end 21 | 22 | it { is_expected.to compile.with_all_deps } 23 | it { is_expected.to contain_service('directadmin').with_hasstatus(hasstatus) } 24 | it { is_expected.to contain_service('exim').with_hasstatus(hasstatus) } 25 | it { is_expected.to contain_service('dovecot').with_hasstatus(hasstatus) } 26 | it { is_expected.to contain_service('httpd').with_hasstatus(hasstatus) } 27 | it { is_expected.to contain_service('named').with_hasstatus(hasstatus) } 28 | it { is_expected.to contain_service('mysqld').with_hasstatus(hasstatus) } 29 | end 30 | 31 | end 32 | end 33 | end 34 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_config_set_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::config::set', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:pre_condition) do 11 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 12 | end 13 | 14 | context "directadmin::config::set define without parameters" do 15 | let(:title) do 16 | 'foobar' 17 | end 18 | 19 | it 'fails' do 20 | expect { subject.call } .to raise_error(/Value can't be empty/) 21 | end 22 | end 23 | 24 | context "directadmin::config::set define with value" do 25 | let(:title) do 26 | 'foobar' 27 | end 28 | 29 | let(:params) {{ 30 | :value => 'bar' 31 | }} 32 | 33 | it { is_expected.to compile.with_all_deps } 34 | it { is_expected.to contain_directadmin__config__set('foobar') } 35 | it { is_expected.to contain_file_line('config-set-foobar-bar').with_line('foobar=bar') } 36 | it { is_expected.to contain_file_line('config-set-foobar-bar').that_requires('Class[directadmin::install]') } 37 | it { is_expected.to contain_file_line('config-set-foobar-bar').that_notifies('Service[directadmin]') } 38 | end 39 | 40 | context "directadmin::config::set define with nameserver settings" do 41 | let(:title) do 42 | 'ns1' 43 | end 44 | 45 | let(:params) {{ 46 | :value => 'bar' 47 | }} 48 | 49 | it { is_expected.to compile.with_all_deps } 50 | it { is_expected.to contain_directadmin__config__set('ns1') } 51 | it { is_expected.to contain_file_line('config-set-ns1-bar') } 52 | it { is_expected.to contain_file_line('config-set-ns1-bar').that_requires('Class[directadmin::install]') } 53 | it { is_expected.to contain_file_line('config-set-admin-reseller-ns1-bar').with_line('ns1=bar')} 54 | it { is_expected.to contain_file_line('config-set-admin-user-ns1-bar').with_line('ns1=bar')} 55 | end 56 | end 57 | end 58 | end 59 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_custombuild_set_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::custombuild::set', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:pre_condition) do 11 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 12 | end 13 | 14 | let(:title) do 15 | 'foobar' 16 | end 17 | 18 | context "directadmin::custombuild::set define without parameters" do 19 | it 'fails' do 20 | expect { subject.call } .to raise_error(/Value can't be empty/) 21 | end 22 | end 23 | 24 | context "directadmin::custombuild::set define with value" do 25 | let(:params) {{ 26 | :value => 'bar' 27 | }} 28 | 29 | it { is_expected.to compile.with_all_deps } 30 | it { is_expected.to contain_directadmin__custombuild__set('foobar') } 31 | it { is_expected.to contain_exec('custombuild-set-foobar-bar').with_command('/usr/local/directadmin/custombuild/build set foobar bar') } 32 | it { is_expected.to contain_exec('custombuild-set-foobar-bar').with_unless('grep /usr/local/directadmin/custombuild/options.conf -e \'^foobar=bar\'') } 33 | it { is_expected.to contain_exec('custombuild-set-foobar-bar').that_requires('Class[directadmin::custombuild]') } 34 | it { is_expected.to contain_exec('custombuild-set-foobar-bar').that_comes_before('Class[directadmin::install]') } 35 | end 36 | end 37 | end 38 | end 39 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_mail_exim_config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::mail::exim::config', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:title) do 11 | 'foobar' 12 | end 13 | 14 | let(:pre_condition) do 15 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 16 | end 17 | 18 | context "directadmin::mail::exim::config define without parameters" do 19 | it 'fails' do 20 | expect { subject.call } .to raise_error(/file must be set/) 21 | end 22 | end 23 | 24 | context "directadmin::mail::exim::config define with /etc in a file" do 25 | let (:params) {{ 26 | :file => '/etc/exim.strings.conf.custom' 27 | }} 28 | 29 | it 'fails' do 30 | expect { subject.call } .to raise_error(/file should be specified without/) 31 | end 32 | end 33 | 34 | context "directadmin::mail::exim::config define without a value" do 35 | let (:params) {{ 36 | :file => 'exim.strings.conf.custom' 37 | }} 38 | 39 | it 'fails' do 40 | expect { subject.call } .to raise_error(/value must be set/) 41 | end 42 | end 43 | 44 | context "directadmin::mail::exim::config define with parameters" do 45 | let(:params) {{ 46 | :file => 'exim.strings.conf.custom', 47 | :value => 'RBL' 48 | }} 49 | 50 | it { is_expected.to compile.with_all_deps } 51 | it { is_expected.to contain_file('/etc/exim.strings.conf.custom') } 52 | it { is_expected.to contain_file_line('exim-set-exim.strings.conf.custom-foobar-RBL') } 53 | it { is_expected.to contain_file_line('exim-set-exim.strings.conf.custom-foobar-RBL').with_path('/etc/exim.strings.conf.custom') } 54 | it { is_expected.to contain_file_line('exim-set-exim.strings.conf.custom-foobar-RBL').with_line('foobar==RBL') } 55 | it { is_expected.to contain_file_line('exim-set-exim.strings.conf.custom-foobar-RBL').that_requires('File[/etc/exim.strings.conf.custom]') } 56 | it { is_expected.to contain_file_line('exim-set-exim.strings.conf.custom-foobar-RBL').that_notifies('Service[exim]') } 57 | end 58 | 59 | end 60 | end 61 | end 62 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_mail_exim_virtual_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::mail::exim::virtual', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:title) do 11 | 'foobar' 12 | end 13 | 14 | let(:pre_condition) do 15 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 16 | end 17 | 18 | context "directadmin::mail::exim::virtual define without parameters" do 19 | it 'fails' do 20 | expect { subject.call } .to raise_error(/file must be set/) 21 | end 22 | end 23 | 24 | context "directadmin::mail::exim::virtual define with /etc in a file" do 25 | let (:params) {{ 26 | :file => '/etc/virtual/skip_rbl_hosts_ip' 27 | }} 28 | 29 | it 'fails' do 30 | expect { subject.call } .to raise_error(/file should be specified without/) 31 | end 32 | end 33 | 34 | context "directadmin::mail::exim::virtual define without a value" do 35 | let (:params) {{ 36 | :file => 'skip_rbl_hosts_ip' 37 | }} 38 | 39 | it 'fails' do 40 | expect { subject.call } .to raise_error(/value must be set/) 41 | end 42 | end 43 | 44 | context "directadmin::mail::exim::virtual define with parameters" do 45 | let(:params) {{ 46 | :file => 'skip_rbl_hosts_ip', 47 | :value => '127.0.0.1' 48 | }} 49 | 50 | it { is_expected.to compile.with_all_deps } 51 | it { is_expected.to contain_file('/etc/virtual/skip_rbl_hosts_ip') } 52 | it { is_expected.to contain_file('/etc/virtual/skip_rbl_hosts_ip').with_require('Exec[directadmin-installer]') } 53 | it { is_expected.to contain_file_line('exim-set-skip_rbl_hosts_ip-127.0.0.1') } 54 | it { is_expected.to contain_file_line('exim-set-skip_rbl_hosts_ip-127.0.0.1').with_path('/etc/virtual/skip_rbl_hosts_ip') } 55 | it { is_expected.to contain_file_line('exim-set-skip_rbl_hosts_ip-127.0.0.1').with_line('127.0.0.1') } 56 | it { is_expected.to contain_file_line('exim-set-skip_rbl_hosts_ip-127.0.0.1').that_requires('File[/etc/virtual/skip_rbl_hosts_ip]') } 57 | it { is_expected.to contain_file_line('exim-set-skip_rbl_hosts_ip-127.0.0.1').that_notifies('Service[exim]') } 58 | end 59 | 60 | end 61 | end 62 | end 63 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_mail_spamassassin_config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::mail::spamassassin::config', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:title) do 11 | 'foobar' 12 | end 13 | 14 | let(:pre_condition) do 15 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 16 | end 17 | 18 | context "directadmin::mail::spamassassin::config define without parameters" do 19 | it { is_expected.to compile.with_all_deps } 20 | it { is_expected.to contain_file('99-foobar') } 21 | it { is_expected.to contain_file('99-foobar').with_ensure('present') } 22 | it { is_expected.to contain_file('99-foobar').with_path('/etc/mail/spamassassin/99-foobar.cf') } 23 | it { is_expected.to contain_file('99-foobar').with_content('') } 24 | it { is_expected.to contain_file('99-foobar').that_requires('Exec[directadmin-installer]') } 25 | it { is_expected.to contain_file('99-foobar').that_notifies('Service[exim]') } 26 | end 27 | 28 | context "directadmin::mail::spamassassin::config define with parameters" do 29 | let(:params) {{ 30 | :order => '40', 31 | :content => 'bar' 32 | }} 33 | it { is_expected.to compile.with_all_deps } 34 | it { is_expected.to contain_file('40-foobar') } 35 | it { is_expected.to contain_file('40-foobar').with_ensure('present') } 36 | it { is_expected.to contain_file('40-foobar').with_path('/etc/mail/spamassassin/40-foobar.cf') } 37 | it { is_expected.to contain_file('40-foobar').with_content('bar') } 38 | it { is_expected.to contain_file('40-foobar').that_requires('Exec[directadmin-installer]') } 39 | it { is_expected.to contain_file('40-foobar').that_notifies('Service[exim]') } 40 | end 41 | 42 | end 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_mail_spamassassin_score_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::mail::spamassassin::score', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:title) do 11 | 'foobar' 12 | end 13 | 14 | context "directadmin::mail::spamassassin::score define without parameters" do 15 | let(:pre_condition) do 16 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 17 | end 18 | 19 | it { is_expected.to compile.with_all_deps } 20 | it { is_expected.to contain_file_line('enable-foobar-1') } 21 | it { is_expected.to contain_file_line('enable-foobar-1').with_line('score foobar 1') } 22 | it { is_expected.to contain_file_line('enable-foobar-1').that_notifies('Service[exim]') } 23 | it { is_expected.to contain_file_line('enable-foobar-1').that_requires('Exec[directadmin-installer]') } 24 | end 25 | 26 | context "directadmin::mail::spamassassin::score define with a score specified" do 27 | let(:pre_condition) do 28 | 'class { "::directadmin": clientid => 1234, licenseid => 123456, admin_password => \'hashed\' }' 29 | end 30 | 31 | let(:params) {{ 32 | :score => '10', 33 | }} 34 | 35 | it { is_expected.to compile.with_all_deps } 36 | it { is_expected.to contain_file_line('enable-foobar-10') } 37 | it { is_expected.to contain_file_line('enable-foobar-10').with_line('score foobar 10') } 38 | it { is_expected.to contain_file_line('enable-foobar-10').that_notifies('Service[exim]') } 39 | it { is_expected.to contain_file_line('enable-foobar-10').that_requires('Exec[directadmin-installer]') } 40 | end 41 | 42 | end 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /spec/defines/directadmin_user_ssl_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe 'directadmin::user_ssl', :type => :define do 3 | context 'supported operating systems' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) do 7 | facts 8 | end 9 | 10 | let(:pre_condition) do 11 | 'class { "::directadmin": clientid => 1234, licenseid => 123456 }' 12 | end 13 | 14 | context "directadmin::user_ssl define without parameters" do 15 | let(:title) do 16 | 'foobar' 17 | end 18 | 19 | it 'fails' do 20 | expect { subject.call } .to raise_error(/user can't be empty/) 21 | end 22 | end 23 | 24 | context "directadmin::user_ssl define without sslcert" do 25 | let(:title) do 26 | 'foobar' 27 | end 28 | 29 | let(:params) {{ 30 | :user => 'admin' 31 | }} 32 | 33 | it 'fails' do 34 | expect { subject.call } .to raise_error(/sslcert can't be empty/) 35 | end 36 | end 37 | 38 | context "directadmin::user_ssl define without sslkey" do 39 | let(:title) do 40 | 'foobar' 41 | end 42 | 43 | let(:params) {{ 44 | :user => 'admin', 45 | :sslcert => 'CERT' 46 | }} 47 | 48 | it 'fails' do 49 | expect { subject.call } .to raise_error(/sslkey can't be empty/) 50 | end 51 | end 52 | 53 | context "directadmin::user_ssl with values" do 54 | let(:title) do 55 | 'foobar' 56 | end 57 | 58 | let(:params) {{ 59 | :user => 'admin', 60 | :sslcert => 'CERT', 61 | :sslkey => 'KEY' 62 | }} 63 | 64 | it { is_expected.to compile.with_all_deps } 65 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cert') } 66 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cert').with_content('CERT') } 67 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.key') } 68 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.key').with_content('KEY') } 69 | end 70 | 71 | context "directadmin::user_ssl with ca certificate" do 72 | let(:title) do 73 | 'foobar' 74 | end 75 | 76 | let(:params) {{ 77 | :user => 'admin', 78 | :sslcert => 'CERT', 79 | :sslkey => 'KEY', 80 | :sslca => 'CA' 81 | }} 82 | 83 | it { is_expected.to compile.with_all_deps } 84 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cacert') } 85 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cacert').with_content('CA') } 86 | end 87 | 88 | context "directadmin::user_ssl with pem certificate" do 89 | let(:title) do 90 | 'foobar' 91 | end 92 | 93 | let(:params) {{ 94 | :user => 'admin', 95 | :sslcert => 'CERT', 96 | :sslkey => 'KEY', 97 | :sslpem => 'PEM' 98 | }} 99 | 100 | it { is_expected.to compile.with_all_deps } 101 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cert.combined') } 102 | it { is_expected.to contain_file('/usr/local/directadmin/data/users/admin/domains/foobar.cert.combined').with_content('PEM') } 103 | end 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'puppetlabs_spec_helper/module_spec_helper' 2 | require 'rspec-puppet-facts' 3 | 4 | include RspecPuppetFacts 5 | 6 | require 'simplecov' 7 | require 'simplecov-console' 8 | 9 | SimpleCov.start do 10 | add_filter '/spec' 11 | add_filter '/vendor' 12 | formatter SimpleCov::Formatter::MultiFormatter.new([ 13 | SimpleCov::Formatter::HTMLFormatter, 14 | SimpleCov::Formatter::Console 15 | ]) 16 | end 17 | 18 | RSpec.configure do |c| 19 | c.hiera_config = File.expand_path(File.join(__FILE__, '../fixtures/hiera.yaml')) 20 | end -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | require 'beaker-rspec/spec_helper' 2 | require 'beaker-rspec/helpers/serverspec' 3 | require 'beaker/puppet_install_helper' 4 | 5 | RSpec.configure do |c| 6 | # Project root 7 | proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) 8 | fixture_modules = File.join(proj_root, 'spec', 'fixtures', 'modules') 9 | 10 | # Readable test descriptions 11 | c.formatter = :documentation 12 | 13 | # Configure all nodes in nodeset 14 | c.before :suite do 15 | hosts.each do |host| 16 | # This is our workaround for Ubuntu 16.04 servers 17 | if host['platform'] == 'ubuntu-1604-amd64' 18 | unless ENV['BEAKER_provision'] == 'no' 19 | # Install the repo and the puppet agent package 20 | on host, 'wget -O /tmp/puppetlabs-release-pc1-xenial.deb https://apt.puppetlabs.com/puppetlabs-release-pc1-xenial.deb' 21 | on host, 'dpkg -i /tmp/puppetlabs-release-pc1-xenial.deb' 22 | on host, 'apt-get update' 23 | install_package(host, 'puppet-agent') 24 | 25 | # Sorry, it's a symlink 26 | on host, 'ln -s /opt/puppetlabs/bin/puppet /usr/bin/puppet' 27 | on host, 'puppet --version' 28 | 29 | # Override the module directory as this is required for Puppet 4 30 | on host, 'mkdir -p /etc/puppet/modules' 31 | on host, 'rm -rf /opt/puppetlabs/puppet/modules' 32 | on host, 'ln -s /etc/puppet/modules/ /opt/puppetlabs/puppet/modules' 33 | end 34 | else 35 | run_puppet_install_helper unless ENV['BEAKER_provision'] == 'no' 36 | end 37 | 38 | install_package(host, 'rsync') 39 | rsync_to(host, fixture_modules, '/etc/puppet/modules/') 40 | end 41 | 42 | # Install module and dependencies 43 | puppet_module_install(:source => proj_root, :module_name => 'directadmin') 44 | end 45 | end -------------------------------------------------------------------------------- /templates/modsecurity/modsec-wordpress.conf.erb: -------------------------------------------------------------------------------- 1 | SecAction phase:2,nolog,pass,initcol:ip=%{REMOTE_ADDR},initcol:user=%{REMOTE_ADDR},id:5000134 2 | 3 | # Setup brute force detection. 4 | # React if block flag has been set. 5 | SecRule user:bf_block "@gt 0" "deny,status:401,log,id:5000135,msg:'ip address blocked for 5 minutes, more than 10 login attempts in 3 minutes.'" 6 | # Setup tracking. On a successful login, a 302 redirect is performed, a 200 indicates login failed. 7 | SecRule RESPONSE_STATUS "^302" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000136" 8 | SecRule RESPONSE_STATUS "^200" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000137" 9 | SecRule ip:bf_counter "@gt 10" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0" 10 | 11 | 12 | SecAction phase:2,nolog,pass,initcol:ip=%{REMOTE_ADDR},initcol:user=%{REMOTE_ADDR},id:5000234 13 | 14 | # Rate limit requests to xml-rpc 15 | SecRule user:bf_block "@gt 0" "deny,status:401,log,id:5000235,msg:'ip address blocked for 5 minutes, more than 10 attempts in 3 minutes.'" 16 | # Setup tracking. Whenever it gets a 200 or 405 status code, increase our brute force counter. 17 | SecRule RESPONSE_STATUS "^(200|405)" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000237" 18 | SecRule ip:bf_counter "@gt 10" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0" 19 | 20 | --------------------------------------------------------------------------------