Ejemplo n.º 1
0
    def __init__(self, cb, config=None, address='', port=58337, backlog=100):
        self.cb = cb

        # Parse config <3
        if config is not None:
            with open(config, 'r') as f:
                cfg = yaml.load(f)
        else:
            cfg = {}

        logfile = cfg.get('logfile', None)
        if logfile is not None:
            paramiko.util.log_to_file(logile)

        host_key_path = cfg.get('host_key', 'server.key')
        host_key_password = cfg.get('host_key_password', None)
        try:
            self.host_key = RSAKey.from_private_key_file(
                host_key_path, host_key_password)
        except paramiko.ssh_exception.PasswordRequiredException:
            print 'Invalid host_key_password'
            sys.exit(1)
        except IOError:
            print '*****************************************'
            print '**      host_key does not exists!      **'
            print '** In the name of security by default, **'
            print '**   Sheet will generate one for you.  **'
            print '*****************************************'
            RSAKey.generate(2048).write_private_key_file(
                host_key_path, host_key_password)

        self.handler = Broker.get(cfg.get('auth_handler', 'BaseAuth'))
        self.handler_conf = cfg.get('auth_handler_config', {})

        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind((address, port))
        except Exception as e:
            print 'Bind failed: ', str(e)
            traceback.print_exc()
            sys.exit(1)

        try:
            self.socket.listen(backlog)
        except Exception as e:
            print 'Listen/accept failed:', str(e)
            traceback.print_exc()
            sys.exit(1)
Ejemplo n.º 2
0
    def generatekey(self):
        public_key = StringIO()
        private_key = StringIO()
        public_key_value = None
        private_key_value = None
        try:
            if self.keytype == 'rsa':
                key = RSAKey.generate(self.rsabits)
            elif self.keytype == 'ecdsa':
                key = ECDSAKey.generate(bits=self.ecdsabits)
            elif self.keytype == 'dss':
                key = DSSKey.generate(bits=self.dssbits)
            else:
                return None, "sshkey暂时不支持其它类型 %s" % self.keytype
            key.write_private_key(private_key)
            public_key.write("%s %s %s" %
                             (key.get_name(), key.get_base64(), self.basename))
            public_key_value = public_key.getvalue()
            private_key_value = private_key.getvalue()
            cache.set("user_%s_private_key" % self.username, private_key_value)
            cache.set("user_%s_public_key" % self.username, public_key_value)

        except Exception as e:
            logger.error(e.args)
            return None, e.args
        finally:
            public_key.close()
            private_key.close()
        return {
            "publickey": public_key_value,
            "privatekey": private_key_value
        }, None
Ejemplo n.º 3
0
def test_authorize_remote(fx_app, fx_authorized_servers, fx_master_key,
                          fx_authorized_remote_set, fx_authorized_identity,
                          fx_token_id, fx_key_store):
    public_key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, public_key)
    alias, remote = dict(fx_authorized_remote_set).popitem()
    with fx_app.test_client() as client:
        response = client.post(
            get_url('authorize_remote', token_id=fx_token_id, alias=alias))
        assert response.status_code == 200
        assert response.mimetype == 'application/json'
        result = json.loads(response.get_data())
        assert result['success'] == 'authorized'
        assert result['remote'] == remote_dict(remote)
        expires_at = parse_date(result['expires_at'])
    thread, path, ev = fx_authorized_servers[remote.port]
    authorized_keys_path = path.join('.ssh', 'authorized_keys')
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {fx_master_key, public_key}
    while datetime.datetime.now(datetime.timezone.utc) <= expires_at:
        time.sleep(1)
    time.sleep(1)
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {fx_master_key}
Ejemplo n.º 4
0
def start_server(path: str, host: str, port: int, terminated: threading.Event):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.settimeout(1)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    server_socket.bind((host, port))
    server_socket.listen(1)
    stub_cls = type('StubSFTPServer', (StubSFTPServer,), {'ROOT': path})
    host_key = RSAKey.generate(1024)

    def accept(server_socket, mask):
        conn, addr = server_socket.accept()
        transport = Transport(conn)
        transport.add_server_key(host_key)
        transport.set_subsystem_handler('sftp', SFTPServer, stub_cls)
        server = StubServer(path)
        transport.start_server(server=server)
        while not terminated.is_set():
            channel = transport.accept(1)
            if channel is not None and not terminated.is_set():
                while transport.is_active() and not terminated.is_set():
                    terminated.wait(1)
                break

    sel = selectors.DefaultSelector()
    sel.register(server_socket, selectors.EVENT_READ, accept)
    last_used = time.time()
    while not terminated.is_set() and last_used + 10 > time.time():
        events = sel.select(1)
        for key, mask in events:
            key.data(key.fileobj, mask)
            last_used = time.time()
Ejemplo n.º 5
0
def test_public_key(fx_app, fx_key_store,
                    fx_authorized_identity,
                    fx_token_id):
    key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, key)
    with fx_app.test_client() as client:
        response = client.get(
            get_url(
                'public_key',
                token_id=fx_token_id,
                fingerprint=key.get_fingerprint()
            )
        )
        assert response.status_code == 200
        assert response.mimetype == 'text/plain'
        assert parse_openssh_pubkey(response.data.decode()) == key
    with fx_app.test_client() as client:
        response = client.get(
            get_url(
                'public_key',
                token_id=fx_token_id,
                fingerprint=os.urandom(16)
            )
        )
        assert response.status_code == 404
        assert response.mimetype == 'application/json'
        error = json.loads(response.data.decode('utf-8'))
        assert error['error'] == 'not-found'
