Beispiel #1
0
def toggle_cloud(request):
    """
    Tags: clouds
    ---
    Toggles cloud with given cloud id.
    EDIT permission required on cloud.
    ---
    cloud_id:
      in: path
      required: true
      type: string
    new_state:
      enum:
      - '0'
      - '1'
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except Cloud.DoesNotExist:
        raise NotFoundError('Cloud does not exist')

    auth_context.check_perm('cloud', 'edit', cloud_id)

    new_state = params_from_request(request).get('new_state', None)
    dns_enabled = params_from_request(request).get('dns_enabled', None)

    if new_state == '1':
        cloud.ctl.enable()
    elif new_state == '0':
        cloud.ctl.disable()
    elif new_state:
        raise BadRequestError('Invalid cloud state')

    if dns_enabled == 1:
        cloud.ctl.dns_enable()
    elif dns_enabled == 0:
        cloud.ctl.dns_disable()
    elif dns_enabled:
        raise BadRequestError('Invalid DNS state')

    if new_state is None and dns_enabled is None:
        raise RequiredParameterMissingError('new_state or dns_enabled')

    trigger_session_update(auth_context.owner, ['clouds'])
    return OK
Beispiel #2
0
def get_stats(request):
    """
    Tags: monitoring
    ---
    Request monitoring data for a machine
    ---
    machine:
      in: path
      type: string
      required: true
    start:
      in: query
      type: string
      default: now
      required: false
      description: time (eg. '10s') since when to fetch stats
    stop:
      in: query
      type: string
      required: false
      description: time until when to fetch stats
    step:
      in: query
      type: string
      required: false
      description: step to fetch stats, used in aggregations
    metrics:
      in: query
      type: string
      required: false
    request_id:
      in: query
      type: string
      required: false

    """
    machine = _machine_from_matchdict(request)
    if not machine.monitoring.hasmonitoring:
        raise MethodNotAllowedError("Machine doesn't have monitoring enabled")

    # SEC require permission READ on machine
    auth_context = auth_context_from_request(request)
    auth_context.check_perm('machine', 'read', machine.id)

    params = params_from_request(request)
    start = params.get('start', '')
    stop = params.get('stop', '')
    step = params.get('step', '')
    try:
        metrics = params.getall('metrics')
    except:
        metrics = params.get('metrics')

    data = mist.api.monitoring.methods.get_stats(machine,
                                                 start=start,
                                                 stop=stop,
                                                 step=step,
                                                 metrics=metrics)
    data['request_id'] = params.get('request_id')
    return data
Beispiel #3
0
def rename_cloud(request):
    """
    Rename a cloud
    Renames cloud with given cloud_id.
    EDIT permission required on cloud.
    ---
    cloud:
      in: path
      required: true
      type: string
    new_name:
      description: ' New name for the key (will also serve as the key''s id)'
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']
    try:
        Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None)
    except Cloud.DoesNotExist:
        raise NotFoundError('Cloud does not exist')

    params = params_from_request(request)
    new_name = params.get('new_name', '')
    if not new_name:
        raise RequiredParameterMissingError('new_name')
    auth_context.check_perm('cloud', 'edit', cloud_id)

    m_rename_cloud(auth_context.owner, cloud_id, new_name)
    return OK
Beispiel #4
0
def su(request):
    """
    Impersonate another user.

    This allows an admin to take the identity of any other user. It is meant to
    be used strictly for debugging. You can return to your regular user simply
    by logging out. This won't affect the last login time of the actual user.
    An email should be immediately sent out to the team, notifying of the 'su'
    action for security reasons.

    """
    # SEC raise exception if user not admin
    user = user_from_request(request, admin=True)

    session = request.environ['session']
    if isinstance(session, ApiToken):
        raise ForbiddenError('Cannot do su when authenticated with api token')
    real_email = user.email
    params = params_from_request(request)
    email = params.get('email')
    if not email:
        raise RequiredParameterMissingError('email')
    try:
        user = User.objects.get(email=email)
    except (UserNotFoundError, User.DoesNotExist):
        raise UserUnauthorizedError()
    reissue_cookie_session(request, real_email, su=user.id)

    # alert admins
    subject = "Some admin used su"
    body = "Admin: %s\nUser: %s\nServer: %s" % (real_email, user.email,
                                                config.CORE_URI)
    send_email(subject, body, config.NOTIFICATION_EMAIL['ops'])
    return HTTPFound('/')
