예제 #1
0
    def get_docker_endpoint(self, owner, cloud_id, job_id=None):
        if job_id:
            event = get_story(owner.id, job_id)
            assert owner.id == event['owner_id'], 'Owner ID mismatch!'
            self.host, docker_port = config.DOCKER_IP, config.DOCKER_PORT
            return docker_port, event['logs'][0]['container_id']

        cloud = Cloud.objects.get(owner=owner, id=cloud_id, deleted=None)
        self.host, docker_port = dnat(owner, self.host, cloud.port)
        return docker_port, cloud
예제 #2
0
    def load(self, machines=None):
        self.hosts = {}
        self.keys = {}
        if not machines:
            clouds = Cloud.objects(owner=self.owner, deleted=None)
            machines = [(machine.cloud.id, machine.machine_id)
                        for machine in Machine.objects(cloud__in=clouds)]
        for bid, mid in machines:
            try:
                name, ip_addr = self.find_machine_details(bid, mid)
                key_id, ssh_user, port = self.find_ssh_settings(bid, mid)
            except Exception as exc:
                print(exc)
                continue
            ip_addr, port = dnat(self.owner, ip_addr, port)
            if key_id not in self.keys:
                key = SSHKey.objects.get(owner=self.owner,
                                         name=key_id,
                                         deleted=None)
                self.keys[key_id] = key.private
                if isinstance(key, SignedSSHKey):
                    # if signed ssh key, provide the key appending a -cert.pub
                    # on the name since this is how ssh will include it as
                    # an identify file
                    self.keys['%s-cert.pub' % key_id] = key.certificate
                    # pub key also needed for openssh 7.2
                    self.keys['%s.pub' % key_id] = key.public
            if name in self.hosts:
                num = 2
                while ('%s-%d' % (name, num)) in self.hosts:
                    num += 1
                name = '%s-%d' % (name, num)

            self.hosts[name] = {
                'ansible_ssh_host': ip_addr,
                'ansible_ssh_port': port,
                'ansible_ssh_user': ssh_user,
                'ansible_ssh_private_key_file': 'id_rsa/%s' % key_id,
            }
예제 #3
0
    def get_lxd_endpoint(self, owner, cloud_id, job_id=None):

        cloud = Cloud.objects.get(owner=owner, id=cloud_id, deleted=None)
        self.host, lxd_port = dnat(owner, self.host, cloud.port)
        return lxd_port, cloud
