Exemplo n.º 1
0
def update_roles(user, roles):
    """
    Replaces the roles with new ones. This will detect
    when are roles added as well as when there are roles
    removed.

    :param user:
    :param roles:
    """
    removed_roles = []
    for ur in user.roles:
        for r in roles:
            if r.id == ur.id:
                break
        else:
            user.roles.remove(ur)
            removed_roles.append(ur.name)

    if removed_roles:
        log_service.audit_log("unassign_role", user.username, f"Un-assigning roles {removed_roles}")

    added_roles = []
    for r in roles:
        for ur in user.roles:
            if r.id == ur.id:
                break
        else:
            user.roles.append(r)
            added_roles.append(r.name)

    if added_roles:
        log_service.audit_log("assign_role", user.username, f"Assigning roles {added_roles}")
Exemplo n.º 2
0
def create(name,
           password=None,
           description=None,
           username=None,
           users=None,
           third_party=False):
    """
    Create a new role

    :param name:
    :param users:
    :param description:
    :param username:
    :param password:
    :return:
    """
    role = Role(
        name=name,
        description=description,
        username=username,
        password=password,
        third_party=third_party,
    )

    if users:
        role.users = users

    log_service.audit_log("create_role", name, "Creating new role")
    return database.create(role)
Exemplo n.º 3
0
def upload(pending_certificate_id, **kwargs):
    """
    Uploads a (signed) pending certificate. The allowed fields are validated by
    PendingCertificateUploadInputSchema. The certificate is also validated to be
    signed by the correct authority.
    """
    pending_cert = get(pending_certificate_id)
    partial_cert = kwargs
    uploaded_chain = partial_cert["chain"]

    authority = authorities_service.get(pending_cert.authority.id)

    # Construct the chain for cert validation
    if uploaded_chain:
        chain = uploaded_chain + "\n" + authority.authority_certificate.body
    else:
        chain = authority.authority_certificate.body

    parsed_chain = parse_cert_chain(chain)

    # Check that the certificate is actually signed by the CA to avoid incorrect cert pasting
    validators.verify_cert_chain([parse_certificate(partial_cert["body"])] +
                                 parsed_chain)

    final_cert = create_certificate(pending_cert, partial_cert,
                                    pending_cert.user)

    pending_cert_final_result = update(pending_cert.id,
                                       resolved_cert_id=final_cert.id)
    update(pending_cert.id, resolved=True)

    log_service.audit_log("resolve_pending_certificate", pending_cert.name,
                          "Resolved the pending certificate")

    return pending_cert_final_result
Exemplo n.º 4
0
def create(label, plugin_name, options, description=None):
    """
    Creates a new destination, that can then be used as a destination for certificates.

    :param label: Destination common name
    :param description:
    :rtype: Destination
    :return: New destination
    """
    # remove any sub-plugin objects before try to save the json options
    for option in options:
        if "plugin" in option["type"]:
            del option["value"]["plugin_object"]

    destination = Destination(label=label,
                              options=options,
                              plugin_name=plugin_name,
                              description=description)
    current_app.logger.info("Destination: %s created", label)

    # add the destination as source, to avoid new destinations that are not in source, as long as an AWS destination
    if add_aws_destination_to_sources(destination):
        current_app.logger.info("Source: %s created", label)

    log_service.audit_log("create_destination", destination.label,
                          "Creating new destination")
    return database.create(destination)
Exemplo n.º 5
0
def update(destination_id, label, plugin_name, options, description):
    """
    Updates an existing destination.

    :param destination_id:  Lemur assigned ID
    :param label: Destination common name
    :param plugin_name:
    :param options:
    :param description:
    :rtype: Destination
    :return:
    """
    destination = get(destination_id)

    destination.label = label
    destination.plugin_name = plugin_name
    # remove any sub-plugin objects before try to save the json options
    for option in options:
        if "plugin" in option["type"]:
            del option["value"]["plugin_object"]
    destination.options = options
    destination.description = description

    log_service.audit_log("update_destination", destination.label,
                          "Updating destination")
    updated = database.update(destination)
    # add the destination as source, to avoid new destinations that are not in source, as long as an AWS destination
    if add_aws_destination_to_sources(updated):
        current_app.logger.info("Source: %s created", label)
    return updated