Beispiel #5
0
def set_script_tags(request):
    """
    Tags: tags
    ---
    Set tags to owner's script.
    EDIT_TAGS permission required on SCRIPT
    ---
    script:
      in: path
      required: true
      type: string
    tags:
      type: dict
      required: true
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    script_id = request.matchdict["script_id"]

    # SEC require EDIT_TAGS permission on script
    auth_context.check_perm("script", "edit_tags", script_id)

    script = Script.objects.get(owner=auth_context.owner,
                                id=script_id,
                                deleted=None)

    tags = params.get("tags")
    if type(tags) != dict:
        raise BadRequestError('tags should be dictionary of tags')

    if not modify_security_tags(auth_context, tags, script):
        raise auth_context._raise('script', 'edit_security_tags')

    return add_tags_to_resource(auth_context.owner, script, list(tags.items()))
Beispiel #6
0
def list_cloud_machines(request):
    """
    Tags: machines
    ---
    Lists machines on cloud along with their metadata.
    Check Permissions takes place in filter_list_machines.
    READ permission required on cloud.
    READ permission required on machine.
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']
    params = params_from_request(request)
    cached = bool(params.get('cached', False))

    # SEC get filtered resources based on auth_context
    try:
        Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None)
    except Cloud.DoesNotExist:
        raise NotFoundError('Cloud does not exist')

    machines = methods.filter_list_machines(auth_context,
                                            cloud_id,
                                            cached=cached)

    return machines
Beispiel #7
0
def set_machine_tags(request):
    """
    Set tags on a machine
    Set tags for a machine, given the cloud and machine id.
    READ permission required on cloud.
    EDIT_TAGS permission required on machine.
    ---
    cloud_id:
      in: path
      required: true
      type: string
    machine_id:
      in: path
      required: true
      type: string
    tags:
      items:
        type: object
      type: array
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    cloud_id = request.matchdict["cloud_id"]
    machine_id = request.matchdict["machine_id"]
    auth_context.check_perm("cloud", "read", cloud_id)
    try:
        machine = Machine.objects.get(cloud=cloud_id, machine_id=machine_id)
    except me.DoesNotExist:
        raise NotFoundError('Resource with that id does not exist')

    # SEC require EDIT_TAGS permission on machine
    auth_context.check_perm("machine", "edit_tags", machine.id)

    tags = params.get("tags")
    if type(tags) != dict:
        raise BadRequestError('tags should be dictionary of tags')

    if not modify_security_tags(auth_context, tags, machine):
        raise auth_context._raise('machine', 'edit_security_tags')

    # FIXME: This is f***** up! This method is utilized by the Ember UI in
    # order to update a machine's tags by providing the entire list of tags
    # to be re-set. However, `add_tags_to_resource` simply appends the new
    # tags without deleting any.

    old_tags = get_tags_for_resource(auth_context.owner, machine)
    add_tags_to_resource(auth_context.owner, machine, tags.items())

    if config.MACHINE_PATCHES:
        new_tags = get_tags_for_resource(auth_context.owner, machine)

        patch = jsonpatch.JsonPatch.from_diff(old_tags, new_tags).patch
        for item in patch:
            item['path'] = '/%s-%s/tags%s' % (machine.id, machine.machine_id,
                                              item['path'])
        amqp_publish_user(auth_context.owner.id,
                          routing_key='patch_machines',
                          data={'cloud_id': cloud_id,
                                'patch': patch})
    return {}
Beispiel #8
0
def set_key_tags(request):
    """
    Set tags to owner's key
    EDIT_TAGS permission required on KEY
    ---
    key_id:
      in: path
      required: true
      type: string
    tags:
      type: dict
      required: true
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    key_id = request.matchdict["key_id"]

    # SEC require EDIT_TAGS permission on key
    auth_context.check_perm("key", "edit_tags", key_id)

    try:
        key = Key.objects.get(owner=auth_context.owner,
                              id=key_id, deleted=None)
    except Key.DoesNotExist:
        raise NotFoundError('Resource with that id does not exist')

    tags = params.get("tags")
    if type(tags) != dict:
        raise BadRequestError('tags should be dictionary of tags')

    if not modify_security_tags(auth_context, tags, key):
        raise auth_context._raise('key', 'edit_security_tags')

    return add_tags_to_resource(auth_context.owner, key, tags.items())
