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>
|
||||
Matthias Jentsch <matthias.jentsch@netways.de>
|
||||
Michael Friedrich <michael.friedrich@netways.de>
|
||||
Paul Richards <paul@minimoo.org>
|
||||
Rene Moser <rene.moser@swisstxt.ch>
|
||||
Susanne Vestner-Ludwig <susanne.vestner-ludwig@inserteffect.com>
|
||||
Sylph Lin <sylph.lin@gmail.com>
|
||||
|
|
|
@ -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\LdapResourceForm;
|
||||
use Icinga\Forms\Config\Resource\LivestatusResourceForm;
|
||||
use Icinga\Forms\Config\Resource\SshResourceForm;
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
|
||||
|
@ -41,6 +42,8 @@ class ResourceConfigForm extends ConfigForm
|
|||
return new LivestatusResourceForm();
|
||||
} elseif ($type === 'file') {
|
||||
return new FileResourceForm();
|
||||
} elseif ($type === 'ssh') {
|
||||
return new SshResourceForm();
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type));
|
||||
}
|
||||
|
@ -55,7 +58,7 @@ class ResourceConfigForm extends ConfigForm
|
|||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -116,6 +119,11 @@ class ResourceConfigForm extends ConfigForm
|
|||
}
|
||||
|
||||
$resourceConfig = $this->config->getSection($name);
|
||||
$resourceForm = $this->getResourceForm($resourceConfig->type);
|
||||
if (method_exists($resourceForm, 'beforeRemove')) {
|
||||
$resourceForm::beforeRemove($resourceConfig);
|
||||
}
|
||||
|
||||
$this->config->removeSection($name);
|
||||
return $resourceConfig;
|
||||
}
|
||||
|
@ -130,8 +138,9 @@ class ResourceConfigForm extends ConfigForm
|
|||
*/
|
||||
public function onSuccess()
|
||||
{
|
||||
$resourceForm = $this->getResourceForm($this->getElement('type')->getValue());
|
||||
|
||||
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
|
||||
$resourceForm = $this->getResourceForm($this->getElement('type')->getValue());
|
||||
if (method_exists($resourceForm, 'isValidResource') && false === $resourceForm::isValidResource($this)) {
|
||||
$this->addElement($this->getForceCreationCheckbox());
|
||||
return false;
|
||||
|
@ -141,6 +150,11 @@ class ResourceConfigForm extends ConfigForm
|
|||
$resource = $this->request->getQuery('resource');
|
||||
try {
|
||||
if ($resource === null) { // create new resource
|
||||
if (method_exists($resourceForm, 'beforeAdd')) {
|
||||
if (! $resourceForm::beforeAdd($this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->add($this->getValues());
|
||||
$message = $this->translate('Resource "%s" has been successfully created');
|
||||
} else { // edit existing resource
|
||||
|
@ -212,6 +226,7 @@ class ResourceConfigForm extends ConfigForm
|
|||
$resourceTypes = array(
|
||||
'file' => $this->translate('File'),
|
||||
'livestatus' => 'Livestatus',
|
||||
'ssh' => $this->translate('SSH Identity'),
|
||||
);
|
||||
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
|
||||
$resourceTypes['ldap'] = 'LDAP';
|
||||
|
|
|
@ -31,15 +31,16 @@ 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-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>
|
||||
<h3><?= $this->translate('Members'); ?></h3>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->sortBox; ?>
|
||||
<?php endif ?>
|
||||
<?= $this->limiter; ?>
|
||||
<?= $this->paginator; ?>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->filterEditor; ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->sortBox; ?>
|
||||
<?php endif ?>
|
||||
<?= $this->limiter; ?>
|
||||
<?= $this->paginator; ?>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->filterEditor; ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="content members" data-base-target="_next">
|
||||
<?php if (count($members) > 0): ?>
|
||||
|
|
|
@ -31,15 +31,16 @@ 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-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>
|
||||
<h3><?= $this->translate('Group Memberships'); ?></h3>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->sortBox; ?>
|
||||
<?php endif ?>
|
||||
<?= $this->limiter; ?>
|
||||
<?= $this->paginator; ?>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->filterEditor; ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->sortBox; ?>
|
||||
<?php endif ?>
|
||||
<?= $this->limiter; ?>
|
||||
<?= $this->paginator; ?>
|
||||
<?php if (! $this->compact): ?>
|
||||
<?= $this->filterEditor; ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="content memberships" data-base-target="_next">
|
||||
<?php if (count($memberships) > 0): ?>
|
||||
|
|
|
@ -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
|
||||
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.
|
||||
|
||||
### <a id="resources-configuration-database"></a> Database
|
||||
|
@ -64,6 +64,26 @@ bind_dn = "cn=admin,ou=people,dc=icinga,dc=org"
|
|||
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 Livestatus resource represents the location of a Livestatus socket which is used for fetching monitoring data.
|
||||
|
|
|
@ -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
|
||||
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}
|
||||
%else
|
||||
usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser}
|
||||
|
|
|
@ -134,18 +134,20 @@ abstract class ApplicationBootstrap
|
|||
$this->vendorDir = $baseDir . '/library/vendor';
|
||||
$this->libDir = realpath(__DIR__ . '/../..');
|
||||
|
||||
$this->setupAutoloader();
|
||||
|
||||
if ($configDir === null) {
|
||||
if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
|
||||
$configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
|
||||
} else {
|
||||
$configDir = '/etc/icingaweb2';
|
||||
$configDir = Platform::isWindows()
|
||||
? $baseDir . '/config'
|
||||
: '/etc/icingaweb2';
|
||||
}
|
||||
}
|
||||
$canonical = realpath($configDir);
|
||||
$this->configDir = $canonical ? $canonical : $configDir;
|
||||
|
||||
$this->setupAutoloader();
|
||||
|
||||
set_include_path(
|
||||
implode(
|
||||
PATH_SEPARATOR,
|
||||
|
|
|
@ -31,7 +31,7 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|||
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// Fix aliases
|
||||
$remove = dirname($_SERVER['PHP_SELF']);
|
||||
$remove = str_replace('\\', '/', dirname($_SERVER['PHP_SELF']));
|
||||
if (substr($ruri, 0, strlen($remove)) !== $remove) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,12 @@ class Params
|
|||
$noOptionFlag = true;
|
||||
} elseif (!$noOptionFlag && substr($argv[$i], 0, 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;
|
||||
} elseif (array_key_exists($key, $this->params)) {
|
||||
if (!is_array($this->params[$key])) {
|
||||
|
|
|
@ -63,7 +63,7 @@ class File extends SplFileObject
|
|||
throw new NotWritableError(sprintf('Path "%s" is not writable', $dirPath));
|
||||
}
|
||||
|
||||
$file = new static($path, 'x');
|
||||
$file = new static($path, 'x+');
|
||||
|
||||
if (! @chmod($path, $accessMode)) {
|
||||
$error = error_get_last();
|
||||
|
|
|
@ -100,7 +100,11 @@ class Translator
|
|||
{
|
||||
$contextString = "{$context}\004{$text}";
|
||||
|
||||
$translation = dcgettext($domain, $contextString, LC_MESSAGES);
|
||||
$translation = dcgettext(
|
||||
$domain,
|
||||
$contextString,
|
||||
defined('LC_MESSAGES') ? LC_MESSAGES : LC_ALL
|
||||
);
|
||||
|
||||
if ($translation == $contextString) {
|
||||
return $text;
|
||||
|
@ -126,7 +130,13 @@ class Translator
|
|||
{
|
||||
$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) {
|
||||
return ($number == 1 ? $textSingular : $textPlural);
|
||||
|
|
|
@ -237,6 +237,10 @@ class Menu implements RecursiveIterator
|
|||
'priority' => 700,
|
||||
'renderer' => 'ProblemMenuItemRenderer'
|
||||
));
|
||||
$section->add(t('About'), array(
|
||||
'url' => 'about',
|
||||
'priority' => 701
|
||||
));
|
||||
if (Logger::writesToFile()) {
|
||||
$section->add(t('Application Log'), array(
|
||||
'url' => 'list/applicationlog',
|
||||
|
@ -279,11 +283,6 @@ class Menu implements RecursiveIterator
|
|||
'priority' => 990,
|
||||
'renderer' => 'ForeignMenuItemRenderer'
|
||||
));
|
||||
|
||||
$this->add(t('About'), array(
|
||||
'url' => 'about',
|
||||
'priority' => 1000
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -374,9 +374,29 @@ 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)
|
||||
{
|
||||
return $this->params;
|
||||
if ($sequenced) {
|
||||
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)
|
||||
|
|
|
@ -309,13 +309,14 @@ EOT;
|
|||
|
||||
private function renderRefreshTab()
|
||||
{
|
||||
$url = Url::fromRequest()->without('renderLayout');
|
||||
$tab = $this->get($this->getActiveName());
|
||||
|
||||
if ($tab !== null) {
|
||||
$url = Url::fromRequest($tab->getUrl()->getParams()->toArray(false))->without('renderLayout');
|
||||
$label = $this->view()->escape(
|
||||
$tab->getLabel()
|
||||
);
|
||||
} else {
|
||||
$url = Url::fromRequest()->without('renderLayout');
|
||||
}
|
||||
|
||||
if (! empty($label)) {
|
||||
|
|
|
@ -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
|
||||
Version: 2.0.0
|
||||
Version: 2.0.0-rc1
|
||||
Description: Documentation module
|
||||
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
|
||||
* be executed as follows:
|
||||
*
|
||||
* icingacli monitoring conference welcome --watch 1
|
||||
* icingacli monitoring conference welcome --watch=1
|
||||
*/
|
||||
public function welcomeAction()
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Icinga\Module\Monitoring\Clicommands;
|
|||
|
||||
use Icinga\Module\Monitoring\Backend;
|
||||
use Icinga\Module\Monitoring\Cli\CliUtils;
|
||||
use Icinga\Util\Format;
|
||||
use Icinga\Date\DateFormatter;
|
||||
use Icinga\Cli\Command;
|
||||
use Icinga\File\Csv;
|
||||
use Icinga\Module\Monitoring\Plugin\PerfdataSet;
|
||||
|
@ -124,19 +124,19 @@ class ListCommand extends Command
|
|||
* --verbose Show detailled output
|
||||
* --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$
|
||||
* 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
|
||||
* true if no filter value is given.
|
||||
*
|
||||
* EXAMPLES
|
||||
*
|
||||
* icingacli monitoring list --unhandled
|
||||
* icingacli monitoring list --host local* --service *disk*
|
||||
* icingacli monitoring list --format '$host$: $service$'
|
||||
* icingacli monitoring list --host=local* --service=*disk*
|
||||
* icingacli monitoring list --format='$host$: $service$'
|
||||
*/
|
||||
public function statusAction()
|
||||
{
|
||||
|
@ -299,7 +299,7 @@ class ListCommand extends Command
|
|||
$leaf,
|
||||
$screen->underline($row->service_description),
|
||||
$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) {
|
||||
$out .= $emptyLine . preg_replace(
|
||||
|
|
|
@ -27,8 +27,8 @@ class NrpeCommand extends Command
|
|||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* icingacli monitoring nrpe 127.0.0.1 CheckMEM --ssl --MaxWarn 80% \
|
||||
* --MaxCrit 90% --type physical
|
||||
* icingacli monitoring nrpe 127.0.0.1 CheckMEM --ssl --MaxWarn=80% \
|
||||
* --MaxCrit=90% --type=physical
|
||||
*/
|
||||
public function checkAction()
|
||||
{
|
||||
|
|
|
@ -63,6 +63,54 @@ class Monitoring_HostController extends MonitoredObjectController
|
|||
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
|
||||
*/
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
<?php
|
||||
/* 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\Widget\Tabs;
|
||||
use Icinga\Web\Widget\Tabextension\OutputFormat;
|
||||
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
||||
use Icinga\Module\Monitoring\Backend;
|
||||
use Icinga\Module\Monitoring\Controller;
|
||||
|
||||
|
@ -22,34 +17,6 @@ class Monitoring_ShowController extends Controller
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -66,36 +33,16 @@ class Monitoring_ShowController extends Controller
|
|||
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/show'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function historyAction()
|
||||
{
|
||||
$this->getTabs()->activate('history');
|
||||
$this->view->object->fetchEventHistory();
|
||||
$this->view->history = $this->view->object->eventhistory;
|
||||
$this->handleFormatRequest($this->view->object->eventhistory);
|
||||
$this->fetchHostStats();
|
||||
if ($this->params->has('service')) {
|
||||
$this->redirectNow(Url::fromRequest()->setPath('monitoring/service/history'));
|
||||
}
|
||||
|
||||
$this->setupLimitControl(50);
|
||||
$this->setupPaginationControl($this->view->history, 50);
|
||||
}
|
||||
|
||||
protected function fetchHostStats()
|
||||
{
|
||||
$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();
|
||||
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/history'));
|
||||
}
|
||||
|
||||
public function contactAction()
|
||||
|
@ -163,78 +110,4 @@ class Monitoring_ShowController extends Controller
|
|||
$this->view->contact = $contact;
|
||||
$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;
|
||||
|
||||
use Icinga\Data\ResourceFactory;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
use Icinga\Web\Form;
|
||||
|
||||
class RemoteInstanceForm extends Form
|
||||
{
|
||||
/**
|
||||
* The available monitoring instance resources split by type
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $resources;
|
||||
|
||||
/**
|
||||
* (non-PHPDoc)
|
||||
* @see Form::init() For the method documentation.
|
||||
|
@ -16,12 +25,89 @@ class RemoteInstanceForm extends Form
|
|||
$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)
|
||||
* @see Form::createElements() For the method documentation.
|
||||
*/
|
||||
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(
|
||||
array(
|
||||
'text',
|
||||
|
@ -43,8 +129,11 @@ class RemoteInstanceForm extends Form
|
|||
'description' => $this->translate('SSH port to connect to on the remote Icinga instance'),
|
||||
'value' => 22
|
||||
)
|
||||
),
|
||||
array(
|
||||
)
|
||||
));
|
||||
|
||||
if (! $useResource) {
|
||||
$this->addElement(
|
||||
'text',
|
||||
'user',
|
||||
array(
|
||||
|
@ -55,18 +144,20 @@ class RemoteInstanceForm extends Form
|
|||
. ' possible for this user'
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$this->addElement(
|
||||
'text',
|
||||
'path',
|
||||
array(
|
||||
'text',
|
||||
'path',
|
||||
array(
|
||||
'required' => true,
|
||||
'label' => $this->translate('Command File'),
|
||||
'value' => '/var/run/icinga2/cmd/icinga2.cmd',
|
||||
'description' => $this->translate('Path to the Icinga command file on the remote Icinga instance')
|
||||
)
|
||||
'required' => true,
|
||||
'label' => $this->translate('Command File'),
|
||||
'value' => '/var/run/icinga2/cmd/icinga2.cmd',
|
||||
'description' => $this->translate('Path to the Icinga command file on the remote Icinga instance')
|
||||
)
|
||||
));
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,6 +143,11 @@ class InstanceConfigForm extends ConfigForm
|
|||
|
||||
$instanceConfig = $this->config->getSection($instanceName)->toArray();
|
||||
$instanceConfig['name'] = $instanceName;
|
||||
|
||||
if (isset($instanceConfig['resource'])) {
|
||||
$instanceConfig['use_resource'] = true;
|
||||
}
|
||||
|
||||
$this->populate($instanceConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,12 @@ use Icinga\Module\Monitoring\Object\Host;
|
|||
use Icinga\Module\Monitoring\Object\Service;
|
||||
|
||||
$self = $this;
|
||||
$hostContext = $object->getType() === 'host';
|
||||
|
||||
if (! $this->compact): ?>
|
||||
<div class="controls">
|
||||
<?= $this->tabs; ?>
|
||||
<?php if ($hostContext): ?>
|
||||
<?= $this->render('partials/host/object-header.phtml'); ?>
|
||||
<?php else: ?>
|
||||
<?= $this->render('partials/service/object-header.phtml'); ?>
|
||||
<?php endif ?>
|
||||
<h1><?= $this->translate('This Object\'s Event History'); ?></h1>
|
||||
<h1><?= $this->translate('This Host\'s Event History'); ?></h1>
|
||||
<?= $this->sortBox; ?>
|
||||
<?= $this->limiter; ?>
|
||||
<?= $this->paginator; ?>
|
||||
|
@ -24,7 +19,7 @@ if (! $this->compact): ?>
|
|||
<?php
|
||||
|
||||
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;
|
||||
}
|
||||
?>
|
||||
|
@ -133,7 +128,7 @@ $output = $this->tickets ? preg_replace_callback(
|
|||
<?php if ($isService): ?>
|
||||
<?= sprintf(
|
||||
$this->translate('%s on %s', 'Service running on host'),
|
||||
$hostContext ? $this->qlink(
|
||||
$this->qlink(
|
||||
$event->service_display_name,
|
||||
'monitoring/show/service',
|
||||
array(
|
||||
|
@ -145,7 +140,7 @@ $output = $this->tickets ? preg_replace_callback(
|
|||
$event->service_display_name,
|
||||
$event->host_display_name
|
||||
))
|
||||
) : $this->escape($event->service_display_name),
|
||||
),
|
||||
$event->host_display_name
|
||||
) ?>
|
||||
<?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(
|
||||
$this->translate('Send notification'),
|
||||
'monitoring/host/send-custom-notification',
|
||||
array('host_name' => $object->getName()),
|
||||
array('host' => $object->getName()),
|
||||
array(
|
||||
'icon' => 'bell',
|
||||
'data-base-target' => '_self',
|
||||
|
@ -23,7 +23,7 @@
|
|||
echo $this->qlink(
|
||||
$this->translate('Send 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(
|
||||
'icon' => 'bell',
|
||||
'data-base-target' => '_self',
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
## Abstract
|
||||
|
||||
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
|
||||
|
||||
|
@ -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)
|
||||
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;
|
||||
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Data\ResourceFactory;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
use Icinga\Module\Monitoring\Command\Exception\TransportException;
|
||||
use Icinga\Module\Monitoring\Command\IcingaCommand;
|
||||
|
@ -44,6 +45,13 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
@ -137,6 +145,55 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||
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
|
||||
*
|
||||
|
@ -192,6 +249,9 @@ class RemoteCommandFile implements CommandTransportInterface
|
|||
if (isset($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(
|
||||
' %s "echo %s > %s" 2>&1', // Redirect stderr to stdout
|
||||
escapeshellarg($this->host),
|
||||
|
|
|
@ -93,6 +93,19 @@ abstract class MonitoredObjectController extends Controller
|
|||
$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
|
||||
*
|
||||
|
@ -145,6 +158,9 @@ abstract class MonitoredObjectController extends Controller
|
|||
$params = array(
|
||||
'host' => $object->getName()
|
||||
);
|
||||
if ($this->params->has('service')) {
|
||||
$params['service'] = $this->params->get('service');
|
||||
}
|
||||
} else {
|
||||
$isService = true;
|
||||
$params = array(
|
||||
|
@ -165,14 +181,14 @@ abstract class MonitoredObjectController extends Controller
|
|||
'urlParams' => $params
|
||||
)
|
||||
);
|
||||
if ($isService) {
|
||||
if ($isService || $this->params->has('service')) {
|
||||
$tabs->add(
|
||||
'service',
|
||||
array(
|
||||
'title' => sprintf(
|
||||
$this->translate('Show detailed information for service %s on host %s'),
|
||||
$object->getName(),
|
||||
$object->getHost()->getName()
|
||||
$isService ? $object->getName() : $this->params->get('service'),
|
||||
$isService ? $object->getHost()->getName() : $object->getName()
|
||||
),
|
||||
'label' => $this->translate('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')) {
|
||||
$tabs->add(
|
||||
'history',
|
||||
|
@ -195,7 +224,7 @@ abstract class MonitoredObjectController extends Controller
|
|||
,
|
||||
'label' => $this->translate('History'),
|
||||
'icon' => 'rewind',
|
||||
'url' => 'monitoring/show/history',
|
||||
'url' => $isService ? 'monitoring/service/history' : 'monitoring/host/history',
|
||||
'urlParams' => $params
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Module: monitoring
|
||||
Version: 2.0.0~alpha4
|
||||
Version: 2.0.0-rc1
|
||||
Description: Icinga monitoring module
|
||||
This is the core module for most Icingaweb users. It provides an
|
||||
abstraction layer for various Icinga data backends.
|
||||
|
|
|
@ -29,7 +29,7 @@ class ConfigCommand extends Command
|
|||
*
|
||||
* 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()
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ class ConfigCommand extends Command
|
|||
*
|
||||
* --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]
|
||||
*
|
||||
|
@ -106,9 +106,9 @@ class ConfigCommand extends Command
|
|||
*
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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 --build
|
||||
* icingacli test php unit --include *SpecialTest
|
||||
* icingacli test php unit --include=*SpecialTest
|
||||
*/
|
||||
public function unitAction()
|
||||
{
|
||||
|
@ -109,8 +109,8 @@ class PhpCommand extends Command
|
|||
*
|
||||
* icingacli test php style --verbose
|
||||
* icingacli test php style --build
|
||||
* icingacli test php style --include path/to/your/file
|
||||
* icingacli test php style --exclude *someFile* --exclude someOtherFile*
|
||||
* icingacli test php style --include=path/to/your/file
|
||||
* icingacli test php style --exclude=*someFile* --exclude=someOtherFile*
|
||||
*/
|
||||
public function styleAction()
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Module: test
|
||||
Version: 2.0.0~alpha4
|
||||
Version: 2.0.0-rc1
|
||||
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.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Module: translation
|
||||
Version: 2.0.0~alpha4
|
||||
Version: 2.0.0-rc1
|
||||
Description: Translation module
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
textarea.resource {
|
||||
&.ssh-identity {
|
||||
width: 50%;
|
||||
height: 25em;
|
||||
}
|
||||
}
|
||||
|
||||
form .description {
|
||||
font-size: 0.8em;
|
||||
margin: 0.3em 0 0 0.6em;
|
||||
|
|
|
@ -236,9 +236,6 @@ div.content.users {
|
|||
}
|
||||
|
||||
div.controls div.user-header {
|
||||
border-bottom: 2px solid @colorPetrol;
|
||||
margin-bottom: 1em;
|
||||
|
||||
.user-name {
|
||||
display: inline-block;
|
||||
margin: 0 0 0.3em;
|
||||
|
@ -302,9 +299,6 @@ div.content.groups {
|
|||
}
|
||||
|
||||
div.controls div.group-header {
|
||||
border-bottom: 2px solid @colorPetrol;
|
||||
margin-bottom: 1em;
|
||||
|
||||
.group-name {
|
||||
display: inline-block;
|
||||
margin: 0 0 0.3em;
|
||||
|
|
Loading…
Reference in New Issue