Exemplo n.º 6
0
def update(destination_id, label, plugin_name, options, description):
    """
    Updates an existing destination.

    :param destination_id:  Lemur assigned ID
    :param label: Destination common name
    :param plugin_name:
    :param options:
    :param description:
    :rtype: Destination
    :return:
    """
    destination = get(destination_id)

    destination.label = label
    destination.plugin_name = plugin_name
    # remove any sub-plugin objects before try to save the json options
    for option in options:
        if "plugin" in option["type"]:
            del option["value"]["plugin_object"]
    destination.options = options
    destination.description = description

    log_service.audit_log("update_destination", destination.label,
                          "Updating destination")
    return database.update(destination)
Exemplo n.º 7
0
def create_certificate(pending_certificate, certificate, user):
    """
    Create and store a certificate with pending certificate's info

    :arg pending_certificate: PendingCertificate which will populate the certificate
    :arg certificate: dict from Authority, which contains the body, chain and external id
    :arg user: User that called this function, used as 'creator' of the certificate if it does not have an owner
    """
    certificate["owner"] = pending_certificate.owner
    data, errors = CertificateUploadInputSchema().load(certificate)
    if errors:
        raise Exception(
            "Unable to create certificate: {reasons}".format(reasons=errors))

    data.update(vars(pending_certificate))
    # Copy relationships, vars doesn't copy this without explicit fields
    data["notifications"] = list(pending_certificate.notifications)
    data["destinations"] = list(pending_certificate.destinations)
    data["sources"] = list(pending_certificate.sources)
    data["roles"] = list(pending_certificate.roles)
    data["replaces"] = list(pending_certificate.replaces)
    data["rotation_policy"] = pending_certificate.rotation_policy

    # Replace external id and chain with the one fetched from source
    data["external_id"] = certificate["external_id"]
    data["chain"] = certificate["chain"]
    creator = user_service.get_by_email(pending_certificate.owner)
    if not creator:
        # Owner of the pending certificate is not the creator, so use the current user who called
        # this as the creator (usually lemur)
        creator = user

    if pending_certificate.rename:
        # If generating name from certificate, remove the one from pending certificate
        del data["name"]
    data["creator"] = creator

    cert = certificate_service.import_certificate(**data)
    database.update(cert)

    metrics.send("certificate_issued",
                 "counter",
                 1,
                 metric_tags=dict(owner=cert.owner, issuer=cert.issuer))
    log_service.audit_log(
        "certificate_from_pending_certificate", cert.name,
        f"Created from the pending certificate {pending_certificate.name}")
    log_data = {
        "function": "lemur.certificates.service.create",
        "owner": cert.owner,
        "name": cert.name,
        "serial": cert.serial,
        "issuer": cert.issuer,
        "not_after": cert.not_after.format('YYYY-MM-DD HH:mm:ss'),
        "not_before": cert.not_before.format('YYYY-MM-DD HH:mm:ss'),
        "sans": cert.san,
    }
    current_app.logger.info(log_data)
    return cert
Exemplo n.º 8
0
def delete(access_key):
    """
    Delete an access key. This is one way to remove a key, though you probably should just set revoked.
    :param access_key:
    :return:
    """
    log_service.audit_log("delete_api_key", access_key.name,
                          "Deleting the API key")
    database.delete(access_key)
Exemplo n.º 9
0
def delete(dns_provider_id):
    """
    Deletes a DNS provider.

    :param dns_provider_id: Lemur assigned ID
    """
    dns_provider = get(dns_provider_id)
    if dns_provider:
        log_service.audit_log("delete_dns_provider", dns_provider.name, "Deleting the DNS provider")
        database.delete(dns_provider)
Exemplo n.º 10
0
def delete(source_id):
    """
    Deletes an source.

    :param source_id: Lemur assigned ID
    """
    source = get(source_id)
    if source:
        log_service.audit_log("delete_source", source.label, "Deleting source")
        database.delete(source)
