2016-11-22 15:02:12 +00:00
|
|
|
# ~*~ coding: utf-8 ~*~
|
|
|
|
from __future__ import unicode_literals, absolute_import
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
import logging
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
from jinja2 import Template
|
|
|
|
from django.db import models
|
2016-12-19 06:07:21 +00:00
|
|
|
from django.utils.timezone import now
|
2016-11-27 03:30:23 +00:00
|
|
|
from assets.models import Asset, AssetGroup
|
2016-11-22 15:02:12 +00:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2016-12-19 15:46:03 +00:00
|
|
|
__all__ = ["HostAlia", "UserAlia", "CmdAlia", "RunasAlia", "Privilege", "Extra_conf", "Sudo"]
|
2016-12-11 04:05:11 +00:00
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class HostAlia(models.Model):
|
|
|
|
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Host_Alias'))
|
|
|
|
host_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
hostA = cls(name=forgery_py.name.full_name(),
|
|
|
|
host_items=forgery_py.lorem_ipsum.sentence(),
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
hostA.save()
|
|
|
|
logger.debug('Generate fake host alia: %s' % hostA.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class UserAlia(models.Model):
|
|
|
|
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('User_Alias'))
|
|
|
|
user_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
userA = cls(name=forgery_py.name.full_name(),
|
|
|
|
user_items=forgery_py.lorem_ipsum.sentence(),
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
userA.save()
|
|
|
|
logger.debug('Generate fake host alia: %s' % userA.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class CmdAlia(models.Model):
|
|
|
|
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Command_Alias'))
|
|
|
|
cmd_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
cmdA = cls(name=forgery_py.name.full_name(),
|
|
|
|
cmd_items=forgery_py.lorem_ipsum.sentence(),
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
cmdA.save()
|
|
|
|
logger.debug('Generate fake command alia: %s' % cmdA.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class RunasAlia(models.Model):
|
|
|
|
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Runas_Alias'))
|
|
|
|
runas_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
runas = cls(name=forgery_py.name.full_name(),
|
|
|
|
runas_items=forgery_py.lorem_ipsum.sentence(),
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
runas.save()
|
|
|
|
logger.debug('Generate fake RunAs alia: %s' % runas.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class Privilege(models.Model):
|
2016-11-27 03:30:23 +00:00
|
|
|
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
|
2016-11-22 15:02:12 +00:00
|
|
|
user = models.ForeignKey(UserAlia, blank=True, null=True, related_name='privileges')
|
|
|
|
host = models.ForeignKey(HostAlia, blank=True, null=True, related_name='privileges')
|
|
|
|
runas = models.ForeignKey(RunasAlia, blank=True, null=True, related_name='privileges')
|
|
|
|
command = models.ForeignKey(CmdAlia, blank=True, null=True, related_name='privileges')
|
|
|
|
nopassword = models.BooleanField(default=True, verbose_name=_('Is_NoPassword'))
|
2016-11-27 03:30:23 +00:00
|
|
|
comment = models.TextField(blank=True, null=True, verbose_name=_('Comment'))
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return "[%s %s %s %s %s]" % (self.user.name,
|
|
|
|
self.host.name,
|
|
|
|
self.runas.name,
|
|
|
|
self.command.name,
|
|
|
|
self.nopassword)
|
|
|
|
|
|
|
|
def to_tuple(self):
|
|
|
|
return self.user.name, self.host.name, self.runas.name, self.command.name, self.nopassword
|
|
|
|
|
2016-12-12 03:08:10 +00:00
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed, choice
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
pri = cls(name=forgery_py.name.full_name(),
|
|
|
|
comment=forgery_py.lorem_ipsum.sentence(),
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
pri.user = choice(UserAlia.objects.all())
|
|
|
|
pri.host = choice(HostAlia.objects.all())
|
|
|
|
pri.runas = choice(RunasAlia.objects.all())
|
|
|
|
pri.command = choice(CmdAlia.objects.all())
|
|
|
|
pri.save()
|
|
|
|
logger.debug('Generate fake privileges: %s' % pri.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
class Extra_conf(models.Model):
|
2016-11-27 03:30:23 +00:00
|
|
|
line = models.TextField(blank=True, null=True, verbose_name=_('Extra_Item'),
|
|
|
|
help_text=_('The extra sudo config line.'))
|
2016-11-22 15:02:12 +00:00
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.line
|
|
|
|
|
|
|
|
|
|
|
|
class Sudo(models.Model):
|
|
|
|
"""
|
|
|
|
Sudo配置文件对象, 用于配置sudo的配置文件
|
|
|
|
|
|
|
|
:param extra_lines: <list> [<line1>, <line2>,...]
|
|
|
|
:param privileges: <list> [(user, host, runas, command, nopassword),]
|
|
|
|
"""
|
|
|
|
|
2016-12-11 12:50:26 +00:00
|
|
|
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'),
|
|
|
|
help_text=_('Name for this sudo'))
|
2016-12-19 06:07:21 +00:00
|
|
|
created_time = models.DateTimeField(verbose_name=_('Created Time'), auto_created=True,
|
2016-12-12 03:08:10 +00:00
|
|
|
help_text=_('The create time of this sudo'))
|
|
|
|
modify_time = models.DateTimeField(auto_now=True, verbose_name=_('Modify Time'),
|
|
|
|
help_text=_('The recent modify time of this sudo'))
|
2016-11-27 03:30:23 +00:00
|
|
|
assets = models.ManyToManyField(Asset, blank=True, related_name='sudos')
|
|
|
|
asset_groups = models.ManyToManyField(AssetGroup, blank=True, related_name='sudos')
|
2016-11-22 15:02:12 +00:00
|
|
|
extra_lines = models.ManyToManyField(Extra_conf, related_name='sudos', blank=True)
|
|
|
|
privilege_items = models.ManyToManyField(Privilege, related_name='sudos', blank=True)
|
|
|
|
|
2016-11-27 03:30:23 +00:00
|
|
|
@property
|
|
|
|
def all_assets(self):
|
|
|
|
assets = list(self.assets.all())
|
|
|
|
for group in self.asset_groups.all():
|
|
|
|
for asset in group.assets.all():
|
|
|
|
if asset not in assets:
|
|
|
|
assets.append(asset)
|
|
|
|
return assets
|
|
|
|
|
2016-11-22 15:02:12 +00:00
|
|
|
@property
|
|
|
|
def users(self):
|
|
|
|
return {privilege.user.name: privilege.user.user_items.split(',') for privilege in self.privilege_items.all()}
|
|
|
|
|
|
|
|
@property
|
|
|
|
def commands(self):
|
|
|
|
return {privilege.command.name: privilege.command.cmd_items.split(',') for privilege in self.privilege_items.all()}
|
|
|
|
|
|
|
|
@property
|
|
|
|
def hosts(self):
|
|
|
|
return {privilege.host.name: privilege.host.host_items.split(',') for privilege in self.privilege_items.all()}
|
|
|
|
|
|
|
|
@property
|
|
|
|
def runas(self):
|
|
|
|
return {privilege.runas.name: privilege.runas.runas_items.split(',') for privilege in self.privilege_items.all()}
|
|
|
|
|
|
|
|
@property
|
|
|
|
def extras(self):
|
|
|
|
return [extra.line for extra in self.extra_lines.all()]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def privileges(self):
|
|
|
|
return [privilege.to_tuple() for privilege in self.privilege_items.all()]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def content(self):
|
|
|
|
template = Template(self.__sudoers_jinja2_tmp__)
|
|
|
|
context = {"User_Alias": self.users,
|
|
|
|
"Cmnd_Alias": self.commands,
|
|
|
|
"Host_Alias": self.hosts,
|
|
|
|
"Runas_Alias": self.runas,
|
|
|
|
"Extra_Lines": self.extras,
|
|
|
|
"Privileges": self.privileges}
|
|
|
|
return template.render(context)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def __sudoers_jinja2_tmp__(self):
|
|
|
|
return """# management by JumpServer
|
|
|
|
# This file MUST be edited with the 'visudo' command as root.
|
|
|
|
#
|
|
|
|
# Please consider adding local content in /etc/sudoers.d/ instead of
|
|
|
|
# directly modifying this file.
|
|
|
|
#
|
|
|
|
# See the man page for details on how to write a sudoers file.
|
|
|
|
#
|
|
|
|
Defaults env_reset
|
|
|
|
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
|
|
|
|
|
|
# JumpServer Generate Other Configure is here
|
|
|
|
{% if Extra_Lines -%}
|
|
|
|
{% for line in Extra_Lines -%}
|
|
|
|
{{ line }}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
# Host alias specification
|
|
|
|
{% if Host_Alias -%}
|
|
|
|
{% for flag, items in Host_Alias.iteritems() -%}
|
|
|
|
Host_Alias {{ flag }} = {{ items|join(', ') }}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
# User alias specification
|
|
|
|
{% if User_Alias -%}
|
|
|
|
{% for flag, items in User_Alias.iteritems() -%}
|
|
|
|
User_Alias {{ flag }} = {{ items|join(', ') }}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
|
|
|
|
# Cmnd alias specification
|
|
|
|
{% if Cmnd_Alias -%}
|
|
|
|
{% for flag, items in Cmnd_Alias.iteritems() -%}
|
|
|
|
Cmnd_Alias {{ flag }} = {{ items|join(', ') }}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
# Run as alias specification
|
|
|
|
{% if Runas_Alias -%}
|
|
|
|
{% for flag, items in Runas_Alias.iteritems() -%}
|
|
|
|
Runas_Alias {{ flag }} = {{ items|join(', ') }}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
# User privilege specification
|
|
|
|
root ALL=(ALL:ALL) ALL
|
|
|
|
|
|
|
|
# JumpServer Generate User privilege is here.
|
|
|
|
# Note privileges is a tuple list like [(user, host, runas, command, nopassword),]
|
|
|
|
{% if Privileges -%}
|
|
|
|
{% for User_Flag, Host_Flag, Runas_Flag, Command_Flag, NopassWord in Privileges -%}
|
|
|
|
{% if NopassWord -%}
|
|
|
|
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) NOPASSWD: {{ Command_Flag }}
|
|
|
|
{%- else -%}
|
|
|
|
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) {{ Command_Flag }}
|
|
|
|
{%- endif %}
|
|
|
|
{% endfor %}
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
# Members of the admin group may gain root privileges
|
|
|
|
%admin ALL=(ALL) ALL
|
|
|
|
|
|
|
|
# Allow members of group sudo to execute any command
|
|
|
|
%sudo ALL=(ALL:ALL) ALL
|
|
|
|
|
|
|
|
# See sudoers(5) for more information on "#include" directives:
|
|
|
|
|
|
|
|
#includedir /etc/sudoers.d
|
2016-12-12 03:08:10 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def generate_fake(cls, count=20):
|
|
|
|
from random import seed, choice
|
|
|
|
import forgery_py
|
|
|
|
|
|
|
|
seed()
|
|
|
|
for i in range(count):
|
|
|
|
sudo = cls(name=forgery_py.name.full_name(),
|
2016-12-19 06:07:21 +00:00
|
|
|
created_time=now()
|
2016-12-12 03:08:10 +00:00
|
|
|
)
|
|
|
|
try:
|
|
|
|
sudo.save()
|
|
|
|
sudo.privilege_items = [choice(Privilege.objects.all())]
|
|
|
|
sudo.save()
|
|
|
|
logger.debug('Generate fake cron: %s' % sudo.name)
|
|
|
|
except Exception as e:
|
|
|
|
print('Error: %s, continue...' % e.message)
|
|
|
|
continue
|