##// END OF EJS Templates
repo: show hooks version and update link in advanced section of repository.
repo: show hooks version and update link in advanced section of repository.

File last commit:

r3363:f08e98b1 default
r3377:e2435f87 default
Show More
utils.py
132 lines | 4.4 KiB | text/x-python | PythonLexer
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 # -*- coding: utf-8 -*-
docs: updated copyrights to 2019
r3363 # Copyright (C) 2016-2019 RhodeCode GmbH
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import os
import stat
import logging
import tempfile
import datetime
from . import config_keys
from rhodecode.model.db import true, joinedload, User, UserSshKeys
log = logging.getLogger(__name__)
HEADER = \
"# This file is managed by RhodeCode, please do not edit it manually. # \n" \
"# Current entries: {}, create date: UTC:{}.\n"
# Default SSH options for authorized_keys file, can be override via .ini
SSH_OPTS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding'
def get_all_active_keys():
result = UserSshKeys.query() \
.options(joinedload(UserSshKeys.user)) \
.filter(UserSshKeys.user != User.get_default_user()) \
.filter(User.active == true()) \
.all()
return result
def _generate_ssh_authorized_keys_file(
ssh: embedded ssh support...
r2043 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts, debug):
ssh: always expand the path for the generated authorized_keys file....
r2211 authorized_keys_file_path = os.path.abspath(
os.path.expanduser(authorized_keys_file_path))
ssh: embedded ssh support...
r2043 import rhodecode
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 all_active_keys = get_all_active_keys()
if allow_shell:
ssh_wrapper_cmd = ssh_wrapper_cmd + ' --shell'
ssh: embedded ssh support...
r2043 if debug:
ssh_wrapper_cmd = ssh_wrapper_cmd + ' --debug'
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994
if not os.path.isfile(authorized_keys_file_path):
ssh: always expand the path for the generated authorized_keys file....
r2211 log.debug('Creating file at %s', authorized_keys_file_path)
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 with open(authorized_keys_file_path, 'w'):
pass
if not os.access(authorized_keys_file_path, os.R_OK):
raise OSError('Access to file {} is without read access'.format(
authorized_keys_file_path))
ssh-support: don't use API calls to fetch the data....
r2186 line_tmpl = '{ssh_opts},command="{wrapper_command} {ini_path} --user-id={user_id} --user={user} --key-id={user_key_id}" {key}\n'
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994
fd, tmp_authorized_keys = tempfile.mkstemp(
'.authorized_keys_write',
dir=os.path.dirname(authorized_keys_file_path))
now = datetime.datetime.utcnow().isoformat()
keys_file = os.fdopen(fd, 'wb')
keys_file.write(HEADER.format(len(all_active_keys), now))
ssh: embedded ssh support...
r2043 ini_path = rhodecode.CONFIG['__file__']
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994
for user_key in all_active_keys:
username = user_key.user.username
ssh: embedded ssh support...
r2043 user_id = user_key.user.user_id
ssh(sec): fix newline problem on key saving that would allow bypassing command sandbox.
r2748 # replace all newline from ends and inside
safe_key_data = user_key.ssh_key_data\
.strip()\
ssh-keys: further sanitize data of inputted SSH keys.
r2751 .replace('\n', ' ') \
.replace('\t', ' ') \
ssh(sec): fix newline problem on key saving that would allow bypassing command sandbox.
r2748 .replace('\r', ' ')
ssh: embedded ssh support...
r2043
ssh(sec): fix newline problem on key saving that would allow bypassing command sandbox.
r2748 line = line_tmpl.format(
ssh_opts=ssh_opts or SSH_OPTS,
wrapper_command=ssh_wrapper_cmd,
ini_path=ini_path,
user_id=user_id,
user=username,
user_key_id=user_key.ssh_key_id,
key=safe_key_data)
keys_file.write(line)
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 log.debug('addkey: Key added for user: `%s`', username)
keys_file.close()
# Explicitly setting read-only permissions to authorized_keys
os.chmod(tmp_authorized_keys, stat.S_IRUSR | stat.S_IWUSR)
# Rename is atomic operation
os.rename(tmp_authorized_keys, authorized_keys_file_path)
def generate_ssh_authorized_keys_file(registry):
log.info('Generating new authorized key file')
authorized_keys_file_path = registry.settings.get(
config_keys.authorized_keys_file_path)
ssh_wrapper_cmd = registry.settings.get(
config_keys.wrapper_cmd)
allow_shell = registry.settings.get(
config_keys.wrapper_allow_shell)
ssh_opts = registry.settings.get(
config_keys.authorized_keys_line_ssh_opts)
ssh: embedded ssh support...
r2043 debug = registry.settings.get(
config_keys.enable_debug_logging)
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994
_generate_ssh_authorized_keys_file(
ssh: embedded ssh support...
r2043 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts,
debug)
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994
return 0