Exemplo n.º 11
0
def delete(notification_id):
    """
    Deletes an notification.

    :param notification_id: Lemur assigned ID
    """
    notification = get(notification_id)
    if notification:
        log_service.audit_log("delete_notification", notification.label, "Deleting notification")
        database.delete(notification)
Exemplo n.º 12
0
def revoke(aid):
    """
    Revokes an api key.
    :param aid:
    :return:
    """
    api_key = get(aid)
    setattr(api_key, "revoked", True)

    log_service.audit_log("revoke_api_key", api_key.name, "Revoking API key")
    return database.update(api_key)
Exemplo n.º 13
0
def delete(destination_id):
    """
    Deletes an destination.

    :param destination_id: Lemur assigned ID
    """
    destination = get(destination_id)
    if destination:
        log_service.audit_log("delete_destination", destination.label,
                              "Deleting destination")
        database.delete(destination)
Exemplo n.º 14
0
def increment_attempt(pending_certificate):
    """
    Increments pending certificate attempt counter and updates it in the database.
    """
    pending_certificate.number_attempts += 1
    database.update(pending_certificate)

    log_service.audit_log("increment_attempt_pending_certificate",
                          pending_certificate.name,
                          "Incremented attempts for the pending certificate")
    return pending_certificate.number_attempts
Exemplo n.º 15
0
def delete(role_id):
    """
    Remove a role

    :param role_id:
    :return:
    """

    role = get(role_id)
    log_service.audit_log("delete_role", role.name, "Deleting role")
    return database.delete(role)
Exemplo n.º 16
0
def update(pending_cert_id, **kwargs):
    """
    Updates a pending certificate.  The allowed fields are validated by
    PendingCertificateEditInputSchema.
    """
    pending_cert = get(pending_cert_id)
    for key, value in kwargs.items():
        setattr(pending_cert, key, value)

    log_service.audit_log("update_pending_certificate", pending_cert.name,
                          f"Update summary - {kwargs}")
    return database.update(pending_cert)
Exemplo n.º 17
0
def update(api_key, **kwargs):
    """
    Updates an api key.
    :param api_key:
    :param kwargs:
    :return:
    """
    for key, value in kwargs.items():
        setattr(api_key, key, value)

    log_service.audit_log("update_api_key", api_key.name,
                          f"Update summary - {kwargs}")
    return database.update(api_key)
Exemplo n.º 18
0
def create(**kwargs):
    """
    Creates a new authority.
    """
    ca_name = kwargs.get("name")
    if get_by_name(ca_name):
        raise Exception(f"Authority with name {ca_name} already exists")
    if role_service.get_by_name(
            f"{ca_name}_admin") or role_service.get_by_name(
                f"{ca_name}_operator"):
        raise Exception(
            f"Admin and/or operator roles for authority {ca_name} already exist"
        )

    body, private_key, chain, roles = mint(**kwargs)

    kwargs["creator"].roles = list(set(list(kwargs["creator"].roles) + roles))

    kwargs["body"] = body
    kwargs["private_key"] = private_key
    kwargs["chain"] = chain

    if kwargs.get("roles"):
        kwargs["roles"] += roles
    else:
        kwargs["roles"] = roles

    cert = upload(**kwargs)
    kwargs["authority_certificate"] = cert
    if kwargs.get("plugin", {}).get("plugin_options", []):
        # encrypt the private key before persisting in DB
        for option in kwargs.get("plugin").get("plugin_options"):
            if option["name"] == "acme_private_key" and option["value"]:
                option["value"] = data_encrypt(option["value"])
        kwargs["options"] = json.dumps(kwargs["plugin"]["plugin_options"])

    authority = Authority(**kwargs)
    authority = database.create(authority)
    kwargs["creator"].authorities.append(authority)

    log_service.audit_log("create_authority", ca_name, "Created new authority")

    issuer = kwargs["plugin"]["plugin_object"]
    current_app.logger.warning(
        f"Created new authority {ca_name} with issuer {issuer.title}")

    metrics.send("authority_created",
                 "counter",
                 1,
                 metric_tags=dict(owner=authority.owner))
    return authority
