summaryrefslogtreecommitdiffstats
path: root/library/Director/Restriction/HostgroupRestriction.php
blob: 1a6792b68608638afc34aeb99d3af463350bf9af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

namespace Icinga\Module\Director\Restriction;

use Icinga\Exception\ProgrammingError;
use Icinga\Module\Director\Db\IcingaObjectFilterHelper;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaHostGroup;
use Icinga\Module\Director\Objects\IcingaObject;
use Zend_Db_Select as ZfSelect;

class HostgroupRestriction extends ObjectRestriction
{
    protected $name = 'director/filter/hostgroups';

    public function allows(IcingaObject $object)
    {
        if ($object instanceof IcingaHost) {
            return $this->allowsHost($object);
        } elseif ($object instanceof IcingaHostGroup) {
            return $this->allowsHostGroup($object);
        } else {
            return $this;
        }
    }

    protected function filterQuery(ZfSelect $query, $tableAlias = 'o')
    {
        $table = $this->getQueryTableByAlias($query, $tableAlias);
        switch ($table) {
            case 'icinga_host':
                $this->filterHostsQuery($query, $tableAlias);
                break;
            case 'icinga_service':
                // TODO: Alias is hardcoded
                $this->filterHostsQuery($query, 'h');
                break;
            case 'icinga_hostgroup':
                $this->filterHostGroupsQuery($query, $tableAlias);
                break;
            // Hint: other tables are ignored, so please take care!
        }

        return $query;
    }

    /**
     * Whether access to the given host is allowed
     *
     * @param IcingaHost $host
     * @return bool
     */
    public function allowsHost(IcingaHost $host)
    {
        if (! $this->isRestricted()) {
            return true;
        }

        // Hint: branched hosts have no id
        if (! $host->hasBeenLoadedFromDb() || $host->hasModifiedGroups() || $host->get('id') === null) {
            foreach ($this->listRestrictedHostgroups() as $group) {
                if ($host->hasGroup($group)) {
                    return true;
                }
            }

            return false;
        }

        $query = $this->db->select()->from(
            ['o' => 'icinga_host'],
            ['id']
        )->where('o.id = ?', $host->id);

        $this->filterHostsQuery($query);
        return (int) $this->db->fetchOne($query) === (int) $host->get('id');
    }

    /**
     * Whether access to the given hostgroup is allowed
     *
     * @param IcingaHostGroup $hostgroup
     * @return bool
     */
    public function allowsHostGroup(IcingaHostGroup $hostgroup)
    {
        if (! $this->isRestricted()) {
            return true;
        }

        $query = $this->db->select()->from(
            ['h' => 'icinga_hostgroup'],
            ['id']
        )->where('id = ?', $hostgroup->id);

        $this->filterHostGroupsQuery($query);
        return (int) $this->db->fetchOne($query) === (int) $hostgroup->get('id');
    }

    /**
     * Apply the restriction to the given Hosts Query
     *
     * We assume that the query wants to fetch hosts and that therefore the
     * icinga_host table already exists in the given query, using the $tableAlias
     * alias.
     *
     * @param ZfSelect $query
     * @param string $tableAlias
     */
    public function filterHostsQuery(ZfSelect $query, $tableAlias = 'o')
    {
        if (! $this->isRestricted()) {
            return;
        }

        IcingaObjectFilterHelper::filterByResolvedHostgroups(
            $query,
            'host',
            $this->listRestrictedHostgroups(),
            $tableAlias
        );
    }

    /**
     * Apply the restriction to the given Hosts Query
     *
     * We assume that the query wants to fetch hosts and that therefore the
     * icinga_host table already exists in the given query, using the $tableAlias
     * alias.
     *
     * @param ZfSelect $query
     * @param string $tableAlias
     */
    protected function filterHostGroupsQuery(ZfSelect $query, $tableAlias = 'o')
    {
        if (! $this->isRestricted()) {
            return;
        }
        $groups = $this->listRestrictedHostgroups();

        if (empty($groups)) {
            $query->where('(1 = 0)');
        } else {
            $query->where("${tableAlias}.object_name IN (?)", $groups);
        }
    }

    /**
     * Give a list of allowed Hostgroups
     *
     * When not restricted, null is returned. This might eventually also give
     * an empty list, and therefore not allow any access at all
     *
     * @return array|null
     */
    protected function listRestrictedHostgroups()
    {
        if ($restrictions = $this->auth->getRestrictions($this->getName())) {
            $groups = array();
            foreach ($restrictions as $restriction) {
                foreach ($this->gracefullySplitOnComma($restriction) as $group) {
                    $groups[$group] = $group;
                }
            }

            return array_keys($groups);
        } else {
            return null;
        }
    }
}