/usr/share/doc/ganeti/html/security.html is in ganeti-doc 2.16.0~rc2-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Security in Ganeti — Ganeti 2.16.0~rc2 documentation</title>
<link rel="stylesheet" href="_static/style.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.16.0~rc2',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Upgrade notes" href="upgrade.html" />
<link rel="prev" title="Ganeti remote API" href="rapi.html" />
</head>
<body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="upgrade.html" title="Upgrade notes"
accesskey="N">next</a></li>
<li class="right" >
<a href="rapi.html" title="Ganeti remote API"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Ganeti 2.16.0~rc2 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="security-in-ganeti">
<h1>Security in Ganeti<a class="headerlink" href="#security-in-ganeti" title="Permalink to this headline">¶</a></h1>
<p>Documents Ganeti version 2.16</p>
<p>Ganeti was developed to run on internal, trusted systems. As such, the
security model is all-or-nothing.</p>
<p>Up to version 2.3 all Ganeti code ran as root. Since version 2.4 it is
possible to run all daemons except the node daemon and the monitoring daemon
as non-root users by specifying user names and groups at build time.
The node daemon continues to require root privileges to create logical volumes,
DRBD devices, start instances, etc. Cluster commands can be run as root or by
users in a group specified at build time. The monitoring daemon requires root
privileges in order to be able to access and present information that are only
avilable to root (such as the output of the <code class="docutils literal"><span class="pre">xm</span></code> command of Xen).</p>
<div class="section" id="host-issues">
<h2>Host issues<a class="headerlink" href="#host-issues" title="Permalink to this headline">¶</a></h2>
<p>For a host on which the Ganeti software has been installed, but not
joined to a cluster, there are no changes to the system.</p>
<p>For a host that has been joined to the cluster, there are very important
changes:</p>
<ul class="simple">
<li>The host will have its SSH host key replaced with the one of the
cluster (which is the one the initial node had at the cluster
creation)</li>
<li>A new public key will be added to root’s <code class="docutils literal"><span class="pre">authorized_keys</span></code> file,
granting root access to all nodes of the cluster. The private part of
the key is also distributed to all nodes. Old files are renamed.</li>
<li>Communication between nodes is encrypted using SSL/TLS. A common key
and certificate combo is shared between all nodes of the cluster. At
this time, no CA is used.</li>
<li>The Ganeti node daemon will accept RPC requests from any host that is
master candidate within the cluster, and the operations it will
do as a result of these requests are:<ul>
<li>running commands under the <code class="docutils literal"><span class="pre">/etc/ganeti/hooks</span></code> directory</li>
<li>creating DRBD disks between it and the IP it has been told</li>
<li>overwrite a defined list of files on the host</li>
</ul>
</li>
</ul>
<p>As you can see, as soon as a node is joined, it becomes equal to all
other nodes in the cluster wrt to SSH and equal to all non-master
candidate nodes wrt to RPC, and the security of the cluster is
determined by the weakest node.</p>
<p>Note that only the SSH key will allow other machines to run any command
on this node; the RPC method will run only:</p>
<ul class="simple">
<li>well defined commands to create, remove, activate logical volumes,
drbd devices, start/stop instances, etc;</li>
<li>run well-defined SSH commands on other nodes in the cluster</li>
<li>scripts under the <code class="docutils literal"><span class="pre">/etc/ganeti/hooks</span></code> directory</li>
<li>scripts under the <code class="docutils literal"><span class="pre">/etc/ganeti/restricted-commands</span></code> directory, if
this feature has been enabled at build time (see below)</li>
</ul>
<p>It is therefore important to make sure that the contents of the
<code class="docutils literal"><span class="pre">/etc/ganeti/hooks</span></code> and <code class="docutils literal"><span class="pre">/etc/ganeti/restricted-commands</span></code>
directories are supervised and only trusted sources can populate them.</p>
<div class="section" id="restricted-commands">
<h3>Restricted commands<a class="headerlink" href="#restricted-commands" title="Permalink to this headline">¶</a></h3>
<p>The restricted commands feature is new in Ganeti 2.7. It enables the
administrator to run any commands in the
<code class="docutils literal"><span class="pre">/etc/ganeti/restricted-commands</span></code> directory, if the feature has been
enabled at build time, subject to the following restrictions:</p>
<ul class="simple">
<li>No parameters may be passed</li>
<li>No absolute or relative path may be passed, only a filename</li>
<li>The <code class="docutils literal"><span class="pre">/etc/ganeti/restricted-commands</span></code> directory must
be owned by root:root and have mode 0755 or stricter</li>
<li>Executables must be regular files or symlinks, and must be executable
by root:root</li>
</ul>
<p>Note that it’s not possible to list the contents of the directory, and
there is an intentional delay when trying to execute a non-existing
command (to slow-down dictionary attacks).</p>
<p>Since for Ganeti itself this functionality is not needed, and is only
provided as a way to help administrate or recover nodes, it is a local
site decision whether to enable or not the restricted commands feature.</p>
<p>By default, this feature is disabled.</p>
</div>
</div>
<div class="section" id="cluster-issues">
<h2>Cluster issues<a class="headerlink" href="#cluster-issues" title="Permalink to this headline">¶</a></h2>
<p>As mentioned above, there are multiple ways of communication between
cluster nodes:</p>
<ul class="simple">
<li>SSH-based, for high-volume traffic like image dumps or for low-level
command, e.g. restarting the Ganeti node daemon</li>
<li>RPC communication between master and nodes</li>
<li>DRBD real-time disk replication traffic</li>
</ul>
<p>The SSH traffic is protected (after the initial login to a new node) by
the cluster-wide shared SSH key.</p>
<p>RPC communication between the master and nodes is protected using
SSL/TLS encryption. The server must have must have the cluster-wide
shared SSL/TLS certificate. When acting as a client, the nodes use an
individual SSL/TLS certificate. On incoming requests, the server checks
whether the client’s certificate is that of a master candidate by
verifying its finterprint to a list of known master candidate
certificates. We decided not to use a CA (yet) to simplify the key
handling.</p>
<p>The DRBD traffic is not protected by encryption, as DRBD does not
support this. It’s therefore recommended to implement host-level
firewalling or to use a separate range of IP addresses for the DRBD
traffic (this is supported in Ganeti through the use of a secondary
interface) which is not routed outside the cluster. DRBD connections are
protected from erroneous connections to other machines (as may happen
due to software issues), and from accepting connections from other
machines, by using a shared secret, exchanged via RPC requests from the
master to the nodes when configuring the device.</p>
</div>
<div class="section" id="master-daemon">
<h2>Master daemon<a class="headerlink" href="#master-daemon" title="Permalink to this headline">¶</a></h2>
<p>The command-line tools to master daemon communication is done via a
UNIX socket, whose permissions are reset to <code class="docutils literal"><span class="pre">0660</span></code> after listening but
before serving requests. This permission-based protection is documented
and works on Linux, but is not-portable; however, Ganeti doesn’t work on
non-Linux system at the moment.</p>
</div>
<div class="section" id="luxi-daemon">
<h2>Luxi daemon<a class="headerlink" href="#luxi-daemon" title="Permalink to this headline">¶</a></h2>
<p>The <code class="docutils literal"><span class="pre">luxid</span></code> daemon (automatically enabled if <code class="docutils literal"><span class="pre">confd</span></code> is enabled at
build time) serves local (UNIX socket) queries about the run-time
configuration. Answering these means talking to other cluster nodes,
exactly as <code class="docutils literal"><span class="pre">masterd</span></code> does. See the notes for <code class="docutils literal"><span class="pre">masterd</span></code> regarding
permission-based protection.</p>
</div>
<div class="section" id="conf-daemon">
<h2>Conf daemon<a class="headerlink" href="#conf-daemon" title="Permalink to this headline">¶</a></h2>
<p>In Ganeti 2.8, the <code class="docutils literal"><span class="pre">confd</span></code> daemon (if enabled at build time), serves
network-originated queries about parts of the static cluster
configuration.</p>
<p>If Ganeti is not configured (at build time) to use separate users,
<code class="docutils literal"><span class="pre">confd</span></code> has access to all Ganeti related files (including internal RPC
SSL certificates). This makes it a bit more sensitive to bugs (a remote
attacker could get direct access to the intra-cluster RPC), so to harden
security it’s recommended to:</p>
<ul class="simple">
<li>disable confd at build time if it (and <code class="docutils literal"><span class="pre">luxid</span></code>) is not needed in
your setup.</li>
<li>configure Ganeti (at build time) to use separate users, so that the
confd daemon doesn’t also have access to the server SSL/TLS
certificates.</li>
<li>add firewall rules to protect the <code class="docutils literal"><span class="pre">confd</span></code> port or bind it to a
trusted address. Make sure that all nodes can access the daemon, as
the monitoring daemon requires it.</li>
</ul>
</div>
<div class="section" id="monitoring-daemon">
<h2>Monitoring daemon<a class="headerlink" href="#monitoring-daemon" title="Permalink to this headline">¶</a></h2>
<p>The monitoring daemon provides information about the status and the
performance of the cluster over HTTP.
It is currently unencrypted and non-authenticated, therefore it is strongly
advised to set proper firewalling rules to prevent unwanted access.</p>
<p>The monitoring daemon runs as root, because it needs to be able to access
privileged information (such as the state of the instances as provided by
the Xen hypervisor). Nevertheless, the security implications are mitigated
by the fact that the agent only provides reporting functionalities,
without the ability to actually modify the state of the cluster.</p>
</div>
<div class="section" id="remote-api">
<h2>Remote API<a class="headerlink" href="#remote-api" title="Permalink to this headline">¶</a></h2>
<p>Starting with Ganeti 2.0, Remote API traffic is encrypted using SSL/TLS
by default. It supports Basic authentication as per <span class="target" id="index-0"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc2617.html"><strong>RFC 2617</strong></a>. Users
can be granted different capabilities. Details can be found in the
<a class="reference internal" href="rapi.html#rapi-users"><span class="std std-ref">RAPI documentation</span></a>.</p>
<p>Paths for certificate, private key and CA files required for SSL/TLS
will be set at source configure time. Symlinks or command line
parameters may be used to use different files.</p>
<p>The RAPI binds to all interfaces by default, and allows read-only
requests without the need for authentication. In the case that one of
the interfaces RAPI binds to is publicly exposed, this will allow
anyone in the world to read the state of the cluster, divulging
potentially useful data such as the names of instances, their IP
addresses, etc. Since the RAPI daemon resides on the master node as
well, DoS attacks can result in Ganeti outages or issues with instances
located on the master node.</p>
<p>We recommend that you reduce the attack surface by either placing RAPI
in an environment where you can control access to it, or should you
need to expose it publicly, use various RAPI daemon options to lock
functionality down to only what you need. RAPI daemon options are best
added to <code class="docutils literal"><span class="pre">/etc/default/ganeti</span></code>, the <code class="docutils literal"><span class="pre">RAPI_ARGS</span></code> variable. Some
examples of situations where you might want to expose the RAPI are
cross-cluster instance moves, which can be done only via the RAPI.</p>
<p>If you do not use RAPI at all, we recommend that you lock it down by
binding it to the loopback interface. This can be done by passing the
<code class="docutils literal"><span class="pre">-b</span> <span class="pre">127.0.0.1</span></code> parameter to the RAPI daemon. Preventing the RAPI
from starting or making it unreachable on the master node is not
recommended, as the watcher performs health checks and will attempt to
restart the daemon repeatedly.</p>
<p>If you intend to use the RAPI and to expose it to the public, make sure
to use the <code class="docutils literal"><span class="pre">--require-authentication</span></code> flag, disabling anonymous HTTP
requests.</p>
<p>Ganeti currently cannot protect users adequately from DoS attacks based
on client-side HTTPS parameter renegotiation due to the Python OpenSSL
library lacking necessary features. To protect yourself from these, the
use of a HTTPS proxy handling this correctly is needed (e.g. nginx).
Useful options for setting RAPI up for cooperation with the proxy are:</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">-p</span> <span class="pre">PORT</span></code> for allowing the default RAPI port to be used by the
proxy</li>
<li><code class="docutils literal"><span class="pre">--no-ssl</span></code> to disable SSL as it will be handled by the proxy anyway</li>
</ul>
</div>
<div class="section" id="inter-cluster-instance-moves">
<h2>Inter-cluster instance moves<a class="headerlink" href="#inter-cluster-instance-moves" title="Permalink to this headline">¶</a></h2>
<p>To move instances between clusters, different clusters must be able to
communicate with each other over a secure channel. Up to and including
Ganeti 2.1, clusters were self-contained entities and had no knowledge
of other clusters. With Ganeti 2.2, clusters can exchange data if tokens
(an encryption certificate) was exchanged by a trusted third party
before.</p>
</div>
<div class="section" id="kvm-security">
<h2>KVM Security<a class="headerlink" href="#kvm-security" title="Permalink to this headline">¶</a></h2>
<p>When running KVM instances under Ganeti three security models ara
available: “none”, “user” and “pool”.</p>
<p>Under security model “none” instances run by default as root. This means
that, if an instance gets jail broken, it will be able to own the host
node, and thus the ganeti cluster. This is the default model, and the
only one available before Ganeti 2.1.2.</p>
<p>Under security model “user” an instance is run as the user specified by
the hypervisor parameter “security_domain”. This makes it easy to run
all instances as non privileged users, and allows one to manually
allocate specific users to specific instances or sets of instances. If
the specified user doesn’t have permissions a jail broken instance will
need some local privilege escalation before being able to take over the
node and the cluster. It’s possible though for a jail broken instance to
affect other ones running under the same user.</p>
<p>Under security model “pool” a global cluster-level uid pool is used to
start each instance on the same node under a different user. The uids in
the cluster pool can be set with <code class="docutils literal"><span class="pre">gnt-cluster</span> <span class="pre">init</span></code> and <code class="docutils literal"><span class="pre">gnt-cluster</span>
<span class="pre">modify</span></code>, and must correspond to existing users on all nodes. Ganeti
will then allocate one to each instance, as needed. This way a jail
broken instance won’t be able to affect any other. Since the users are
handed out by ganeti in a per-node randomized way, in this mode there is
no way to make sure a particular instance is always run as a certain
user. Use mode “user” for that.</p>
<p>In addition to these precautions, if you want to avoid instances sending
traffic on your node network, you can use an iptables rule such as:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">iptables</span> <span class="o">-</span><span class="n">A</span> <span class="n">OUTPUT</span> <span class="o">-</span><span class="n">m</span> <span class="n">owner</span> <span class="o">--</span><span class="n">uid</span><span class="o">-</span><span class="n">owner</span> <span class="o"><</span><span class="n">uid</span><span class="o">></span><span class="p">[</span><span class="o">-<</span><span class="n">uid</span><span class="o">></span><span class="p">]</span> <span class="o">-</span><span class="n">j</span> <span class="n">LOG</span> \
<span class="o">--</span><span class="n">log</span><span class="o">-</span><span class="n">prefix</span> <span class="s2">"ganeti uid pool user network traffic"</span>
<span class="n">iptables</span> <span class="o">-</span><span class="n">A</span> <span class="n">OUTPUT</span> <span class="o">-</span><span class="n">m</span> <span class="n">owner</span> <span class="o">--</span><span class="n">uid</span><span class="o">-</span><span class="n">owner</span> <span class="o"><</span><span class="n">uid</span><span class="o">></span><span class="p">[</span><span class="o">-<</span><span class="n">uid</span><span class="o">></span><span class="p">]</span> <span class="o">-</span><span class="n">j</span> <span class="n">DROP</span>
</pre></div>
</div>
<p>This won’t affect regular instance traffic (that comes out of the tapX
allocated to the instance, and can be filtered or subject to appropriate
policy routes) but will stop any user generated traffic that might come
from a jailbroken instance.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Security in Ganeti</a><ul>
<li><a class="reference internal" href="#host-issues">Host issues</a><ul>
<li><a class="reference internal" href="#restricted-commands">Restricted commands</a></li>
</ul>
</li>
<li><a class="reference internal" href="#cluster-issues">Cluster issues</a></li>
<li><a class="reference internal" href="#master-daemon">Master daemon</a></li>
<li><a class="reference internal" href="#luxi-daemon">Luxi daemon</a></li>
<li><a class="reference internal" href="#conf-daemon">Conf daemon</a></li>
<li><a class="reference internal" href="#monitoring-daemon">Monitoring daemon</a></li>
<li><a class="reference internal" href="#remote-api">Remote API</a></li>
<li><a class="reference internal" href="#inter-cluster-instance-moves">Inter-cluster instance moves</a></li>
<li><a class="reference internal" href="#kvm-security">KVM Security</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="rapi.html"
title="previous chapter">Ganeti remote API</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="upgrade.html"
title="next chapter">Upgrade notes</a></p>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/security.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<div><input type="text" name="q" /></div>
<div><input type="submit" value="Go" /></div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="upgrade.html" title="Upgrade notes"
>next</a></li>
<li class="right" >
<a href="rapi.html" title="Ganeti remote API"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Ganeti 2.16.0~rc2 documentation</a> »</li>
</ul>
</div>
<div class="footer" role="contentinfo">
© Copyright 2018, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Google Inc..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.6.7.
</div>
</body>
</html>
|