Exemplo n.º 19
0
def create(**kwargs):
    """
    Creates a new API Key.

    :param kwargs:
    :return:
    """
    api_key = ApiKey(**kwargs)
    # this logs only metadata about the api key
    log_service.audit_log("create_api_key", api_key.name,
                          f"Creating the API key {api_key}")

    database.create(api_key)
    return api_key
Exemplo n.º 20
0
    def get(self, pending_certificate_id):
        """
        .. http:get:: /pending_certificates/1/key

           Retrieves the private key for a given pneding certificate

           **Example request**:

           .. sourcecode:: http

              GET /pending_certificates/1/key HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                 "key": "-----BEGIN ..."
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated
        """
        cert = service.get(pending_certificate_id)
        if not cert:
            return dict(message="Cannot find specified pending certificate"), 404

        # allow creators
        if g.current_user != cert.user:
            owner_role = role_service.get_by_name(cert.owner)
            permission = CertificatePermission(owner_role, [x.name for x in cert.roles])

            if not permission.can():
                return dict(message="You are not authorized to view this key"), 403

        response = make_response(jsonify(key=cert.private_key), 200)
        response.headers["cache-control"] = "private, max-age=0, no-cache, no-store"
        response.headers["pragma"] = "no-cache"

        log_service.audit_log("export_private_key_pending_certificate", cert.name,
                              "Exported Private key for the pending certificate")
        return response
Exemplo n.º 21
0
    def get(self, role_id):
        """
        .. http:get:: /roles/1/credentials

           View a roles credentials

           **Example request**:

           .. sourcecode:: http

              GET /users/1 HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                  "username": "******",
                  "password": "******"
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated
        """
        permission = RoleMemberPermission(role_id)
        if permission.can():
            role = service.get(role_id)
            response = make_response(
                jsonify(username=role.username, password=role.password), 200
            )
            response.headers["cache-control"] = "private, max-age=0, no-cache, no-store"
            response.headers["pragma"] = "no-cache"

            log_service.audit_log("view_role_credentials", role.name, "View role username and password")

            return response
        return (
            dict(
                message="You are not authorized to view the credentials for this role."
            ),
            403,
        )
Exemplo n.º 22
0
def set_third_party(role_id, third_party_status=False):
    """
    Sets a role to be a third party role. A user should pretty much never
    call this directly.

    :param role_id:
    :param third_party_status:
    :return:
    """
    role = get(role_id)
    role.third_party = third_party_status
    database.update(role)

    log_service.audit_log("update_role", role.name,
                          f"Updated third_party_status={third_party_status}")
    return role
Exemplo n.º 23
0
def create(data):
    provider_name = data.get("name")

    credentials = {}
    for item in data.get("provider_type", {}).get("requirements", []):
        credentials[item["name"]] = item["value"]
    dns_provider = DnsProvider(
        name=provider_name,
        description=data.get("description"),
        provider_type=data.get("provider_type").get("name"),
        credentials=json.dumps(credentials),
    )
    created = database.create(dns_provider)

    log_service.audit_log("create_dns_provider", provider_name, "Created new DNS provider")
    return created.id
Exemplo n.º 24
0
def cancel(pending_certificate, **kwargs):
    """
    Cancel a pending certificate.  A check should be done prior to this function to decide to
    revoke the certificate or just abort cancelling.

    :arg pending_certificate: PendingCertificate to be cancelled
    :return: the pending certificate if successful, raises Exception if there was an issue
    """
    plugin = plugins.get(pending_certificate.authority.plugin_name)
    plugin.cancel_ordered_certificate(pending_certificate, **kwargs)
    pending_certificate.status = "Cancelled"
    database.update(pending_certificate)

    log_service.audit_log("cancel_pending_certificate",
                          pending_certificate.name,
                          "Cancelled the pending certificate")
    return pending_certificate
Exemplo n.º 25
0
def create(label, plugin_name, options, description=None):
    """
    Creates a new source, that can then be used as a source for certificates.

    :param label: Source common name
    :param plugin_name:
    :param options:
    :param description:
    :rtype: Source
    :return: New source
    """
    source = Source(label=label,
                    options=options,
                    plugin_name=plugin_name,
                    description=description)
    log_service.audit_log("create_source", source.label, "Creating new source")
    return database.create(source)