Ejemplo n.º 6
0
def gen_keys(key="", key_path_dir=""):
    """
    在KEY_DIR下创建一个 uuid命名的目录,
    并且在该目录下 生产一对秘钥
    :return: 返回目录名(uuid)
    """
    key_basename = "key-" + uuid4().hex
    if not key_path_dir:
        key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
    private_key = os.path.join(key_path_dir, 'id_rsa')
    public_key = os.path.join(key_path_dir, 'id_rsa.pub')
    mkdir(key_path_dir, mode=0755)
    if not key:
        key = RSAKey.generate(2048)
        key.write_private_key_file(private_key)
    else:
        key_file = os.path.join(key_path_dir, 'id_rsa')
        with open(key_file, 'w') as f:
            f.write(key)
            f.close()
        with open(key_file) as f:
            try:
                key = RSAKey.from_private_key(f)
            except SSHException, e:
                shutil.rmtree(key_path_dir, ignore_errors=True)
                raise SSHException(e)
Ejemplo n.º 7
0
def main():  # pragma: no cover
    """The main function for :program:`geofront-server` CLI program."""
    parser = main_parser()
    args = parser.parse_args()
    try:
        app.config.from_pyfile(os.path.abspath(args.config), silent=False)
    except FileNotFoundError:
        parser.error('unable to load configuration file: ' + args.config)
    logger = logging.getLogger('geofront')
    handler = logging.StreamHandler()
    level = logging.DEBUG if args.debug else logging.INFO
    handler.setLevel(level)
    logger.addHandler(handler)
    logger.setLevel(level)
    master_key_store = get_master_key_store()
    servers = frozenset(get_remote_set().values())
    try:
        key = master_key_store.load()
    except EmptyStoreError:
        if args.create_master_key or args.renew_master_key:
            logger.warn('no master key;  create one...')
            key = RSAKey.generate(1024)
            master_key_store.save(key)
            logger.info('created new master key: %s', get_key_fingerprint(key))
        else:
            parser.error('no master key;  try --create-master-key option '
                         'if you want to create one')
    else:
        if args.renew_master_key and not os.environ.get('WERKZEUG_RUN_MAIN'):
            renew_master_key(servers, master_key_store)
    master_key_renewal_interval = app.config['MASTER_KEY_RENEWAL']
    if not (master_key_renewal_interval is None
            or isinstance(master_key_renewal_interval, datetime.timedelta)):
        raise RuntimeError(
            'MASTER_KEY_RENEWAL configuration must be an instance of '
            'datetime.timedelta, not {!r}'.format(master_key_renewal_interval))
    if master_key_renewal_interval is not None:
        master_key_renewal = PeriodicalRenewal(servers, master_key_store,
                                               master_key_renewal_interval)
    waitress_options = {}
    if args.trusted_proxy:
        if hasattr(Adjustments, 'trusted_proxy'):
            # > 0.8.8
            # https://github.com/Pylons/waitress/pull/42
            waitress_options['trusted_proxy'] = True
        else:
            # <= 0.8.8
            app.wsgi_app = ProxyFix(app.wsgi_app)
    try:
        if args.debug:
            app.run(args.host, args.port, debug=True)
        else:
            serve(app,
                  host=args.host,
                  port=args.port,
                  asyncore_use_poll=True,
                  **waitress_options)
    finally:
        if master_key_renewal_interval is not None:
            master_key_renewal.terminate()
Ejemplo n.º 8
0
def renew_master_key(servers: collections.abc.Set,
                     key_store: MasterKeyStore) -> PKey:
    """Renew the master key.  It creates a new master key, makes ``servers``
    to authorize the new key, replaces the existing master key with the
    new key in the ``key_store``, and then makes ``servers`` to deauthorize
    the old key.  All these operations are done in a two-phase renewal
    transaction.

    :param servers: servers to renew the master key.
                    every element has to be an instance of
                    :class:`~.remote.Remote`
    :type servers: :class:`collections.abc.Set`
    :param key_store: the master key store to update
    :type key_store: :class:`MasterKeyStore`
    :returns: the created new master key
    :rtype: :class:`paramiko.pkey.PKey`

    """
    logger = logging.getLogger(__name__ + '.renew_master_key')
    logger.info('renew the master key...')
    old_key = key_store.load()
    logger.info('the existing master key: %s', get_key_fingerprint(old_key))
    new_key = RSAKey.generate(1024)
    logger.info('created new master key: %s', get_key_fingerprint(new_key))
    logger.info('authorize the new master key...')
    with TwoPhaseRenewal(servers, old_key, new_key):
        logger.info('the new master key is authorized; '
                    'update the key store...')
        key_store.save(new_key)
        logger.info('master key store is successfully updated; '
                    'deauthorize the existing master key...')
    logger.info('master key renewal has finished')
    return new_key
Ejemplo n.º 9
0
def renew_master_key(servers: collections.abc.Set, key_store: MasterKeyStore) -> PKey:
    """Renew the master key.  It creates a new master key, makes ``servers``
    to authorize the new key, replaces the existing master key with the
    new key in the ``key_store``, and then makes ``servers`` to deauthorize
    the old key.  All these operations are done in a two-phase renewal
    transaction.

    :param servers: servers to renew the master key.
                    every element has to be an instance of
                    :class:`~.remote.Remote`
    :type servers: :class:`collections.abc.Set`
    :param key_store: the master key store to update
    :type key_store: :class:`MasterKeyStore`
    :returns: the created new master key
    :rtype: :class:`paramiko.pkey.PKey`

    """
    logger = logging.getLogger(__name__ + ".renew_master_key")
    logger.info("renew the master key...")
    old_key = key_store.load()
    logger.info("the existing master key: %s", get_key_fingerprint(old_key))
    new_key = RSAKey.generate(1024)
    logger.info("created new master key: %s", get_key_fingerprint(new_key))
    logger.info("authorize the new master key...")
    with TwoPhaseRenewal(servers, old_key, new_key):
        logger.info("the new master key is authorized; " "update the key store...")
        key_store.save(new_key)
        logger.info("master key store is successfully updated; " "deauthorize the existing master key...")
    logger.info("master key renewal has finished")
    return new_key