Beispiel #9
0
def delete_account(request):
    """
    A user requests his account to be deleted. In order to verify the request
    the user's password should be included as a parameter.
    """
    email = request.matchdict['email']
    params = params_from_request(request)
    plaintext_password = params.get('password', None)
    if not email:
        raise ValueError('No email provided')

    if config.SSO_TEST_EMAIL == "":
        raise MethodNotAllowedError("Configuration error")

    # SEC only allow test user to self delete
    if email != config.SSO_TEST_EMAIL:
        raise MethodNotAllowedError("This method is only for the test user")

    try:
        user = User.objects.get(email=email)
    except UserNotFoundError:
        return OK
    if not user.check_password(password=plaintext_password):
        raise MethodNotAllowedError("Password is wrong!!")
    user.delete()
    return OK
Beispiel #10
0
def edit_key(request):
    """
    Edit a key
    Edits a given key's name  to new_name
    EDIT permission required on key.
    ---
    new_name:
      description: The new key name
      type: string
    key_id:
      description: The key id
      in: path
      required: true
      type: string
    """
    key_id = request.matchdict['key']
    params = params_from_request(request)
    new_name = params.get('new_name')
    if not new_name:
        raise RequiredParameterMissingError("new_name")

    auth_context = auth_context_from_request(request)
    try:
        key = Key.objects.get(owner=auth_context.owner,
                              id=key_id,
                              deleted=None)
    except me.DoesNotExist:
        raise NotFoundError('Key with that id does not exist')
    auth_context.check_perm('key', 'edit', key.id)
    key.ctl.rename(new_name)

    return {'new_name': new_name}
Beispiel #11
0
def delete_key_tag(request):
    """
    Tags: tags
    ---
    Deletes a tag in the db for specified resource_type.
    EDIT_TAGS permission required on key.
    ---
    tag_key:
      required: true
      type: string
    key_id:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    key_id = request.matchdict["key_id"]
    tag_key = params.get("tag_key")

    # SEC require EDIT_TAGS permission on key
    auth_context.check_perm('key', 'edit_tags', key_id)
    if not delete_security_tag(auth_context, tag_key):
        raise auth_context._raise('key', 'edit_security_tags')

    return resolve_id_and_delete_tags(auth_context.owner,
                                      'key',
                                      key_id,
                                      tags=[tag_key])
Beispiel #12
0
def suppressed_emails(request):

    params = dict(params_from_request(request).copy())

    try:
        mac_verify(params)
    except Exception as exc:
        raise BadRequestError(str(exc))

    try:
        decrypted_str = decrypt(params['token'])
        decrypted_json = json.loads(decrypted_str)
    except Exception as exc:
        log.exception(repr(exc))
        raise BadRequestError()

    if decrypted_json.get('key') != Portal.get_singleton().external_api_key:
        raise NotFoundError()

    action = decrypted_json.get('action')
    if not action:
        raise RequiredParameterMissingError('action')

    if action == 'delete':
        Notification.objects(suppressed=True).delete()
    elif action == 'unsuppress':
        Notification.objects.update(suppressed=False)
    else:
        raise BadRequestError('Action "%s" not supported' % action)

    return Response("OK", 200)
Beispiel #13
0
def transfer_ownership_to_user(request):
    """
    Tags: ownership

    ---

    Transfer ownership of a resource

    If a resource isn't owned by the requesting user, then an UnauthorizedError
    error will be thrown, unless the requesting user is a member of the Owners
    team.

    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)

    if not params.get('user_id'):
        raise RequiredParameterMissingError('user_id')
    try:
        new_owner = User.objects.get(id=params['user_id'])
    except User.DoesNotExist:
        raise NotFoundError('User with id %s' % params['user_id'])

    for rtype, rids in params.get('resources', {}).iteritems():
        Model = get_resource_model(rtype)
        for rid in rids:
            try:
                resource = Model.objects.get(owner=auth_context.owner, id=rid)
                resource.transfer_ownership(auth_context, new_owner)
            except Model.DoesNotExist:
                raise NotFoundError('%s with id %s' % (rtype, rid))

    trigger_session_update(auth_context.owner)

    return Response('OK', 200)