Exemplo n.º 26
0
def update(authority_id, description, owner, active, roles):
    """
    Update an authority with new values.

    :param authority_id:
    :param roles: roles that are allowed to use this authority
    :return:
    """
    authority = get(authority_id)

    authority.roles = roles
    authority.active = active
    authority.description = description
    authority.owner = owner

    log_service.audit_log("update_authority", authority.name, "Updating authority")  # check ui what can be updated
    return database.update(authority)
Exemplo n.º 27
0
def update(role_id, name, description, users):
    """
    Update a role

    :param role_id:
    :param name:
    :param description:
    :param users:
    :return:
    """
    role = get(role_id)
    role.name = name
    role.description = description
    role.users = users
    database.update(role)

    log_service.audit_log("update_role", name,
                          f"Role with id {role_id} updated")
    return role
Exemplo n.º 28
0
def update_user(user, profile, roles):
    """Updates user with current profile information and associated roles.

    :param user:
    :param profile:
    :param roles:
    """
    # if we get an sso user create them an account
    if not user:
        user = user_service.create(
            profile["email"],
            get_psuedo_random_string(),
            profile["email"],
            True,
            profile.get("thumbnailPhotoUrl"),
            roles,
        )

    else:
        # we add 'lemur' specific roles, so they do not get marked as removed
        removed_roles = []
        for ur in user.roles:
            if not ur.third_party:
                roles.append(ur)
            elif ur not in roles:
                # This is a role assigned in lemur, but not returned by sso during current login
                removed_roles.append(ur.name)

        if removed_roles:
            log_service.audit_log("unassign_role", user.username,
                                  f"Un-assigning roles {removed_roles}")
        # update any changes to the user
        user_service.update(
            user.id,
            profile["email"],
            profile["email"],
            True,
            profile.get("thumbnailPhotoUrl"),  # profile isn't google+ enabled
            roles,
        )

    return user
Exemplo n.º 29
0
def create(**kwargs):
    """
    Creates a new authority.
    """
    ca_name = kwargs.get("name")
    if get_by_name(ca_name):
        raise Exception(f"Authority with name {ca_name} already exists")
    if role_service.get_by_name(
            f"{ca_name}_admin") or role_service.get_by_name(
                f"{ca_name}_operator"):
        raise Exception(
            f"Admin and/or operator roles for authority {ca_name} already exist"
        )

    body, private_key, chain, roles = mint(**kwargs)

    kwargs["creator"].roles = list(set(list(kwargs["creator"].roles) + roles))

    kwargs["body"] = body
    kwargs["private_key"] = private_key
    kwargs["chain"] = chain

    if kwargs.get("roles"):
        kwargs["roles"] += roles
    else:
        kwargs["roles"] = roles

    cert = upload(**kwargs)
    kwargs["authority_certificate"] = cert
    if kwargs.get("plugin", {}).get("plugin_options", []):
        kwargs["options"] = json.dumps(kwargs["plugin"]["plugin_options"])

    authority = Authority(**kwargs)
    authority = database.create(authority)
    kwargs["creator"].authorities.append(authority)

    log_service.audit_log("create_authority", ca_name, "Created new authority")
    metrics.send("authority_created",
                 "counter",
                 1,
                 metric_tags=dict(owner=authority.owner))
    return authority
Exemplo n.º 30
0
def delete(source_id):
    """
    Deletes an source.

    :param source_id: Lemur assigned ID
    """
    source = get(source_id)
    if source:
        # remove association of this source from all valid certificates
        certificates = certificate_service.get_all_valid_certificates_with_source(
            source_id)
        for certificate in certificates:
            certificate_service.remove_source_association(certificate, source)
            current_app.logger.warning(
                f"Removed source {source.label} for {certificate.name} during source delete"
            )

        # proceed with source delete
        log_service.audit_log("delete_source", source.label, "Deleting source")
        database.delete(source)