[pkg-nagios-changes] [Git][nagios-team/pkg-icingaweb2][upstream] New upstream version 2.9.3

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Thu Aug 12 15:25:46 BST 2021



Bas Couwenberg pushed to branch upstream at Debian Nagios Maintainer Group / pkg-icingaweb2


Commits:
7c663274 by Bas Couwenberg at 2021-08-12T16:15:39+02:00
New upstream version 2.9.3
- - - - -


21 changed files:

- CHANGELOG.md
- VERSION
- application/VERSION
- application/controllers/AuthenticationController.php
- application/forms/Authentication/LoginForm.php
- doc/02-Installation.md
- library/Icinga/Application/Version.php
- library/Icinga/Crypt/AesCrypt.php
- library/Icinga/Web/JavaScript.php
- library/Icinga/Web/RememberMe.php
- modules/doc/module.info
- modules/migrate/module.info
- modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
- + modules/monitoring/library/Monitoring/Command/Object/ApiScheduleHostDowntimeCommand.php
- modules/monitoring/library/Monitoring/Command/Object/ScheduleHostDowntimeCommand.php
- modules/monitoring/library/Monitoring/Command/Renderer/IcingaApiCommandRenderer.php
- modules/monitoring/module.info
- modules/setup/module.info
- modules/test/module.info
- modules/translation/module.info
- public/css/icinga/login.less


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -4,6 +4,33 @@ Please make sure to always read our [Upgrading](doc/80-Upgrading.md) documentati
 
 ## What's New
 
