Exemplo n.º 1
0
def post(capsule_id, user):
    sshkey_data = request.get_json()
    capsule = _get_capsule(capsule_id, user)

    for public_key in sshkey_data:
        if not valid_sshkey(public_key):
            raise BadRequest(description=f"'{public_key}' is not "
                             "a valid ssh public key")

        for key in capsule.authorized_keys:
            if public_key == key.public_key:
                raise Conflict(description="'public_key' already exist "
                               "for this capsule")

        sshkey = SSHKey(public_key=public_key)
        capsule.authorized_keys.append(sshkey)

    db.session.commit()

    now = datetime.datetime.now()
    if now > (capsule.no_update + datetime.timedelta(hours=24)):
        nats.publish_webapp_present(capsule)

    result = Capsule.query.filter_by(id=capsule_id).first()
    return capsule_output_schema.dump(result), 201, {
        'Location': f'{request.base_url}/capsules/{capsule.id}',
    }
Exemplo n.º 2
0
def patch(capsule_id, user):
    try:
        capsule = Capsule.query.filter_by(id=capsule_id).first()
    except StatementError:
        raise BadRequest(description=f"'{capsule_id}' is not a valid id.")

    if capsule is None:
        raise NotFound(description=f"The requested capsule '{capsule_id}' "
                       "has not been found.")

    owners = capsule_output_schema.dump(capsule)['owners']
    if (user.role is RoleEnum.user) and (user.name not in owners):
        raise Forbidden

    data = request.get_json()

    if 'no_update' in data:
        if data['no_update']:
            capsule.no_update = datetime.datetime.now()
        else:
            capsule.no_update = datetime.date(1970, 1, 1)

    if 'comment' in data:
        capsule.comment = data['comment']

    if 'size' in data:
        if (user.role is RoleEnum.user) and (not user.parts_manager):
            raise Forbidden(description='You cannot set the capsule size.')

        cluster_parts = getClusterPartsUsage(capsule.name)
        proposed_parts = SizeEnum.getparts(data['size'])
        target_parts = cluster_parts + proposed_parts
        if target_parts > current_app.config['CLUSTER_PARTS']:
            msg = 'Please set a lower size for this capsule or prepare '\
                  'some Bitcoins... :-)'
            raise PaymentRequired(description=msg)
        capsule.size = data['size']

    db.session.commit()

    caps = Capsule.query.filter_by(id=capsule_id).first()
    result = capsule_output_schema.dump(caps)

    return result, 200, {
        'Location': f'{request.base_url}/capsules/{capsule.id}',
    }
Exemplo n.º 3
0
def get(capsule_id, verbose, user):
    try:
        capsule = Capsule.query.filter_by(id=capsule_id).first()
    except StatementError:
        raise BadRequest(description=f"'{capsule_id}' is not a valid id.")

    if capsule is None:
        raise NotFound(description=f"The requested capsule '{capsule_id}' "
                       "has not been found.")

    capsule_data = capsule_output_schema.dump(capsule)
    owners = capsule_data['owners']
    if (user.role is RoleEnum.user) and (user.name not in owners):
        raise Forbidden

    if verbose is True:
        return capsule_verbose_schema.dump(capsule)
    else:
        return capsule_output_schema.dump(capsule)
Exemplo n.º 4
0
def patch(capsule_id, user):
    capsule = _get_capsule(capsule_id, user, check_delegate=True)
    data = request.get_json()

    if ("key" in data and "crt" not in data) or \
            ("crt" in data and "key" not in data):
        raise BadRequest(description="Both crt and key are "
                         "required together")

    if "crt" in data and "key" in data:
        try:
            str_cert = base64.b64decode(data['crt'])
            str_key = base64.b64decode(data['key'])
        except binascii.Error:
            raise BadRequest(description="'crt' and 'key' must be "
                             "base64 encoded.")
        try:
            # Ensure that certificate and key are paired.
            if not is_keycert_associated(str_key, str_cert):
                raise BadRequest(description="The certificate and the key "
                                 "are not associated")
        except NotValidPEMFile:  # Possible ??
            raise BadRequest
        capsule.tls_crt = data["crt"]
        capsule.tls_key = data["key"]

    if "force_redirect_https" in data:
        if data['force_redirect_https']:
            capsule.enable_https = True
        capsule.force_redirect_https = data["force_redirect_https"]

    if "enable_https" in data:
        if not data['enable_https']:
            capsule.force_redirect_https = False
        capsule.enable_https = data["enable_https"]

    db.session.commit()

    webapp = capsule.webapp
    now = datetime.datetime.now()
    if now > (capsule.no_update + datetime.timedelta(hours=24)) and\
       webapp is not None:
        nats.publish_webapp_present(capsule)

    result = capsule_output_schema.dump(capsule)
    return result, 200, {
        'Location': f'{request.base_url}/capsules/{capsule.id}',
    }
