""" .. module: lemur.endpoints.service :platform: Unix :synopsis: This module contains all of the services level functions used to administer endpoints in Lemur :copyright: (c) 2018 by Netflix Inc., see AUTHORS for more :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ import arrow from sqlalchemy import func from lemur import database from lemur.common.utils import truthiness from lemur.endpoints.models import Endpoint, Policy, Cipher from lemur.extensions import metrics def get_all(): """ Get all endpoints that are currently in Lemur. :rtype : List :return: """ query = database.session_query(Endpoint) return database.find_all(query, Endpoint, {}).all() def get(endpoint_id): """ Retrieves an endpoint given it's ID :param endpoint_id: :return: """ return database.get(Endpoint, endpoint_id) def get_by_name(name): """ Retrieves an endpoint given it's name. :param name: :return: """ return database.get(Endpoint, name, field="name") def get_by_dnsname(dnsname): """ Retrieves an endpoint given it's name. :param dnsname: :return: """ return database.get(Endpoint, dnsname, field="dnsname") def get_by_dnsname_and_port(dnsname, port): """ Retrieves and endpoint by it's dnsname and port. :param dnsname: :param port: :return: """ return ( Endpoint.query.filter(Endpoint.dnsname == dnsname) .filter(Endpoint.port == port) .scalar() ) def get_by_source(source_label): """ Retrieves all endpoints for a given source. :param source_label: :return: """ return Endpoint.query.filter(Endpoint.source.label == source_label).all() # noqa def get_all_pending_rotation(): """ Retrieves all endpoints which have certificates deployed that have been replaced. :return: """ return Endpoint.query.filter(Endpoint.replaced.any()).all() def create(**kwargs): """ Creates a new endpoint. :param kwargs: :return: """ endpoint = Endpoint(**kwargs) database.create(endpoint) metrics.send( "endpoint_added", "counter", 1, metric_tags={"source": endpoint.source.label} ) return endpoint def get_or_create_policy(**kwargs): policy = database.get(Policy, kwargs["name"], field="name") if not policy: policy = Policy(**kwargs) database.create(policy) return policy def get_or_create_cipher(**kwargs): cipher = database.get(Cipher, kwargs["name"], field="name") if not cipher: cipher = Cipher(**kwargs) database.create(cipher) return cipher def update(endpoint_id, **kwargs): endpoint = database.get(Endpoint, endpoint_id) endpoint.policy = kwargs["policy"] endpoint.certificate = kwargs["certificate"] endpoint.source = kwargs["source"] endpoint.last_updated = arrow.utcnow() metrics.send( "endpoint_updated", "counter", 1, metric_tags={"source": endpoint.source.label} ) database.update(endpoint) return endpoint def render(args): """ Helper that helps us render the REST Api responses. :param args: :return: """ query = database.session_query(Endpoint) filt = args.pop("filter") if filt: terms = filt.split(";") if "active" in filt: # this is really weird but strcmp seems to not work here?? query = query.filter(Endpoint.active == truthiness(terms[1])) elif "port" in filt: if terms[1] != "null": # ng-table adds 'null' if a number is removed query = query.filter(Endpoint.port == terms[1]) elif "ciphers" in filt: query = query.filter(Cipher.name == terms[1]) else: query = database.filter(query, Endpoint, terms) return database.sort_and_page(query, Endpoint, args) def stats(**kwargs): """ Helper that defines some useful statistics about endpoints. :param kwargs: :return: """ attr = getattr(Endpoint, kwargs.get("metric")) query = database.db.session.query(attr, func.count(attr)) items = query.group_by(attr).all() keys = [] values = [] for key, count in items: keys.append(key) values.append(count) return {"labels": keys, "values": values}