+### What's New in Version 2.9.3
+
+You can also find the issues related to this release on our [Roadmap](https://github.com/Icinga/icingaweb2/milestone/66?closed=1).
+
+#### Staying remembered on RHEL/CentOS 7 now possible
+
+RHEL/CentOS 7 still relies on OpenSSL v1.0.2 by default. A change in v2.9.1 resulted in an error in combination with
+this when ticking `Stay Logged In` during authentication. Staying logged in now works fine also on this platform.
+
+* Stay Logged In - Unknown cipher algorithm [#4493](https://github.com/Icinga/icingaweb2/issues/4493)
+
+#### Missing icons with SLES/OpenSUSE 15
+
+If you're running Icinga Web 2 Version 2.9.x on a SLES/OpenSUSE 15.x, you may have noticed some missing icons in the UI.
+This is due to a missing PHP extension `fileinfo`. By upgrading to this release using packages, this dependency will now
+be installed automatically.
+
+* Missing fileinfo php extension on SLES/OpenSUSE 15+ [#4503](https://github.com/Icinga/icingaweb2/issues/4503)
+
+#### Child downtimes for services are now removed automatically
+
+With Icinga v2.13, Icinga Web 2 will now make sure that service downtimes that were created automatically are also
+removed automatically. This will only work for downtimes you create with the `All Services` option after upgrading
+to this release. It will not work for downtimes created with earlier versions of Icinga Web 2.
+
+* If appropriate, set the API parameter all_services for schedule-downtime [#4501](https://github.com/Icinga/icingaweb2/pull/4501)
+
 ### What's New in Version 2.9.2
 
 This is a hotfix release. v2.9.1 included a change that wasn't compatible with PostgreSQL again. This has been fixed


=====================================
VERSION
=====================================
@@ -1 +1 @@
-v2.9.2
+v2.9.3


=====================================
application/VERSION
=====================================
@@ -1 +1 @@
-07e25a923bd80001e9ab52bbbbc1008aa8befb06 2021-07-28 09:34:07 +0200
+c757a17530c326c7d6daebd6171486cb8167a8a1 2021-08-10 10:12:17 +0200


=====================================
application/controllers/AuthenticationController.php
=====================================
@@ -45,15 +45,13 @@ class AuthenticationController extends Controller
 
         if (RememberMe::hasCookie() && $this->hasDb()) {
             $authenticated = false;
-            $iv = null;
             try {
                 $rememberMeOld = RememberMe::fromCookie();
-                $iv = $rememberMeOld->getAesCrypt()->getIv();
                 $authenticated = $rememberMeOld->authenticate();
                 if ($authenticated) {
                     $rememberMe = $rememberMeOld->renew();
                     $this->getResponse()->setCookie($rememberMe->getCookie());
-                    $rememberMe->persist($iv);
+                    $rememberMe->persist($rememberMeOld->getAesCrypt()->getIv());
                 }
             } catch (RuntimeException $e) {
                 Logger::error("Can't authenticate user via remember me cookie: %s", $e->getMessage());
@@ -62,7 +60,6 @@ class AuthenticationController extends Controller
             }
 
             if (! $authenticated) {
-                (new RememberMe())->remove(bin2hex($iv));
                 $this->getResponse()->setCookie(RememberMe::forget());
             }
         }
@@ -110,12 +107,6 @@ class AuthenticationController extends Controller
             $this->getResponse()->setHttpResponseCode(401);
         } else {
             if (RememberMe::hasCookie() && $this->hasDb()) {
-                try {
-                    (new RememberMe())->remove(bin2hex(RememberMe::fromCookie()->getAesCrypt()->getIV()));
-                } catch (RuntimeException $e) {
-                    // pass
-                }
-
                 $this->getResponse()->setCookie(RememberMe::forget());
             }
 


=====================================
application/forms/Authentication/LoginForm.php
=====================================
@@ -3,8 +3,10 @@
 
 namespace Icinga\Forms\Authentication;
 
+use Exception;
 use Icinga\Application\Config;
 use Icinga\Application\Hook\AuthenticationHook;
+use Icinga\Application\Logger;
 use Icinga\Authentication\Auth;
 use Icinga\Authentication\User\ExternalBackend;
 use Icinga\Common\Database;
@@ -90,10 +92,13 @@ class LoginForm extends Form
                 ]
             ]
         );
-        if (! $this->hasDb()) {
+        if (! RememberMe::isSupported()) {
             $this->getElement('rememberme')
                 ->setAttrib('disabled', true)
-                ->setAttrib('title', "You can't stay logged in without a database configuration backend");
+                ->setDescription($this->translate(
+                    'Staying logged in requires a database configuration backend'
+                    . ' and an appropriate OpenSSL encryption method'
+                ));
         }
 
         $this->addElement(
@@ -137,9 +142,13 @@ class LoginForm extends Form
         if ($authenticated) {
             $auth->setAuthenticated($user);
             if ($this->getElement('rememberme')->isChecked()) {
-                $rememberMe = RememberMe::fromCredentials($user->getUsername(), $password);
-                $this->getResponse()->setCookie($rememberMe->getCookie());
-                $rememberMe->persist();
+                try {
+                    $rememberMe = RememberMe::fromCredentials($user->getUsername(), $password);
+                    $this->getResponse()->setCookie($rememberMe->getCookie());
+                    $rememberMe->persist();
+                } catch (Exception $e) {
+                    Logger::error('Failed to let user "%s" stay logged in: %s', $user->getUsername(), $e);
+                }
             }
 
             // Call provided AuthenticationHook(s) after successful login


=====================================
doc/02-Installation.md
=====================================
@@ -18,7 +18,7 @@ chapter.
   * Older versions (5.6+) are only supported up until version 2.11
 * [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.6)
 * [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.10)
-* The following PHP modules must be installed: cURL, json, gettext, intl, dom, OpenSSL and xml
+* The following PHP modules must be installed: cURL, json, gettext, fileinfo, intl, dom, OpenSSL and xml
 * For exports to PDF also the following PHP modules are required: mbstring, GD, Imagick
 * LDAP PHP library when using Active Directory or LDAP for authentication
 * MySQL or PostgreSQL PHP libraries


=====================================
library/Icinga/Application/Version.php
=====================================
@@ -8,7 +8,7 @@ namespace Icinga\Application;
  */
 class Version
 {
-    const VERSION = '2.9.2';
+    const VERSION = '2.9.3';
 
     /**
      * Get the version of this instance of Icinga Web 2


=====================================
library/Icinga/Crypt/AesCrypt.php
=====================================
@@ -14,7 +14,7 @@ use RuntimeException;
  * ```php
  *
  * // Encryption
- * $encryptedData = new AesCrypt()->encrypt($data); // Accepts a string
+ * $encryptedData = (new AesCrypt())->encrypt($data); // Accepts a string
  *
  *
  * // Encrypt and encode to Base64
@@ -23,7 +23,7 @@ use RuntimeException;
  *
  * // Decryption
  * $aesCrypt = (new AesCrypt())
- *          ->setTag($tag)
+ *          ->setTag($tag)  // if exists
  *          ->setIV($iv)
  *          ->setKey($key);
  *
@@ -35,15 +35,25 @@ use RuntimeException;
  *          ->setIV($iv)
  *          ->setKey($key);
  *
- * $decryptedData = $aesCrypt->->decryptFromBase64($data);
+ * $decryptedData = $aesCrypt->decryptFromBase64($data);
  * ```
  *
  */
 class AesCrypt
 {
+    /** @var array The list of cipher methods */
+    const METHODS = [
+        'aes-256-gcm',
+        'aes-256-cbc',
+        'aes-256-ctr'
+    ];
+
     /** @var string The encryption key */
     private $key;
 
+    /** @var int The length of the key */
+    private $keyLength;
+
     /** @var string The initialization vector which is not NULL */
     private $iv;
 
@@ -51,21 +61,15 @@ class AesCrypt
     private $tag;
 
     /** @var string The cipher method */
-    private $method = 'AES-128-GCM';
-
-    const GCM_SUPPORT_VERSION = '7.1';
+    private $method;
 
-    public function __construct($random_bytes_len = 128)
+    public function __construct($keyLength = 128)
     {
-        if (version_compare(PHP_VERSION, self::GCM_SUPPORT_VERSION, '<')) {
-            $this->method = 'AES-128-CBC';
-        }
-
-        $this->key = random_bytes($random_bytes_len);
+        $this->keyLength = $keyLength;
     }
 
     /**
-     * Force set the method
+     * Set the method
      *
      * @return $this
      */
@@ -76,6 +80,45 @@ class AesCrypt
         return $this;
     }
 
+    /**
+     * Get the method
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        if ($this->method === null) {
+            $this->method = $this->getSupportedMethod();
+        }
+
+        return $this->method;
+    }
+
+    /**
+     * Get supported method
+     *
+     * @return string
+     *
+     * @throws RuntimeException If none of the methods listed in the METHODS array is available
+     */
+    protected function getSupportedMethod()
+    {
+        $availableMethods = openssl_get_cipher_methods();
+        $methods = self::METHODS;
+
+        if (! $this->isAuthenticatedEncryptionSupported()) {
+            unset($methods[0]);
+        }
+
+        foreach ($methods as $method) {
+            if (in_array($method, $availableMethods)) {
+                return $method;
+            }
+        }
+
+        throw new RuntimeException('No supported method found');
+    }
+
     /**
      * Set the key
      *
@@ -93,12 +136,11 @@ class AesCrypt
      *
      * @return string
      *
-     * @throws RuntimeException If the key is not set
      */
     public function getKey()
     {
         if (empty($this->key)) {
-            throw new RuntimeException('No key set');
+            $this->key = random_bytes($this->keyLength);
         }
 
         return $this->key;
@@ -121,12 +163,11 @@ class AesCrypt
      *
      * @return string
      *
-     * @throws RuntimeException If the IV is not set
      */
     public function getIV()
     {
         if (empty($this->iv)) {
-            $len = openssl_cipher_iv_length($this->method);
+            $len = openssl_cipher_iv_length($this->getMethod());
             $this->iv = random_bytes($len);
         }
 
@@ -137,9 +178,20 @@ class AesCrypt
      * Set the Tag
      *
      * @return $this
+     *
+     * @throws RuntimeException If a tag is available but authenticated encryption (AE) is not supported.
+     *
+     * @throws UnexpectedValueException If tag length is less then 16
      */
     public function setTag($tag)
     {
+        if (! $this->isAuthenticatedEncryptionSupported()) {
+            throw new RuntimeException(sprintf(
+                "The given decryption method is not supported in php version '%s'",
+                PHP_VERSION
+            ));
+        }
+
         if (strlen($tag) !== 16) {
             throw new UnexpectedValueException(sprintf(
                 'expects tag length to be 16, got instead %s',
@@ -169,7 +221,7 @@ class AesCrypt
     }
 
     /**
-     * Decrypt the given data using the key, iv and tag
+     * Decrypt the given string
      *
      * @param string $data
      *
@@ -179,11 +231,11 @@ class AesCrypt
      */
     public function decrypt($data)
     {
-        if ($this->method === 'AES-128-CBC') {
-            return $this->decryptCBC($data);
+        if (! $this->isAuthenticatedEncryptionRequired()) {
+            return $this->nonAEDecrypt($data);
         }
 
-        $decrypt = openssl_decrypt($data, $this->method, $this->getKey(), 0, $this->getIV(), $this->getTag());
+        $decrypt = openssl_decrypt($data, $this->getMethod(), $this->getKey(), 0, $this->getIV(), $this->getTag());
 
         if ($decrypt === false) {
             throw new RuntimeException('Decryption failed');
@@ -193,11 +245,13 @@ class AesCrypt
     }
 
     /**
-     * Decode from Base64 and decrypt the given data using the key, iv and tag
+     * Decode from Base64 and decrypt the given string
      *
      * @param string $data
      *
-     * @return string decrypted data
+     * @return string The base64 decoded and decrypted string
+     *
+     * @deprecated Use decrypt() instead as it also returns a base64 decoded string
      *
      * @throws RuntimeException If decryption fails
      */
@@ -207,21 +261,21 @@ class AesCrypt
     }
 
     /**
-     * Encrypt the given data using the key, iv and tag
+     * Encrypt the given string
      *
      * @param string $data
      *
-     * @return string encrypted data
+     * @return string encrypted string
      *
      * @throws RuntimeException If decryption fails
      */
     public function encrypt($data)
     {
-        if ($this->method === 'AES-128-CBC') {
-            return $this->encryptCBC($data);
+        if (! $this->isAuthenticatedEncryptionRequired()) {
+            return $this->nonAEEncrypt($data);
         }
 
-        $encrypt = openssl_encrypt($data, $this->method, $this->getkey(), 0, $this->getIV(), $this->tag);
+        $encrypt = openssl_encrypt($data, $this->getMethod(), $this->getKey(), 0, $this->getIV(), $this->tag);
 
         if ($encrypt === false) {
             throw new RuntimeException('Encryption failed');
@@ -231,11 +285,13 @@ class AesCrypt
     }
 
     /**
-     * Encrypt the given string using the the key, iv, tag and encode to Base64
+     * Encrypt the given string and encode to Base64
      *
      * @param string $data
      *
-     * @return string encrypted and encoded to Base64 data
+     * @return string encrypted and base64 encoded string
+     *
+     * @deprecated Use encrypt() instead as it also returns a base64 encoded string
      *
      * @throws RuntimeException If encryption fails
      */
@@ -244,18 +300,23 @@ class AesCrypt
         return base64_encode($this->encrypt($data));
     }
 
-    private function decryptCBC($data)
+    /**
+     * Decrypt the given string with non Authenticated encryption (AE) cipher method
+     *
+     * @param string $data
+     *
+     * @return string decrypted string
+     *
+     * @throws RuntimeException If decryption fails
+     */
+    private function nonAEDecrypt($data)
     {
-        if (strlen($this->getIV()) !== 16) {
-            throw new RuntimeException('Decryption failed');
-        }
-
         $c = base64_decode($data);
         $hmac = substr($c, 0, 32);
         $data = substr($c, 32);
 
-        $decrypt = openssl_decrypt($data, $this->method, $this->getKey(), 0, $this->getIV());
-        $calcHmac = hash_hmac('sha256', $data, $this->getKey(), true);
+        $decrypt = openssl_decrypt($data, $this->getMethod(), $this->getKey(), 0, $this->getIV());
+        $calcHmac = hash_hmac('sha256', $this->getIV() . $data, $this->getKey(), true);
 
         if ($decrypt === false || ! hash_equals($hmac, $calcHmac)) {
             throw new RuntimeException('Decryption failed');
@@ -264,16 +325,45 @@ class AesCrypt
         return $decrypt;
     }
 
-    private function encryptCBC($data)
+    /**
+     * Encrypt the given string with non Authenticated encryption (AE) cipher method
+     *
+     * @param string $data
+     *
+     * @return string encrypted string
+     *
+     * @throws RuntimeException If encryption fails
+     */
+    private function nonAEEncrypt($data)
     {
-        $encrypt = openssl_encrypt($data, $this->method, $this->getkey(), 0, $this->getIV());
+        $encrypt = openssl_encrypt($data, $this->getMethod(), $this->getKey(), 0, $this->getIV());
 
         if ($encrypt === false) {
             throw new RuntimeException('Encryption failed');
         }
 
-        $hmac = hash_hmac('sha256', $encrypt, $this->getkey(), true);
+        $hmac = hash_hmac('sha256', $this->getIV() . $encrypt, $this->getKey(), true);
 
         return base64_encode($hmac . $encrypt);
     }
+
+    /**
+     * Whether the Authenticated encryption (a tag) is required
+     *
+     * @return bool True if required false otherwise
+     */
+    public function isAuthenticatedEncryptionRequired()
+    {
+        return $this->getMethod() === 'aes-256-gcm';
+    }
+
+    /**
+     * Whether the php version supports Authenticated encryption (AE) or not
+     *
+     * @return bool True if supported false otherwise
+     */
+    public function isAuthenticatedEncryptionSupported()
+    {
+        return PHP_VERSION_ID >= 70100;
+    }
 }


=====================================
library/Icinga/Web/JavaScript.php
=====================================
@@ -226,7 +226,7 @@ class JavaScript
      */
     public static function optimizeDefine($js, $filePath, $basePath, $packageName)
     {
-        if (! preg_match(self::DEFINE_RE, $js, $match)) {
+        if (! preg_match(self::DEFINE_RE, $js, $match) || strpos($js, 'define.amd') !== false) {
             return $js;
         }
 
@@ -245,12 +245,17 @@ class JavaScript
             $assetName = Json::encode($assetName, JSON_UNESCAPED_SLASHES);
         } catch (JsonDecodeException $_) {
             $assetName = $match[1];
-            Logger::error('Can\'t optimize name of "%s". Are single quotes used instead of double quotes?', $filePath);
+            Logger::debug('Can\'t optimize name of "%s". Are single quotes used instead of double quotes?', $filePath);
         }
 
         try {
             $dependencies = $match[2] ? Json::decode($match[2]) : [];
             foreach ($dependencies as &$dependencyName) {
+                if ($dependencyName === 'exports') {
+                    // exports is a special keyword and doesn't need optimization
+                    continue;
+                }
+
                 if (preg_match('~^((?:\.\.?/)+)*(.*)~', $dependencyName, $natch)) {
                     $dependencyName = join(DIRECTORY_SEPARATOR, array_filter([
                         $packageName,
@@ -266,7 +271,7 @@ class JavaScript
             $dependencies = Json::encode($dependencies, JSON_UNESCAPED_SLASHES);
         } catch (JsonDecodeException $_) {
             $dependencies = $match[2];
-            Logger::error(
+            Logger::debug(
                 'Can\'t optimize dependencies of "%s". Are single quotes used instead of double quotes?',
                 $filePath
             );


=====================================
library/Icinga/Web/RememberMe.php
=====================================
@@ -39,6 +39,28 @@ class RememberMe
     /** @var int Timestamp when the remember me cookie expires */
     protected $expiresAt;
 
+    /**
+     * Get whether staying logged in is possible
+     *
+     * @return bool
+     */
+    public static function isSupported()
+    {
+        $self = new self();
+
+        if (! $self->hasDb()) {
+            return false;
+        }
+
+        try {
+            (new AesCrypt())->getMethod();
+        } catch (RuntimeException $_) {
+            return false;
+        }
+
+        return true;
+    }
+
     /**
      * Get whether the remember cookie is set
      *
@@ -50,12 +72,18 @@ class RememberMe
     }
 
     /**
-     * Unset the remember me cookie from PHP's `$_COOKIE` superglobal and return the invalidation cookie
+     * Remove the database entry if exists and unset the remember me cookie from PHP's `$_COOKIE` superglobal
      *
-     * @return Cookie Cookie which has to be sent to client in oder to remove the remember me cookie
+     * @return Cookie The invalidation cookie which has to be sent to client in oder to remove the remember me cookie
      */
     public static function forget()
     {
+        if (self::hasCookie()) {
+            $data = explode('|', $_COOKIE[static::COOKIE]);
+            $iv = base64_decode(array_pop($data));
+            (new self())->remove(bin2hex($iv));
+        }
+
         unset($_COOKIE[static::COOKIE]);
 
         return (new Cookie(static::COOKIE))
@@ -92,19 +120,15 @@ class RememberMe
             ->setKey(hex2bin($rs->passphrase))
             ->setIV($iv);
 
-        if (version_compare(PHP_VERSION, AesCrypt::GCM_SUPPORT_VERSION, '>=')) {
-            $tag = array_pop($data);
-
-            if (empty($data)) {
-                $rememberMe->aesCrypt = (new AesCrypt())
-                    ->setMethod('AES-128-CBC')
-                    ->setKey(hex2bin($rs->passphrase))
-                    ->setIV($iv);
-
-                $data[0] = $tag; // encryptedPass
-            } else {
-                $rememberMe->aesCrypt->setTag(base64_decode($tag));
-            }
+        if (count($data) > 1) {
+            $rememberMe->aesCrypt->setTag(
+                base64_decode(array_pop($data))
+            );
+        } elseif ($rememberMe->aesCrypt->isAuthenticatedEncryptionRequired()) {
+            throw new RuntimeException(
+                "The given decryption method needs a tag, but is not specified. "
+                . "You have probably updated the PHP version."
+            );
         }
 
         $rememberMe->username = $rs->username;
@@ -125,7 +149,7 @@ class RememberMe
     {
         $aesCrypt = new AesCrypt();
         $rememberMe = new static();
-        $rememberMe->encryptedPassword = $aesCrypt->encryptToBase64($password);
+        $rememberMe->encryptedPassword = $aesCrypt->encrypt($password);
         $rememberMe->username = $username;
         $rememberMe->aesCrypt = $aesCrypt;
 
@@ -159,7 +183,7 @@ class RememberMe
             base64_encode($this->aesCrypt->getIV()),
         ];
 
-        if (version_compare(PHP_VERSION, AesCrypt::GCM_SUPPORT_VERSION, '>=')) {
+        if ($this->aesCrypt->isAuthenticatedEncryptionRequired()) {
             array_splice($values, 1, 0, base64_encode($this->aesCrypt->getTag()));
         }
 
@@ -208,7 +232,6 @@ class RememberMe
      */
     public function authenticate()
     {
-        $password = $this->aesCrypt->decryptFromBase64($this->encryptedPassword);
         $auth = Auth::getInstance();
         $authChain = $auth->getAuthChain();
         $authChain->setSkipExternalBackends(true);
@@ -217,7 +240,11 @@ class RememberMe
             $user->setDomain(Config::app()->get('authentication', 'default_domain'));
         }
 
-        $authenticated = $authChain->authenticate($user, $password);
+        $authenticated = $authChain->authenticate(
+            $user,
+            $this->aesCrypt->decrypt($this->encryptedPassword)
+        );
+
         if ($authenticated) {
             $auth->setAuthenticated($user);
         }
@@ -228,9 +255,9 @@ class RememberMe
     /**
      * Persist the remember me information into the database
      *
-     * Any previous stored information is automatically removed.
+     * To remove any previous stored information, set the iv
      *
-     * @param string|null $iv
+     * @param string|null $iv To remove a specific iv record from the database
      *
      * @return $this
      */
@@ -254,7 +281,7 @@ class RememberMe
     }
 
     /**
-     * Remove remember me information from the database
+     * Remove remember me information from the database on the basis of iv
      *
      * @param string $iv
      *
@@ -278,14 +305,14 @@ class RememberMe
     {
         return static::fromCredentials(
             $this->username,
-            $this->aesCrypt->decryptFromBase64($this->encryptedPassword)
+            $this->aesCrypt->decrypt($this->encryptedPassword)
         );
     }
 
     /**
-     * Get all users using rememberme cookie
+     * Get all users using remember me cookie
      *
-     * @return array
+     * @return array Array of users
      */
     public static function getAllUser()
     {
@@ -303,11 +330,11 @@ class RememberMe
     }
 
     /**
-     * Get all rememberme cookies of the given user
+     * Get all remember me entries from the database of the given user.
      *
      * @param $username
      *
-     * @return array
+     * @return array Array of database entries
      */
     public static function getAllByUsername($username)
     {
@@ -325,7 +352,7 @@ class RememberMe
     }
 
     /**
-     * Get the encrypton/decryption instance
+     * Get the AesCrypt instance
      *
      * @return AesCrypt
      */


=====================================
modules/doc/module.info
=====================================
@@ -1,4 +1,4 @@
 Module: doc
-Version: 2.9.2
+Version: 2.9.3
 Description: Documentation module
  Extracts, shows and exports documentation for Icinga Web 2 and its modules.


=====================================
modules/migrate/module.info
=====================================
@@ -1,5 +1,5 @@
 Module: migrate
-Version: 2.9.2
+Version: 2.9.3
 Description: Migrate module
  This module was introduced with the domain-aware authentication feature in version 2.5.0.
  It helps you migrating users and user configurations according to a given domain.


=====================================
modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
=====================================
@@ -6,9 +6,12 @@ namespace Icinga\Module\Monitoring\Forms\Command\Object;
 use DateInterval;
 use DateTime;
 use Icinga\Application\Config;
+use Icinga\Module\Monitoring\Command\Object\ApiScheduleHostDowntimeCommand;
 use Icinga\Module\Monitoring\Command\Object\PropagateHostDowntimeCommand;
 use Icinga\Module\Monitoring\Command\Object\ScheduleHostDowntimeCommand;
 use Icinga\Module\Monitoring\Command\Object\ScheduleServiceDowntimeCommand;
+use Icinga\Module\Monitoring\Command\Transport\ApiCommandTransport;
+use Icinga\Module\Monitoring\Command\Transport\CommandTransport;
 use Icinga\Web\Notification;
 
 /**
@@ -105,7 +108,37 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
             return false;
         }
 
+        // Send all_services API parameter if Icinga is equal to or greater than 2.11.0
+        $allServicesNative = version_compare($this->getBackend()->getProgramVersion(), '2.11.0', '>=');
+        // Use ApiScheduleHostDowntimeCommand only when Icinga is equal to or greater than 2.11.0 and
+        // when an API command transport is requested or only API command transports are configured:
+        $useApiDowntime = $allServicesNative;
+        if ($useApiDowntime) {
+            $transport = $this->getTransport($this->getRequest());
+            if ($transport instanceof CommandTransport) {
+                foreach ($transport::getConfig() as $config) {
+                    if (strtolower($config->transport) !== 'api') {
+                        $useApiDowntime = false;
+                        break;
+                    }
+                }
+            } elseif (! $transport instanceof ApiCommandTransport) {
+                $useApiDowntime = false;
+            }
+        }
+
         foreach ($this->objects as $object) {
+            if ($useApiDowntime) {
+                $hostDowntime = (new ApiScheduleHostDowntimeCommand())
+                    ->setForAllServices($this->getElement('all_services')->isChecked())
+                    ->setChildOptions((int) $this->getElement('child_hosts')->getValue());
+                // Code duplicated for readability and scope
+                $hostDowntime->setObject($object);
+                $this->scheduleDowntime($hostDowntime, $this->request);
+
+                continue;
+            }
+
             /** @var \Icinga\Module\Monitoring\Object\Host $object */
             if (($childHostsEl = $this->getElement('child_hosts')) !== null) {
                 $childHosts = (int) $childHostsEl->getValue();
@@ -114,7 +147,8 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
             }
             $allServices = $this->getElement('all_services')->isChecked();
             if ($childHosts === 0) {
-                $hostDowntime = new ScheduleHostDowntimeCommand();
+                $hostDowntime = (new ScheduleHostDowntimeCommand())
+                    ->setForAllServicesNative($allServicesNative);
                 if ($allServices === true) {
                     $hostDowntime->setForAllServices();
                 };


=====================================
modules/monitoring/library/Monitoring/Command/Object/ApiScheduleHostDowntimeCommand.php
=====================================
@@ -0,0 +1,40 @@
+<?php
+/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Command\Object;
+
+/**
+ * Schedule host downtime command for API command transport and Icinga >= 2.11.0 that
+ * sends all_services and child_options in a single request
+ */
+class ApiScheduleHostDowntimeCommand extends ScheduleHostDowntimeCommand
+{
+    /** @var int Whether no, triggered, or non-triggered child downtimes should be scheduled */
+    protected $childOptions;
+
+    protected $forAllServicesNative = true;
+
+    /**
+     * Get child options, i.e. whether no, triggered, or non-triggered child downtimes should be scheduled
+     *
+     * @return int
+     */
+    public function getChildOptions()
+    {
+        return $this->childOptions;
+    }
+
+    /**
+     * Set child options, i.e. whether no, triggered, or non-triggered child downtimes should be scheduled
+     *
+     * @param int $childOptions
+     *
+     * @return $this
+     */
+    public function setChildOptions($childOptions)
+    {
+        $this->childOptions = $childOptions;
+
+        return $this;
+    }
+}


=====================================
modules/monitoring/library/Monitoring/Command/Object/ScheduleHostDowntimeCommand.php
=====================================
@@ -23,6 +23,9 @@ class ScheduleHostDowntimeCommand extends ScheduleServiceDowntimeCommand
      */
     protected $forAllServices = false;
 
+    /** @var bool Whether to send the all_services API parameter */
+    protected $forAllServicesNative;
+
     /**
      * Set whether to schedule a downtime for all services associated with a particular host
      *
@@ -45,4 +48,28 @@ class ScheduleHostDowntimeCommand extends ScheduleServiceDowntimeCommand
     {
         return $this->forAllServices;
     }
+
+    /**
+     * Get whether to send the all_services API parameter
+     *
+     * @return bool
+     */
+    public function isForAllServicesNative()
+    {
+        return $this->forAllServicesNative;
+    }
+
+    /**
+     * Get whether to send the all_services API parameter
+     *
+     * @param bool $forAllServicesNative
+     *
+     * @return $this
+     */
+    public function setForAllServicesNative($forAllServicesNative = true)
+    {
+        $this->forAllServicesNative = (bool) $forAllServicesNative;
+
+        return $this;
+    }
 }


=====================================
modules/monitoring/library/Monitoring/Command/Renderer/IcingaApiCommandRenderer.php
=====================================
@@ -3,10 +3,12 @@
 
 namespace Icinga\Module\Monitoring\Command\Renderer;
 
+use Icinga\Module\Monitoring\Backend\MonitoringBackend;
 use Icinga\Module\Monitoring\Command\IcingaApiCommand;
 use Icinga\Module\Monitoring\Command\Instance\ToggleInstanceFeatureCommand;
 use Icinga\Module\Monitoring\Command\Object\AcknowledgeProblemCommand;
 use Icinga\Module\Monitoring\Command\Object\AddCommentCommand;
+use Icinga\Module\Monitoring\Command\Object\ApiScheduleHostDowntimeCommand;
 use Icinga\Module\Monitoring\Command\Object\DeleteCommentCommand;
 use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
 use Icinga\Module\Monitoring\Command\Object\ProcessCheckResultCommand;
@@ -156,25 +158,40 @@ class IcingaApiCommandRenderer implements IcingaCommandRendererInterface
             'trigger_name'  => $command->getTriggerId()
         );
         $commandData = $data;
+
         if ($command instanceof PropagateHostDowntimeCommand) {
-            /** @var \Icinga\Module\Monitoring\Command\Object\PropagateHostDowntimeCommand $command */
             $commandData['child_options'] = $command->getTriggered() ? 1 : 2;
+        } elseif ($command instanceof ApiScheduleHostDowntimeCommand) {
+            // We assume that it has previously been verified that the Icinga version is
+            // equal to or greater than 2.11.0
+            $commandData['child_options'] = $command->getChildOptions();
+        }
+
+        $allServicesCompat = false;
+        if ($command instanceof ScheduleHostDowntimeCommand) {
+            if ($command->isForAllServicesNative()) {
+                // We assume that it has previously been verified that the Icinga version is
+                // equal to or greater than 2.11.0
+                $commandData['all_services'] = $command->getForAllServices();
+            } else {
+                $allServicesCompat = $command->getForAllServices();
+            }
         }
+
         $this->applyFilter($commandData, $command->getObject());
         $apiCommand = IcingaApiCommand::create($endpoint, $commandData);
-        if ($command instanceof ScheduleHostDowntimeCommand
-            /** @var \Icinga\Module\Monitoring\Command\Object\ScheduleHostDowntimeCommand $command */
-            && $command->getForAllServices()
-        ) {
-            $commandData = $data + array(
-                'type'          => 'Service',
-                'filter'        => 'host.name == host_name',
-                'filter_vars'   => array(
+
+        if ($allServicesCompat) {
+            $commandData = $data + [
+                'type'        => 'Service',
+                'filter'      => 'host.name == host_name',
+                'filter_vars' => [
                     'host_name' => $command->getObject()->getName()
-                )
-            );
+                ]
+            ];
             $apiCommand->setNext(IcingaApiCommand::create($endpoint, $commandData));
         }
+
         return $apiCommand;
     }
 


=====================================
modules/monitoring/module.info
=====================================
@@ -1,5 +1,5 @@
 Module: monitoring
-Version: 2.9.2
+Version: 2.9.3
 Description: Icinga monitoring module
  IDO accessor and UI for your monitoring. This is the initial instalment for a
  graphical presentation of Icinga environments. The predecessor of Icinga DB.


=====================================
modules/setup/module.info
=====================================
@@ -1,5 +1,5 @@
 Module: setup
-Version: 2.9.2
+Version: 2.9.3
 Description: Setup module
  Web based wizard for setting up Icinga Web 2 and its modules.
  This includes the data backends (e.g. relational database, LDAP),


=====================================
modules/test/module.info
=====================================
@@ -1,5 +1,5 @@
 Module: test
-Version: 2.9.2
+Version: 2.9.3
 Description: Translation module
  This module allows developers to run (unit) tests against Icinga Web 2 and
  any of its modules. Usually you do not need to enable this.


=====================================
modules/translation/module.info
=====================================
@@ -1,5 +1,5 @@
 Module: translation
-Version: 2.9.2
+Version: 2.9.3
 Description: Translation module
  This module allows developers and translators to translate modules for multiple
  languages. You do not need this module to run an internationalized web frontend.


=====================================
public/css/icinga/login.less
=====================================
@@ -113,6 +113,11 @@
     .toggle-switch {
       margin-right: 1em;
     }
+
+    .control-info {
+      line-height: 1.5;
+      margin-left: .5em;
+    }
   }
 }
 



View it on GitLab: https://salsa.debian.org/nagios-team/pkg-icingaweb2/-/commit/7c663274ac198d7654b722540605a26e861f37f2

-- 
View it on GitLab: https://salsa.debian.org/nagios-team/pkg-icingaweb2/-/commit/7c663274ac198d7654b722540605a26e861f37f2
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-nagios-changes/attachments/20210812/6bac95e5/attachment-0001.htm>


More information about the pkg-nagios-changes mailing list