Beispiel #14
0
def set_cloud_tags(request):
    """
    Tags: tags
    ---
    Set tags to owner's cloud.
    EDIT_TAGS permission required on SCRIPT
    ---
    tags:
      type: dict
      required: true
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    cloud_id = request.matchdict["cloud_id"]

    # SEC require EDIT_TAGS permission on cloud
    auth_context.check_perm("cloud", "edit_tags", cloud_id)
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except me.DoesNotExist:
        raise NotFoundError('Resource with that id does not exist')

    tags = params.get("tags")
    if type(tags) != dict:
        raise BadRequestError('tags should be dictionary of tags')

    if not modify_security_tags(auth_context, tags, cloud):
        raise auth_context._raise('cloud', 'edit_security_tags')

    return add_tags_to_resource(auth_context.owner, cloud, list(tags.items()))
Beispiel #15
0
def disassociate_metric(request):
    """
    Tags: monitoring
    ---
    Disassociate a metric from a machine.
    READ permission required on cloud.
    EDIT_GRAPHS permission required on machine
    ---
    machine:
      in: path
      type: string
      required: true
    metric_id:
      type: string
      required: true
    """
    auth_context = auth_context_from_request(request)
    machine = _machine_from_matchdict(request)

    # SEC require permission EDIT_GRAPHS on machine
    auth_context.check_perm("machine", "edit_graphs", machine.id)

    params = params_from_request(request)
    metric_id = params.get('metric_id')
    if not metric_id:
        raise RequiredParameterMissingError('metric_id')

    mist.api.monitoring.methods.disassociate_metric(machine, metric_id)
    return {}
Beispiel #16
0
def revoke_session(request):
    """
    Tags: sessions
    ---
    Revoke an active session
    ---
    id:
      description: Session ID
    """

    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    auth_token_id = params.get("id")

    if not auth_token_id:
        raise RequiredParameterMissingError("No token id parameter provided")

    try:
        if auth_context.is_owner():
            auth_token = AuthToken.objects.get(org=auth_context.org,
                                               id=auth_token_id)
        else:
            auth_token = AuthToken.objects.get(
                user_id=auth_context.user.get_id(), id=auth_token_id)
        if auth_token.is_valid():
            auth_token.invalidate()
            auth_token.save()

    except me.DoesNotExist:
        raise NotFoundError('Session not found')

    return OK
Beispiel #17
0
def create_dns_zone(request):
    """
    Tags: dns
    ---
    Creates a new DNS zone under the given cloud.
    CREATE_RESOURCES permission required on cloud.
    ADD permission required on zone.
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)

    cloud_id = request.matchdict['cloud']
    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("cloud", "create_resources", cloud_id)
    tags, _ = auth_context.check_perm("zone", "add", None)

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError

    params = params_from_request(request)
    new_zone = Zone.add(owner=cloud.owner, cloud=cloud, **params)
    new_zone.assign_to(auth_context.user)

    if tags:
        resolve_id_and_set_tags(auth_context.owner, 'zone', new_zone.id,
                                tags, cloud_id=cloud_id)

    return new_zone.as_dict()
