Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix CVE-2015-4053 world-readable permissions on client.admin key #300

Merged
merged 7 commits into from
May 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ceph_deploy/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def admin(args):
LOG.debug('Pushing admin keys and conf to %s', hostname)
try:
distro = hosts.get(hostname, username=args.username)
hostname = distro.conn.remote_module.shortname()

distro.conn.remote_module.write_conf(
args.cluster,
Expand All @@ -37,7 +36,8 @@ def admin(args):

distro.conn.remote_module.write_file(
'/etc/ceph/%s.client.admin.keyring' % args.cluster,
keyring
keyring,
0600,
)

distro.conn.exit()
Expand All @@ -58,7 +58,7 @@ def make(parser):
parser.add_argument(
'client',
metavar='HOST',
nargs='*',
nargs='+',
help='host to configure for ceph administration',
)
parser.set_defaults(
Expand Down
8 changes: 6 additions & 2 deletions ceph_deploy/hosts/remotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,12 @@ def write_monitor_keyring(keyring, monitor_keyring):
write_file(keyring, monitor_keyring)


def write_file(path, content):
with file(path, 'w') as f:
def write_file(path, content, mode=0644, directory=None):
if directory:
if path.startswith("/"):
path = path[1:]
path = os.path.join(directory, path)
with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, mode), 'w') as f:
f.write(content)


Expand Down
82 changes: 82 additions & 0 deletions ceph_deploy/tests/test_cli_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os
import subprocess

import pytest
from mock import patch, MagicMock, Mock

from ceph_deploy.cli import _main as main
from ceph_deploy.hosts import remotes
from ceph_deploy.tests.directory import directory

def test_help(tmpdir, cli):
with cli(
args=['ceph-deploy', 'admin', '--help'],
stdout=subprocess.PIPE,
) as p:
result = p.stdout.read()
assert 'usage: ceph-deploy admin' in result
assert 'positional arguments' in result
assert 'optional arguments' in result


def test_bad_no_hosts(tmpdir, cli):
with pytest.raises(cli.Failed) as err:
with cli(
args=['ceph-deploy', 'admin'],
stderr=subprocess.PIPE,
) as p:
result = p.stderr.read()
assert 'usage: ceph-deploy admin' in result
assert 'too few arguments' in result
assert err.value.status == 2


def test_bad_no_conf(tmpdir, cli):
with pytest.raises(cli.Failed) as err:
with cli(
args=['ceph-deploy', 'admin', 'host1'],
stderr=subprocess.PIPE,
) as p:
result = p.stderr.read()
assert 'No such file or directory: \'ceph.conf\'' in result
assert err.value.status == 1


def test_bad_no_key(tmpdir, cli):
with tmpdir.join('ceph.conf').open('w'):
pass
with pytest.raises(cli.Failed) as err:
with cli(
args=['ceph-deploy', 'admin', 'host1'],
stderr=subprocess.PIPE,
) as p:
result = p.stderr.read()
assert 'ceph.client.admin.keyring not found' in result
assert err.value.status == 1


def test_write_keyring(tmpdir):
with tmpdir.join('ceph.conf').open('w'):
pass
with tmpdir.join('ceph.client.admin.keyring').open('w'):
pass

etc_ceph = os.path.join(str(tmpdir), 'etc', 'ceph')
os.makedirs(etc_ceph)

distro = MagicMock()
distro.conn = MagicMock()
remotes.write_file.func_defaults = (str(tmpdir),)
distro.conn.remote_module = remotes
distro.conn.remote_module.write_conf = Mock()

with patch('ceph_deploy.admin.hosts'):
with patch('ceph_deploy.admin.hosts.get', MagicMock(return_value=distro)):
with directory(str(tmpdir)):
main(args=['admin', 'host1'])

keyring_file = os.path.join(etc_ceph, 'ceph.client.admin.keyring')
assert os.path.exists(keyring_file)

file_mode = oct(os.stat(keyring_file).st_mode & 0777)
assert file_mode == oct(0600)