Ejemplo n.º 1
0
def system_actions(id):
	if not does_user_have_system_permission(id,"view.detail","systems.all.view"):
		abort(403)

	# Get the system
	system = cortex.lib.systems.get_system_by_id(id)

	# Ensure that the system actually exists, and return a 404 if it doesn't
	if system is None:
		abort(404)

	# Get the list of actions we can perform
	actions = []
	for action in app.wf_system_functions:
		if action['menu']:
			## Add to menu ONLY if:
			### they have workflows.all
			### they have the per-system permission set in the workflow action
			### they have the global permission set in the workflow action

			if does_user_have_permission("workflows.all"):
				actions.append(action)
			elif does_user_have_system_permission(id,action['system_permission']):
				app.logger.debug("User " + session['username'] + " does not have workflows.all")
				actions.append(action)
			elif action['permission'] is not None:
				app.logger.debug("User " + session['username'] + " does not have " + action['system_permission'])

				if does_user_have_permission("workflows." + action['permission']):
					actions.append(action)
				else:
					app.logger.debug("User " + session['username'] + " does not have " + action['permission'])

	return render_template('systems/actions.html', system=system, active='systems', actions=actions, title=system['name'])
Ejemplo n.º 2
0
def favourites(system_type='all'):

    # Check user permissions
    if not (does_user_have_permission("systems.all.view")
            or does_user_have_permission("systems.own.view")):
        abort(403)

    # Get the list of active classes (used to populate the tab bar)
    classes = {}
    if does_user_have_permission("systems.all.view"):
        classes = cortex.lib.classes.get_list()

    if system_type != "all" and system_type not in [
            class_obj["name"] for class_obj in classes
    ]:
        flash("system type {} does not exist.".format(system_type),
              category="alert-info")

    # Get the search string, if any and strip
    query = request.args["q"].strip() if request.args.get(
        "q", None) is not None else None

    # Render
    return render_template('systems/list.html',
                           classes=classes,
                           active='favourites',
                           title="Favourites",
                           favourites=1,
                           q=query,
                           hide_inactive=False,
                           display=system_type)
Ejemplo n.º 3
0
	def get(self):
		"""
		Returns a paginated list of rows from the systems_info_view.
		"""

		page, per_page, limit_start, limit_length = process_pagination_arguments(request)

		if not (does_user_have_permission("systems.all.view") or does_user_have_permission("systems.own.view")):
			raise InvalidPermissionException

		class_name = None
		hide_inactive = False
		only_other = False
		show_expired = False
		show_nocmdb = False
		show_allocated_and_perms = False

		if does_user_have_permission("systems.all.view"):
			only_allocated_by = None
		else:
			# Show the systems where the user has permissions AND the ones they allocated.
			show_allocated_and_perms = True
			if request.authorization:
				only_allocated_by = request.authorization.username
			else:
				if 'username' in session:
					only_allocated_by = session['username']
				else:
					raise InvalidPermissionException

		total = cortex.lib.systems.get_system_count(class_name=class_name, hide_inactive=hide_inactive, only_other=only_other, show_expired=show_expired, show_nocmdb=show_nocmdb, show_allocated_and_perms=show_allocated_and_perms, only_allocated_by=only_allocated_by)
		results = cortex.lib.systems.get_systems(class_name=class_name, order='id', limit_start=limit_start, limit_length=limit_length, hide_inactive=hide_inactive, only_other=only_other, show_expired=show_expired, show_nocmdb=show_nocmdb, show_allocated_and_perms=show_allocated_and_perms, only_allocated_by=only_allocated_by)

		return pagination_response(results, page, per_page, total)
Ejemplo n.º 4
0
def systems_search():
	"""Allows the user to search for a system by entering its name in the 
	search box"""

	# Check user permissions
	if not (does_user_have_permission("systems.all.view") or does_user_have_permission("systems.own.view")):
		abort(403)

	# Get the query from the URL
	query = request.args.get('query')
	if query is None:
		app.logger.warn('Missing \'query\' parameter in systems search request')
		return abort(400)

	# Search for the system
	curd = g.db.cursor(mysql.cursors.DictCursor)

	if 'imfeelinglucky' in request.args and request.args.get('imfeelinglucky') == 'yes':
		# Use this rather than .format due to Unicode problems.
		like_query = '%' + query + '%'
		# Use a LIKE query.
		curd.execute("SELECT * FROM `systems_info_view` WHERE `name` LIKE %s", (like_query,))
	else:
		# Search by exact name matches only.
		curd.execute("SELECT * FROM `systems_info_view` WHERE `name`=%s", (query,))

	system = curd.fetchone()
	
	# Check if there was only 1 result.
	if curd.rowcount == 1 and system is not None:
		# If we found the system, redirect to the system page
		return redirect(url_for('system', id=system['id']))
	else:
		# If we didn't find the system, search for it instead
		return redirect(url_for('systems',q=query))
Ejemplo n.º 5
0
def system_actions(id):
	if not does_user_have_system_permission(id,"view","systems.all.view"):
		abort(403)

	# Get the system
	system = cortex.lib.systems.get_system_by_id(id)

	# Ensure that the system actually exists, and return a 404 if it doesn't
	if system is None:
		abort(404)

	# Get the list of actions we can perform
	actions = []
	for action in app.wf_system_functions:
		if action['menu']:
			## Add to menu ONLY if:
			### they have workflows.all
			### they have the per-system permission set in the workflow action
			### they have the global permission set in the workflow action

			if does_user_have_permission("workflows.all"):
				actions.append(action)
			elif does_user_have_system_permission(id,action['system_permission']):
				app.logger.debug("User " + session['username'] + " does not have workflows.all")
				actions.append(action)								
			elif action['permission'] is not None:
				app.logger.debug("User " + session['username'] + " does not have " + action['system_permission'])

				if does_user_have_permission("workflows." + action['permission']):
					actions.append(action)
				else:
					app.logger.debug("User " + session['username'] + " does not have " + action['permission'])

	return render_template('systems/actions.html', system=system, active='systems', actions=actions, title=system['name'])
Ejemplo n.º 6
0
def puppet_groups():
	"""Handles the Puppet Groups page"""

	# Check user permissions
	if not does_user_have_permission("puppet.groups.view"):
		abort(403)

	# Get a cursor to the databaseo
	curd = g.db.cursor(mysql.cursors.DictCursor)

	if request.method == 'GET':
		# Get OS statistics
		curd.execute('SELECT * FROM `puppet_groups`')
		results = curd.fetchall()

		return render_template('puppet/groups.html', active='puppet', data=results, title="Puppet Groups")
	else:
		# Check user permissions
		if not does_user_have_permission("puppet.groups.edit"):
			abort(403)

		if request.form['action'] == 'add':
			netgroup_name = request.form['netgroup_name']

			if len(netgroup_name.strip()) == 0:
				flash('Invalid netgroup name', 'alert-danger')
				return redirect(url_for('puppet_groups'))

			# Make sure that group hasnt already been imported
			curd.execute('SELECT 1 FROM `puppet_groups` WHERE `name` = %s', (netgroup_name,))
			found = curd.fetchone()
			if found:
				flash('That netgroup has already been imported as a Puppet Group', 'alert-warning')
				return redirect(url_for('puppet_groups'))			

			if not cortex.lib.netgroup.exists(netgroup_name):
				flash('That netgroup does not exist', 'alert-danger')
				return redirect(url_for('puppet_groups'))

			curd.execute('INSERT INTO `puppet_groups` (`name`) VALUES (%s)', (netgroup_name,))
			g.db.commit()
			cortex.lib.core.log(__name__, "puppet.group.created", "Netgroup '" + netgroup_name + "' imported as a Puppet Group")

			flash('The netgroup "' + netgroup_name + '" has imported as a Puppet Group', 'alert-success')
			return redirect(url_for('puppet_groups'))
		elif request.form['action'] == 'delete':
			group_name = request.form['group']

			try:
				curd.execute('DELETE FROM `puppet_groups` WHERE `name` = %s', (group_name,))
				g.db.commit()
				cortex.lib.core.log(__name__, "puppet.group.deleted", "Deleted Puppet group '" + group_name + "'")
				flash('Deleted Puppet group "' + group_name + '"', 'alert-success')
			except Exception, e:
				flash('Failed to delete Puppet group', 'alert-danger')

			return redirect(url_for('puppet_groups'))