예제 #4
0
    def autoconfigure(self,
                      owner,
                      cloud_id,
                      machine_id,
                      key_id=None,
                      username=None,
                      password=None,
                      port=22):
        """Autoconfigure SSH client.

        This will do its best effort to find a suitable key and username
        and will try to connect. If it fails it raises
        MachineUnauthorizedError, otherwise it initializes self and returns a
        (key_id, ssh_user) tuple. If connection succeeds, it updates the
        association information in the key with the current timestamp and the
        username used to connect.

        """
        log.info("autoconfiguring Shell for machine %s:%s", cloud_id,
                 machine_id)

        cloud = Cloud.objects.get(owner=owner, id=cloud_id, deleted=None)
        machine = Machine.objects.get(cloud=cloud, id=machine_id)
        key_associations = KeyMachineAssociation.objects(machine=machine)
        log.info('Got cloud & machine: %d key associations' %
                 len(key_associations))
        if key_id:
            keys = [Key.objects.get(owner=owner, id=key_id, deleted=None)]
            log.info('Got key')
        else:
            keys = [
                association.key for association in key_associations
                if isinstance(association.key, Key)
            ]
            log.info('Got keys %d' % len(keys))
        if username:
            users = [username]
        else:
            users = list(
                set([
                    association.ssh_user for association in key_associations
                    if association.ssh_user
                ]))
        log.info('Got users:{}'.format(users))
        if not users:
            for name in [
                    'root', 'ubuntu', 'ec2-user', 'user', 'azureuser', 'core',
                    'centos', 'cloud-user', 'fedora'
            ]:
                if name not in users:
                    users.append(name)
        if port != 22:
            ports = [port]
        else:
            ports = list(
                set([key_assoc.port for key_assoc in key_associations]))
        if 22 not in ports:
            ports.append(22)
        log.info('Got ports:{}'.format(ports))
        # store the original destination IP to prevent rewriting it when NATing
        ssh_host = self.host
        for key in keys:
            for ssh_user in users:
                for port in ports:
                    try:
                        # store the original ssh port in case of NAT
                        # by the OpenVPN server
                        ssh_port = port
                        self.host, port = dnat(owner, ssh_host, port)
                        log.info("ssh -i %s %s@%s:%s", key.name, ssh_user,
                                 self.host, port)
                        cert_file = ''
                        if isinstance(key, SignedSSHKey):
                            cert_file = key.certificate

                        self.connect(username=ssh_user,
                                     key=key,
                                     password=password,
                                     cert_file=cert_file,
                                     port=port)
                    except MachineUnauthorizedError:
                        continue

                    retval, resp = self.command('uptime')
                    new_ssh_user = None
                    if 'Please login as the user ' in resp:
                        new_ssh_user = resp.split()[5].strip('"')
                    elif 'Please login as the' in resp:
                        # for EC2 Amazon Linux machines, usually with ec2-user
                        new_ssh_user = resp.split()[4].strip('"')
                    if new_ssh_user:
                        log.info("retrying as %s", new_ssh_user)
                        try:
                            self.disconnect()
                            cert_file = ''
                            if isinstance(key, SignedSSHKey):
                                cert_file = key.certificate
                            self.connect(username=new_ssh_user,
                                         key=key,
                                         password=password,
                                         cert_file=cert_file,
                                         port=port)
                            ssh_user = new_ssh_user
                        except MachineUnauthorizedError:
                            continue
                    # we managed to connect successfully, return
                    # but first update key
                    trigger_session_update_flag = False
                    for key_assoc in KeyMachineAssociation.objects(
                            machine=machine):
                        if key_assoc.key == key:
                            if key_assoc.ssh_user != ssh_user:
                                key_assoc.ssh_user = ssh_user
                                trigger_session_update_flag = True
                            break
                    else:
                        trigger_session_update_flag = True
                        # in case of a private host do NOT update the key
                        # associations with the port allocated by the OpenVPN
                        # server, instead use the original ssh_port
                        key_assoc = KeyMachineAssociation(
                            key=key,
                            machine=machine,
                            ssh_user=ssh_user,
                            port=ssh_port,
                            sudo=self.check_sudo())
                        key_assoc.save()
                    machine.save()
                    if trigger_session_update_flag:
                        trigger_session_update(owner.id, ['keys'])
                    return key.name, ssh_user

        raise MachineUnauthorizedError("%s:%s" % (cloud_id, machine_id))
예제 #5
0
def machine_rdp(request):
    """
    Tags: machines
    ---
    Rdp file for windows machines.
    Generates and returns an rdp file for windows machines.
    READ permission required on cloud.
    READ permission required on machine.
    ---
    cloud:
      in: path
      required: true
      type: string
    machine:
      in: path
      required: true
      type: string
    rdp_port:
      default: 3389
      in: query
      required: true
      type: integer
    host:
      in: query
      required: true
      type: string
    """
    cloud_id = request.matchdict.get('cloud')

    auth_context = auth_context_from_request(request)

    if cloud_id:
        machine_id = request.matchdict['machine']
        auth_context.check_perm("cloud", "read", cloud_id)
        try:
            machine = Machine.objects.get(cloud=cloud_id,
                                          machine_id=machine_id,
                                          state__ne='terminated')
            # used by logging_view_decorator
            request.environ['machine_uuid'] = machine.id
        except Machine.DoesNotExist:
            raise NotFoundError("Machine %s doesn't exist" % machine_id)
    else:
        machine_uuid = request.matchdict['machine_uuid']
        try:
            machine = Machine.objects.get(id=machine_uuid,
                                          state__ne='terminated')
            # used by logging_view_decorator
            request.environ['machine_id'] = machine.machine_id
            request.environ['cloud_id'] = machine.cloud.id
        except Machine.DoesNotExist:
            raise NotFoundError("Machine %s doesn't exist" % machine_uuid)

        cloud_id = machine.cloud.id
        auth_context.check_perm("cloud", "read", cloud_id)

    auth_context.check_perm("machine", "read", machine.id)
    rdp_port = request.params.get('rdp_port', 3389)
    host = request.params.get('host')

    if not host:
        raise BadRequestError('No hostname specified')
    try:
        1 < int(rdp_port) < 65535
    except (ValueError, TypeError):
        rdp_port = 3389

    host, rdp_port = dnat(auth_context.owner, host, rdp_port)

    rdp_content = 'full address:s:%s:%s\nprompt for credentials:i:1' % \
                  (host, rdp_port)
    return Response(content_type='application/octet-stream',
                    content_disposition='attachment; filename="%s.rdp"' % host,
                    charset='utf8',
                    pragma='no-cache',
                    body=rdp_content)