Beispiel #18
0
def create_dns_zone(request):
    """
    Create a new DNS zone under a specific cloud.
    ---
    """
    auth_context = auth_context_from_request(request)

    cloud_id = request.matchdict['cloud']
    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("cloud", "create_resources", cloud_id)
    tags = auth_context.check_perm("zone", "add", None)
    # Try to get the specific cloud for which we will create the zone.
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError

    params = params_from_request(request)
    new_zone = Zone.add(owner=cloud.owner, cloud=cloud, **params).as_dict()

    if tags:
        resolve_id_and_set_tags(auth_context.owner,
                                'zone',
                                new_zone['id'],
                                tags,
                                cloud_id=cloud_id)

    # Schedule a UI update
    trigger_session_update(auth_context.owner, ['zones'])
    return new_zone
Beispiel #19
0
def list_machines(request):
    """
    Tags: machines
    ---
    Gets machines and their metadata from all clouds.
    Check Permissions take place in filter_list_machines.
    READ permission required on cloud.
    READ permission required on location.
    READ permission required on machine.
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    cached = not params.get('fresh', False)  # return cached by default

    # to prevent iterate throw every cloud
    auth_context.check_perm("cloud", "read", None)
    clouds = filter_list_clouds(auth_context)
    machines = []
    for cloud in clouds:
        if cloud.get('enabled'):
            try:
                cloud_machines = methods.filter_list_machines(auth_context,
                                                              cloud.get('id'),
                                                              cached=cached)
                machines.extend(cloud_machines)
            except (CloudUnavailableError, CloudUnauthorizedError):
                pass
    return machines
Beispiel #20
0
def associate_ip(request):
    """
    Tags: networks
    ---
    Associates ip with the specific network and machine.
    READ permission required on cloud.
    EDIT permission required on cloud.
    ---
    parameters:
    - name: cloud
      in: path
      required: true
      schema:
        type: string
    - name: network
      in: path
      required: true
      schema:
        type: string
    requestBody:
      description: Foo
      required: true
      content:
        'application/json':
          schema:
            type: object
            properties:
              assign:
                default: true
                type: boolean
              ip:
                type: string
              machine:
                type: string
            required:
            - ip
            - machine
    """
    cloud_id = request.matchdict['cloud']
    network_id = request.matchdict['network']
    params = params_from_request(request)
    ip = params.get('ip')
    machine_id = params.get('machine')
    assign = params.get('assign', True)
    auth_context = auth_context_from_request(request)
    auth_context.check_perm("cloud", "read", cloud_id)
    try:
        machine = Machine.objects.get(cloud=cloud_id, machine_id=machine_id)
        machine_uuid = machine.id
    except me.DoesNotExist:
        machine_uuid = ""
    auth_context.check_perm("machine", "edit", machine_uuid)

    ret = associate_ip_method(auth_context.owner, cloud_id, network_id, ip,
                              machine_id, assign)
    if ret:
        return OK
    else:
        return Response("Bad Request", 400)
Beispiel #21
0
def associate_key(request):
    """
    Tags: keys
    ---
    Associates a key with a machine. If host is set it will also attempt to
    actually deploy it to the machine. To do that it requires another key
    (existing_key) that can connect to the machine.
    READ permission required on cloud.
    READ_PRIVATE permission required on key.
    ASSOCIATE_KEY permission required on machine.
    ---
    machine:
      in: path
      required: true
      type: string
    key:
      in: path
      required: true
      type: string
    port:
      default: 22
      type: integer
    user:
      description: The ssh user
      type: string
    """
    key_id = request.matchdict['key']

    params = params_from_request(request)
    ssh_user = params.get('user', None)
    try:
        ssh_port = int(request.json_body.get('port', 22))
    except:
        ssh_port = 22

    auth_context = auth_context_from_request(request)
    try:
        key = Key.objects.get(owner=auth_context.owner,
                              id=key_id,
                              deleted=None)
    except Key.DoesNotExist:
        raise NotFoundError('Key id does not exist')
    auth_context.check_perm('key', 'read_private', key.id)

    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", "associate_key", machine.id)

    return key.ctl.associate(machine, username=ssh_user, port=ssh_port)
Beispiel #22
0
def update_user_settings(request):
    """
    Tags: users
    ---
    User related actions
    Edit name, Update password
    """

    # SEC raise exception if not user
    user = user_from_request(request)

    auth_context = auth_context_from_request(request)

    params = params_from_request(request)

    action = params.get('action')
    actions = ['update_details', 'update_password']
    if action not in actions:
        log.error("Update_user_settings bad action='%s'", action)
        raise BadRequestError('action')

    if action == 'update_details':
        avatar = params.get('avatar')
        if avatar:
            try:
                Avatar.objects.get(id=avatar)
                user.avatar = avatar
            except DoesNotExist:
                raise BadRequestError('Avatar does not exist')
        if params.get('first_name') or params.get('last_name'):
            user.first_name = params.get('first_name')
            user.last_name = params.get('last_name')
        elif params.get('name'):
            name_array = params.get('name').split(' ')
            if len(name_array) > 1:
                user.last_name = name_array[-1]
            user.first_name = ' '.join(name_array[:-1])
        user.save()
        trigger_session_update(auth_context.owner, ['user'])
        return {}

    if action == 'update_password':
        current_password = params.get('current_password', '')
        password = params.get('password', '')
        # check if current_password provided
        if not current_password and (user.password and user.password != ''):
            raise RequiredParameterMissingError("Current password")
        # check if new password provided
        if not password:
            raise RequiredParameterMissingError("New password")

        # SEC check if current_password valid
        if not user.check_password(current_password):
            raise UnauthorizedError("Invalid current password")

        # set new password
        user.set_password(password)
        return {}
Beispiel #23
0
def create_network(request):
    """
    Create network on a cloud
    Creates a new network. If subnet dict is specified,
    after creating the network it will use the new
    network's id to create a subnet.
    CREATE_RESOURCES permission required on cloud.
    ---
    cloud_id:
      in: path
      required: true
      description: The Cloud ID
      type: string
    network:
      required: true
      type: dict
    subnet:
      type: dict
    """
    cloud_id = request.matchdict['cloud']

    params = params_from_request(request)
    network_params = params.get('network')
    subnet_params = params.get('subnet')

    auth_context = auth_context_from_request(request)

    if not network_params:
        raise RequiredParameterMissingError('network')

    # TODO
    if not auth_context.is_owner():
        raise PolicyUnauthorizedError()

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError

    network = methods.create_network(auth_context.owner, cloud, network_params)
    network_dict = network.as_dict()

    # Bundling Subnet creation in this call because it is required
    #  for backwards compatibility with the current UI
    if subnet_params:
        try:
            subnet = create_subnet(auth_context.owner, cloud,
                                   network, subnet_params)
        except Exception as exc:
            # Cleaning up the network object in case subnet creation
            #  fails for any reason
            network.ctl.delete()
            raise exc
        network_dict['subnet'] = subnet.as_dict()

    return network.as_dict()
Beispiel #24
0
def update_monitoring(request):
    """
    Tags: monitoring
    ---
    Enable or disable monitoring for a machine
    ---
    machine:
      in: path
      type: string
      required: true
    action:
      enum:
      - enable
      - disable
      type: string
      required: true
    no_ssh:
      type: boolean
      default: false
    dry:
      type: boolean
      default: false

    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    no_ssh = bool(params.get('no_ssh'))
    dry = bool(params.get('dry'))
    action = params.get('action')
    if not action:
        raise RequiredParameterMissingError('action')

    if action == 'enable':
        machine = _machine_from_matchdict(request)
    elif action == 'disable':
        machine = _machine_from_matchdict(request, deleted=True)
    else:
        raise BadRequestError('Action must be one of (enable, disable)')

    # SEC require permission EDIT on machine
    auth_context.check_perm("machine", "edit", machine.id)

    if action == 'enable':
        return mist.api.monitoring.methods.enable_monitoring(
            owner=auth_context.owner,
            cloud_id=machine.cloud.id,
            machine_id=machine.machine_id,
            no_ssh=no_ssh,
            dry=dry)
    elif action == 'disable':
        return mist.api.monitoring.methods.disable_monitoring(
            owner=auth_context.owner,
            cloud_id=machine.cloud.id,
            machine_id=machine.machine_id,
            no_ssh=no_ssh)