Ejemplo n.º 10
0
def generate_ssh_key(path):
    """Create a new SSH private/public key pair."""
    key = RSAKey.generate(2048)
    key.write_private_key_file(path)
    with open(path + ".pub", "wb") as f:
        s = "%s %s" % (key.get_name(), key.get_base64())
        f.write(s.encode("ascii"))
Ejemplo n.º 11
0
def test_delete_public_key(fx_app, fx_key_store,
                           fx_authorized_identity,
                           fx_token_id):
    key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, key)
    with fx_app.test_client() as client:
        response = client.delete(
            get_url(
                'delete_public_key',
                token_id=fx_token_id,
                fingerprint=key.get_fingerprint()
            )
        )
        assert response.status_code == 200
    assert key not in fx_key_store.list_keys(fx_authorized_identity)
    with fx_app.test_client() as client:
        response = client.delete(
            get_url(
                'delete_public_key',
                token_id=fx_token_id,
                fingerprint=key.get_fingerprint()
            )
        )
        assert response.status_code == 404
        assert response.mimetype == 'application/json'
        error = json.loads(response.data.decode('utf-8'))
        assert error['error'] == 'not-found'
Ejemplo n.º 12
0
def test_authorize_remote(fx_app, fx_authorized_servers, fx_master_key,
                          fx_authorized_remote_set, fx_authorized_identity,
                          fx_token_id, fx_key_store):
    public_key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, public_key)
    alias, remote = dict(fx_authorized_remote_set).popitem()
    with fx_app.test_client() as client:
        response = client.post(
            get_url('authorize_remote', token_id=fx_token_id, alias=alias)
        )
        assert response.status_code == 200
        assert response.mimetype == 'application/json'
        result = json.loads(response.data)
        assert result['success'] == 'authorized'
        assert result['remote'] == remote_dict(remote)
        expires_at = parse_date(result['expires_at'])
    thread, path, ev = fx_authorized_servers[remote.port]
    authorized_keys_path = path.join('.ssh', 'authorized_keys')
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {fx_master_key, public_key}
    while datetime.datetime.now(datetime.timezone.utc) <= expires_at:
        time.sleep(1)
    time.sleep(1)
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {fx_master_key}
Ejemplo n.º 13
0
 def create_test_ssh_key(self):
     self.test_key = RSAKey.generate(1024)
     self.test_pubkey = "\nssh-rsa %s %s\n" % \
         (self.test_key.get_base64(), Tests.TEST_KEY_COMMENT)
     f = open(os.path.expanduser("~/.ssh/authorized_keys"), "a")
     f.write(self.test_pubkey)
     f.close()
Ejemplo n.º 14
0
def gen_keys(key="", key_path_dir=""):
    """
    在KEY_DIR下创建一个 uuid命名的目录,
    并且在该目录下 生产一对秘钥
    :return: 返回目录名(uuid)
    """
    key_basename = "key-" + uuid4().hex
    if not key_path_dir:
        key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
    private_key = os.path.join(key_path_dir, 'id_rsa')
    public_key = os.path.join(key_path_dir, 'id_rsa.pub')
    mkdir(key_path_dir, mode=755)
    if not key:
        key = RSAKey.generate(2048)
        key.write_private_key_file(private_key)
    else:
        key_file = os.path.join(key_path_dir, 'id_rsa')
        with open(key_file, 'w') as f:
            f.write(key)
            f.close()
        with open(key_file) as f:
            try:
                key = RSAKey.from_private_key(f)
            except SSHException, e:
                shutil.rmtree(key_path_dir, ignore_errors=True)
                raise SSHException(e)
Ejemplo n.º 15
0
def start_server(path: str, host: str, port: int, terminated: threading.Event):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.settimeout(1)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    server_socket.bind((host, port))
    server_socket.listen(1)
    stub_cls = type('StubSFTPServer', (StubSFTPServer, ), {'ROOT': path})
    host_key = RSAKey.generate(1024)

    def accept(server_socket, mask):
        conn, addr = server_socket.accept()
        transport = Transport(conn)
        transport.add_server_key(host_key)
        transport.set_subsystem_handler('sftp', SFTPServer, stub_cls)
        server = StubServer(path)
        transport.start_server(server=server)
        while not terminated.is_set():
            channel = transport.accept(1)
            if channel is not None and not terminated.is_set():
                while transport.is_active() and not terminated.is_set():
                    terminated.wait(1)
                break

    sel = selectors.DefaultSelector()
    sel.register(server_socket, selectors.EVENT_READ, accept)
    last_used = time.time()
    while not terminated.is_set() and last_used + 10 > time.time():
        events = sel.select(1)
        for key, mask in events:
            key.data(key.fileobj, mask)
            last_used = time.time()
Ejemplo n.º 16
0
def test_get_public_key(fx_app, fx_key_store, fx_authorized_identity,
                        fx_token_id):
    key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, key)
    with fx_app.test_request_context():
        found = get_public_key(fx_token_id, key.get_fingerprint())
        assert found == key