Ejemplo n.º 7
0
def puppet_groups():
    """Handles the Puppet Groups page"""

    # Check user permissions
    if not does_user_have_permission("puppet.groups.view"):
        abort(403)

        # Get a cursor to the databaseo
    curd = g.db.cursor(mysql.cursors.DictCursor)

    if request.method == "GET":
        # Get OS statistics
        curd.execute("SELECT * FROM `puppet_groups`")
        results = curd.fetchall()

        return render_template("puppet/groups.html", active="puppet", data=results, title="Puppet Groups")
    else:
        # Check user permissions
        if not does_user_have_permission("puppet.groups.edit"):
            abort(403)

        if request.form["action"] == "add":
            netgroup_name = request.form["netgroup_name"]

            if len(netgroup_name.strip()) == 0:
                flash("Invalid netgroup name", "alert-danger")
                return redirect(url_for("puppet_groups"))

                # Make sure that group hasnt already been imported
            curd.execute("SELECT 1 FROM `puppet_groups` WHERE `name` = %s", netgroup_name)
            found = curd.fetchone()
            if found:
                flash("That netgroup has already been imported as a Puppet Group", "alert-warning")
                return redirect(url_for("puppet_groups"))

            if not cortex.lib.netgroup.exists(netgroup_name):
                flash("That netgroup does not exist", "alert-danger")
                return redirect(url_for("puppet_groups"))

            curd.execute("INSERT INTO `puppet_groups` (`name`) VALUES (%s)", (netgroup_name))
            g.db.commit()

            flash('The netgroup "' + netgroup_name + '" has imported as a Puppet Group', "alert-success")
            return redirect(url_for("puppet_groups"))
        elif request.form["action"] == "delete":
            group_name = request.form["group"]

            try:
                curd.execute("DELETE FROM `puppet_groups` WHERE `name` = %s", group_name)
                g.db.commit()
                flash('Deleted Puppet group "' + group_name + '"', "alert-success")
            except Exception, e:
                flash("Failed to delete Puppet group", "alert-danger")

            return redirect(url_for("puppet_groups"))
Ejemplo n.º 8
0
def admin_specs():
	"""Displays a page to edit VM spec settings for the standard VM."""

	# Check user permissions
	if not does_user_have_permission("specs.view"):
		abort(403)

	# Defaults
	vm_spec_json = {}

	# Get the VM Specs from the DB
	try:
		vm_spec_json = cortex.lib.admin.get_kv_setting('vm.specs', load_as_json=True)
	except ValueError:
		flash("Could not parse JSON from the database.", "alert-danger")
		vm_spec_json = {}

	# Get the VM Specs Config from the DB.
	try:
		vm_spec_config_json = cortex.lib.admin.get_kv_setting('vm.specs.config', load_as_json=True)
	except ValueError:
		flash("Could not parse JSON from the database.", "alert-danger")
		vm_spec_config_json = {}

	if request.method == 'POST':

		# Check user permissions
		if not does_user_have_permission("specs.edit"):
			abort(403)

		if 'specs' in request.form:
			try:
				vm_spec_json = json.loads(request.form['specs'])
			except ValueError:
				flash("The JSON you submitted was invalid, your changes have not been saved.", "alert-danger")
				return render_template('admin/specs.html', active='specs', title="VM Specs", vm_spec_json=request.form['specs'], vm_spec_config_json=json.dumps(vm_spec_config_json, sort_keys=True, indent=4))
			else:
				cortex.lib.admin.set_kv_setting('vm.specs', json.dumps(vm_spec_json))

		if 'specsconfig' in request.form:
			try:
				vm_spec_config_json = json.loads(request.form['specsconfig'])
			except ValueError:
				flash("The JSON you submitted was invalid, your changes have not been saved.", "alert-danger")
				return render_template('admin/specs.html', active='specs', title="VM Specs", vm_spec_json=json.dumps(vm_spec_json, sort_keys=True, indent=4), vm_spec_config_json=request.form['specsconfig'])
			else:

				# Do some simple validation.
				if 'spec-order' in vm_spec_config_json and not all(s in vm_spec_json for s in vm_spec_config_json['spec-order']):
					flash("You have specified a 'spec-order' which contains specification names not in the 'VM Specification JSON'. Your changes have not been saved.", "alert-warning")
				else:
					cortex.lib.admin.set_kv_setting('vm.specs.config', json.dumps(vm_spec_config_json))

	# Render the page
	return render_template('admin/specs.html', active='specs', title="VM Specs", vm_spec_json=json.dumps(vm_spec_json, sort_keys=True, indent=4), vm_spec_config_json=json.dumps(vm_spec_config_json, sort_keys=True, indent=4))
Ejemplo n.º 9
0
def sysrequest(id):

    # Get the system
    sysrequest = cortex.lib.sysrequests.get_request_by_id(id)

    # Ensure that the request actually exists, and return a 404 if it doesn't
    if sysrequest is None:
        abort(404)

    # Check user permissions. User must have either sysrequests.all or own
    # the request
    if sysrequest['requested_who'] != session[
            'username'] and not does_user_have_permission(
                "sysrequests.all.view"):
        abort(403)

    if request.method == 'POST':
        try:
            action = request.form.get('action')
            if len(request.form.get('status_text', '')) > 0:
                status_text = request.form.get('status_text')
            else:
                status_text = None
            if action == 'approve' and does_user_have_permission(
                    "sysrequests.all.approve"):
                cortex.lib.sysrequests.approve(id, status_text)
            elif action == 'reject' and does_user_have_permission(
                    "sysrequests.all.reject"):
                cortex.lib.sysrequests.reject(id, status_text)
            else:
                raise ValueError('Unexpected action: "' + action + '".')
            # get the updated system
            sysrequest = cortex.lib.sysrequests.get_request_by_id(id)
        except ValueError as e:
            abort(400)

    sysrequest['requested_who'] = cortex.lib.user.get_user_realname(
        sysrequest['requested_who']) + ' (' + sysrequest['requested_who'] + ')'

    #get action permssions to decide whether or not to show controls
    perms = {
        'approve': does_user_have_permission("sysrequests.all.approve"),
        'reject': does_user_have_permission("sysrequests.all.reject")
    }

    return render_template('sysrequests/view.html',
                           request=sysrequest,
                           title="Request #" + str(sysrequest['id']),
                           perms=perms)
Ejemplo n.º 10
0
def puppet_group_edit(name):
    """Handles the Puppet group editing page (for assigning classes to a group)"""

    # Check user permissions
    if not does_user_have_permission("puppet.groups.view"):
        abort(403)

        # Get a cursor to the database
    curd = g.db.cursor(mysql.cursors.DictCursor)

    # Get the group from the DB
    curd.execute("SELECT * FROM `puppet_groups` WHERE `name` = %s", name)
    group = curd.fetchone()
    if not group:
        flash("I could not find a Puppet Group with that name", "alert-warning")
        return redirect(url_for("puppet_groups"))

    if group["classes"] is None:
        group["classes"] = "# Classes to include can be entered here\n"

        # On any GET request, just display the information
    if request.method == "GET":
        return render_template("puppet/group.html", group=group, active="puppet", title=group["name"])

        # On any POST request, validate the input and then save
    elif request.method == "POST":
        # Check user permissions
        if not does_user_have_permission("puppet.groups.edit"):
            abort(403)

            # Extract data from form
        classes = request.form.get("classes", "")

        # Validate classes YAML
        try:
            yaml.load(classes)
        except Exception, e:
            flash("Invalid YAML syntax for classes: " + str(e), "alert-danger")
            return render_template(
                "puppet/group.html", group=group, classes=classes, active="puppet", title=group["name"]
            )

            # Update the system
        curd.execute("UPDATE `puppet_groups` SET `classes` = %s WHERE `name` = %s", (classes, name))
        g.db.commit()

        # Redirect back to the systems page
        flash("Changes saved successfully", "alert-success")
        return redirect(url_for("puppet_group_edit", name=name))