Beispiel #25
0
def add_key(request):
    """
    Tags: keys
    ---
    Adds key.
    ADD permission required on key.
    ---
    name:
      description: The key's name
      required: true
      type: string
    priv:
      description: The private key
      required: true
      type: string
    certificate:
      description: The signed public key, when using signed ssh keys
      type: string
    """
    params = params_from_request(request)
    key_name = params.pop('name', None)
    private_key = params.get('priv', None)
    certificate = params.get('certificate', None)
    auth_context = auth_context_from_request(request)
    key_tags = auth_context.check_perm("key", "add", None)

    if not key_name:
        raise BadRequestError("Key name is not provided")
    if not private_key:
        raise RequiredParameterMissingError("Private key is not provided")

    if certificate:
        key = SignedSSHKey.add(auth_context.owner, key_name, **params)
    else:
        key = SSHKey.add(auth_context.owner, key_name, **params)

    # Set ownership.
    key.assign_to(auth_context.user)

    if key_tags:
        add_tags_to_resource(auth_context.owner, key, key_tags.items())
    # since its a new key machines fields should be an empty list

    clouds = Cloud.objects(owner=auth_context.owner, deleted=None)
    machines = Machine.objects(cloud__in=clouds,
                               key_associations__keypair__exact=key)

    assoc_machines = transform_key_machine_associations(machines, key)

    return {
        'id': key.id,
        'name': key.name,
        'machines': assoc_machines,
        'isDefault': key.default
    }