Ejemplo n.º 17
0
    def __init__(self, cb, config=None, address='', port=58337, backlog=100):
        self.cb = cb

        # Parse config <3
        if config is not None:
            with open(config, 'r') as f:
                cfg = yaml.load(f)
        else:
            cfg = {}

        logfile = cfg.get('logfile', None)
        if logfile is not None:
            paramiko.util.log_to_file(logile)

        host_key_path = cfg.get('host_key', 'server.key')
        host_key_password = cfg.get('host_key_password', None)
        try:
            self.host_key = RSAKey.from_private_key_file(host_key_path, host_key_password)
        except paramiko.ssh_exception.PasswordRequiredException:
            print 'Invalid host_key_password'
            sys.exit(1)
        except IOError:
            print '*****************************************'
            print '**      host_key does not exists!      **'
            print '** In the name of security by default, **'
            print '**   Sheet will generate one for you.  **'
            print '*****************************************'
            RSAKey.generate(2048).write_private_key_file(host_key_path, host_key_password)

        self.handler = Broker.get(cfg.get('auth_handler', 'BaseAuth'))
        self.handler_conf = cfg.get('auth_handler_config', {})

        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind((address, port))
        except Exception as e:
            print 'Bind failed: ', str(e)
            traceback.print_exc()
            sys.exit(1)

        try:
            self.socket.listen(backlog)
        except Exception as e:
            print 'Listen/accept failed:', str(e)
            traceback.print_exc()
            sys.exit(1)
Ejemplo n.º 18
0
    def generate_rsa_keypair(cls: type):
        new_key = RSAKey.generate(4096)
        private_key = StringIO()
        new_key.write_private_key(private_key)

        return cls.objects.create(public_key=' '.join(
            [new_key.get_name(), new_key.get_base64()]),
                                  private_key=private_key.getvalue())
Ejemplo n.º 19
0
def test_get_public_key(fx_app, fx_key_store,
                        fx_authorized_identity,
                        fx_token_id):
    key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, key)
    with fx_app.test_request_context():
        found = get_public_key(fx_token_id, key.get_fingerprint())
        assert found == key