Exemplo n.º 5
0
def patch(capsule_id, user):
    capsule = _get_capsule(capsule_id, user)
    owner_data = request.get_json()

    if "newOwner" not in owner_data:
        raise BadRequest("The key newOwner is required.")
    new_owner = owner_data["newOwner"]

    user_is_owner = False
    for owner in capsule.owners:
        if user.name == owner.name:
            user_is_owner = True
        if new_owner == owner.name:
            msg = f'{new_owner} is already in owners list!'
            raise Conflict(description=msg)

    if (not user_is_owner) and (user.role == RoleEnum.user):
        raise Forbidden

    try:  # Check if owners exist on Keycloak
        check_owners_on_keycloak([new_owner])
    except KeycloakUserNotFound as e:
        raise NotFound(description=f'{e.missing_username} was not '
                                   'found in Keycloak.')

    # Get existent users, create the others
    user = User.query.filter_by(name=new_owner).one_or_none()
    if user is None:  # User does not exist in DB
        new_user = User(name=new_owner, role=RoleEnum.user)
    else:
        new_user = user

    capsule.owners.append(new_user)
    db.session.commit()

    now = datetime.datetime.now()
    if now > (capsule.no_update + datetime.timedelta(hours=24)):
        nats.publish_webapp_present(capsule)

    result = Capsule.query.filter_by(id=capsule_id).first()
    return capsule_output_schema.dump(result), 200, {
        'Location': f'{request.base_url}/{capsule.id}',
    }
Exemplo n.º 6
0
def post():
    capsule_data = request.get_json()
    data = capsule_input_schema.load(capsule_data)

    cluster_parts = getClusterPartsUsage("")
    if 'size' in data:
        proposed_parts = SizeEnum.getparts(data['size'])
    else:
        proposed_parts = SizeEnum.getparts(SizeEnum.tiny)
    target_parts = cluster_parts + proposed_parts
    if target_parts > current_app.config['CLUSTER_PARTS']:
        msg = 'Please set a lower size for this capsule or prepare '\
              'some Bitcoins... :-)'
        raise PaymentRequired(description=msg)

    try:  # Check if owners exist on Keycloak
        check_owners_on_keycloak(data['owners'])
    except KeycloakUserNotFound as e:
        raise BadRequest(
            description=f'{e.missing_username} is an invalid user.')

    # Get existent users, create the others
    for i, owner in enumerate(data['owners']):
        user = User.query.filter_by(name=owner).one_or_none()
        if user is None:  # User does not exist in DB
            data['owners'][i] = User(name=owner, role=RoleEnum.user)
        else:
            data['owners'][i] = user

    # Get existent ssh keys, create the others
    if 'authorized_keys' in data:
        for i, public_key in enumerate(data['authorized_keys']):
            sshkey = SSHKey.query\
                .filter_by(public_key=public_key).one_or_none()
            if sshkey is None:
                data['authorized_keys'][i] = SSHKey(public_key=public_key)
            else:
                data['authorized_keys'][i] = sshkey

    capsule_name = data['name']

    # https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
    if not is_valid_name(capsule_name):
        msg = f'The capsule name "{capsule_name}" is invalid: only lowercase '\
            'alphanumeric characters or "-" are allowed, the first and the '\
            'last characters must be alphanumeric, the name must have at '\
            'least 2 characters and less than 64 characters.'
        raise BadRequest(description=msg)

    newArgs = dict()
    if "fqdns" in data:
        fqdns_list = [e['name'] for e in data["fqdns"]]
        if len(fqdns_list) != len(set(fqdns_list)):
            raise BadRequest(description='Repetitions are not '
                             'allowed for FQDNs')
        try:
            fqdns = FQDN.create(data["fqdns"])
        except FQDNAlreadyExists as e:
            raise BadRequest(description=f'{e.existing_fqdn} already exists.')
        data.pop("fqdns")
        newArgs["fqdns"] = fqdns

    caps = Capsule.query.filter_by(name=capsule_name).limit(1).one_or_none()
    if caps is not None:
        raise BadRequest(description=f'{capsule_name} already exists.')

    capsule = Capsule(**data, **newArgs)
    db.session.add(capsule)
    db.session.commit()

    caps = Capsule.query.filter_by(id=capsule.id).first()
    result = capsule_output_schema.dump(caps)

    return result, 201, {
        'Location': f'{request.base_url}/capsules/{capsule.id}',
    }