Beispiel #26
0
def create_dns_record(request):
    """
    Tags: dns
    ---
    Creates a new record under a specific zone.
    CREATE_RESOURCES permission required on cloud.
    CREATE_RECORDS permission required on zone
    ---
    cloud:
      in: path
      required: true
      type: string
    zone:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)

    cloud_id = request.matchdict['cloud']
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError()

    zone_id = request.matchdict['zone']
    try:
        zone = Zone.objects.get(owner=auth_context.owner,
                                id=zone_id,
                                cloud=cloud)
    except Zone.DoesNotExist:
        raise NotFoundError('Zone does not exist')

    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("zone", "read", zone_id)
    auth_context.check_perm("zone", "create_records", zone_id)
    tags = auth_context.check_perm("record", "add", None)

    params = params_from_request(request)
    dns_cls = RECORDS[params['type']]

    rec = dns_cls.add(owner=auth_context.owner, zone=zone, **params)
    rec.assign_to(auth_context.user)

    if tags:
        resolve_id_and_set_tags(auth_context.owner,
                                'record',
                                rec.id,
                                tags,
                                cloud_id=cloud_id,
                                zone_id=zone_id)

    trigger_session_update(auth_context.owner, ['zones'])
    return rec.as_dict()
Beispiel #27
0
def get_load(request):
    """
    Tags: monitoring
    ---
    Request load data for all monitored machines
    ---
    start:
      in: query
      type: string
      default: now
      required: false
      description: time (eg. '10s') since when to fetch stats
    stop:
      in: query
      type: string
      required: false
      description: time until when to fetch stats
    step:
      in: query
      type: string
      required: false
      description: step to fetch stats, used in aggregations
    request_id:
      in: query
      type: string
      required: false

    """
    auth_context = auth_context_from_request(request)
    cloud_ids = [
        cloud['id'] for cloud in filter_list_clouds(auth_context)
        if cloud['enabled']
    ]
    uuids = [
        machine.id for machine in Machine.objects(
            cloud__in=cloud_ids,
            monitoring__hasmonitoring=True,
        ).only('id')
    ]
    if not auth_context.is_owner():
        allowed_uuids = auth_context.get_allowed_resources(rtype='machines')
        uuids = set(uuids) & set(allowed_uuids)

    params = params_from_request(request)
    start = params.get('start', '')
    stop = params.get('stop', '')
    step = params.get('step', '')
    data = mist.api.monitoring.methods.get_load(auth_context.owner,
                                                start=start,
                                                stop=stop,
                                                step=step,
                                                uuids=uuids)
    data['request_id'] = params.get('request_id')
    return data
Beispiel #28
0
def delete_keys(request):
    """
    Tags: keys
    ---
    Deletes multiple keys.
    Provide a list of key ids to be deleted. The method will try to delete
    all of them and then return a json that describes for each key id
    whether or not it was deleted or not_found if the key id could not
    be located. If no key id was found then a 404(Not Found) response will
    be returned.
    REMOVE permission required on each key.
    ---
    key_ids:
      required: true
      type: array
      items:
        type: string
    """
    auth_context = auth_context_from_request(request)

    params = params_from_request(request)
    key_ids = params.get('key_ids', [])
    if type(key_ids) != list or len(key_ids) == 0:
        raise RequiredParameterMissingError('No key ids provided')
    # remove duplicate ids if there are any
    key_ids = set(key_ids)

    report = {}
    for key_id in key_ids:
        try:
            key = Key.objects.get(owner=auth_context.owner,
                                  id=key_id,
                                  deleted=None)
        except me.DoesNotExist:
            report[key_id] = 'not_found'
            continue
        try:
            auth_context.check_perm('key', 'remove', key.id)
        except PolicyUnauthorizedError:
            report[key_id] = 'unauthorized'
        else:
            delete_key(auth_context.owner, key_id)
            report[key_id] = 'deleted'

    # if no key id was valid raise exception
    if len(filter(lambda key_id: report[key_id] == 'not_found',
                  report)) == len(key_ids):
        raise NotFoundError('No valid key id provided')
    # if user was unauthorized for all keys
    if len(filter(lambda key_id: report[key_id] == 'unauthorized',
                  report)) == len(key_ids):
        raise NotFoundError('Unauthorized to modify any of the keys')
    return report
Beispiel #29
0
def find_metrics(request):
    """
    Tags: monitoring
    ---
    Get all metrics associated with specific machine.

    READ permission required on cloud.
    READ permission required on machine.

    ---

    resource_type:
      in: query
      required: false
      type: string

    id:
      in: query
      required: false
      type: string

    tags:
      in: query
      required: false
      type: string

    """

    auth_context = auth_context_from_request(request)

    params = params_from_request(request)
    resource_type = params.get('resource_type', None)
    resource_id = params.get('resource_id', None)
    tags = params.get('tags', None)

    # Convert the tag list to a dict
    if tags:
        tags = dict(
            (key, value[0] if value else '')
            for key, *value in (pair.split(':') for pair in tags.split(',')))

    if resource_id:
        return mist.api.monitoring.methods.find_metrics_by_resource_id(
            auth_context, resource_id, resource_type)

    if resource_type:
        return mist.api.monitoring.methods.find_metrics_by_resource_type(
            auth_context, resource_type, tags)

    if tags:
        return mist.api.monitoring.methods.find_metrics_by_tags(
            auth_context, tags)
Beispiel #30
0
def create_subnet(request):
    """
    Tags: networks
    ---
    Create subnet in a given network on a cloud

    ADD permission required on subnet
    READ permission required on cloud
    READ permission required on network
    CREATE_SUBNETS permission required on network
    CREATE_RESOURCES permission required on cloud
    ---
    cloud_id:
      in: path
      required: true
      description: The Cloud ID
      type: string
    network_id:
      in: path
      required: true
      description: The ID of the Network that will contain the new subnet
      type: string
    subnet:
      required: true
      type: object
    """
    cloud_id = request.matchdict['cloud']
    network_id = request.matchdict['network']

    params = params_from_request(request)

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    auth_context.check_perm('cloud', 'create_resources', cloud_id)
    auth_context.check_perm('network', 'read', network_id)
    auth_context.check_perm('network', 'edit_subnets', network_id)

    try:
        cloud = Cloud.objects.get(id=cloud_id, owner=auth_context.owner)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    try:
        network = Network.objects.get(id=network_id, cloud=cloud)
    except Network.DoesNotExist:
        raise NetworkNotFoundError()

    # Create subnet.
    subnet = SUBNETS[cloud.ctl.provider].add(network=network, **params)

    return subnet.as_dict()