Ejemplo n.º 20
0
def test_add_public_key_415(fx_app, fx_key_store, fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(get_url("add_public_key", token_id=fx_token_id), data={"key": format_openssh_pubkey(pkey)})
        assert response.status_code == 415
        error = json.loads(response.data)
        assert error["error"] == "unsupported-content-type"
        assert pkey not in fx_key_store.list_keys(fx_authorized_identity)
Ejemplo n.º 21
0
def test_cloud_master_public_key_store():
    driver = KeyPairSupportedDummyNodeDriver("")
    actual_store = MemoryMasterKeyStore()
    store = CloudMasterPublicKeyStore(driver, "geofront-masterkey", actual_store)
    for _ in range(2):
        master_key = RSAKey.generate(1024)
        store.save(master_key)
        assert actual_store.load() == store.load() == master_key
        assert parse_openssh_pubkey(driver.get_key_pair("geofront-masterkey").public_key) == master_key
Ejemplo n.º 22
0
def ssh_keygen():
    output = io.StringIO()
    try:
        key = RSAKey.generate(2048)
        key.write_private_key(output)
        private_key = output.getvalue()
        publick_key = '{HEAD} {KEY} {DOMAIN}'.format(HEAD='ssh-rsa', KEY=key.get_base64(), DOMAIN='*****@*****.**')
    except IOError as e:
        raise IOError('gen_keys: there was an error writing to the file')
    return private_key,publick_key
Ejemplo n.º 23
0
    def generateKey(self):
        self.pkey = RSAKey.generate(bits=4096)

        try:
            self.pkey.write_private_key_file(KEYFILE_PATH)
        except IOError as e:
            print("Unable to write private key to disk: {0}".format(e))
            return False
        else:
            return True
Ejemplo n.º 24
0
def test_fs_master_key_store_save(tmpdir):
    path = tmpdir.join('id_rsa')
    s = FileSystemMasterKeyStore(str(path))
    with raises(EmptyStoreError):
        s.load()
    key = RSAKey.generate(1024)
    s.save(key)
    stored_key = s.load()
    assert isinstance(stored_key, RSAKey)
    assert stored_key.get_base64() == stored_key.get_base64()
Ejemplo n.º 25
0
def test_fs_master_key_store_save(tmpdir):
    path = tmpdir.join('id_rsa')
    s = FileSystemMasterKeyStore(str(path))
    with raises(EmptyStoreError):
        s.load()
    key = RSAKey.generate(1024)
    s.save(key)
    stored_key = s.load()
    assert isinstance(stored_key, RSAKey)
    assert stored_key.get_base64() == stored_key.get_base64()
Ejemplo n.º 26
0
def test_add_public_key_415(fx_app, fx_key_store, fx_authorized_identity,
                            fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(get_url('add_public_key', token_id=fx_token_id),
                          data={'key': format_openssh_pubkey(pkey)})
        assert response.status_code == 415
        error = json.loads(response.get_data())
        assert error['error'] == 'unsupported-content-type'
        assert pkey not in fx_key_store.list_keys(fx_authorized_identity)
Ejemplo n.º 27
0
    def get_sshkey(self, email):
        output = io.StringIO()
        sbuffer = io.StringIO()

        key = RSAKey.generate(2048)
        key.write_private_key(output)
        private_key = output.getvalue()

        sbuffer.write("{} {} {}".format(key.get_name(), key.get_base64(), email))
        public_key = sbuffer.getvalue()
        return private_key, public_key
Ejemplo n.º 28
0
def test_cloud_master_public_key_store():
    driver = KeyPairSupportedDummyNodeDriver('')
    actual_store = MemoryMasterKeyStore()
    store = CloudMasterPublicKeyStore(driver, 'geofront-masterkey',
                                      actual_store)
    for _ in range(2):
        master_key = RSAKey.generate(1024)
        store.save(master_key)
        assert actual_store.load() == store.load() == master_key
        assert parse_openssh_pubkey(
            driver.get_key_pair('geofront-masterkey').public_key) == master_key
Ejemplo n.º 29
0
def test_add_public_key_duplicate_key(fx_app, fx_key_store,
                                      fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, pkey)
    with fx_app.test_client() as c:
        response = c.post(get_url('add_public_key', token_id=fx_token_id),
                          content_type='text/plain',
                          data=format_openssh_pubkey(pkey).encode())
        assert response.status_code == 400
        error = json.loads(response.get_data())
        assert error['error'] == 'duplicate-key'
Ejemplo n.º 30
0
def test_authorized_keys_list_extend(fx_authorized_sftp):
    sftp_client, path, keys = fx_authorized_sftp
    key_list = AuthorizedKeyList(sftp_client)
    new_keys = [RSAKey.generate(1024) for _ in range(3)]
    key_list.extend(new_keys)
    with path.join('.ssh', 'authorized_keys').open() as f:
        for i in range(6):
            assert parse_openssh_pubkey(f.readline().strip()) == keys[i]
        for i in range(3):
            assert parse_openssh_pubkey(f.readline().strip()) == new_keys[i]
        assert not f.readline().strip()
Ejemplo n.º 31
0
def test_authorized_keys_list_extend(fx_authorized_sftp):
    sftp_client, path, keys = fx_authorized_sftp
    key_list = AuthorizedKeyList(sftp_client)
    new_keys = [RSAKey.generate(1024) for _ in range(3)]
    key_list.extend(new_keys)
    with path.join('.ssh', 'authorized_keys').open() as f:
        for i in range(6):
            assert parse_openssh_pubkey(f.readline().strip()) == keys[i]
        for i in range(3):
            assert parse_openssh_pubkey(f.readline().strip()) == new_keys[i]
        assert not f.readline().strip()
Ejemplo n.º 32
0
def test_authorized_keys_list_insert(fx_authorized_sftp):
    sftp_client, path, keys = fx_authorized_sftp
    key_list = AuthorizedKeyList(sftp_client)
    new_key = RSAKey.generate(1024)
    key_list.insert(2, new_key)
    with path.join('.ssh', 'authorized_keys').open() as f:
        assert parse_openssh_pubkey(f.readline().strip()) == keys[0]
        assert parse_openssh_pubkey(f.readline().strip()) == keys[1]
        assert parse_openssh_pubkey(f.readline().strip()) == new_key
        for i in range(2, 6):
            assert parse_openssh_pubkey(f.readline().strip()) == keys[i]
        assert not f.readline().strip()
Ejemplo n.º 33
0
    def _get_key_name_pattern(self, identity: Identity) -> Pattern[str]:
        """Make the regex pattern from the format string.  Put two different
        random keys, compare two outputs, and then replace the difference
        with wildcard.

        """
        cls = type(self)
        sample_keys = cls._sample_keys
        if sample_keys is None:
            sample_keys = (RSAKey.generate(bits=512),
                           RSAKey.generate(bits=512),
                           ECDSAKey.generate(bits=256),
                           ECDSAKey.generate(bits=256))
            cls._sample_keys = sample_keys
        sample_names = [self._get_key_name(identity, k) for k in sample_keys]
        if len(frozenset(sample_names)) < 2:
            return re.compile('^' + re.escape(sample_names[0]) + '$')
        prefix = os.path.commonprefix(sample_names)
        postfix = os.path.commonprefix([n[::-1] for n in sample_names])[::-1]
        return re.compile('^{}.+?{}$'.format(re.escape(prefix),
                                             re.escape(postfix)))
Ejemplo n.º 34
0
def test_add_public_key_unsupported_type(fx_app, fx_key_store, fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(
            get_url("add_public_key", token_id=fx_token_id),
            content_type="text/plain",
            data=("invalid-type " + format_openssh_pubkey(pkey)[7:]).encode(),
        )
        assert response.status_code == 400
        error = json.loads(response.data)
        assert error["error"] == "unsupported-key-type"
        assert pkey not in fx_key_store.list_keys(fx_authorized_identity)
Ejemplo n.º 35
0
def test_authorized_keys_list_insert(fx_authorized_sftp):
    sftp_client, path, keys = fx_authorized_sftp
    key_list = AuthorizedKeyList(sftp_client)
    new_key = RSAKey.generate(1024)
    key_list.insert(2, new_key)
    with path.join('.ssh', 'authorized_keys').open() as f:
        assert parse_openssh_pubkey(f.readline().strip()) == keys[0]
        assert parse_openssh_pubkey(f.readline().strip()) == keys[1]
        assert parse_openssh_pubkey(f.readline().strip()) == new_key
        for i in range(2, 6):
            assert parse_openssh_pubkey(f.readline().strip()) == keys[i]
        assert not f.readline().strip()
Ejemplo n.º 36
0
    def _get_key_name_pattern(self, identity: Identity):
        """Make the regex pattern from the format string.  Put two different
        random keys, compare two outputs, and then replace the difference
        with wildcard.

        """
        cls = type(self)
        try:
            sample_keys = cls.sample_keys
        except AttributeError:
            sample_keys = RSAKey.generate(1024), RSAKey.generate(1024)
            cls.sample_keys = sample_keys
        sample_name_a = self._get_key_name(identity, sample_keys[0])
        sample_name_b = self._get_key_name(identity, sample_keys[1])
        if sample_name_a == sample_name_b:
            return re.compile('^' + re.escape(sample_name_a) + '$')
        prefix = os.path.commonprefix([sample_name_a, sample_name_b])
        postfix = os.path.commonprefix(
            [sample_name_a[::-1], sample_name_b[::-1]])[::-1]
        return re.compile('^{}.+?{}$'.format(re.escape(prefix),
                                             re.escape(postfix)))
Ejemplo n.º 37
0
def test_add_public_key_unsupported_type(fx_app, fx_key_store,
                                         fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(get_url('add_public_key', token_id=fx_token_id),
                          content_type='text/plain',
                          data=('invalid-type ' +
                                format_openssh_pubkey(pkey)[7:]).encode())
        assert response.status_code == 400
        error = json.loads(response.get_data())
        assert error['error'] == 'unsupported-key-type'
        assert pkey not in fx_key_store.list_keys(fx_authorized_identity)
Ejemplo n.º 38
0
def test_add_public_key_duplicate_key(fx_app, fx_key_store, fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, pkey)
    with fx_app.test_client() as c:
        response = c.post(
            get_url("add_public_key", token_id=fx_token_id),
            content_type="text/plain",
            data=format_openssh_pubkey(pkey).encode(),
        )
        assert response.status_code == 400
        error = json.loads(response.data)
        assert error["error"] == "duplicate-key"
Ejemplo n.º 39
0
def test_authorize(fx_sftpd):
    port, (thread, path, ev) = fx_sftpd.popitem()
    thread.start()
    master_key = RSAKey.generate(1024)
    public_keys = {RSAKey.generate(1024), RSAKey.generate(1024)}
    authorized_keys_path = path.mkdir('.ssh').join('authorized_keys')
    with authorized_keys_path.open('w') as f:
        print(format_openssh_pubkey(master_key), file=f)
    expires_at = authorize(public_keys,
                           master_key,
                           Remote('user', '127.0.0.1', port),
                           timeout=datetime.timedelta(seconds=5))
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == (public_keys | {master_key})
    while datetime.datetime.now(datetime.timezone.utc) <= expires_at:
        time.sleep(1)
    time.sleep(1)
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {master_key}
Ejemplo n.º 40
0
def generate_and_save_ssh_key():
    keys = GlobalConfig.query.filter(GlobalConfig.name.in_(['ssh_private_key', 'ssh_public_key'])).all()
    if len(keys) == 0:
        key_obj = StringIO()
        key = RSAKey.generate(2048)
        key.write_private_key(key_obj)
        private_key, public_key = generate_ssh_key()
        GlobalConfig(name='ssh_private_key', value=private_key, desc='SSH私钥').add()
        GlobalConfig(name='ssh_public_key', value=public_key, desc='SSH公钥').save()
        return key, key.get_base64()
    else:
        raise Exception('Already has ssh key')
Ejemplo n.º 41
0
 def __init__(self, private_key=None, private_key_path=None, pub_data=None, _key=None, password=None):
     if private_key:
         self._key = RSAKey(file_obj=io.StringIO(private_key))
     elif private_key_path:
         self._key = RSAKey(filename=private_key_path, password=password)
     elif pub_data:
         if pub_data.startswith(self.SSH_PUB_KEY_PREFIX):
             pub_data = pub_data[len(self.SSH_PUB_KEY_PREFIX):]
         self._key = RSAKey(data=b64decode(pub_data.encode('utf-8')))
     elif _key:
         self._key = _key
     else:
         self._key = RSAKey.generate(self.KEY_SIZE)
Ejemplo n.º 42
0
    def _get_key_name_pattern(self, identity: Identity):
        """Make the regex pattern from the format string.  Put two different
        random keys, compare two outputs, and then replace the difference
        with wildcard.

        """
        cls = type(self)
        try:
            sample_keys = cls.sample_keys
        except AttributeError:
            sample_keys = RSAKey.generate(1024), RSAKey.generate(1024)
            cls.sample_keys = sample_keys
        sample_name_a = self._get_key_name(identity, sample_keys[0])
        sample_name_b = self._get_key_name(identity, sample_keys[1])
        if sample_name_a == sample_name_b:
            return re.compile('^' + re.escape(sample_name_a) + '$')
        prefix = os.path.commonprefix([sample_name_a, sample_name_b])
        postfix = os.path.commonprefix([sample_name_a[::-1],
                                        sample_name_b[::-1]])[::-1]
        return re.compile(
            '^{}.+?{}$'.format(re.escape(prefix), re.escape(postfix))
        )
Ejemplo n.º 43
0
def test_add_public_key(fx_app, fx_key_store, fx_authorized_identity,
                        fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(get_url('add_public_key', token_id=fx_token_id),
                          content_type='text/plain',
                          data=format_openssh_pubkey(pkey).encode())
        assert response.status_code == 201
        key_data = response.get_data()
        assert parse_openssh_pubkey(key_data.decode()) == pkey
        assert pkey in fx_key_store.list_keys(fx_authorized_identity)
        r = c.get(response.location)
        assert r.get_data() == key_data
Ejemplo n.º 44
0
def test_two_phase_renewal(fx_authorized_servers, fx_master_key):
    remote_set = {
        Remote('user', '127.0.0.1', port)
        for port in fx_authorized_servers
    }
    old_key = fx_master_key
    new_key = RSAKey.generate(1024)
    for t, path, ev in fx_authorized_servers.values():
        assert authorized_key_set(path) == {old_key}
    with TwoPhaseRenewal(remote_set, old_key, new_key):
        for t, path, ev in fx_authorized_servers.values():
            assert authorized_key_set(path) == {old_key, new_key}
    for t, path, ev in fx_authorized_servers.values():
        assert authorized_key_set(path) == {new_key}
Ejemplo n.º 45
0
    def _get_key_name_pattern(self,
                              identity: Identity) -> Pattern[str]:
        """Make the regex pattern from the format string.  Put two different
        random keys, compare two outputs, and then replace the difference
        with wildcard.

        """
        cls = type(self)
        sample_keys = cls._sample_keys
        if sample_keys is None:
            sample_keys = (RSAKey.generate(bits=512),
                           RSAKey.generate(bits=512),
                           ECDSAKey.generate(bits=256),
                           ECDSAKey.generate(bits=256))
            cls._sample_keys = sample_keys
        sample_names = [self._get_key_name(identity, k) for k in sample_keys]
        if len(frozenset(sample_names)) < 2:
            return re.compile('^' + re.escape(sample_names[0]) + '$')
        prefix = os.path.commonprefix(sample_names)
        postfix = os.path.commonprefix([n[::-1] for n in sample_names])[::-1]
        return re.compile(
            '^{}.+?{}$'.format(re.escape(prefix), re.escape(postfix))
        )
Ejemplo n.º 46
0
def test_list_public_keys(fx_app, fx_key_store, fx_authorized_identity, fx_token_id):
    with fx_app.test_client() as c:
        response = c.get(get_url("list_public_keys", token_id=fx_token_id))
        assert response.status_code == 200
        assert response.mimetype == "application/json"
        assert response.data == b"{}"
    key = RSAKey.generate(1024)
    fx_key_store.register(fx_authorized_identity, key)
    with fx_app.test_client() as c:
        response = c.get(get_url("list_public_keys", token_id=fx_token_id))
        assert response.status_code == 200
        assert response.mimetype == "application/json"
        data = {f: parse_openssh_pubkey(k) for f, k in json.loads(response.data).items()}
        assert data == {get_key_fingerprint(key): key}
Ejemplo n.º 47
0
def test_add_public_key(fx_app, fx_key_store, fx_authorized_identity, fx_token_id):
    pkey = RSAKey.generate(1024)
    with fx_app.test_client() as c:
        response = c.post(
            get_url("add_public_key", token_id=fx_token_id),
            content_type="text/plain",
            data=format_openssh_pubkey(pkey).encode(),
        )
        assert response.status_code == 201
        key_data = response.data
        assert parse_openssh_pubkey(key_data.decode()) == pkey
        assert pkey in fx_key_store.list_keys(fx_authorized_identity)
        r = c.get(response.location)
        assert r.data == key_data
Ejemplo n.º 48
0
def gen_keys(emial, key=""):
    """
    生成公钥 私钥
    """
    output = StringIO.StringIO()
    sbuffer = StringIO.StringIO()
    key_content = {}
    if not key:
        try:
            key = RSAKey.generate(2048)
            key.write_private_key(output)
            private_key = output.getvalue()
        except Exception, ex:
            return False, str(ex)
Ejemplo n.º 49
0
def test_two_phase_renewal(fx_authorized_servers, fx_master_key):
    remote_set = {
        Remote('user', '127.0.0.1', port)
        for port in fx_authorized_servers
    }
    old_key = fx_master_key
    new_key = RSAKey.generate(1024)
    for t, path, ev in fx_authorized_servers.values():
        assert authorized_key_set(path) == {old_key}
    with TwoPhaseRenewal(remote_set, old_key, new_key):
        for t, path, ev in fx_authorized_servers.values():
            assert authorized_key_set(path) == {old_key, new_key}
    for t, path, ev in fx_authorized_servers.values():
        assert authorized_key_set(path) == {new_key}
Ejemplo n.º 50
0
def test_authorize(fx_sftpd):
    port, (thread, path, ev) = fx_sftpd.popitem()
    thread.start()
    master_key = RSAKey.generate(1024)
    public_keys = {RSAKey.generate(1024), RSAKey.generate(1024)}
    authorized_keys_path = path.mkdir('.ssh').join('authorized_keys')
    with authorized_keys_path.open('w') as f:
        print(format_openssh_pubkey(master_key), file=f)
    expires_at = authorize(
        public_keys,
        master_key,
        Remote('user', '127.0.0.1', port),
        timeout=datetime.timedelta(seconds=5)
    )
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == (public_keys | {master_key})
    while datetime.datetime.now(datetime.timezone.utc) <= expires_at:
        time.sleep(1)
    time.sleep(1)
    with authorized_keys_path.open() as f:
        saved_keys = map(parse_openssh_pubkey, f)
        assert frozenset(saved_keys) == {master_key}
Ejemplo n.º 51
0
def generate_key_pair(cluster, girder_token=None):
    """
    Task to generate a new key pair for a user.
    """
    cluster_id = cluster['_id']
    status_url = '%s/clusters/%s' \
        % (cumulus.config.girder.baseUrl, cluster_id)
    log = get_cluster_logger(cluster, girder_token)
    headers = {'Girder-Token': girder_token}

    try:
        new_key = RSAKey.generate(bits=4096)
        passphrase = ''.join(
            random.SystemRandom().choice(string.ascii_uppercase +
                                         string.digits) for _ in range(64))
        key_path = os.path.join(cumulus.config.ssh.keyStore, cluster_id)

        new_key.write_private_key_file(key_path, password=passphrase)
        # Allow group read as well
        os.chmod(key_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP)

        comment = 'cumulus generated access key'
        public_key = '%s %s %s' % (new_key.get_name(), new_key.get_base64(),
                                   comment)

        # Update passphrase and public key on cluster model
        config_update = {
            'config': {
                'ssh': {
                    'passphrase': passphrase,
                    'publicKey': public_key
                }
            },
            'status': 'created'
        }

        patch_url = '%s/clusters/%s' % (cumulus.config.girder.baseUrl,
                                        cluster_id)
        request = requests.patch(patch_url,
                                 json=config_update,
                                 headers=headers)
        check_status(request)
    except Exception as ex:
        r = requests.patch(status_url,
                           headers=headers,
                           json={'status': 'error'})
        check_status(r)
        # Log the error message
        log.error(ex)
Ejemplo n.º 52
0
def fx_authorized_sftp(fx_sftpd, fx_authorized_keys):
    port, (thread, path, ev) = fx_sftpd.popitem()
    thread.start()
    key = RSAKey.generate(1024)
    dot_ssh = path.mkdir('.ssh')
    with dot_ssh.join('authorized_keys').open('w') as f:
        print(format_openssh_pubkey(key), file=f)
        for authorized_key in fx_authorized_keys:
            print(format_openssh_pubkey(authorized_key), file=f)
    transport = Transport(('127.0.0.1', port))
    transport.connect(username='******', pkey=key)
    sftp_client = SFTPClient.from_transport(transport)
    yield sftp_client, path, [key] + fx_authorized_keys
    sftp_client.close()
    transport.close()
Ejemplo n.º 53
0
def generate_private_rsa_key_file(ssh_path, key_base_name):
    """
        Generate a default PRIVATE SSH key file using RSA
    """
    # paramiko uses pycrypto's RandomPool which throws a deprecation warning
    import warnings
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        from paramiko import RSAKey

    key = RSAKey.generate(2048)
    private_key_file_name = ssh_path + "/" + key_base_name
    key.write_private_key_file(private_key_file_name)

    # Ok, pass back private key object
    return key
Ejemplo n.º 54
0
def generate_key_pair(cluster, girder_token=None):
    '''
    Task to generate a new key pair for a user.
    '''
    cluster_id = cluster['_id']
    status_url = '%s/clusters/%s' \
        % (cumulus.config.girder.baseUrl, cluster_id)
    log = get_cluster_logger(cluster, girder_token)
    headers = {'Girder-Token':  girder_token}

    try:
        new_key = RSAKey.generate(bits=4096)
        passphrase = ''.join(random.SystemRandom()
                             .choice(string.ascii_uppercase +
                                     string.digits) for _ in range(64))
        key_path = os.path.join(cumulus.config.ssh.keyStore, cluster_id)

        new_key.write_private_key_file(key_path, password=passphrase)
        # Allow group read as well
        os.chmod(key_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP)

        comment = 'cumulus generated access key'
        public_key = '%s %s %s' % (new_key.get_name(), new_key.get_base64(),
                                   comment)

        # Update passphrase and public key on cluster model
        config_update = {
            'config': {
                'ssh': {
                    'passphrase': passphrase,
                    'publicKey': public_key
                }
            },
            'status': 'created'
        }

        patch_url = '%s/clusters/%s' % (cumulus.config.girder.baseUrl,
                                        cluster_id)
        request = requests.patch(patch_url, json=config_update, headers=headers)
        check_status(request)
    except Exception as ex:
        r = requests.patch(status_url, headers=headers,
                           json={'status': 'error'})
        check_status(r)
        # Log the error message
        log.error(ex.message)
Ejemplo n.º 55
0
def test_cloud_master_key_store():
    driver = DummyStorageDriver('', '')
    container = driver.create_container('geofront-test')
    s = CloudMasterKeyStore(driver, container, 'test_id_rsa')
    with raises(EmptyStoreError):
        s.load()
    key = RSAKey.generate(1024)
    s.save(key)
    driver.get_object(container.name, 'test_id_rsa')  # assert object exists
    # Mocking implementation
    with io.StringIO() as mock:
        key.write_private_key(mock)
        mock.seek(0)
        dummy.DummyFileObject = lambda *a, **k: mock
        stored_key = s.load()
        assert isinstance(stored_key, RSAKey)
        assert stored_key.get_base64() == stored_key.get_base64()
Ejemplo n.º 56
0
def test_two_phase_renewal_stop(fx_authorized_servers, fx_master_key):
    remote_set = {
        Remote('user', '127.0.0.1', port)
        for port in fx_authorized_servers
    }
    old_key = fx_master_key
    new_key = RSAKey.generate(1024)
    for t, path, ev in fx_authorized_servers.values():
        assert authorized_key_set(path) == {old_key}
    SomeException = type('SomeException', (Exception,), {})
    with raises(SomeException):
        with TwoPhaseRenewal(remote_set, old_key, new_key):
            for t, path, ev in fx_authorized_servers.values():
                assert authorized_key_set(path) == {old_key, new_key}
            raise SomeException('something went wrong')
    for t, path, ev in fx_authorized_servers.values():
        assert old_key in authorized_key_set(path)
Ejemplo n.º 57
0
def renew_master_key(servers: collections.abc.Set,
                     key_store: MasterKeyStore,
                     bits: int=2048) -> PKey:
    """Renew the master key.  It creates a new master key, makes ``servers``
    to authorize the new key, replaces the existing master key with the
    new key in the ``key_store``, and then makes ``servers`` to deauthorize
    the old key.  All these operations are done in a two-phase renewal
    transaction.

    :param servers: servers to renew the master key.
                    every element has to be an instance of
                    :class:`~.remote.Remote`
    :type servers: :class:`collections.abc.Set`
    :param key_store: the master key store to update
    :type key_store: :class:`MasterKeyStore`
    :param bits: the number of bits the generated key should be.
                 it has to be 1024 at least, and a multiple of 256.
                 2048 by default
    :type bits: :class:`int`
    :returns: the created new master key
    :rtype: :class:`paramiko.pkey.PKey`

    .. versionadded:: 0.2.0
       The ``bits`` optional parameter.

    """
    logger = logging.getLogger(__name__ + '.renew_master_key')
    logger.info('renew the master key...')
    old_key = key_store.load()
    logger.info('the existing master key: %s', get_key_fingerprint(old_key))
    new_key = RSAKey.generate(bits)
    logger.info('created new master key: %s', get_key_fingerprint(new_key))
    logger.info('authorize the new master key...')
    with TwoPhaseRenewal(servers, old_key, new_key):
        logger.info('the new master key is authorized; '
                    'update the key store...')
        key_store.save(new_key)
        logger.info('master key store is successfully updated; '
                    'deauthorize the existing master key...')
    logger.info('master key renewal has finished')
    return new_key