mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-27 15:54:03 +02:00
Merge branch 'master' into feature/monitoring-restrictions-9009
Conflicts: modules/monitoring/application/controllers/ShowController.php modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php
This commit is contained in:
commit
e8058c09c5
1
AUTHORS
1
AUTHORS
@ -18,6 +18,7 @@ Marius Hein <marius.hein@netways.de>
|
|||||||
Markus Frosch <markus@lazyfrosch.de>
|
Markus Frosch <markus@lazyfrosch.de>
|
||||||
Matthias Jentsch <matthias.jentsch@netways.de>
|
Matthias Jentsch <matthias.jentsch@netways.de>
|
||||||
Michael Friedrich <michael.friedrich@netways.de>
|
Michael Friedrich <michael.friedrich@netways.de>
|
||||||
|
Paul Richards <paul@minimoo.org>
|
||||||
Rene Moser <rene.moser@swisstxt.ch>
|
Rene Moser <rene.moser@swisstxt.ch>
|
||||||
Susanne Vestner-Ludwig <susanne.vestner-ludwig@inserteffect.com>
|
Susanne Vestner-Ludwig <susanne.vestner-ludwig@inserteffect.com>
|
||||||
Sylph Lin <sylph.lin@gmail.com>
|
Sylph Lin <sylph.lin@gmail.com>
|
||||||
|
147
application/forms/Config/Resource/SshResourceForm.php
Normal file
147
application/forms/Config/Resource/SshResourceForm.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Forms\Config\Resource;
|
||||||
|
|
||||||
|
use Icinga\Application\Icinga;
|
||||||
|
use Icinga\Data\ConfigObject;
|
||||||
|
use Icinga\Forms\Config\ResourceConfigForm;
|
||||||
|
use Icinga\Web\Form;
|
||||||
|
use Icinga\Util\File;
|
||||||
|
use Zend_Validate_Callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form class for adding/modifying ssh identity resources
|
||||||
|
*/
|
||||||
|
class SshResourceForm extends Form
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initialize this form
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->setName('form_config_resource_ssh');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Form::createElements()
|
||||||
|
*/
|
||||||
|
public function createElements(array $formData)
|
||||||
|
{
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'name',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'label' => $this->translate('Resource Name'),
|
||||||
|
'description' => $this->translate('The unique name of this resource')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'user',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'label' => $this->translate('User'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'User to log in as on the remote Icinga instance. Please note that key-based SSH login must be'
|
||||||
|
. ' possible for this user'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->getRequest()->getActionName() != 'editresource') {
|
||||||
|
|
||||||
|
$callbackValidator = new Zend_Validate_Callback(function ($value) {
|
||||||
|
if (openssl_pkey_get_private($value) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
$callbackValidator->setMessage(
|
||||||
|
$this->translate('The given SSH key is invalid'),
|
||||||
|
Zend_Validate_Callback::INVALID_VALUE
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->addElement(
|
||||||
|
'textarea',
|
||||||
|
'private_key',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'label' => $this->translate('Private Key'),
|
||||||
|
'description' => $this->translate('The private key which will be used for the SSH connections'),
|
||||||
|
'class' => 'resource ssh-identity',
|
||||||
|
'validators' => array($callbackValidator)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$resourceName = $formData['name'];
|
||||||
|
$this->addElement(
|
||||||
|
'note',
|
||||||
|
'private_key_note',
|
||||||
|
array(
|
||||||
|
'escape' => false,
|
||||||
|
'label' => $this->translate('Private Key'),
|
||||||
|
'value' => sprintf(
|
||||||
|
'<a href="%1$s" data-base-target="_next" title="%2$s" aria-label="%2$s">%3$s</a>',
|
||||||
|
$this->getView()->url('config/removeresource', array('resource' => $resourceName)),
|
||||||
|
sprintf($this->translate(
|
||||||
|
'Remove the %s resource'
|
||||||
|
), $resourceName),
|
||||||
|
$this->translate('To modify the private key you must recreate this resource.')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the assigned key to the resource
|
||||||
|
*
|
||||||
|
* @param ConfigObject $config
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function beforeRemove(ConfigObject $config)
|
||||||
|
{
|
||||||
|
$file = $config->private_key;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the assigned key to the resource
|
||||||
|
*
|
||||||
|
* @param ResourceConfigForm $form
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function beforeAdd(ResourceConfigForm $form)
|
||||||
|
{
|
||||||
|
$configDir = Icinga::app()->getConfigDir();
|
||||||
|
$user = $form->getElement('user')->getValue();
|
||||||
|
|
||||||
|
$filePath = $configDir . '/ssh/' . $user;
|
||||||
|
|
||||||
|
if (! file_exists($filePath)) {
|
||||||
|
$file = File::create($filePath, 0600);
|
||||||
|
} else {
|
||||||
|
$form->error(
|
||||||
|
sprintf($form->translate('The private key for the user "%s" is already exists.'), $user)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file->fwrite($form->getElement('private_key')->getValue());
|
||||||
|
|
||||||
|
$form->getElement('private_key')->setValue($configDir . '/ssh/' . $user);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ use Icinga\Forms\Config\Resource\DbResourceForm;
|
|||||||
use Icinga\Forms\Config\Resource\FileResourceForm;
|
use Icinga\Forms\Config\Resource\FileResourceForm;
|
||||||
use Icinga\Forms\Config\Resource\LdapResourceForm;
|
use Icinga\Forms\Config\Resource\LdapResourceForm;
|
||||||
use Icinga\Forms\Config\Resource\LivestatusResourceForm;
|
use Icinga\Forms\Config\Resource\LivestatusResourceForm;
|
||||||
|
use Icinga\Forms\Config\Resource\SshResourceForm;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
|
|
||||||
@ -41,6 +42,8 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
return new LivestatusResourceForm();
|
return new LivestatusResourceForm();
|
||||||
} elseif ($type === 'file') {
|
} elseif ($type === 'file') {
|
||||||
return new FileResourceForm();
|
return new FileResourceForm();
|
||||||
|
} elseif ($type === 'ssh') {
|
||||||
|
return new SshResourceForm();
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type));
|
throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type));
|
||||||
}
|
}
|
||||||
@ -55,7 +58,7 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*
|
*
|
||||||
* @thrwos InvalidArgumentException In case the resource does already exist
|
* @throws InvalidArgumentException In case the resource does already exist
|
||||||
*/
|
*/
|
||||||
public function add(array $values)
|
public function add(array $values)
|
||||||
{
|
{
|
||||||
@ -116,6 +119,11 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
|
|
||||||
$resourceConfig = $this->config->getSection($name);
|
$resourceConfig = $this->config->getSection($name);
|
||||||
|
$resourceForm = $this->getResourceForm($resourceConfig->type);
|
||||||
|
if (method_exists($resourceForm, 'beforeRemove')) {
|
||||||
|
$resourceForm::beforeRemove($resourceConfig);
|
||||||
|
}
|
||||||
|
|
||||||
$this->config->removeSection($name);
|
$this->config->removeSection($name);
|
||||||
return $resourceConfig;
|
return $resourceConfig;
|
||||||
}
|
}
|
||||||
@ -130,8 +138,9 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
*/
|
*/
|
||||||
public function onSuccess()
|
public function onSuccess()
|
||||||
{
|
{
|
||||||
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
|
|
||||||
$resourceForm = $this->getResourceForm($this->getElement('type')->getValue());
|
$resourceForm = $this->getResourceForm($this->getElement('type')->getValue());
|
||||||
|
|
||||||
|
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
|
||||||
if (method_exists($resourceForm, 'isValidResource') && false === $resourceForm::isValidResource($this)) {
|
if (method_exists($resourceForm, 'isValidResource') && false === $resourceForm::isValidResource($this)) {
|
||||||
$this->addElement($this->getForceCreationCheckbox());
|
$this->addElement($this->getForceCreationCheckbox());
|
||||||
return false;
|
return false;
|
||||||
@ -141,6 +150,11 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
$resource = $this->request->getQuery('resource');
|
$resource = $this->request->getQuery('resource');
|
||||||
try {
|
try {
|
||||||
if ($resource === null) { // create new resource
|
if ($resource === null) { // create new resource
|
||||||
|
if (method_exists($resourceForm, 'beforeAdd')) {
|
||||||
|
if (! $resourceForm::beforeAdd($this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
$this->add($this->getValues());
|
$this->add($this->getValues());
|
||||||
$message = $this->translate('Resource "%s" has been successfully created');
|
$message = $this->translate('Resource "%s" has been successfully created');
|
||||||
} else { // edit existing resource
|
} else { // edit existing resource
|
||||||
@ -212,6 +226,7 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
$resourceTypes = array(
|
$resourceTypes = array(
|
||||||
'file' => $this->translate('File'),
|
'file' => $this->translate('File'),
|
||||||
'livestatus' => 'Livestatus',
|
'livestatus' => 'Livestatus',
|
||||||
|
'ssh' => $this->translate('SSH Identity'),
|
||||||
);
|
);
|
||||||
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
|
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
|
||||||
$resourceTypes['ldap'] = 'LDAP';
|
$resourceTypes['ldap'] = 'LDAP';
|
||||||
|
@ -31,7 +31,7 @@ if ($this->hasPermission('config/authentication/groups/edit') && $backend instan
|
|||||||
<p class="group-name"><strong><?= $this->escape($group->group_name); ?></strong></p> <?= $editLink; ?>
|
<p class="group-name"><strong><?= $this->escape($group->group_name); ?></strong></p> <?= $editLink; ?>
|
||||||
<p class="group-created"><strong><?= $this->translate('Created at'); ?>:</strong> <?= $group->created_at === null ? '-' : $this->formatDateTime($group->created_at); ?></p>
|
<p class="group-created"><strong><?= $this->translate('Created at'); ?>:</strong> <?= $group->created_at === null ? '-' : $this->formatDateTime($group->created_at); ?></p>
|
||||||
<p class="group-modified"><strong><?= $this->translate('Last modified'); ?>:</strong> <?= $group->last_modified === null ? '-' : $this->formatDateTime($group->last_modified); ?></p>
|
<p class="group-modified"><strong><?= $this->translate('Last modified'); ?>:</strong> <?= $group->last_modified === null ? '-' : $this->formatDateTime($group->last_modified); ?></p>
|
||||||
</div>
|
<h3><?= $this->translate('Members'); ?></h3>
|
||||||
<?php if (! $this->compact): ?>
|
<?php if (! $this->compact): ?>
|
||||||
<?= $this->sortBox; ?>
|
<?= $this->sortBox; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
@ -41,6 +41,7 @@ if ($this->hasPermission('config/authentication/groups/edit') && $backend instan
|
|||||||
<?= $this->filterEditor; ?>
|
<?= $this->filterEditor; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="content members" data-base-target="_next">
|
<div class="content members" data-base-target="_next">
|
||||||
<?php if (count($members) > 0): ?>
|
<?php if (count($members) > 0): ?>
|
||||||
<table data-base-target="_next" class="action member-list">
|
<table data-base-target="_next" class="action member-list">
|
||||||
|
@ -31,7 +31,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc
|
|||||||
<p class="user-state"><strong><?= $this->translate('State'); ?>:</strong> <?= $user->is_active === null ? '-' : ($user->is_active ? $this->translate('Active') : $this->translate('Inactive')); ?></p>
|
<p class="user-state"><strong><?= $this->translate('State'); ?>:</strong> <?= $user->is_active === null ? '-' : ($user->is_active ? $this->translate('Active') : $this->translate('Inactive')); ?></p>
|
||||||
<p class="user-created"><strong><?= $this->translate('Created at'); ?>:</strong> <?= $user->created_at === null ? '-' : $this->formatDateTime($user->created_at); ?></p>
|
<p class="user-created"><strong><?= $this->translate('Created at'); ?>:</strong> <?= $user->created_at === null ? '-' : $this->formatDateTime($user->created_at); ?></p>
|
||||||
<p class="user-modified"><strong><?= $this->translate('Last modified'); ?>:</strong> <?= $user->last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?></p>
|
<p class="user-modified"><strong><?= $this->translate('Last modified'); ?>:</strong> <?= $user->last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?></p>
|
||||||
</div>
|
<h3><?= $this->translate('Group Memberships'); ?></h3>
|
||||||
<?php if (! $this->compact): ?>
|
<?php if (! $this->compact): ?>
|
||||||
<?= $this->sortBox; ?>
|
<?= $this->sortBox; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
@ -41,6 +41,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc
|
|||||||
<?= $this->filterEditor; ?>
|
<?= $this->filterEditor; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="content memberships" data-base-target="_next">
|
<div class="content memberships" data-base-target="_next">
|
||||||
<?php if (count($memberships) > 0): ?>
|
<?php if (count($memberships) > 0): ?>
|
||||||
<table data-base-target="_next" class="action membership-list">
|
<table data-base-target="_next" class="action membership-list">
|
||||||
|
70
doc/about.md
Normal file
70
doc/about.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# <a id="about"></a> About Icinga Web 2
|
||||||
|
|
||||||
|
Icinga Web 2 is a powerful PHP framework for web applications that comes in a clean and reduced design.
|
||||||
|
It's fast, responsive, accessible and easily extensible with modules.
|
||||||
|
|
||||||
|
## <a id="about-monitoring"></a> The monitoring module
|
||||||
|
|
||||||
|
This is the core module for most Icinga Web 2 users.
|
||||||
|
|
||||||
|
It provides an intuitive user interface for monitoring with Icinga (1 and 2).
|
||||||
|
Especially there are lots of list and detail views (e.g. for hosts and services)
|
||||||
|
you can sort and filter depending on what you want to see.
|
||||||
|
|
||||||
|
You can also control the monitoring process itself by sending external commands to Icinga.
|
||||||
|
Most such actions (like rescheduling a check) can be done with just a single click.
|
||||||
|
|
||||||
|
## <a id="about-installation"></a> Installation
|
||||||
|
|
||||||
|
Icinga Web 2 can be installed easily from packages from the official package repositories.
|
||||||
|
Setting it up is also easy with the web based setup wizard.
|
||||||
|
|
||||||
|
See [here](installation#installation) for more information about the installation.
|
||||||
|
|
||||||
|
## <a id="about-configuration"></a> Configuration
|
||||||
|
|
||||||
|
Icinga Web 2 can be configured via the user interface and .ini files.
|
||||||
|
|
||||||
|
See [here](configuration#configuration) for more information about the configuration.
|
||||||
|
|
||||||
|
## <a id="about-authentication"></a> Authentication
|
||||||
|
|
||||||
|
With Icinga Web 2 you can authenticate against relational databases, LDAP and more.
|
||||||
|
These authentication methods can be easily configured (via the corresponding .ini file).
|
||||||
|
|
||||||
|
See [here](authentication#authentication) for more information about
|
||||||
|
the different authentication methods available and how to configure them.
|
||||||
|
|
||||||
|
## <a id="about-authorization"></a> Authorization
|
||||||
|
|
||||||
|
In Icinga Web 2 there are permissions and restrictions to allow and deny (respectively)
|
||||||
|
roles to view or to do certain things.
|
||||||
|
These roles can be assigned to users and groups.
|
||||||
|
|
||||||
|
See [here](security#security) for more information about authorization
|
||||||
|
and how to configure roles.
|
||||||
|
|
||||||
|
## <a id="about-preferences"></a> User preferences
|
||||||
|
|
||||||
|
Besides the global configuration each user has individual configuration options
|
||||||
|
like the interface's language or the current timezone.
|
||||||
|
They can be stored either in a database or in .ini files.
|
||||||
|
|
||||||
|
See [here](preferences#preferences) for more information about a user's preferences
|
||||||
|
and how to configure their storage type.
|
||||||
|
|
||||||
|
## <a id="about-documentation"></a> Documentation
|
||||||
|
|
||||||
|
With the documentation module you can read the documentation of the framework (and any module) directly in the user interface.
|
||||||
|
|
||||||
|
The module can also export the documentation to PDF.
|
||||||
|
|
||||||
|
## <a id="about-translation"></a> Translation
|
||||||
|
|
||||||
|
With the translation module every piece of text in the user interface (of the framework itself and any module) can be translated to a language of your choice.
|
||||||
|
|
||||||
|
Currently provided languages:
|
||||||
|
|
||||||
|
* German
|
||||||
|
* Italian
|
||||||
|
* Portuguese
|
@ -8,7 +8,7 @@ different files, when the information about a data source changes.
|
|||||||
|
|
||||||
Each section in **config/resources.ini** represents a data source with the section name being the identifier used to
|
Each section in **config/resources.ini** represents a data source with the section name being the identifier used to
|
||||||
reference this specific data source. Depending on the data source type, the sections define different directives.
|
reference this specific data source. Depending on the data source type, the sections define different directives.
|
||||||
The available data source types are *db*, *ldap* and *livestatus* which will described in detail in the following
|
The available data source types are *db*, *ldap*, *ssh* and *livestatus* which will described in detail in the following
|
||||||
paragraphs.
|
paragraphs.
|
||||||
|
|
||||||
### <a id="resources-configuration-database"></a> Database
|
### <a id="resources-configuration-database"></a> Database
|
||||||
@ -64,6 +64,26 @@ bind_dn = "cn=admin,ou=people,dc=icinga,dc=org"
|
|||||||
bind_pw = admin`
|
bind_pw = admin`
|
||||||
````
|
````
|
||||||
|
|
||||||
|
### <a id="resources-configuration-ssh"></a> SSH
|
||||||
|
|
||||||
|
A SSH resource contains the information about the user and the private key location, which can be used for the key-based
|
||||||
|
ssh authentication.
|
||||||
|
|
||||||
|
Directive | Description
|
||||||
|
--------------------|------------
|
||||||
|
**type** | `ssh`
|
||||||
|
**user** | The username to use when connecting to the server.
|
||||||
|
**private_key** | The path to the private key of the user.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
````
|
||||||
|
[ssh]
|
||||||
|
type = "ssh"
|
||||||
|
user = "ssh-user"
|
||||||
|
private_key = "/etc/icingaweb2/ssh/ssh-user"
|
||||||
|
````
|
||||||
|
|
||||||
### <a id="resources-configuration-livestatus"></a> Livestatus
|
### <a id="resources-configuration-livestatus"></a> Livestatus
|
||||||
|
|
||||||
A Livestatus resource represents the location of a Livestatus socket which is used for fetching monitoring data.
|
A Livestatus resource represents the location of a Livestatus socket which is used for fetching monitoring data.
|
||||||
|
279
doc/security.md
Normal file
279
doc/security.md
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
# <a id="security"></a> Security
|
||||||
|
|
||||||
|
Access control is a vital part of configuring Icinga Web 2 in a secure way.
|
||||||
|
It is important that not every user that has access to Icinga Web 2 is able
|
||||||
|
to do any action or to see any host and service. For example, it is useful to allow
|
||||||
|
only a small group of administrators to change the Icinga Web 2 configuration,
|
||||||
|
to prevent misconfiguration or security breaches. Another important use case is
|
||||||
|
creating groups of users which can only see the fraction of the monitoring
|
||||||
|
environment they are in charge of.
|
||||||
|
|
||||||
|
This chapter will describe how to do the security configuration of Icinga Web 2
|
||||||
|
and how to apply permissions and restrictions to users or groups of users.
|
||||||
|
|
||||||
|
## Basics
|
||||||
|
|
||||||
|
Icinga Web 2 access control is done by defining **roles** that associate permissions
|
||||||
|
and restrictions with **users** and **groups**. There are two general kinds of
|
||||||
|
things to which access can be managed: actions and objects.
|
||||||
|
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
Actions are all the things an Icinga Web 2 user can do, like changing a certain configuration,
|
||||||
|
changing permissions or sending a command to the Icinga instance through the
|
||||||
|
<a href="http://docs.icinga.org/icinga2/latest/doc/module/icinga2/toc#!/icinga2/latest/doc/module/icinga2/chapter/getting-started#setting-up-external-command-pipe">Command Pipe</a>
|
||||||
|
in the monitoring module. All actions must be be **allowed explicitly** using permissions.
|
||||||
|
|
||||||
|
A permission is a simple list of identifiers of actions a user is
|
||||||
|
allowed to do. Permissions are described in greater detail in the
|
||||||
|
section [Permissions](#permissions).
|
||||||
|
|
||||||
|
### Objects
|
||||||
|
|
||||||
|
There are all kinds of different objects in Icinga Web 2: Hosts, Services, Notifications, Downtimes and Events.
|
||||||
|
|
||||||
|
By default, a user can **see everything**, but it is possible to **explicitly restrict** what each user can see using restrictions.
|
||||||
|
|
||||||
|
Restrictions are complex filter queries that describe what objects should be displayed to a user. Restrictions are described
|
||||||
|
in greater detail in the section [Restrictions](#restrictions).
|
||||||
|
|
||||||
|
### Users
|
||||||
|
|
||||||
|
Anyone who can **login** to Icinga Web 2 is considered a user and can be referenced to by the
|
||||||
|
**user name** used during login.
|
||||||
|
For example, there might be user called **jdoe** authenticated
|
||||||
|
using Active Directory, and a user **icingaadmin** that is authenticated using a MySQL-Database as backend.
|
||||||
|
In the configuration, both can be referenced to by using their user names **icingaadmin** or **jdoe**.
|
||||||
|
|
||||||
|
Icinga Web 2 users and groups are not configured by a configuration file, but provided by
|
||||||
|
an **authentication backend**. For extended information on setting up authentication backends and managing users, please read the chapter [Authentication](authentication.md#authentication).
|
||||||
|
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
Since Icinga Web 2, users in the Icinga configuration and the web authentication are separated, to allow
|
||||||
|
use of external authentication providers. This means that users and groups defined in the Icinga configuration are not available to Icinga Web 2. Instead it uses its own authentication
|
||||||
|
backend to fetch users and groups from, which must be configured separately.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#### Managing Users
|
||||||
|
|
||||||
|
When using a [Database
|
||||||
|
as authentication backend](authentication.md#authentication-configuration-db-authentication), it is possible to create, add and delete users directly in the frontend. This configuration
|
||||||
|
can be found at **Configuration > Authentication > Users **.
|
||||||
|
|
||||||
|
### Groups
|
||||||
|
|
||||||
|
If there is a big amount of users to manage, it would be tedious to specify each user
|
||||||
|
separately when regularly referring to the same group of users. Because of that, it is possible to group users.
|
||||||
|
A user can be member of multiple groups and will inherit all permissions and restrictions.
|
||||||
|
|
||||||
|
Like users, groups are identified solely by their **name** that is provided by
|
||||||
|
a **group backend**. For extended information on setting up group backends,
|
||||||
|
please read the chapter [Authentication](authentication.md#authentication).
|
||||||
|
|
||||||
|
|
||||||
|
#### Managing Groups
|
||||||
|
|
||||||
|
When using a [Database as an authentication backend](#authentication.md#authentication-configuration-db-authentication),
|
||||||
|
it is possible to manage groups and group memberships directly in the frontend. This configuration
|
||||||
|
can be found at **Configuration > Authentication > Groups **.
|
||||||
|
|
||||||
|
## Roles
|
||||||
|
|
||||||
|
A role defines a set of **permissions** and **restrictions** and assigns
|
||||||
|
those to **users** and **groups**. For example, a role **admins** could define that certain
|
||||||
|
users have access to all configuration options, or another role **support**
|
||||||
|
could define that a list of users or groups is restricted to see only hosts and services
|
||||||
|
that match a specific query.
|
||||||
|
|
||||||
|
The actual permission of a certain user will be determined by merging the permissions
|
||||||
|
and restrictions of the user itself and all the groups the user is member of. Permissions can
|
||||||
|
be simply added up, while restrictions follow a slighty more complex pattern, that is described
|
||||||
|
in the section [Stacking Filters](#stacking-filters).
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Roles can be changed either through the icingaweb2 interface, by navigation
|
||||||
|
to the page **Configuration > Authentication > Roles**, or through editing the
|
||||||
|
configuration file:
|
||||||
|
|
||||||
|
|
||||||
|
/etc/icingaweb2/roles.ini
|
||||||
|
|
||||||
|
|
||||||
|
#### Introducing Example
|
||||||
|
|
||||||
|
To get you a quick start, here is an example of what a role definition could look like:
|
||||||
|
|
||||||
|
|
||||||
|
[winadmin]
|
||||||
|
users = "jdoe, janedoe"
|
||||||
|
groups = "admin"
|
||||||
|
permissions = "config/application/*, monitoring/commands/schedule-check"
|
||||||
|
monitoring/filter/objects = "host=*win*"
|
||||||
|
|
||||||
|
|
||||||
|
This example creates a role called **winadmin**, that grants all permissions in `config/application/*` and `monitoring/commands/schedule-check` and additionally only
|
||||||
|
allows the hosts and services that match the filter `host=*win*` to be displayed. The users
|
||||||
|
**jdoe** and **janedoe** and all members of the group **admin** will be affected
|
||||||
|
by this role.
|
||||||
|
|
||||||
|
|
||||||
|
#### <a id="syntax"></a> Syntax
|
||||||
|
|
||||||
|
Each role is defined as a section, with the name of the role as section name. The following
|
||||||
|
attributes can be defined for each role in a default Icinga Web 2 installation:
|
||||||
|
|
||||||
|
|
||||||
|
Directive | Description
|
||||||
|
---------------------------|-----------------------------------------------------------------------------
|
||||||
|
users | A comma-separated list of user **user names** that are affected by this role
|
||||||
|
groups | A comma-separated list of **group names** that are affected by this role
|
||||||
|
permissions | A comma-separated list of **permissions** granted by this role
|
||||||
|
monitoring/filter/objects | A **filter expression** that restricts the access to services and hosts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## <a id="permissions"></a> Permissions
|
||||||
|
|
||||||
|
Permissions can be used to allow users or groups certain **actions**. By default,
|
||||||
|
all actions are **prohibited** and must be allowed explicitly by a role for any user.
|
||||||
|
|
||||||
|
Each action in Icinga Web 2 is denoted by a **namespaced key**, which is used to order and
|
||||||
|
group those actions. All actions that affect the configuration of Icinga Web 2, are in a
|
||||||
|
namespace called **config**, while all configurations that affect authentication
|
||||||
|
are in the namespace `config/authentication`
|
||||||
|
|
||||||
|
**Wildcards** can be used to grant permission for all actions in a certain namespace.
|
||||||
|
The permission `config/*` would grant permission to all configuration actions,
|
||||||
|
while just specifying a wildcard `*` would give permission for all actions.
|
||||||
|
|
||||||
|
When multiple roles assign permissions to the same user (either directly or indirectly
|
||||||
|
through a group) all permissions can simply be added together to get the users actual permission set.
|
||||||
|
|
||||||
|
#### Global permissions
|
||||||
|
|
||||||
|
Name | Permits
|
||||||
|
-------------------------------------|-----------------------------------------------------------------
|
||||||
|
* | Allow everything, including module-specific permissions
|
||||||
|
config/* | Allow all configuration actions
|
||||||
|
config/application/* | Allow configuring IcingaWeb2
|
||||||
|
config/application/general | Allow general settings, like logging or preferences
|
||||||
|
config/application/resources | Allow changing resources for retrieving data
|
||||||
|
config/application/userbackend | Allow changing backends for retrieving available users
|
||||||
|
config/application/usergroupbackend | Allow changing backends for retrieving available groups
|
||||||
|
config/authentication/* | Allow configuring IcingaWeb2 authentication mechanisms
|
||||||
|
config/authentication/users/* | Allow all user actions
|
||||||
|
config/authentication/users/show | Allow displaying avilable users
|
||||||
|
config/authentication/users/add | Allow adding a new user to the backend
|
||||||
|
config/authentication/users/edit | Allow editing an existing user in the backend
|
||||||
|
config/authentication/users/remove | Allow removing an existing user from the backend
|
||||||
|
config/authentication/groups/* | Allow all group actions
|
||||||
|
config/authentication/groups/show | Allow displaying all available groups
|
||||||
|
config/authentication/groups/add | Allow adding a new group to the backend
|
||||||
|
config/authentication/groups/edit | Allow editing existing groups in a backend
|
||||||
|
config/authentication/groups/remove | Allow removing existing groups from the backend
|
||||||
|
config/authentication/roles/* | Allow all role actions
|
||||||
|
config/authentication/roles/add | Allow adding a new role
|
||||||
|
config/authentication/roles/show | Allow displaying available roles
|
||||||
|
config/authentication/roles/edit | Allow changing an existing role
|
||||||
|
config/authentication/roles/remove | Allow removing an existing row
|
||||||
|
config/modules | Allow enabling or disabling modules
|
||||||
|
|
||||||
|
|
||||||
|
#### Monitoring module permissions
|
||||||
|
|
||||||
|
The built-in monitoring module defines an additional set of permissions, that
|
||||||
|
is described in detail in [monitoring module documentation](/icingaweb2/doc/module/doc/chapter/monitoring-security#monitoring-security).
|
||||||
|
|
||||||
|
|
||||||
|
## <a id="restrictions"></a> Restrictions
|
||||||
|
|
||||||
|
Restrictions can be used to define what a user or group can see by specifying
|
||||||
|
a filter expression that applies to a defined set of data. By default, when no
|
||||||
|
restrictions are defined, a user will be able to see every information that is available.
|
||||||
|
|
||||||
|
A restrictions is always specified for a certain **filter directive**, that defines what
|
||||||
|
data the filter is applied to. The **filter directive** is a simple identifier, that was
|
||||||
|
defined in an Icinga Web 2 module. The only filter directive that is available
|
||||||
|
in a default installation, is the `monitoring/filter/objects` directive, defined by the monitoring module,
|
||||||
|
that can be used to apply filter to hosts and services. This directive was previously
|
||||||
|
mentioned in the section [Syntax](#syntax).
|
||||||
|
|
||||||
|
### Filter Expressions
|
||||||
|
|
||||||
|
Filters operate on columns. A complete list of all available filter columns on hosts and services can be found in
|
||||||
|
the [monitoring module documentation](/icingaweb2/doc/module/doc/chapter/monitoring-security#monitoring-security-restrictions).
|
||||||
|
|
||||||
|
Any filter expression that is allowed in the filtered view, is also an allowed filter expression.
|
||||||
|
This means, that it is possible to define negations, wildcards, and even nested
|
||||||
|
filter expressions containing AND and OR-Clauses.
|
||||||
|
|
||||||
|
The filter expression will be **implicitly** added as an **AND-Clause** to each query on
|
||||||
|
the filtered data. The following shows the filter expression `host=*win*` being applied on `monitoring/filter/objects`.
|
||||||
|
|
||||||
|
|
||||||
|
Regular filter query:
|
||||||
|
|
||||||
|
AND-- service_problem = 1
|
||||||
|
|
|
||||||
|
+--- service_handled = 0
|
||||||
|
|
||||||
|
|
||||||
|
With our restriction applied, any user affected by this restrictions will see the
|
||||||
|
results of this query instead:
|
||||||
|
|
||||||
|
|
||||||
|
AND-- host = *win*
|
||||||
|
|
|
||||||
|
+--AND-- service_problem = 1
|
||||||
|
|
|
||||||
|
+--- service_handled = 0
|
||||||
|
|
||||||
|
|
||||||
|
#### <a id="stacking-filters"></a> Stacking Filters
|
||||||
|
|
||||||
|
When multiple roles assign restrictions to the same user, either directly or indirectly
|
||||||
|
through a group, all filters will be combined using an **OR-Clause**, resulting in the final
|
||||||
|
expression:
|
||||||
|
|
||||||
|
|
||||||
|
AND-- OR-- $FILTER1
|
||||||
|
| |
|
||||||
|
| +-- $FILTER2
|
||||||
|
| |
|
||||||
|
| +-- $FILTER3
|
||||||
|
|
|
||||||
|
+--AND-- service_problem = 1
|
||||||
|
|
|
||||||
|
+--- service_handled = 0
|
||||||
|
|
||||||
|
|
||||||
|
As a result, a user is be able to see hosts that are matched by **ANY** of
|
||||||
|
the filter expressions. The following examples will show the usefulness of this behavior:
|
||||||
|
|
||||||
|
#### Example 1: Negation
|
||||||
|
|
||||||
|
[winadmin]
|
||||||
|
groups = "windows-admins"
|
||||||
|
monitoring/filter/objects = "host=*win*"
|
||||||
|
|
||||||
|
Will display only hosts and services whose host name contains **win**.
|
||||||
|
|
||||||
|
[webadmin]
|
||||||
|
groups = "web-admins"
|
||||||
|
monitoring/filter/objects = "host!=*win*"
|
||||||
|
|
||||||
|
Will only match hosts and services whose host name does **not** contain **win**
|
||||||
|
|
||||||
|
Notice that because of the behavior of two stacking filters, a user that is member of **windows-admins** and **web-admins**, will now be able to see both, Windows and non-Windows hosts and services.
|
||||||
|
|
||||||
|
#### Example 2: Hostgroups
|
||||||
|
|
||||||
|
[unix-server]
|
||||||
|
groups = "unix-admins"
|
||||||
|
monitoring/filter/objects = "(hostgroup_name=bsd-servers|hostgroup_name=linux-servers)"
|
||||||
|
|
||||||
|
This role allows all members of the group unix-admins to see hosts and services
|
||||||
|
that are part of the host-group linux-servers or the host-group bsd-servers.
|
@ -201,7 +201,7 @@ cp -prv packages/files/config/modules/setup %{buildroot}/%{configdir}/modules/
|
|||||||
|
|
||||||
%pre
|
%pre
|
||||||
getent group icingacmd >/dev/null || groupadd -r icingacmd
|
getent group icingacmd >/dev/null || groupadd -r icingacmd
|
||||||
%if 0%{?suse_version}
|
%if 0%{?suse_version} && 0%{?suse_version} < 01200
|
||||||
usermod -A icingacmd,%{icingawebgroup} %{wwwuser}
|
usermod -A icingacmd,%{icingawebgroup} %{wwwuser}
|
||||||
%else
|
%else
|
||||||
usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser}
|
usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser}
|
||||||
|
@ -134,18 +134,20 @@ abstract class ApplicationBootstrap
|
|||||||
$this->vendorDir = $baseDir . '/library/vendor';
|
$this->vendorDir = $baseDir . '/library/vendor';
|
||||||
$this->libDir = realpath(__DIR__ . '/../..');
|
$this->libDir = realpath(__DIR__ . '/../..');
|
||||||
|
|
||||||
|
$this->setupAutoloader();
|
||||||
|
|
||||||
if ($configDir === null) {
|
if ($configDir === null) {
|
||||||
if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
|
if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
|
||||||
$configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
|
$configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
|
||||||
} else {
|
} else {
|
||||||
$configDir = '/etc/icingaweb2';
|
$configDir = Platform::isWindows()
|
||||||
|
? $baseDir . '/config'
|
||||||
|
: '/etc/icingaweb2';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$canonical = realpath($configDir);
|
$canonical = realpath($configDir);
|
||||||
$this->configDir = $canonical ? $canonical : $configDir;
|
$this->configDir = $canonical ? $canonical : $configDir;
|
||||||
|
|
||||||
$this->setupAutoloader();
|
|
||||||
|
|
||||||
set_include_path(
|
set_include_path(
|
||||||
implode(
|
implode(
|
||||||
PATH_SEPARATOR,
|
PATH_SEPARATOR,
|
||||||
|
@ -31,7 +31,7 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|||||||
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']);
|
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']);
|
||||||
|
|
||||||
// Fix aliases
|
// Fix aliases
|
||||||
$remove = dirname($_SERVER['PHP_SELF']);
|
$remove = str_replace('\\', '/', dirname($_SERVER['PHP_SELF']));
|
||||||
if (substr($ruri, 0, strlen($remove)) !== $remove) {
|
if (substr($ruri, 0, strlen($remove)) !== $remove) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,12 @@ class Params
|
|||||||
$noOptionFlag = true;
|
$noOptionFlag = true;
|
||||||
} elseif (!$noOptionFlag && substr($argv[$i], 0, 2) === '--') {
|
} elseif (!$noOptionFlag && substr($argv[$i], 0, 2) === '--') {
|
||||||
$key = substr($argv[$i], 2);
|
$key = substr($argv[$i], 2);
|
||||||
if (! isset($argv[$i + 1]) || substr($argv[$i + 1], 0, 2) === '--') {
|
$matches = array();
|
||||||
|
if (1 === preg_match(
|
||||||
|
'/(?<!.)([^=]+)=(.*)(?!.)/ms', $key, $matches
|
||||||
|
)) {
|
||||||
|
$this->params[$matches[1]] = $matches[2];
|
||||||
|
} elseif (! isset($argv[$i + 1]) || substr($argv[$i + 1], 0, 2) === '--') {
|
||||||
$this->params[$key] = true;
|
$this->params[$key] = true;
|
||||||
} elseif (array_key_exists($key, $this->params)) {
|
} elseif (array_key_exists($key, $this->params)) {
|
||||||
if (!is_array($this->params[$key])) {
|
if (!is_array($this->params[$key])) {
|
||||||
|
@ -63,7 +63,7 @@ class File extends SplFileObject
|
|||||||
throw new NotWritableError(sprintf('Path "%s" is not writable', $dirPath));
|
throw new NotWritableError(sprintf('Path "%s" is not writable', $dirPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
$file = new static($path, 'x');
|
$file = new static($path, 'x+');
|
||||||
|
|
||||||
if (! @chmod($path, $accessMode)) {
|
if (! @chmod($path, $accessMode)) {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
|
@ -100,7 +100,11 @@ class Translator
|
|||||||
{
|
{
|
||||||
$contextString = "{$context}\004{$text}";
|
$contextString = "{$context}\004{$text}";
|
||||||
|
|
||||||
$translation = dcgettext($domain, $contextString, LC_MESSAGES);
|
$translation = dcgettext(
|
||||||
|
$domain,
|
||||||
|
$contextString,
|
||||||
|
defined('LC_MESSAGES') ? LC_MESSAGES : LC_ALL
|
||||||
|
);
|
||||||
|
|
||||||
if ($translation == $contextString) {
|
if ($translation == $contextString) {
|
||||||
return $text;
|
return $text;
|
||||||
@ -126,7 +130,13 @@ class Translator
|
|||||||
{
|
{
|
||||||
$contextString = "{$context}\004{$textSingular}";
|
$contextString = "{$context}\004{$textSingular}";
|
||||||
|
|
||||||
$translation = dcngettext($domain, $contextString, $textPlural, $number, LC_MESSAGES);
|
$translation = dcngettext(
|
||||||
|
$domain,
|
||||||
|
$contextString,
|
||||||
|
$textPlural,
|
||||||
|
$number,
|
||||||
|
defined('LC_MESSAGES') ? LC_MESSAGES : LC_ALL
|
||||||
|
);
|
||||||
|
|
||||||
if ($translation == $contextString || $translation == $textPlural) {
|
if ($translation == $contextString || $translation == $textPlural) {
|
||||||
return ($number == 1 ? $textSingular : $textPlural);
|
return ($number == 1 ? $textSingular : $textPlural);
|
||||||
|
@ -237,6 +237,10 @@ class Menu implements RecursiveIterator
|
|||||||
'priority' => 700,
|
'priority' => 700,
|
||||||
'renderer' => 'ProblemMenuItemRenderer'
|
'renderer' => 'ProblemMenuItemRenderer'
|
||||||
));
|
));
|
||||||
|
$section->add(t('About'), array(
|
||||||
|
'url' => 'about',
|
||||||
|
'priority' => 701
|
||||||
|
));
|
||||||
if (Logger::writesToFile()) {
|
if (Logger::writesToFile()) {
|
||||||
$section->add(t('Application Log'), array(
|
$section->add(t('Application Log'), array(
|
||||||
'url' => 'list/applicationlog',
|
'url' => 'list/applicationlog',
|
||||||
@ -279,11 +283,6 @@ class Menu implements RecursiveIterator
|
|||||||
'priority' => 990,
|
'priority' => 990,
|
||||||
'renderer' => 'ForeignMenuItemRenderer'
|
'renderer' => 'ForeignMenuItemRenderer'
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->add(t('About'), array(
|
|
||||||
'url' => 'about',
|
|
||||||
'priority' => 1000
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,11 +374,31 @@ class UrlParams
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toArray()
|
/**
|
||||||
|
* Return the parameters of this url as sequenced or associative array
|
||||||
|
*
|
||||||
|
* @param bool $sequenced
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($sequenced = true)
|
||||||
{
|
{
|
||||||
|
if ($sequenced) {
|
||||||
return $this->params;
|
return $this->params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$params = array();
|
||||||
|
foreach ($this->params as $param) {
|
||||||
|
if ($param[1] === true) {
|
||||||
|
$params[] = $param[0];
|
||||||
|
} else {
|
||||||
|
$params[$param[0]] = $param[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
|
||||||
public function toString($separator = null)
|
public function toString($separator = null)
|
||||||
{
|
{
|
||||||
if ($separator === null) {
|
if ($separator === null) {
|
||||||
|
@ -309,13 +309,14 @@ EOT;
|
|||||||
|
|
||||||
private function renderRefreshTab()
|
private function renderRefreshTab()
|
||||||
{
|
{
|
||||||
$url = Url::fromRequest()->without('renderLayout');
|
|
||||||
$tab = $this->get($this->getActiveName());
|
$tab = $this->get($this->getActiveName());
|
||||||
|
|
||||||
if ($tab !== null) {
|
if ($tab !== null) {
|
||||||
|
$url = Url::fromRequest($tab->getUrl()->getParams()->toArray(false))->without('renderLayout');
|
||||||
$label = $this->view()->escape(
|
$label = $this->view()->escape(
|
||||||
$tab->getLabel()
|
$tab->getLabel()
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$url = Url::fromRequest()->without('renderLayout');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! empty($label)) {
|
if (! empty($label)) {
|
||||||
|
65
modules/doc/doc/security.md
Normal file
65
modules/doc/doc/security.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# <a id="monitoring-security"></a> Security
|
||||||
|
|
||||||
|
The monitoring module provides an additional set of restrictions and permissions
|
||||||
|
that can be used for access control. The following sections will list those
|
||||||
|
restrictions and permissions in detail:
|
||||||
|
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
The Icinga Web 2 monitoring module can send commands to the current Icinga2 instance
|
||||||
|
through the command pipe. A user needs specific permissions to be able to send those
|
||||||
|
commands when using the monitoring module.
|
||||||
|
|
||||||
|
|
||||||
|
| Name | Permits |
|
||||||
|
|---------------------------------------------|-----------------------------------------------------------------------------|
|
||||||
|
| monitoring/command/* | Allow all commands |
|
||||||
|
| monitoring/command/schedule-check | Allow scheduling host and service checks' |
|
||||||
|
| monitoring/command/acknowledge-problem | Allow acknowledging host and service problems |
|
||||||
|
| monitoring/command/remove-acknowledgement | Allow removing problem acknowledgements |
|
||||||
|
| monitoring/command/comment/* | Allow adding and deleting host and service comments |
|
||||||
|
| monitoring/command/comment/add | Allow commenting on hosts and services |
|
||||||
|
| monitoring/command/downtime/delete | Allow deleting host and service downtimes' |
|
||||||
|
| monitoring/command/process-check-result | Allow processing host and service check results |
|
||||||
|
| monitoring/command/feature/instance | Allow processing commands for toggling features on an instance-wide basis |
|
||||||
|
| monitoring/command/feature/object | Allow processing commands for toggling features on host and service objects |
|
||||||
|
| monitoring/command/send-custom-notification | Allow sending custom notifications for hosts and services |
|
||||||
|
|
||||||
|
|
||||||
|
## <a id="monitoring-security-restrictions"></a> Restrictions
|
||||||
|
|
||||||
|
The monitoring module allows filtering objects:
|
||||||
|
|
||||||
|
|
||||||
|
| Keys | Restricts |
|
||||||
|
|----------------------------|-----------------------------------------------|
|
||||||
|
| monitoring/filter/objects | Applies a filter to all hosts and services |
|
||||||
|
|
||||||
|
|
||||||
|
This filter will affect all hosts and services. Furthermore, it will also
|
||||||
|
affect all related objects, like notifications, downtimes or events. If a
|
||||||
|
service is hidden, all notifications, downtimes on that service will be hidden too.
|
||||||
|
|
||||||
|
|
||||||
|
### Filter Column Names
|
||||||
|
|
||||||
|
The following filter column names are available in filter expressions:
|
||||||
|
|
||||||
|
|
||||||
|
| Column |
|
||||||
|
|------------------------------------------------------|
|
||||||
|
| host |
|
||||||
|
| host_alias |
|
||||||
|
| host_display_name |
|
||||||
|
| host_name |
|
||||||
|
| hostgroup |
|
||||||
|
| hostgroup_alias |
|
||||||
|
| hostgroup_name |
|
||||||
|
| service |
|
||||||
|
| service_description |
|
||||||
|
| service_display_name |
|
||||||
|
| service_group |
|
||||||
|
| service_group_alias |
|
||||||
|
| service_group_name |
|
||||||
|
| + all custom variables prefixed with host or service |
|
@ -1,4 +1,4 @@
|
|||||||
Module: doc
|
Module: doc
|
||||||
Version: 2.0.0
|
Version: 2.0.0-rc1
|
||||||
Description: Documentation module
|
Description: Documentation module
|
||||||
Extracts, shows and exports documentation for Icinga Web 2 and its modules.
|
Extracts, shows and exports documentation for Icinga Web 2 and its modules.
|
||||||
|
@ -20,7 +20,7 @@ class ConferenceCommand extends Command
|
|||||||
* Use this command in case you feel that you should be friendly. Should
|
* Use this command in case you feel that you should be friendly. Should
|
||||||
* be executed as follows:
|
* be executed as follows:
|
||||||
*
|
*
|
||||||
* icingacli monitoring conference welcome --watch 1
|
* icingacli monitoring conference welcome --watch=1
|
||||||
*/
|
*/
|
||||||
public function welcomeAction()
|
public function welcomeAction()
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ namespace Icinga\Module\Monitoring\Clicommands;
|
|||||||
|
|
||||||
use Icinga\Module\Monitoring\Backend;
|
use Icinga\Module\Monitoring\Backend;
|
||||||
use Icinga\Module\Monitoring\Cli\CliUtils;
|
use Icinga\Module\Monitoring\Cli\CliUtils;
|
||||||
use Icinga\Util\Format;
|
use Icinga\Date\DateFormatter;
|
||||||
use Icinga\Cli\Command;
|
use Icinga\Cli\Command;
|
||||||
use Icinga\File\Csv;
|
use Icinga\File\Csv;
|
||||||
use Icinga\Module\Monitoring\Plugin\PerfdataSet;
|
use Icinga\Module\Monitoring\Plugin\PerfdataSet;
|
||||||
@ -124,19 +124,19 @@ class ListCommand extends Command
|
|||||||
* --verbose Show detailled output
|
* --verbose Show detailled output
|
||||||
* --showsql Dump generated SQL query (DB backend only)
|
* --showsql Dump generated SQL query (DB backend only)
|
||||||
*
|
*
|
||||||
* --format <csv|json|<custom>>
|
* --format=<csv|json|<custom>>
|
||||||
* Dump columns in the given format. <custom> format allows $column$
|
* Dump columns in the given format. <custom> format allows $column$
|
||||||
* placeholders, e.g. --format '$host$: $service$'
|
* placeholders, e.g. --format='$host$: $service$'
|
||||||
*
|
*
|
||||||
* --<column> [filter]
|
* --<column>[=filter]
|
||||||
* Filter given column by optional filter. Boolean (1/0) columns are
|
* Filter given column by optional filter. Boolean (1/0) columns are
|
||||||
* true if no filter value is given.
|
* true if no filter value is given.
|
||||||
*
|
*
|
||||||
* EXAMPLES
|
* EXAMPLES
|
||||||
*
|
*
|
||||||
* icingacli monitoring list --unhandled
|
* icingacli monitoring list --unhandled
|
||||||
* icingacli monitoring list --host local* --service *disk*
|
* icingacli monitoring list --host=local* --service=*disk*
|
||||||
* icingacli monitoring list --format '$host$: $service$'
|
* icingacli monitoring list --format='$host$: $service$'
|
||||||
*/
|
*/
|
||||||
public function statusAction()
|
public function statusAction()
|
||||||
{
|
{
|
||||||
@ -299,7 +299,7 @@ class ListCommand extends Command
|
|||||||
$leaf,
|
$leaf,
|
||||||
$screen->underline($row->service_description),
|
$screen->underline($row->service_description),
|
||||||
$screen->colorize($utils->objectStateFlags('service', $row) . $perf, 'lightblue'),
|
$screen->colorize($utils->objectStateFlags('service', $row) . $perf, 'lightblue'),
|
||||||
ucfirst(Format::timeSince($row->service_last_state_change))
|
ucfirst(DateFormatter::timeSince($row->service_last_state_change))
|
||||||
);
|
);
|
||||||
if ($this->isVerbose) {
|
if ($this->isVerbose) {
|
||||||
$out .= $emptyLine . preg_replace(
|
$out .= $emptyLine . preg_replace(
|
||||||
|
@ -27,8 +27,8 @@ class NrpeCommand extends Command
|
|||||||
*
|
*
|
||||||
* EXAMPLE
|
* EXAMPLE
|
||||||
*
|
*
|
||||||
* icingacli monitoring nrpe 127.0.0.1 CheckMEM --ssl --MaxWarn 80% \
|
* icingacli monitoring nrpe 127.0.0.1 CheckMEM --ssl --MaxWarn=80% \
|
||||||
* --MaxCrit 90% --type physical
|
* --MaxCrit=90% --type=physical
|
||||||
*/
|
*/
|
||||||
public function checkAction()
|
public function checkAction()
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,54 @@ class Monitoring_HostController extends MonitoredObjectController
|
|||||||
parent::showAction();
|
parent::showAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List a host's services
|
||||||
|
*/
|
||||||
|
public function servicesAction()
|
||||||
|
{
|
||||||
|
$this->setAutorefreshInterval(10);
|
||||||
|
$this->getTabs()->activate('services');
|
||||||
|
$query = $this->backend->select()->from('servicestatus', array(
|
||||||
|
'host_name',
|
||||||
|
'host_display_name',
|
||||||
|
'host_state',
|
||||||
|
'host_state_type',
|
||||||
|
'host_last_state_change',
|
||||||
|
'host_address',
|
||||||
|
'host_handled',
|
||||||
|
'service_description',
|
||||||
|
'service_display_name',
|
||||||
|
'service_state',
|
||||||
|
'service_in_downtime',
|
||||||
|
'service_acknowledged',
|
||||||
|
'service_handled',
|
||||||
|
'service_output',
|
||||||
|
'service_perfdata',
|
||||||
|
'service_attempt',
|
||||||
|
'service_last_state_change',
|
||||||
|
'service_icon_image',
|
||||||
|
'service_icon_image_alt',
|
||||||
|
'service_is_flapping',
|
||||||
|
'service_state_type',
|
||||||
|
'service_handled',
|
||||||
|
'service_severity',
|
||||||
|
'service_last_check',
|
||||||
|
'service_notifications_enabled',
|
||||||
|
'service_action_url',
|
||||||
|
'service_notes_url',
|
||||||
|
'service_last_comment',
|
||||||
|
'service_last_ack',
|
||||||
|
'service_last_downtime',
|
||||||
|
'service_active_checks_enabled',
|
||||||
|
'service_passive_checks_enabled',
|
||||||
|
'current_check_attempt' => 'service_current_check_attempt',
|
||||||
|
'max_check_attempts' => 'service_max_check_attempts'
|
||||||
|
));
|
||||||
|
$this->applyRestriction('monitoring/filter/objects', $query);
|
||||||
|
$this->view->services = $query->where('host_name', $this->object->getName());
|
||||||
|
$this->view->object = $this->object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acknowledge a host problem
|
* Acknowledge a host problem
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
use Icinga\Module\Monitoring\Object\MonitoredObject;
|
|
||||||
use Icinga\Web\Hook;
|
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Web\Widget\Tabs;
|
|
||||||
use Icinga\Web\Widget\Tabextension\OutputFormat;
|
|
||||||
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
|
||||||
use Icinga\Module\Monitoring\Backend;
|
use Icinga\Module\Monitoring\Backend;
|
||||||
use Icinga\Module\Monitoring\Controller;
|
use Icinga\Module\Monitoring\Controller;
|
||||||
|
|
||||||
@ -22,34 +17,6 @@ class Monitoring_ShowController extends Controller
|
|||||||
*/
|
*/
|
||||||
protected $backend;
|
protected $backend;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Hook\GrapherHook
|
|
||||||
*/
|
|
||||||
protected $grapher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the controller
|
|
||||||
*/
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
$this->view->object = MonitoredObject::fromParams($this->params);
|
|
||||||
if ($this->view->object && $this->view->object->fetch() === false) {
|
|
||||||
throw new Zend_Controller_Action_Exception($this->translate('Host or service not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hook::has('ticket')) {
|
|
||||||
$this->view->tickets = Hook::first('ticket');
|
|
||||||
}
|
|
||||||
if (Hook::has('grapher')) {
|
|
||||||
$this->grapher = Hook::first('grapher');
|
|
||||||
if ($this->grapher && ! $this->grapher->hasPreviews()) {
|
|
||||||
$this->grapher = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->createTabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
@ -66,36 +33,16 @@ class Monitoring_ShowController extends Controller
|
|||||||
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/show'));
|
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/show'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
public function historyAction()
|
public function historyAction()
|
||||||
{
|
{
|
||||||
$this->getTabs()->activate('history');
|
if ($this->params->has('service')) {
|
||||||
$this->view->object->fetchEventHistory();
|
$this->redirectNow(Url::fromRequest()->setPath('monitoring/service/history'));
|
||||||
$this->view->history = $this->view->object->eventhistory;
|
|
||||||
$this->handleFormatRequest($this->view->object->eventhistory);
|
|
||||||
$this->fetchHostStats();
|
|
||||||
|
|
||||||
$this->setupLimitControl(50);
|
|
||||||
$this->setupPaginationControl($this->view->history, 50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fetchHostStats()
|
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/history'));
|
||||||
{
|
|
||||||
$query = $this->backend->select()->from('servicestatussummary', array(
|
|
||||||
'services_total',
|
|
||||||
'services_ok',
|
|
||||||
'services_critical',
|
|
||||||
'services_critical_unhandled',
|
|
||||||
'services_critical_handled',
|
|
||||||
'services_warning',
|
|
||||||
'services_warning_unhandled',
|
|
||||||
'services_warning_handled',
|
|
||||||
'services_unknown',
|
|
||||||
'services_unknown_unhandled',
|
|
||||||
'services_unknown_handled',
|
|
||||||
'services_pending',
|
|
||||||
))->where('service_host_name', $this->params->get('host'));
|
|
||||||
$this->applyRestriction('monitoring/filter/objects', $query);
|
|
||||||
$this->view->stats = $query->getQuery()->fetchRow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function contactAction()
|
public function contactAction()
|
||||||
@ -163,78 +110,4 @@ class Monitoring_ShowController extends Controller
|
|||||||
$this->view->contact = $contact;
|
$this->view->contact = $contact;
|
||||||
$this->view->contactName = $contactName;
|
$this->view->contactName = $contactName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creating tabs for this controller
|
|
||||||
* @return Tabs
|
|
||||||
*/
|
|
||||||
protected function createTabs()
|
|
||||||
{
|
|
||||||
if (($object = $this->view->object) === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ($object->getType() === $object::TYPE_HOST) {
|
|
||||||
$isService = false;
|
|
||||||
$params = array(
|
|
||||||
'host' => $object->getName()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$isService = true;
|
|
||||||
$params = array(
|
|
||||||
'host' => $object->getHost()->getName(),
|
|
||||||
'service' => $object->getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$tabs = $this->getTabs();
|
|
||||||
$tabs->add(
|
|
||||||
'host',
|
|
||||||
array(
|
|
||||||
'title' => sprintf(
|
|
||||||
$this->translate('Show detailed information for host %s'),
|
|
||||||
$isService ? $object->getHost()->getName() : $object->getName()
|
|
||||||
),
|
|
||||||
'label' => $this->translate('Host'),
|
|
||||||
'icon' => 'host',
|
|
||||||
'url' => 'monitoring/show/host',
|
|
||||||
'urlParams' => $params,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if ($isService) {
|
|
||||||
$tabs->add(
|
|
||||||
'service',
|
|
||||||
array(
|
|
||||||
'title' => sprintf(
|
|
||||||
$this->translate('Show detailed information for service %s on host %s'),
|
|
||||||
$object->getName(),
|
|
||||||
$object->getHost()->getName()
|
|
||||||
),
|
|
||||||
'label' => $this->translate('Service'),
|
|
||||||
'icon' => 'service',
|
|
||||||
'url' => 'monitoring/show/service',
|
|
||||||
'urlParams' => $params,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($this->backend->hasQuery('eventhistory')) {
|
|
||||||
$tabs->add(
|
|
||||||
'history',
|
|
||||||
array(
|
|
||||||
'title' => $isService
|
|
||||||
? sprintf(
|
|
||||||
$this->translate('Show all event records of service %s on host %s'),
|
|
||||||
$object->getName(),
|
|
||||||
$object->getHost()->getName()
|
|
||||||
)
|
|
||||||
: sprintf($this->translate('Show all event records of host %s'), $object->getName())
|
|
||||||
,
|
|
||||||
'label' => $this->translate('History'),
|
|
||||||
'icon' => 'rewind',
|
|
||||||
'url' => 'monitoring/show/history',
|
|
||||||
'urlParams' => $params,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$tabs->extend(new OutputFormat())
|
|
||||||
->extend(new DashboardAction());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,19 @@
|
|||||||
|
|
||||||
namespace Icinga\Module\Monitoring\Forms\Config\Instance;
|
namespace Icinga\Module\Monitoring\Forms\Config\Instance;
|
||||||
|
|
||||||
|
use Icinga\Data\ResourceFactory;
|
||||||
|
use Icinga\Exception\ConfigurationError;
|
||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
|
|
||||||
class RemoteInstanceForm extends Form
|
class RemoteInstanceForm extends Form
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The available monitoring instance resources split by type
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $resources;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (non-PHPDoc)
|
* (non-PHPDoc)
|
||||||
* @see Form::init() For the method documentation.
|
* @see Form::init() For the method documentation.
|
||||||
@ -16,12 +25,89 @@ class RemoteInstanceForm extends Form
|
|||||||
$this->setName('form_config_monitoring_instance_remote');
|
$this->setName('form_config_monitoring_instance_remote');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all available ssh identity resources
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Icinga\Exception\ConfigurationError
|
||||||
|
*/
|
||||||
|
public function loadResources()
|
||||||
|
{
|
||||||
|
$resourceConfig = ResourceFactory::getResourceConfigs();
|
||||||
|
|
||||||
|
$resources = array();
|
||||||
|
foreach ($resourceConfig as $name => $resource) {
|
||||||
|
if ($resource->type === 'ssh') {
|
||||||
|
$resources['ssh'][$name] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($resources)) {
|
||||||
|
throw new ConfigurationError($this->translate('Could not find any valid monitoring instance resources'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resources = $resources;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (non-PHPDoc)
|
* (non-PHPDoc)
|
||||||
* @see Form::createElements() For the method documentation.
|
* @see Form::createElements() For the method documentation.
|
||||||
*/
|
*/
|
||||||
public function createElements(array $formData = array())
|
public function createElements(array $formData = array())
|
||||||
{
|
{
|
||||||
|
$useResource = isset($formData['use_resource']) ? $formData['use_resource'] : $this->getValue('use_resource');
|
||||||
|
|
||||||
|
$this->addElement(
|
||||||
|
'checkbox',
|
||||||
|
'use_resource',
|
||||||
|
array(
|
||||||
|
'label' => $this->translate('Use SSH Identity'),
|
||||||
|
'description' => $this->translate('Make use of the ssh identity resource'),
|
||||||
|
'autosubmit' => true,
|
||||||
|
'ignore' => true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($useResource) {
|
||||||
|
|
||||||
|
$this->loadResources();
|
||||||
|
|
||||||
|
$decorators = static::$defaultElementDecorators;
|
||||||
|
array_pop($decorators); // Removes the HtmlTag decorator
|
||||||
|
|
||||||
|
$this->addElement(
|
||||||
|
'select',
|
||||||
|
'resource',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'label' => $this->translate('SSH Identity'),
|
||||||
|
'description' => $this->translate('The resource to use'),
|
||||||
|
'decorators' => $decorators,
|
||||||
|
'multiOptions' => $this->resources['ssh'],
|
||||||
|
'value' => current($this->resources['ssh']),
|
||||||
|
'autosubmit' => false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$resourceName = isset($formData['resource']) ? $formData['resource'] : $this->getValue('resource');
|
||||||
|
$this->addElement(
|
||||||
|
'note',
|
||||||
|
'resource_note',
|
||||||
|
array(
|
||||||
|
'escape' => false,
|
||||||
|
'decorators' => $decorators,
|
||||||
|
'value' => sprintf(
|
||||||
|
'<a href="%1$s" data-base-target="_next" title="%2$s" aria-label="%2$s">%3$s</a>',
|
||||||
|
$this->getView()->url('config/editresource', array('resource' => $resourceName)),
|
||||||
|
sprintf($this->translate('Show the configuration of the %s resource'), $resourceName),
|
||||||
|
$this->translate('Show resource configuration')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->addElements(array(
|
$this->addElements(array(
|
||||||
array(
|
array(
|
||||||
'text',
|
'text',
|
||||||
@ -43,8 +129,11 @@ class RemoteInstanceForm extends Form
|
|||||||
'description' => $this->translate('SSH port to connect to on the remote Icinga instance'),
|
'description' => $this->translate('SSH port to connect to on the remote Icinga instance'),
|
||||||
'value' => 22
|
'value' => 22
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
array(
|
));
|
||||||
|
|
||||||
|
if (! $useResource) {
|
||||||
|
$this->addElement(
|
||||||
'text',
|
'text',
|
||||||
'user',
|
'user',
|
||||||
array(
|
array(
|
||||||
@ -55,8 +144,10 @@ class RemoteInstanceForm extends Form
|
|||||||
. ' possible for this user'
|
. ' possible for this user'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
);
|
||||||
array(
|
}
|
||||||
|
|
||||||
|
$this->addElement(
|
||||||
'text',
|
'text',
|
||||||
'path',
|
'path',
|
||||||
array(
|
array(
|
||||||
@ -65,8 +156,8 @@ class RemoteInstanceForm extends Form
|
|||||||
'value' => '/var/run/icinga2/cmd/icinga2.cmd',
|
'value' => '/var/run/icinga2/cmd/icinga2.cmd',
|
||||||
'description' => $this->translate('Path to the Icinga command file on the remote Icinga instance')
|
'description' => $this->translate('Path to the Icinga command file on the remote Icinga instance')
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
));
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,11 @@ class InstanceConfigForm extends ConfigForm
|
|||||||
|
|
||||||
$instanceConfig = $this->config->getSection($instanceName)->toArray();
|
$instanceConfig = $this->config->getSection($instanceName)->toArray();
|
||||||
$instanceConfig['name'] = $instanceName;
|
$instanceConfig['name'] = $instanceName;
|
||||||
|
|
||||||
|
if (isset($instanceConfig['resource'])) {
|
||||||
|
$instanceConfig['use_resource'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
$this->populate($instanceConfig);
|
$this->populate($instanceConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,12 @@ use Icinga\Module\Monitoring\Object\Host;
|
|||||||
use Icinga\Module\Monitoring\Object\Service;
|
use Icinga\Module\Monitoring\Object\Service;
|
||||||
|
|
||||||
$self = $this;
|
$self = $this;
|
||||||
$hostContext = $object->getType() === 'host';
|
|
||||||
|
|
||||||
if (! $this->compact): ?>
|
if (! $this->compact): ?>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<?= $this->tabs; ?>
|
<?= $this->tabs; ?>
|
||||||
<?php if ($hostContext): ?>
|
|
||||||
<?= $this->render('partials/host/object-header.phtml'); ?>
|
<?= $this->render('partials/host/object-header.phtml'); ?>
|
||||||
<?php else: ?>
|
<h1><?= $this->translate('This Host\'s Event History'); ?></h1>
|
||||||
<?= $this->render('partials/service/object-header.phtml'); ?>
|
|
||||||
<?php endif ?>
|
|
||||||
<h1><?= $this->translate('This Object\'s Event History'); ?></h1>
|
|
||||||
<?= $this->sortBox; ?>
|
<?= $this->sortBox; ?>
|
||||||
<?= $this->limiter; ?>
|
<?= $this->limiter; ?>
|
||||||
<?= $this->paginator; ?>
|
<?= $this->paginator; ?>
|
||||||
@ -24,7 +19,7 @@ if (! $this->compact): ?>
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
if (count($history) === 0) {
|
if (count($history) === 0) {
|
||||||
echo $this->translate('No history available for this object') . '</div>';
|
echo $this->translate('No history events found matching the filter') . '</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@ -133,7 +128,7 @@ $output = $this->tickets ? preg_replace_callback(
|
|||||||
<?php if ($isService): ?>
|
<?php if ($isService): ?>
|
||||||
<?= sprintf(
|
<?= sprintf(
|
||||||
$this->translate('%s on %s', 'Service running on host'),
|
$this->translate('%s on %s', 'Service running on host'),
|
||||||
$hostContext ? $this->qlink(
|
$this->qlink(
|
||||||
$event->service_display_name,
|
$event->service_display_name,
|
||||||
'monitoring/show/service',
|
'monitoring/show/service',
|
||||||
array(
|
array(
|
||||||
@ -145,7 +140,7 @@ $output = $this->tickets ? preg_replace_callback(
|
|||||||
$event->service_display_name,
|
$event->service_display_name,
|
||||||
$event->host_display_name
|
$event->host_display_name
|
||||||
))
|
))
|
||||||
) : $this->escape($event->service_display_name),
|
),
|
||||||
$event->host_display_name
|
$event->host_display_name
|
||||||
) ?>
|
) ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
@ -0,0 +1,17 @@
|
|||||||
|
<div class="controls">
|
||||||
|
<?php if (! $this->compact): ?>
|
||||||
|
<?= $this->tabs; ?>
|
||||||
|
<?php endif ?>
|
||||||
|
<?= $this->render('partials/host/object-header.phtml') ?>
|
||||||
|
<?= $this->render('partials/host/servicesummary.phtml') ?>
|
||||||
|
</div>
|
||||||
|
<?= $this->partial(
|
||||||
|
'list/services.phtml',
|
||||||
|
'monitoring',
|
||||||
|
array(
|
||||||
|
'compact' => true,
|
||||||
|
'showHost' => false,
|
||||||
|
'services' => $services,
|
||||||
|
'addColumns' => array()
|
||||||
|
)
|
||||||
|
); ?>
|
@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
use Icinga\Module\Monitoring\Object\Service;
|
||||||
|
|
||||||
|
$self = $this;
|
||||||
|
|
||||||
|
if (! $this->compact): ?>
|
||||||
|
<div class="controls">
|
||||||
|
<?= $this->tabs; ?>
|
||||||
|
<?= $this->render('partials/service/object-header.phtml'); ?>
|
||||||
|
<h1><?= $this->translate('This Service\'s Event History'); ?></h1>
|
||||||
|
<?= $this->sortBox; ?>
|
||||||
|
<?= $this->limiter; ?>
|
||||||
|
<?= $this->paginator; ?>
|
||||||
|
<?= $this->filterEditor; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
|
<div class="content">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if (count($history) === 0) {
|
||||||
|
echo $this->translate('No history events found matching the filter') . '</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
function contactsLink($match, $view) {
|
||||||
|
$links = array();
|
||||||
|
foreach (preg_split('/,\s/', $match[1]) as $contact) {
|
||||||
|
$links[] = $view->qlink(
|
||||||
|
$contact,
|
||||||
|
'monitoring/show/contact',
|
||||||
|
array('contact_name' => $contact),
|
||||||
|
array('title' => sprintf($view->translate('Show detailed information about %s'), $contact))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return '[' . implode(', ', $links) . ']';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<table data-base-target="_next" class="action objecthistory">
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($history as $event): ?>
|
||||||
|
<?php
|
||||||
|
$stateClass = 'invalid';
|
||||||
|
switch ($event->type) {
|
||||||
|
case 'notify':
|
||||||
|
$icon = 'notification';
|
||||||
|
$title = $this->translate('Notification');
|
||||||
|
$stateClass = Service::getStateText($event->state);
|
||||||
|
|
||||||
|
$msg = preg_replace_callback(
|
||||||
|
'/^\[([^\]]+)\]/',
|
||||||
|
function($match) use ($self) { return contactsLink($match, $self); },
|
||||||
|
$this->escape($event->output)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'comment':
|
||||||
|
$icon = 'comment';
|
||||||
|
$title = $this->translate('Comment');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'comment_deleted':
|
||||||
|
$icon = 'remove';
|
||||||
|
$title = $this->translate('Comment deleted');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'ack':
|
||||||
|
$icon = 'acknowledgement';
|
||||||
|
$title = $this->translate('Acknowledge');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'ack_deleted':
|
||||||
|
$icon = 'remove';
|
||||||
|
$title = $this->translate('Ack removed');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'dt_comment':
|
||||||
|
$icon = 'in_downtime';
|
||||||
|
$title = $this->translate('In Downtime');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'dt_comment_deleted':
|
||||||
|
$icon = 'remove';
|
||||||
|
$title = $this->translate('Downtime removed');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'flapping':
|
||||||
|
$icon = 'flapping';
|
||||||
|
$title = $this->translate('Flapping');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'flapping_deleted':
|
||||||
|
$icon = 'remove';
|
||||||
|
$title = $this->translate('Flapping stopped');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'hard_state':
|
||||||
|
$msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output);
|
||||||
|
$stateClass = Service::getStateText($event->state);
|
||||||
|
$icon = 'attention-alt';
|
||||||
|
$title = Service::getStateText($event->state);
|
||||||
|
break;
|
||||||
|
case 'soft_state':
|
||||||
|
$icon = 'spinner';
|
||||||
|
$msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output);
|
||||||
|
$stateClass = Service::getStateText($event->state);
|
||||||
|
$title = Service::getStateText($event->state);
|
||||||
|
break;
|
||||||
|
case 'dt_start':
|
||||||
|
$icon = 'downtime_start';
|
||||||
|
$title = $this->translate('Downtime Start');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
case 'dt_end':
|
||||||
|
$icon = 'downtime_end';
|
||||||
|
$title = $this->translate('Downtime End');
|
||||||
|
$msg = $this->escape($event->output);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tr class="state <?= $stateClass; ?>">
|
||||||
|
<td class="state">
|
||||||
|
<strong><?= $this->escape($title); ?></strong>
|
||||||
|
<br>
|
||||||
|
<?= date('d.m. H:i', $event->timestamp); ?>
|
||||||
|
</td>
|
||||||
|
<td><?php
|
||||||
|
|
||||||
|
$output = $this->tickets ? preg_replace_callback(
|
||||||
|
$this->tickets->getPattern(),
|
||||||
|
array($this->tickets, 'createLink'),
|
||||||
|
$msg
|
||||||
|
) : $msg;
|
||||||
|
|
||||||
|
?>
|
||||||
|
<?= sprintf(
|
||||||
|
$this->translate('%s on %s', 'Service running on host'),
|
||||||
|
$this->escape($event->service_display_name),
|
||||||
|
$event->host_display_name
|
||||||
|
) ?>
|
||||||
|
<br>
|
||||||
|
<div>
|
||||||
|
<?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $msg; ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
@ -9,7 +9,7 @@
|
|||||||
echo $this->qlink(
|
echo $this->qlink(
|
||||||
$this->translate('Send notification'),
|
$this->translate('Send notification'),
|
||||||
'monitoring/host/send-custom-notification',
|
'monitoring/host/send-custom-notification',
|
||||||
array('host_name' => $object->getName()),
|
array('host' => $object->getName()),
|
||||||
array(
|
array(
|
||||||
'icon' => 'bell',
|
'icon' => 'bell',
|
||||||
'data-base-target' => '_self',
|
'data-base-target' => '_self',
|
||||||
@ -23,7 +23,7 @@
|
|||||||
echo $this->qlink(
|
echo $this->qlink(
|
||||||
$this->translate('Send notification'),
|
$this->translate('Send notification'),
|
||||||
'monitoring/service/send-custom-notification',
|
'monitoring/service/send-custom-notification',
|
||||||
array('host_name' => $object->getHost()->getName(), 'service_description' => $object->getName()),
|
array('host' => $object->getHost()->getName(), 'service' => $object->getName()),
|
||||||
array(
|
array(
|
||||||
'icon' => 'bell',
|
'icon' => 'bell',
|
||||||
'data-base-target' => '_self',
|
'data-base-target' => '_self',
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
## Abstract
|
## Abstract
|
||||||
|
|
||||||
The instance.ini defines how icingaweb accesses the command pipe of your icinga process in order to submit external
|
The instance.ini defines how icingaweb accesses the command pipe of your icinga process in order to submit external
|
||||||
commands. When you are at the root of your icingaweb installation you can find it under ./config/modules/monitoring/instances.ini.
|
commands. Depending on the config path (default: /etc/icingaweb2) of your icingaweb installation you can find it
|
||||||
|
under ./modules/monitoring/instances.ini.
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
@ -33,5 +34,22 @@ setup key authentication at the endpoint and allow your icingweb's user to acces
|
|||||||
port=22 ; the port to use (22 if none is given)
|
port=22 ; the port to use (22 if none is given)
|
||||||
user=jdoe ; the user to authenticate with
|
user=jdoe ; the user to authenticate with
|
||||||
|
|
||||||
|
You can also make use of the ssh resource for accessing an icinga pipe with key-based authentication, which will give
|
||||||
|
you the possibility to define the location of the private key for a specific user, let's have a look:
|
||||||
|
|
||||||
|
[icinga]
|
||||||
|
path=/usr/local/icinga/var/rw/icinga.cmd ; the path on the remote machine where the icinga.cmd can be found
|
||||||
|
host=my.remote.machine.com ; the hostname or address of the remote machine
|
||||||
|
port=22 ; the port to use (22 if none is given)
|
||||||
|
resource=ssh ; the ssh resource which contains the username and the location of the private key
|
||||||
|
|
||||||
|
And the associated ssh resource:
|
||||||
|
|
||||||
|
[ssh]
|
||||||
|
type = "ssh"
|
||||||
|
user = "ssh-user"
|
||||||
|
private_key = "/etc/icingaweb2/ssh/ssh-user"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
namespace Icinga\Module\Monitoring\Command\Transport;
|
namespace Icinga\Module\Monitoring\Command\Transport;
|
||||||
|
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
|
use Icinga\Data\ResourceFactory;
|
||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
use Icinga\Module\Monitoring\Command\Exception\TransportException;
|
use Icinga\Module\Monitoring\Command\Exception\TransportException;
|
||||||
use Icinga\Module\Monitoring\Command\IcingaCommand;
|
use Icinga\Module\Monitoring\Command\IcingaCommand;
|
||||||
@ -44,6 +45,13 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to the private key file for the key-based authentication
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $privateKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to the Icinga command file on the remote host
|
* Path to the Icinga command file on the remote host
|
||||||
*
|
*
|
||||||
@ -137,6 +145,55 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path to the private key file
|
||||||
|
*
|
||||||
|
* @param string $privateKey
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setPrivateKey($privateKey)
|
||||||
|
{
|
||||||
|
$this->privateKey = (string) $privateKey;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the private key
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPrivateKey()
|
||||||
|
{
|
||||||
|
return $this->privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a given resource to set the user and the key
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
*
|
||||||
|
* @throws ConfigurationError
|
||||||
|
*/
|
||||||
|
public function setResource($resource = null)
|
||||||
|
{
|
||||||
|
$config = ResourceFactory::getResourceConfig($resource);
|
||||||
|
|
||||||
|
if (! isset($config->user)) {
|
||||||
|
throw new ConfigurationError(
|
||||||
|
t("Can't send external Icinga Command. Remote user is missing")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (! isset($config->private_key)) {
|
||||||
|
throw new ConfigurationError(
|
||||||
|
t("Can't send external Icinga Command. The private key for the remote user is missing")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setUser($config->user);
|
||||||
|
$this->setPrivateKey($config->private_key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the path to the Icinga command file on the remote host
|
* Set the path to the Icinga command file on the remote host
|
||||||
*
|
*
|
||||||
@ -192,6 +249,9 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||||||
if (isset($this->user)) {
|
if (isset($this->user)) {
|
||||||
$ssh .= sprintf(' -l %s', escapeshellarg($this->user));
|
$ssh .= sprintf(' -l %s', escapeshellarg($this->user));
|
||||||
}
|
}
|
||||||
|
if (isset($this->privateKey)) {
|
||||||
|
$ssh .= sprintf(' -o StrictHostKeyChecking=no -i %s', escapeshellarg($this->privateKey));
|
||||||
|
}
|
||||||
$ssh .= sprintf(
|
$ssh .= sprintf(
|
||||||
' %s "echo %s > %s" 2>&1', // Redirect stderr to stdout
|
' %s "echo %s > %s" 2>&1', // Redirect stderr to stdout
|
||||||
escapeshellarg($this->host),
|
escapeshellarg($this->host),
|
||||||
|
@ -93,6 +93,19 @@ abstract class MonitoredObjectController extends Controller
|
|||||||
$this->view->object = $this->object;
|
$this->view->object = $this->object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the history for a host or service
|
||||||
|
*/
|
||||||
|
public function historyAction()
|
||||||
|
{
|
||||||
|
$this->getTabs()->activate('history');
|
||||||
|
$this->view->history = $this->object->fetchEventHistory()->eventhistory;
|
||||||
|
|
||||||
|
$this->setupLimitControl(50);
|
||||||
|
$this->setupPaginationControl($this->view->history, 50);
|
||||||
|
$this->view->object = $this->object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a command form
|
* Handle a command form
|
||||||
*
|
*
|
||||||
@ -145,6 +158,9 @@ abstract class MonitoredObjectController extends Controller
|
|||||||
$params = array(
|
$params = array(
|
||||||
'host' => $object->getName()
|
'host' => $object->getName()
|
||||||
);
|
);
|
||||||
|
if ($this->params->has('service')) {
|
||||||
|
$params['service'] = $this->params->get('service');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$isService = true;
|
$isService = true;
|
||||||
$params = array(
|
$params = array(
|
||||||
@ -165,14 +181,14 @@ abstract class MonitoredObjectController extends Controller
|
|||||||
'urlParams' => $params
|
'urlParams' => $params
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if ($isService) {
|
if ($isService || $this->params->has('service')) {
|
||||||
$tabs->add(
|
$tabs->add(
|
||||||
'service',
|
'service',
|
||||||
array(
|
array(
|
||||||
'title' => sprintf(
|
'title' => sprintf(
|
||||||
$this->translate('Show detailed information for service %s on host %s'),
|
$this->translate('Show detailed information for service %s on host %s'),
|
||||||
$object->getName(),
|
$isService ? $object->getName() : $this->params->get('service'),
|
||||||
$object->getHost()->getName()
|
$isService ? $object->getHost()->getName() : $object->getName()
|
||||||
),
|
),
|
||||||
'label' => $this->translate('Service'),
|
'label' => $this->translate('Service'),
|
||||||
'icon' => 'service',
|
'icon' => 'service',
|
||||||
@ -181,6 +197,19 @@ abstract class MonitoredObjectController extends Controller
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$tabs->add(
|
||||||
|
'services',
|
||||||
|
array(
|
||||||
|
'title' => sprintf(
|
||||||
|
$this->translate('List all services on host %s'),
|
||||||
|
$isService ? $object->getHost()->getName() : $object->getName()
|
||||||
|
),
|
||||||
|
'label' => $this->translate('Services'),
|
||||||
|
'icon' => 'services',
|
||||||
|
'url' => 'monitoring/host/services',
|
||||||
|
'urlParams' => $params
|
||||||
|
)
|
||||||
|
);
|
||||||
if ($this->backend->hasQuery('eventhistory')) {
|
if ($this->backend->hasQuery('eventhistory')) {
|
||||||
$tabs->add(
|
$tabs->add(
|
||||||
'history',
|
'history',
|
||||||
@ -195,7 +224,7 @@ abstract class MonitoredObjectController extends Controller
|
|||||||
,
|
,
|
||||||
'label' => $this->translate('History'),
|
'label' => $this->translate('History'),
|
||||||
'icon' => 'rewind',
|
'icon' => 'rewind',
|
||||||
'url' => 'monitoring/show/history',
|
'url' => $isService ? 'monitoring/service/history' : 'monitoring/host/history',
|
||||||
'urlParams' => $params
|
'urlParams' => $params
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Module: monitoring
|
Module: monitoring
|
||||||
Version: 2.0.0~alpha4
|
Version: 2.0.0-rc1
|
||||||
Description: Icinga monitoring module
|
Description: Icinga monitoring module
|
||||||
This is the core module for most Icingaweb users. It provides an
|
This is the core module for most Icingaweb users. It provides an
|
||||||
abstraction layer for various Icinga data backends.
|
abstraction layer for various Icinga data backends.
|
||||||
|
@ -29,7 +29,7 @@ class ConfigCommand extends Command
|
|||||||
*
|
*
|
||||||
* icingacli setup config directory
|
* icingacli setup config directory
|
||||||
*
|
*
|
||||||
* icingacli setup config directory --mode 2775 --config /opt/icingaweb2/etc
|
* icingacli setup config directory --mode=2775 --config=/opt/icingaweb2/etc
|
||||||
*/
|
*/
|
||||||
public function directoryAction()
|
public function directoryAction()
|
||||||
{
|
{
|
||||||
@ -96,7 +96,7 @@ class ConfigCommand extends Command
|
|||||||
*
|
*
|
||||||
* --path=<urlpath> The URL path to Icinga Web 2 [/icingaweb2]
|
* --path=<urlpath> The URL path to Icinga Web 2 [/icingaweb2]
|
||||||
*
|
*
|
||||||
* --root/--document-root=<directory> The directory from which the webserver will serve files [/path/to/icingaweb2/public]
|
* --root|--document-root=<directory> The directory from which the webserver will serve files [/path/to/icingaweb2/public]
|
||||||
*
|
*
|
||||||
* --config=<directory> Path to Icinga Web 2's configuration files [/etc/icingaweb2]
|
* --config=<directory> Path to Icinga Web 2's configuration files [/etc/icingaweb2]
|
||||||
*
|
*
|
||||||
@ -106,9 +106,9 @@ class ConfigCommand extends Command
|
|||||||
*
|
*
|
||||||
* icingacli setup config webserver apache
|
* icingacli setup config webserver apache
|
||||||
*
|
*
|
||||||
* icingacli setup config webserver apache --path /icingaweb2 --document-root /usr/share/icingaweb2/public --config=/etc/icingaweb2
|
* icingacli setup config webserver apache --path=/icingaweb2 --document-root=/usr/share/icingaweb2/public --config=/etc/icingaweb2
|
||||||
*
|
*
|
||||||
* icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb2.conf
|
* icingacli setup config webserver apache --file=/etc/apache2/conf.d/icingaweb2.conf
|
||||||
*
|
*
|
||||||
* icingacli setup config webserver nginx
|
* icingacli setup config webserver nginx
|
||||||
*/
|
*/
|
||||||
|
6
modules/setup/module.info
Normal file
6
modules/setup/module.info
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Module: setup
|
||||||
|
Version: 2.0.0-rc1
|
||||||
|
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),
|
||||||
|
the authentication method, where to store the user preferences and much more.
|
@ -41,7 +41,7 @@ class PhpCommand extends Command
|
|||||||
*
|
*
|
||||||
* icingacli test php unit --verbose
|
* icingacli test php unit --verbose
|
||||||
* icingacli test php unit --build
|
* icingacli test php unit --build
|
||||||
* icingacli test php unit --include *SpecialTest
|
* icingacli test php unit --include=*SpecialTest
|
||||||
*/
|
*/
|
||||||
public function unitAction()
|
public function unitAction()
|
||||||
{
|
{
|
||||||
@ -109,8 +109,8 @@ class PhpCommand extends Command
|
|||||||
*
|
*
|
||||||
* icingacli test php style --verbose
|
* icingacli test php style --verbose
|
||||||
* icingacli test php style --build
|
* icingacli test php style --build
|
||||||
* icingacli test php style --include path/to/your/file
|
* icingacli test php style --include=path/to/your/file
|
||||||
* icingacli test php style --exclude *someFile* --exclude someOtherFile*
|
* icingacli test php style --exclude=*someFile* --exclude=someOtherFile*
|
||||||
*/
|
*/
|
||||||
public function styleAction()
|
public function styleAction()
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Module: test
|
Module: test
|
||||||
Version: 2.0.0~alpha4
|
Version: 2.0.0-rc1
|
||||||
Description: Translation module
|
Description: Translation module
|
||||||
This module allows developers to run (unit) tests against Icinga Web 2 and
|
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.
|
any of its modules. Usually you do not need to enable this.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Module: translation
|
Module: translation
|
||||||
Version: 2.0.0~alpha4
|
Version: 2.0.0-rc1
|
||||||
Description: Translation module
|
Description: Translation module
|
||||||
This module allows developers and translators to translate Icinga Web 2 and
|
This module allows developers and translators to translate Icinga Web 2 and
|
||||||
its modules for multiple languages. You do not need this module to run an
|
its modules for multiple languages. You do not need this module to run an
|
||||||
internationalized web frontend. This is only for people who want to contribute
|
internationalized web frontend. This is only for people who want to contribute
|
||||||
translations or translate just their own moduls.
|
translations or translate just their own modules.
|
||||||
|
@ -210,6 +210,13 @@ textarea {
|
|||||||
height: 4em;
|
height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea.resource {
|
||||||
|
&.ssh-identity {
|
||||||
|
width: 50%;
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
form .description {
|
form .description {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
margin: 0.3em 0 0 0.6em;
|
margin: 0.3em 0 0 0.6em;
|
||||||
|
@ -236,9 +236,6 @@ div.content.users {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.controls div.user-header {
|
div.controls div.user-header {
|
||||||
border-bottom: 2px solid @colorPetrol;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
|
|
||||||
.user-name {
|
.user-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 0 0.3em;
|
margin: 0 0 0.3em;
|
||||||
@ -302,9 +299,6 @@ div.content.groups {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.controls div.group-header {
|
div.controls div.group-header {
|
||||||
border-bottom: 2px solid @colorPetrol;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
|
|
||||||
.group-name {
|
.group-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 0 0.3em;
|
margin: 0 0 0.3em;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user