Ejemplo n.º 11
0
def puppet_group_edit(name):
	"""Handles the Puppet group editing page (for assigning classes to a group)"""

	# Check user permissions
	if not does_user_have_permission("puppet.groups.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get the group from the DB
	curd.execute('SELECT * FROM `puppet_groups` WHERE `name` = %s', (name,))
	group = curd.fetchone()
	if not group:
		flash('I could not find a Puppet Group with that name', 'alert-warning')
		return redirect(url_for('puppet_groups'))

	if group['classes'] is None:
		group['classes'] = "# Classes to include can be entered here\n"

	# On any GET request, just display the information
	if request.method == 'GET':
		return render_template('puppet/group.html', group=group, active='puppet', title=group['name'])

	# On any POST request, validate the input and then save
	elif request.method == 'POST':
		# Check user permissions
		if not does_user_have_permission("puppet.groups.edit"):
			abort(403)

		# Extract data from form
		classes = request.form.get('classes', '')

		# Validate classes YAML
		try:
			data = yaml.load(classes)
		except Exception, e:
			flash('Invalid YAML syntax for classes: ' + str(e), 'alert-danger')
			group['classes'] = classes
			return render_template('puppet/group.html', group=group, active='puppet', title=group['name'])

		try:
			if not data is None:
				assert isinstance(data, dict)
		except Exception, e:
			flash('Invalid YAML syntax: result was not a list of classes, did you forget a trailing colon? ' + str(e), 'alert-danger')
			group['classes'] = classes
			return render_template('puppet/group.html', group=group, active='puppet', title=group['name'])
Ejemplo n.º 12
0
def vmware_history():
	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Figure out how many days to show
	if 'd' in request.args:
		d = int(request.args['d'])
	else:
		d = 14

	# Get VM count history
	curd.execute('SELECT `timestamp`, `value` FROM `stats_vm_count` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL ' + str(d) + ' DAY) ORDER BY `timestamp` DESC')
	stats_vms = curd.fetchall()

	# Get Linux VM count history
	curd.execute('SELECT `timestamp`, `value` FROM `stats_linux_vm_count` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL ' + str(d) + ' DAY) ORDER BY `timestamp` DESC')
	stats_linux_vms = curd.fetchall()

	# Get Windows VM count history
	curd.execute('SELECT `timestamp`, `value` FROM `stats_windows_vm_count` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL ' + str(d) + ' DAY) ORDER BY `timestamp` DESC')
	stats_windows_vms = curd.fetchall()

	# Get Desktop VM count history
	curd.execute('SELECT `timestamp`, `value` FROM `stats_desktop_vm_count` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL ' + str(d) + ' DAY) ORDER BY `timestamp` DESC')
	stats_desktop_vms = curd.fetchall()

	# Render
	return render_template('vmware/history.html', active='vmware', stats_vms=stats_vms, stats_linux_vms=stats_linux_vms, stats_windows_vms=stats_windows_vms, stats_desktop_vms=stats_desktop_vms, title='VMware History', d=d)
Ejemplo n.º 13
0
    def get(self):
        """
		Returns a paginated list of rows from the tasks lists.
		"""

        page, per_page, limit_start, limit_length = process_pagination_arguments(
            request)

        if not does_user_have_permission("tasks.view"):
            raise InvalidPermissionException

        tasks_args = tasks_arguments.parse_args(request)
        username = tasks_args.get('username', None)
        module = tasks_args.get('module', None)
        status = tasks_args.get('status', None)

        total = cortex.lib.core.tasks_count(username=username,
                                            module=module,
                                            status=status)
        results = cortex.lib.core.tasks_get(username=username,
                                            module=module,
                                            status=status,
                                            order='id',
                                            limit_start=limit_start,
                                            limit_length=limit_length)

        return pagination_response(results, page, per_page, total)
Ejemplo n.º 14
0
def systems_bulk_save():
	"""This is a POST handler used to set comments for a series of existing 
	systems which have been allocated already"""

	# Check user permissions
	if not does_user_have_permission("systems.allocate_name"):
		abort(403)

	found_keys = []

	# Find a list of systems from the form. Each of the form input elements
	# containing a system comment has a name that starts "system_comment_"
	for key, value in request.form.iteritems():
		if key.startswith("system_comment_"):
			# Yay we found one! blindly update it!
			updateid = key.replace("system_comment_", "")
			found_keys.append(updateid)
			cur = g.db.cursor()
			cur.execute("UPDATE `systems` SET `allocation_comment` = %s WHERE `id` = %s", (request.form[key], updateid))
			cortex.lib.core.log(__name__, "systems.comment.edit", "System comment updated for id " + str(updateid),related_id=updateid)

	g.db.commit()

	flash("Comments successfully updated", "alert-success")
	return(redirect(url_for("systems_bulk_view", start=min(found_keys), finish=max(found_keys))))
Ejemplo n.º 15
0
def systems_new():
	"""Handles the Allocate New System Name(s) page"""

	# Check user permissions
	if not does_user_have_permission("systems.allocate_name"):
		abort(403)

	# On GET requests, just show big buttons for all the classes
	if request.method == 'GET':
		classes = cortex.lib.classes.list(hide_disabled=True)
		return render_template('systems/new.html', classes=classes, active='systems', title="Allocate new system names")

	# On POST requests...
	elif request.method == 'POST':
		# The user has asked for one or more new system names.

		# Grab the prefix chosen and validate it's a valid class name.
		# The regular expression matches on an entire string of 1 to 16 lowercase characters
		class_name = request.form['class_name']
		if not re.match(r'^[a-z]{1,16}$', class_name):
			flash("The class prefix you sent was invalid. It can only contain lowercase letters and be at least 1 character long and at most 16", "alert-danger")
			return redirect(url_for('systems_new'))

		# Grab how many names the user wants and validate it
		system_number = int(request.form['system_number'])

		# Validate the number of systems
		if system_number < 1 or system_number > 50:
			flash("You cannot allocate more than 50 names at once, sorry about that.", "alert-danger")
			return redirect(url_for('admin_classes'))

		# Grab the comment
		if 'system_comment' in request.form:
			system_comment = request.form['system_comment']
		else:
			system_comment = ""

		# Allocate the names asked for
		try:
			# To prevent code duplication, this is done remotely by Neocortex. So, connect:
			neocortex   = cortex.lib.core.neocortex_connect()

			# Allocate the name
			new_systems = neocortex.allocate_name(class_name, system_comment, username=session['username'], num=system_number)
		except Exception as ex:
			flash("A fatal error occured when trying to allocate names: " + str(ex), "alert-danger")
			return redirect(url_for('systems_new'))

		for new_system_name in new_systems:
			cortex.lib.core.log(__name__, "systems.name.allocate", "New system name allocated: " + new_system_name,related_id=new_systems[new_system_name])

		# If the user only wanted one system, redirect back to the systems
		# list page and flash up success. If they requested more than one
		# system, then redirect to a bulk-comments-edit page where they can
		# change the comments on all of the systems.
		if len(new_systems) == 1:
			flash("System name allocated successfully", "alert-success")
			return redirect(url_for('system', id=new_systems[new_systems.keys()[0]]))
		else:
			return render_template('systems/new-bulk.html', systems=new_systems, comment=system_comment, title="Systems")
Ejemplo n.º 16
0
def puppet_nodes():
    """Handles the Puppet nodes list page"""

    # Check user permissions
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

        # Get a cursor to the database
    curd = g.db.cursor(mysql.cursors.DictCursor)

    # Get Puppet nodes from the database
    curd.execute(
        "SELECT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`  FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` ORDER BY `puppet_nodes`.`certname` "
    )
    results = curd.fetchall()

    # Get node statuses
    try:
        statuses = cortex.lib.puppet.puppetdb_get_node_statuses()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    for row in results:
        if row["certname"] in statuses:
            row["status"] = statuses[row["certname"]]
        else:
            row["status"] = "unknown"

            # Render
    return render_template("puppet/nodes.html", active="puppet", data=results, title="Puppet Nodes")
Ejemplo n.º 17
0
def task_status_log(task_id):
    """Much like task_status, but only returns the event log. This is used by
	an AJAX routine on the page to refresh the log every 10 seconds."""

    ## Get the task details
    task = cortex.lib.core.task_get(task_id)

    # Return a 404 if we've not found the task
    if not task:
        abort(404)

    # Check the user has the permission to view this task
    if not task['username'] == session['username']:
        if not does_user_have_permission("tasks.view"):
            abort(403)

    # Check if the hide success flag is set
    hide_success = False
    if "hide_success" in request.args and request.args.get(
            "hide_success", None):
        hide_success = True

    return cortex.lib.core.task_render_status(task,
                                              "tasks/status-log.html",
                                              hide_success=hide_success)
Ejemplo n.º 18
0
def puppet_search():
    """Provides search functionality for puppet classes and environment
	variables"""

    # Check user permissions
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

    q = request.args.get('q')
    if q is None:
        app.logger.warn('Missing \'query\' parameter in puppet search request')
        return abort(400)

    q.strip()
    # escape wildcards
    q = q.replace('%', '\%').replace('_', '\_')

    #Search for the text
    curd = g.db.cursor(mysql.cursors.DictCursor)
    curd.execute(
        '''SELECT DISTINCT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`  FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` WHERE `puppet_nodes`.`classes` LIKE %s OR `puppet_nodes`.`variables` LIKE %s ORDER BY `puppet_nodes`.`certname`''',
        ('%' + q + '%', '%' + q + '%'))
    results = curd.fetchall()

    return render_template('puppet/search.html',
                           active='puppet',
                           data=results,
                           title="Puppet search")
Ejemplo n.º 19
0
def puppet_nodes():
	"""Handles the Puppet nodes list page"""

	# Check user permissions
	if not does_user_have_permission("puppet.nodes.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get Puppet nodes from the database
	curd.execute('SELECT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`  FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` ORDER BY `puppet_nodes`.`certname` ')
	results = curd.fetchall()

	# Get node statuses
	try:
		statuses = cortex.lib.puppet.puppetdb_get_node_statuses()
	except Exception as ex:
		return stderr("Unable to connect to PuppetDB","Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex))


	for row in results:
		if row['certname'] in statuses:
			row['status'] = statuses[row['certname']]
		else:
			row['status'] = 'unknown'

	# Render
	return render_template('puppet/nodes.html', active='puppet', data=results, title="Puppet Nodes")
Ejemplo n.º 20
0
    def delete(self, digest):
        """
		Removes a certificate from the list of known certificates
		"""

        # Check if we have permission (API token has all permissions)
        if 'api_token_valid' not in session or session[
                'api_token_valid'] is not True:
            if not does_user_have_permission("certificates.view"):
                raise InvalidPermissionException

        # Make sure the certificate exists
        curd = g.db.cursor(mysql.cursors.DictCursor)
        curd.execute('SELECT `digest` FROM `certificate` WHERE `digest` = %s',
                     (digest, ))
        result = curd.fetchone()

        if result is None:
            return certificates_namespace.abort(404, 'Certificate not found')

        # Delete the certificate
        curd.execute('DELETE FROM `certificate` WHERE `digest` = %s',
                     (digest, ))
        g.db.commit()

        # Return HTTP No Content
        return "", 204
Ejemplo n.º 21
0
def vmware_clusters():
	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Generate statistics about the clusters
	curd.execute('SELECT `b`.`name`, `b`.`vcenter`, `b`.`hosts`, `a`.`vm_count`, (`b`.`ram_usage` * 1048576) AS `ram_usage`, (`a`.`assigned_ram` * 1048576) AS `assigned_ram`, `b`.`ram` AS `total_ram`, `a`.`assigned_cores`, `b`.`cores` AS `total_cores`, `b`.`cpu_usage` AS `cpu_usage_mhz`, ROUND(`b`.`cpuhz` / 1000) AS `total_mhz` FROM (SELECT `cluster`, `vcenter`, COUNT(*) AS `vm_count`, SUM(`numCPU`) AS `assigned_cores`, SUM(`memoryMB`) AS `assigned_ram` FROM `vmware_cache_vm` WHERE `cluster` != "None" group by `cluster`) `a` RIGHT JOIN `vmware_cache_clusters` `b` ON `a`.`cluster` = `b`.`name`')

	# Take the above query and group it by vCenter
	vcenters = {}
	row = curd.fetchone()
	while row is not None:
		# If this is the first time we've seen a vCenter, create a new array
		if row['vcenter'] not in vcenters:
			vcenters[row['vcenter']] = []

		# Deal with Nones (which can appear if there are no hosts or VMs on a cluster)
		for key in ['ram_usage', 'assigned_ram', 'total_ram', 'assigned_cores', 'total_cores', 'cpu_usage_mhz', 'total_mhz', 'vm_count']:
			if row[key] is None:
				row[key] = 0

		# Add a row to the array
		vcenters[row['vcenter']].append(row)

		# Iterate to next cluster
		row = curd.fetchone()

	# Render
	return render_template('vmware/clusters.html', active='vmware', vcenters=vcenters, title="VMware Clusters")
Ejemplo n.º 22
0
def admin_tasks_active():
    """Displays the active tasks"""

    # Check user permissions
    if not does_user_have_permission("tasks.view"):
        abort(403)

        # Get the list of tasks from NeoCortex
    curd = g.db.cursor(mysql.cursors.DictCursor)
    neocortex = cortex.lib.core.neocortex_connect()
    neotasks = neocortex.active_tasks()
    tasks = []

    # Get additional information out of the database
    for ntask in neotasks:
        curd.execute(
            "SELECT `id`, `module`, `username`, `start`, `end`, `status`, `description` FROM `tasks` WHERE `id` = %s",
            (ntask["id"]),
        )
        task = curd.fetchone()
        if not task == None:
            tasks.append(task)

            # Render the page
    return render_template("admin/tasks.html", tasks=tasks, active="admin", title="Active Tasks", tasktype="active")
Ejemplo n.º 23
0
def admin_tasks_active():
    """Displays the active tasks"""

    # Check user permissions
    if not does_user_have_permission("tasks.view"):
        abort(403)

    # Get the list of tasks from NeoCortex
    curd = g.db.cursor(mysql.cursors.DictCursor)
    neocortex = cortex.lib.core.neocortex_connect()
    neotasks = neocortex.active_tasks()
    tasks = []

    # Get additional information out of the database
    for ntask in neotasks:
        curd.execute(
            "SELECT `id`, `module`, `username`, `start`, `end`, `status`, `description` FROM `tasks` WHERE `id` = %s",
            (ntask['id'], ))
        task = curd.fetchone()
        if not task == None:
            tasks.append(task)

    # Render the page
    return render_template('admin/tasks.html',
                           tasks=tasks,
                           active='admin',
                           title="Active Tasks",
                           tasktype='active')
Ejemplo n.º 24
0
	def get(self, id):
		# Check user permissions. User must have either systems.all.view.rubrik
		if not does_user_have_permission("systems.all.view.rubrik"):
			abort(403)

		# Get the name of the vm
		system = cortex.lib.systems.get_system_by_id(id)
		if not system:
			abort(404)

		try:
			vm = self.rubrik.get_vm(system['name'])
		except:
			abort(500)

		# If the VM was not found, return early
		if vm is None:
			return render_template('systems/backup.html', system=system, vm=None, title=system['name'])

		# Get the list of all SLA Domains
		sla_domains = self.rubrik.get_sla_domains()

		# Get the SLA Domains and Snapshots for the VM
		vm['effectiveSlaDomain'] = next((sla_domain for sla_domain in sla_domains['data'] if sla_domain['id'] == vm['effectiveSlaDomainId']), 'unknown')
		vm['snapshots'] = self.rubrik.get_vm_snapshots(vm['id'])

		# Try to limit to the most recent 10, ignoring the error if there are less
		try:
			vm['snapshots']['data'] = vm['snapshots']['data'][:10]
		except (KeyError,):
			pass

		return render_template('systems/backup.html', system=system, sla_domains=sla_domains,
				vm=vm, title=system['name'])
Ejemplo n.º 25
0
def puppet_dashboard_status(status):
    """This view is responsible for listing puppet nodes but only those matching
	a certain status in PuppetDB."""

    # Check user permissions (note this is the nodes permission rather than dashboard)
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

        # For the purposes of the dashboard, unreported is the same as unknown
    if status == "unreported":
        status = "unknown"

        # Page Titles to use
    page_title_map = {
        "unchanged": "Normal",
        "changed": "Changed",
        "noop": "Disabled",
        "failed": "Failed",
        "unknown": "Unknown/Unreported",
        "all": "Registered",
    }

    # If we have an invalid status, return 404
    if status not in page_title_map:
        abort(404)

        # Connect to PuppetDB
    try:
        db = cortex.lib.puppet.puppetdb_connect()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

        # Get information about all the nodes, including their status
    nodes = db.nodes(with_status=True)

    # Create a filterd array
    nodes_of_type = []

    # Iterate over nodes and do the filtering
    if status != "all":
        for node in nodes:
            # If the status matches...
            if node.status == status:
                nodes_of_type.append(node)
                # Or if the required status is 'unknown' and it's not one of the normal statii
            elif status == "unknown" and node.status not in ["unchanged", "changed", "noop", "failed"]:
                nodes_of_type.append(node)
    else:
        nodes_of_type = nodes

    return render_template(
        "puppet/dashboard-status.html",
        active="puppet",
        title="Puppet Dashboard",
        nodes=nodes_of_type,
        status=page_title_map[status],
    )
Ejemplo n.º 26
0
def puppet_documentation(environment_id=None, module_id=None):
    """Show the Puppet documentation"""

    # Check user permissions
    if not does_user_have_permission("puppet.documentation.view"):
        abort(403)

    # Get the database cursor
    curd = g.db.cursor(mysql.cursors.DictCursor)
    module = None
    data = {}
    if module_id:
        curd.execute(
            "SELECT `puppet_modules`.`id` AS `id`, `puppet_modules`.`module_name` AS `module_name`, `puppet_environments`.`environment_name` AS `environment_name`, `puppet_modules`.`last_updated` AS `last_updated` FROM `puppet_modules` LEFT JOIN `puppet_environments` ON `puppet_modules`.`environment_id`=`puppet_environments`.`id` WHERE `puppet_modules`.`id`=%s AND `puppet_environments`.`id`=%s",
            (module_id, environment_id))
        module = curd.fetchone()

        if not module:
            abort(404)

        curd.execute(
            "SELECT * FROM `puppet_classes` LEFT JOIN `puppet_documentation` ON `puppet_classes`.`id`=`puppet_documentation`.`class_id` WHERE `puppet_classes`.`module_id`=%s;",
            (module["id"], ))
        for row in curd.fetchall():
            if row["class_name"] not in data:
                data[row["class_name"]] = {"desc": row["desc"]}

            if row["tag"] not in data[row["class_name"]]:
                data[row["class_name"]][row["tag"]] = []

            if any(row[k] for k in ["name", "text"]):
                data[row["class_name"]][row["tag"]].append({
                    "name":
                    row.get("name", "") if row.get("name") else "",
                    "text":
                    row.get("text", "") if row.get("text") else "",
                    "types":
                    json.loads(row["types"]) if row["types"] else [],
                })
    else:
        curd.execute(
            "SELECT `puppet_modules`.`id` AS `module_id`, `puppet_modules`.`module_name` AS `module_name`, `puppet_environments`.`id` AS `environment_id`, `puppet_environments`.`environment_name` AS `environment_name`, `puppet_environments`.`short_name` AS `short_name` FROM `puppet_modules` LEFT JOIN `puppet_environments` ON `puppet_modules`.`environment_id`=`puppet_environments`.`id`"
        )
        for row in curd.fetchall():
            if row["environment_id"] not in data:
                data[row["environment_id"]] = {
                    "name": row["environment_name"],
                    "short_name": row["short_name"],
                    "modules": {}
                }
            data[row["environment_id"]]["modules"][
                row["module_id"]] = row["module_name"]

    return render_template('puppet/docs.html',
                           active='puppet',
                           title="Puppet Documentation",
                           module=module,
                           data=data,
                           q=request.args.get("q", None))
Ejemplo n.º 27
0
			def decorated_function(*args, **kwargs):
				id = kwargs['id']

				## Grant permission ONLY if
				### they have workflows.all
				### they have the per-system permission set in the workflow action
				### they have the global permission set in the workflow action

				if permission is None:
					if not does_user_have_system_permission(id,system_permission) and not does_user_have_permission("workflows.all"):
						abort(403)

				else:
					if not does_user_have_system_permission(id,system_permission) and not does_user_have_permission("workflows." + permission) and not does_user_have_permission("workflows.all"):
						abort(403)

				return fn(*args, **kwargs)
Ejemplo n.º 28
0
			def decorated_function(*args, **kwargs):
				system_id = kwargs['target_id']

				## Grant permission ONLY if
				### they have workflows.all
				### they have the per-system permission set in the workflow action
				### they have the global permission set in the workflow action

				if permission is None:
					if not does_user_have_system_permission(system_id, system_permission) and not does_user_have_permission("workflows.all"):
						abort(403)

				else:
					if not does_user_have_system_permission(system_id, system_permission) and not does_user_have_permission("workflows." + permission) and not does_user_have_permission("workflows.all"):
						abort(403)

				return func(*args, **kwargs)
Ejemplo n.º 29
0
def puppet_enc_default():
    """Handles the Puppet ENC Default Classes page"""

    # Check user permissions
    if not does_user_have_permission("puppet.default_classes.view"):
        abort(403)

        # Get the default YAML out of the kv table
    curd = g.db.cursor(mysql.cursors.DictCursor)
    curd.execute("SELECT `value` FROM `kv_settings` WHERE `key` = 'puppet.enc.default'")
    result = curd.fetchone()
    if result == None:
        classes = "# Classes to include on all nodes using the default settings can be entered here\n"
    else:
        classes = result["value"]

        # On any GET request, just display the information
    if request.method == "GET":
        return render_template("puppet/default.html", classes=classes, active="puppet", title="Default Classes")

        # On any POST request, validate the input and then save
    elif request.method == "POST":
        # Check user permissions
        if not does_user_have_permission("puppet.default_classes.edit"):
            abort(403)

            # Extract data from form
        classes = request.form.get("classes", "")

        # Validate classes YAML
        try:
            yaml.load(classes)
        except Exception, e:
            flash("Invalid YAML syntax: " + str(e), "alert-danger")
            return render_template("puppet/default.html", classes=classes, active="puppet", title="Default Classes")

            # Get a cursor to the database
            # Update the system
        curd.execute('REPLACE INTO `kv_settings` (`key`, `value`) VALUES ("puppet.enc.default", %s)', (classes,))
        g.db.commit()

        # Redirect back
        flash("Puppet default settings updated", "alert-success")

        return redirect(url_for("puppet_enc_default"))
Ejemplo n.º 30
0
def system_perms_roles():

    # Check user permissions
    if not does_user_have_permission("admin.permissions"):
        abort(403)

    # Cursor for the DB
    curd = g.db.cursor(mysql.cursors.DictCursor)

    ## View list
    if request.method == 'GET':
        # Get the list of roles from the database
        roles = cortex.lib.perms.get_system_roles()

        # Render the page
        return render_template('perms/roles.html',
                               active='perms',
                               title="System Roles",
                               roles=roles,
                               manage_role_route='system_perms_role')

    ## Create new role
    elif request.method == 'POST':

        # Validate role name/prefix
        name = request.form['name']
        if len(name) < 3 or len(name) > 64:
            flash(
                'The name you chose is invalid. It must be between 3 and 64 characters long.',
                'alert-danger')
            return redirect(url_for('system_perms_roles'))

        # Validate the description
        desc = request.form['description']
        if len(desc) < 3 or len(desc) > 512:
            flash(
                'The description you chose was invalid. It must be between 3 and 512 characters long.',
                'alert-danger')
            return redirect(url_for('system_perms_roles'))

        # Check if the class already exists
        curd.execute('SELECT 1 FROM `system_roles` WHERE `name` = %s;',
                     (name, ))
        if curd.fetchone() is not None:
            flash('A role already exists with that name', 'alert-danger')
            return redirect(url_for('system_perms_roles'))

        # SQL insert
        curd.execute(
            "INSERT INTO `system_roles` (`name`, `description`) VALUES (%s, %s)",
            (name, desc))
        g.db.commit()
        cortex.lib.core.log(__name__, "permissions.system.role.create",
                            "Permission system role '" + name + "' created")

        flash("System Role created", "alert-success")
        return redirect(url_for('system_perms_roles'))
Ejemplo n.º 31
0
def systems_new():
	"""Handles the Allocate New System Name(s) page"""

	# Check user permissions
	if not does_user_have_permission("systems.allocate_name"):
		abort(403)

	# On GET requests, just show big buttons for all the classes
	if request.method == 'GET':
		classes = cortex.lib.classes.list(hide_disabled=True)
		return render_template('systems/new.html', classes=classes, active='systems', title="Allocate new system names")

	# On POST requests...
	elif request.method == 'POST':
		# The user has asked for one or more new system names.

		# Grab the prefix chosen and validate it's a valid class name.
		# The regular expression matches on an entire string of 1 to 16 lowercase characters
		class_name = request.form['class_name']
		if not re.match(r'^[a-z]{1,16}$', class_name):
			flash("The class prefix you sent was invalid. It can only contain lowercase letters and be at least 1 character long and at most 16", "alert-danger")
			return redirect(url_for('systems_new'))

		# Grab how many names the user wants and validate it
		system_number = int(request.form['system_number'])

		# Validate the number of systems
		if system_number < 1 or system_number > 50:
			flash("You cannot allocate more than 50 names at once, sorry about that.", "alert-danger")
			return redirect(url_for('admin_classes'))

		# Grab the comment
		if 'system_comment' in request.form:
			system_comment = request.form['system_comment']
		else:
			system_comment = ""

		# Allocate the names asked for
		try:
			# To prevent code duplication, this is done remotely by Neocortex. So, connect:
			neocortex   = cortex.lib.core.neocortex_connect()

			# Allocate the name
			new_systems = neocortex.allocate_name(class_name, system_comment, username=session['username'], num=system_number)
		except Exception as ex:
			flash("A fatal error occured when trying to allocate names: " + str(ex), "alert-danger")
			return redirect(url_for('systems_new'))

		# If the user only wanted one system, redirect back to the systems
		# list page and flash up success. If they requested more than one
		# system, then redirect to a bulk-comments-edit page where they can
		# change the comments on all of the systems.
		if len(new_systems) == 1: 
			flash("System name allocated successfully", "alert-success")
			return redirect(url_for('system', id=new_systems[new_systems.keys()[0]]))
		else:
			return render_template('systems/new-bulk.html', systems=new_systems, comment=system_comment, title="Systems")
Ejemplo n.º 32
0
def admin_tasks_system():
	"""Displays the list of tasks started by the system"""

	# Check user permissions
	if not does_user_have_permission("tasks.view"):
		abort(403)

	# Render the page
	return render_template('admin/tasks.html', active='admin', title="System Tasks", tasktype='system', json_source=url_for('admin_tasks_json', tasktype='system'), filters={})
Ejemplo n.º 33
0
def admin_events(src="all"):
	"""Displays the list of events, excluding any system events"""

	# Check user permissions
	if not does_user_have_permission("events.view"):
		abort(403)

	# Render the page
	return render_template('admin/events.html', active='admin', title="Events", event_source=src, json_source=url_for('admin_events_json', event_source=src))
Ejemplo n.º 34
0
def admin_tasks_user():
	"""Displays the list of tasks, excluding any system tasks"""

	# Check user permissions
	if not does_user_have_permission("tasks.view"):
		abort(403)

	# Render the page
	return render_template('admin/tasks.html', active='admin', title="User Tasks", tasktype='user', json_source=url_for('admin_tasks_json', tasktype='user'), filters={})
Ejemplo n.º 35
0
def perms_roles():
    """View function to let administrators view and manage the list of roles"""

    # Check user permissions
    if not does_user_have_permission("admin.permissions"):
        abort(403)

    # Cursor for the DB
    curd = g.db.cursor(mysql.cursors.DictCursor)

    ## View list
    if request.method == 'GET':
        # Get the list of roles from the database
        roles = cortex.lib.perms.get_roles()

        # Render the page
        return render_template('perms/roles.html',
                               active='perms',
                               title="Roles",
                               roles=roles)

    ## Create new role
    elif request.method == 'POST':

        # Validate class name/prefix
        name = request.form['name']
        if not re.match(r'^[a-zA-Z0-9\s\-\_\'\"\&\@\,\:]{3,64}$', name):
            flash(
                "The name you chose is invalid. It can only contain lowercase letters and be at least 3 characters long and at most 64",
                "alert-danger")
            return redirect(url_for('perms_roles'))

        # Validate the description
        desc = request.form['description']
        if not re.match(r'^.{3,512}$', desc):
            flash(
                "The description you sent was invalid. It must be between 3 and 512 characters long.",
                "alert-danger")
            return redirect(url_for('perms_roles'))

        # Check if the class already exists
        curd.execute('SELECT 1 FROM `roles` WHERE `name` = %s;', (name, ))
        if curd.fetchone() is not None:
            flash('A role already exists with that name', 'alert-danger')
            return redirect(url_for('perms_roles'))

        # SQL insert
        curd.execute(
            '''INSERT INTO `roles` (`name`, `description`) VALUES (%s, %s)''',
            (name, desc))
        g.db.commit()
        cortex.lib.core.log(__name__, "permissions.role.create",
                            "Permission role '" + name + "' created")

        flash("Role created", "alert-success")
        return redirect(url_for('perms_roles'))
Ejemplo n.º 36
0
def favourites(display='all'):

    # Check user permissions
    if not (does_user_have_permission("systems.all.view")
            or does_user_have_permission("systems.own.view")):
        abort(403)

    # Get the list of active classes (used to populate the tab bar)
    classes = {}
    if does_user_have_permission("systems.all.view"):
        classes = cortex.lib.classes.list()

    # Validate system type
    flag = False
    if classes and display != 'all':
        for c in classes:
            if display == c["name"]:
                flag = True
                break
    else:
        flag = True

    if not flag:
        flash('System type %s does not exist.' % (display),
              category='alert-info')
        display = 'all'

    # Get the search string, if any
    q = request.args.get('q', None)

    # Strip any leading and or trailing spaces
    if q is not None:
        q = q.strip()

    # Render
    return render_template('systems/list.html',
                           classes=classes,
                           active='favourites',
                           title="Favourites",
                           favourites=1,
                           q=q,
                           hide_inactive=False,
                           display=display)
Ejemplo n.º 37
0
def puppet_enc_default():
	"""Handles the Puppet ENC Default Classes page"""

	# Check user permissions
	if not does_user_have_permission("puppet.default_classes.view"):
		abort(403)

	# Get the default YAML out of the kv table
	curd = g.db.cursor(mysql.cursors.DictCursor)
	curd.execute("SELECT `value` FROM `kv_settings` WHERE `key` = 'puppet.enc.default'")
	result = curd.fetchone()
	if result == None:
		classes = "# Classes to include on all nodes using the default settings can be entered here\n"
	else:
		classes = result['value']

	# On any GET request, just display the information
	if request.method == 'GET':
		return render_template('puppet/default.html', classes=classes, active='puppet', title="Default Classes")

	# On any POST request, validate the input and then save
	elif request.method == 'POST':
		# Check user permissions
		if not does_user_have_permission("puppet.default_classes.edit"):
			abort(403)

		# Extract data from form
		classes = request.form.get('classes', '')

		# Validate classes YAML
		try:
			data = yaml.load(classes)
		except Exception, e:
			flash('Invalid YAML syntax: ' + str(e), 'alert-danger')
			return render_template('puppet/default.html', classes=classes, active='puppet', title="Default Classes")

		try:
			if not data is None:
				assert isinstance(data, dict)
		except Exception, e:
			flash('Invalid YAML syntax: result was not a list of classes, did you forget a trailing colon? ' + str(e), 'alert-danger')
			return render_template('puppet/default.html', classes=classes, active='puppet', title="Default Classes")
Ejemplo n.º 38
0
def vmware_os():
	"""Shows VM operating system statistics."""

	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	types = cortex.lib.vmware.get_os_stats()

	# Render
	return render_template('vmware/os.html', active='vmware', types=types, title="Statistics - Operating Systems")
Ejemplo n.º 39
0
def systems_download_csv():
	"""Downloads the list of allocated server names as a CSV file."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of systems
	curd = cortex.lib.systems.get_systems(return_cursor=True, hide_inactive=False)

	# Return the response
	return Response(cortex.lib.systems.csv_stream(curd), mimetype="text/csv", headers={'Content-Disposition': 'attachment; filename="systems.csv"'})
Ejemplo n.º 40
0
def systems_nocmdb():
	"""Shows the list of systems missing CMDB reocords to the user."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='systems', title="Systems missing CMDB record", nocmdb=True, hide_inactive=True)
Ejemplo n.º 41
0
def systems_withperms():
	"""Shows the list of systems which have permissions"""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='perms', title="Systems with permissions", perms_only=True)
Ejemplo n.º 42
0
def systems_expired():
	"""Shows the list of expired systems to the user."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='systems', title="Expired systems", expired=True, hide_inactive=True)
Ejemplo n.º 43
0
def certificates():
    """Displays the certificates list."""

    # Check user permissions
    if not does_user_have_permission("certificates.view"):
        abort(403)

    # Get arguments with default
    self_signed = request.args.get('self_signed', 'any')
    validity = request.args.get('validity', 'any')
    last_seen = request.args.get('last_seen', None)

    # Build query parts
    query_parts = []
    if self_signed == 'only':
        query_parts.append(
            '`certificate`.`subjectCN` = `certificate`.`issuerCN`')
    elif self_signed == 'not':
        query_parts.append(
            '`certificate`.`subjectCN` != `certificate`.`issuerCN`')
    if validity == 'expired':
        query_parts.append('`certificate`.`notAfter` < NOW()')
    elif validity == 'current':
        query_parts.append('`certificate`.`notAfter` >= NOW()')
    if last_seen is not None:
        if last_seen >= 0:
            query_parts.append(
                '`scan_result`.`when` >= DATE_SUB(NOW(), INTERVAL ' +
                str(int(last_seen)) + ' DAY)')
        else:
            query_parts.append(
                '`scan_result`.`when` < DATE_SUB(NOW(), INTERVAL ' +
                str(-int(last_seen)) + ' DAY)')

    # Build where clause from query parts
    where_clause = ''
    if len(query_parts) > 0:
        where_clause = ' WHERE ' + (' AND '.join(query_parts))

    # Build query
    query = 'SELECT `certificate`.`digest` AS `digest`, `certificate`.`subjectCN` AS `subjectCN`, `certificate`.`subjectDN` AS `subjectDN`, `certificate`.`notBefore` AS `notBefore`, `certificate`.`notAfter` AS `notAfter`, `certificate`.`issuerCN` AS `issuerCN`, `certificate`.`issuerDN` AS `issuerDN`, MAX(`scan_result`.`when`) AS `lastSeen`, COUNT(DISTINCT `scan_result`.`host`) AS `numHosts`, `certificate`.`keySize` AS `keySize` FROM `certificate` LEFT JOIN `scan_result` ON `certificate`.`digest` = `scan_result`.`cert_digest`' + where_clause + ' GROUP BY `certificate`.`digest`'

    # Get the list of certificates
    curd = g.db.cursor(mysql.cursors.DictCursor)
    curd.execute(query)
    certificates = curd.fetchall()

    return render_template('certificates/certificates.html',
                           active='certificates',
                           title='Certificates',
                           certificates=certificates,
                           self_signed=self_signed,
                           validity=validity)
Ejemplo n.º 44
0
def systems_withperms():
	"""Shows the list of systems which have permissions"""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='perms', title="Systems with permissions", perms_only=True)
Ejemplo n.º 45
0
def systems_nocmdb():
	"""Shows the list of systems missing CMDB reocords to the user."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='systems', title="Systems missing CMDB record", nocmdb=True, hide_inactive=True)
Ejemplo n.º 46
0
def systems_expired():
	"""Shows the list of expired systems to the user."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Render
	return render_template('systems/list.html', classes=classes, active='systems', title="Expired systems", expired=True, hide_inactive=True)
Ejemplo n.º 47
0
def vmware_download_csv():
	"""Downloads the VMware data as a CSV file."""

	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get the list of systems
	curd = g.db.cursor(mysql.cursors.DictCursor)
	curd.execute('SELECT * FROM `vmware_cache_vm` ORDER BY `name`')

	# Return the response
	return Response(vmware_csv_stream(curd), mimetype="text/csv", headers={'Content-Disposition': 'attachment; filename="vmware.csv"'})
Ejemplo n.º 48
0
def systems_cmdb_json():
	"""Used by DataTables to extract information from the ServiceNow CMDB CI
	cache. The parameters and return format are as dictated by DataTables"""

	# Check user permissions	
	# either they have systems.all.view (view all systems)
	# OR they have at least one instance of the per-system permission 'edit.cmdb' 
	# (cos if they have that they need to be able to list the CMDB entries)
	# or if they have systems.all.edit.cmdb 

	if not does_user_have_permission("systems.all.view") and not does_user_have_permission("systems.all.edit.cmdb"):
		if not does_user_have_any_system_permission("edit.cmdb"):
			abort(403)

	# Extract information from DataTables
	(draw, start, length, order_column, order_asc, search) = _systems_extract_datatables()

	# Validate and convert the ordering column number to the name of the
	# column as it is in the database
	if order_column == 0:
		order_column = 'u_number'
	elif order_column == 1:
		order_column = 'short_description'
	else:
		app.logger.warn('Invalid ordering column parameter in DataTables request')
		abort(400)

	# Get results of query
	total_count    = cortex.lib.cmdb.get_ci_count()
	filtered_count = cortex.lib.cmdb.get_ci_count(search)
	results        = cortex.lib.cmdb.get_cis(start, length, search, order_column, order_asc)

	system_data = []
	for row in results:
		system_data.append([row['u_number'], row['name'], row['sys_id']])

	# Return JSON data in the format DataTables wants
	return jsonify(draw=draw, recordsTotal=total_count, recordsFiltered=filtered_count, data=system_data)
Ejemplo n.º 49
0
def systems_bulk_view(start, finish):
	"""This is a GET handler to view the list of assigned names"""

	# Check user permissions
	if not does_user_have_permission("systems.allocate_name"):
		abort(403)

	start  = int(start)
	finish = int(finish)

	curd = g.db.cursor(mysql.cursors.DictCursor)
	curd.execute("SELECT `id`, `name`, `allocation_comment` AS `comment` FROM `systems` WHERE `id` >= %s AND `id` <= %s", (start, finish))
	systems = curd.fetchall()

	return render_template('systems/new-bulk-done.html', systems=systems, title="Systems")
Ejemplo n.º 50
0
def admin_tasks_system():
    """Displays the list of tasks started by the system"""

    # Check user permissions
    if not does_user_have_permission("tasks.view"):
        abort(403)

        # Render the page
    return render_template(
        "admin/tasks.html",
        active="admin",
        title="System Tasks",
        tasktype="system",
        json_source=url_for("admin_tasks_json", tasktype="system"),
    )
Ejemplo n.º 51
0
def admin_tasks_user():
    """Displays the list of tasks, excluding any system tasks"""

    # Check user permissions
    if not does_user_have_permission("tasks.view"):
        abort(403)

        # Render the page
    return render_template(
        "admin/tasks.html",
        active="admin",
        title="User Tasks",
        tasktype="user",
        json_source=url_for("admin_tasks_json", tasktype="user"),
    )
Ejemplo n.º 52
0
def task_status(id):
    """Handles the Task Status page for a individual task."""

    ## Get the task details
    task = cortex.lib.core.task_get(id)

    # Return a 404 if we've not found the task
    if not task:
        abort(404)

        # Check the user has the permission to view this task
    if not task["username"] == session["username"]:
        if not does_user_have_permission("tasks.view"):
            abort(403)

    return cortex.lib.core.task_render_status(task, "tasks/status.html")
Ejemplo n.º 53
0
def puppet_dashboard():
    """Handles the Puppet dashboard page."""

    # Check user permissions
    if not does_user_have_permission("puppet.dashboard.view"):
        abort(403)

    try:
        stats = cortex.lib.puppet.puppetdb_get_node_stats()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    return render_template("puppet/dashboard.html", stats=stats, active="puppet", title="Puppet Dashboard")
Ejemplo n.º 54
0
def task_status_log(id):
    """Much like task_status, but only returns the event log. This is used by 
	an AJAX routine on the page to refresh the log every 10 seconds."""

    ## Get the task details
    task = cortex.lib.core.task_get(id)

    # Return a 404 if we've not found the task
    if not task:
        abort(404)

        # Check the user has the permission to view this task
    if not task["username"] == session["username"]:
        if not does_user_have_permission("tasks.view"):
            abort(403)

    return cortex.lib.core.task_render_status(task, "tasks/status-log.html")
Ejemplo n.º 55
0
def vmware_data():
	"""Displays page containing a giant table of information of everything
	we know about all the VMs."""

	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get all the information about every VM
	curd.execute('SELECT * FROM `vmware_cache_vm` WHERE `template` = 0 ORDER BY `name`')
	results = curd.fetchall()

	# Render
	return render_template('vmware/data.html', active='vmware', data=results, title="VMware Data")
Ejemplo n.º 56
0
def perms_roles():
	"""View function to let administrators view and manage the list of roles"""

	# Check user permissions
	if not does_user_have_permission("admin.permissions"):
		abort(403)
	
	# Cursor for the DB
	curd = g.db.cursor(mysql.cursors.DictCursor)

	## View list
	if request.method == 'GET':
		# Get the list of roles from the database
		roles = cortex.lib.perms.get_roles()

		# Render the page
		return render_template('perms/roles.html', active='perms', title="Roles", roles=roles)

	## Create new role
	elif request.method == 'POST':

		# Validate class name/prefix
		name = request.form['name']
		if not re.match(r'^[a-zA-Z0-9\s\-\_\'\"\&\@\,\:]{3,64}$', name):
			flash("The name you chose is invalid. It can only contain lowercase letters and be at least 3 characters long and at most 64", "alert-danger")
			return redirect(url_for('perms_roles'))

		# Validate the description
		desc = request.form['description']
		if not re.match(r'^.{3,512}$', desc):
			flash("The description you sent was invalid. It must be between 3 and 512 characters long.", "alert-danger")
			return redirect(url_for('perms_roles'))

		# Check if the class already exists
		curd.execute('SELECT 1 FROM `roles` WHERE `name` = %s;', (name))
		if curd.fetchone() is not None:
			flash('A role already exists with that name', 'alert-danger')
			return redirect(url_for('perms_roles'))

		# SQL insert
		curd.execute('''INSERT INTO `roles` (`name`, `description`) VALUES (%s, %s)''', (name, desc))
		g.db.commit()

		flash("Role created", "alert-success")
		return redirect(url_for('perms_roles'))
Ejemplo n.º 57
0
def vmware_data_unlinked():
	"""Displays page containing a giant table of information of everything
	we know about VMs which are not linked to Cortex system records. It is 
	currently hard coded to exclude virtual machines on the ECS cluster."""

	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get all the information about every VM
	curd.execute('SELECT * FROM `vmware_cache_vm` WHERE `template` = 0 AND `cluster` != "ORANGE_ECS_TIDT" AND `uuid` NOT IN (SELECT `vmware_uuid` FROM `systems` WHERE `vmware_uuid` IS NOT NULL) ORDER BY `name`')
	results = curd.fetchall()

	# Render
	return render_template('vmware/unlinked.html', active='vmware', data=results, title="Unlinked VMs")
Ejemplo n.º 58
0
def systems():
	"""Shows the list of known systems to the user."""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the list of active classes (used to populate the tab bar)
	classes = cortex.lib.classes.list()

	# Get the search string, if any
	q = request.args.get('q', None)
	
	# Strip any leading and or trailing spaces
	if q is not None:
		q = q.strip()

	# Render
	return render_template('systems/list.html', classes=classes, active='systems', title="Systems", q=q, hide_inactive=True)
Ejemplo n.º 59
0
def systems_search():
	"""Allows the user to search for a system by entering its name in the 
	search box"""

	# Check user permissions
	if not does_user_have_permission("systems.all.view"):
		abort(403)

	# Get the query from the URL
	query = request.args.get('query')
	if query is None:
		app.logger.warn('Missing \'query\' parameter in systems search request')
		return abort(400)

	# Search for the system
	system = cortex.lib.systems.get_system_by_name(query)

	if system is not None:
		# If we found the system, redirect to the system page
		return redirect(url_for('system', id=system['id']))
	else:
		# If we didn't find the system, search for it instead
		return redirect(url_for('systems',q=query))
Ejemplo n.º 60
0
def vmware_hwtools():
	"""Shows VM related graphs"""

	# Check user permissions
	if not does_user_have_permission("vmware.view"):
		abort(403)

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get OS statistics
	curd.execute('SELECT `hwVersion`, COUNT(*) AS `count` FROM `vmware_cache_vm` GROUP BY `hwVersion` ORDER BY `hwVersion`')
	stats_hw = curd.fetchall()

	# Shows VM hardware power state statistics.

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get the power statistics
	curd.execute('SELECT `powerState`, COUNT(*) AS `count` FROM `vmware_cache_vm` GROUP BY `powerState` ORDER BY `powerState`')
	stats_power = curd.fetchall()

	#Shows VM tools statistics.

	# Get a cursor to the database
	curd = g.db.cursor(mysql.cursors.DictCursor)

	# Get tools statistics
	curd.execute('SELECT `toolsRunningStatus`, COUNT(*) AS `count` FROM `vmware_cache_vm` WHERE `powerState` = "poweredOn" GROUP BY `toolsRunningStatus` ORDER BY `toolsRunningStatus`')
	stats_status = curd.fetchall()
	curd.execute('SELECT `toolsVersionStatus`, COUNT(*) AS `count` FROM `vmware_cache_vm` WHERE `powerState` = "poweredOn" GROUP BY `toolsVersionStatus` ORDER BY `toolsVersionStatus`')
	stats_version = curd.fetchall()

	# Render
	return render_template('vmware/hwtools.html', active='vmware', stats_hw=stats_hw, stats_power=stats_power,stats_status=stats_status, stats_version=stats_version, title="Statistics")