class Indicator(models.Model):
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    indicator_id = models.CharField(max_length=255)
    namespace = models.ManyToManyField('Namespace', blank=True)
    indicator_types = models.ManyToManyField(Indicator_Type, blank=True)
    confidence = models.ManyToManyField(Confidence, blank=True)
    related_indicators = models.ManyToManyField('self', blank=True)
    indicator_composition_operator = models.CharField(max_length=3, default="OR")
    ttps = models.ManyToManyField('TTP', blank=True)
    produced_time = models.DateTimeField(null=True, blank=True)
    kill_chain_phases = models.ManyToManyField(Indicator_Kill_Chain_Phase, blank=True)

    def __unicode__(self):
        return u"%s" % (self.name) class Indicator_Type(models.Model):
    itype = models.CharField(max_length=255, unique=True)

    def __unicode__(self):
        return u"%s" % (self.itype) class Observable(models.Model):
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    namespace = models.ManyToManyField('Namespace', blank=True)
    indicators = models.ManyToManyField(Indicator, blank=True)
    compositions = models.ManyToManyField(ObservableComposition, blank=True)
    observable_type = models.CharField(max_length=255, null=True, blank=True)
    observable_id = models.CharField(max_length=255, unique=True)

    def __unicode__(self):
        return u"%s" % (self.name) class ThreatActor(models.Model):
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    namespace = models.ManyToManyField('Namespace', blank=True)
    campaigns = models.ManyToManyField(Campaign, blank=True)
    associated_threat_actors = models.ManyToManyField('self', blank=True)
    threat_actor_id = models.CharField(max_length=255)
    observed_ttps = models.ManyToManyField(TTP, through='ObservedTTP', symmetrical=False, related_name='ttp_observed_at_ta', blank=True)

    def add_observed_ttp(self, ttp, relationship):
        obs_ttp, obs_ttp_created = ObservedTTP.objects.get_or_create(
            ta=self,
            ttp=ttp,
            relationship=relationship
        )
        return obs_ttp

    def __unicode__(self):
        return u"%s" % (self.name) class Campaign(models.Model):
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    namespace = models.ManyToManyField('Namespace', blank=True)
    status = models.CharField(max_length=255, default='Ongoing')
    campaign_id = models.CharField(max_length=255)
    confidence = models.ManyToManyField(Confidence, blank=True)
    related_indicators = models.ManyToManyField('Indicator', blank=True)
    related_ttps = models.ManyToManyField(TTP, through='RelationCampaignTTP', symmetrical=False, related_name='ttp_related_to_campaign', blank=True)
    associated_campaigns = models.ManyToManyField('self', blank=True)

    def add_related_ttp(self, ttp, relationship):
        rel_ttp, rel_ttp_created = RelationCampaignTTP.objects.get_or_create(
            campaign=self,
            ttp=ttp,
            relationship=relationship
        )
        return rel_ttp

    def __unicode__(self):
        return u"%s" % (self.name) class Confidence(models.Model):
    value = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)

    def __unicode__(self):
        return u"%s" % (self.value) class Package(models.Model):
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    namespace = models.ManyToManyField('Namespace', blank=True)
    version = models.CharField(max_length=255)
    package_id = models.CharField(max_length=255)
    source = models.CharField(max_length=255)
    produced_time = models.DateTimeField(null=True, blank=True)
    threat_actors = models.ManyToManyField('ThreatActor', blank=True)
    campaigns = models.ManyToManyField('Campaign', blank=True)
    indicators = models.ManyToManyField('Indicator', blank=True)
    observables = models.ManyToManyField('Observable', blank=True)
    ttps = models.ManyToManyField('TTP', blank=True)

    def __unicode__(self):
        return u"%s" % (self.name) class ObservableComposition(models.Model):
    name = models.CharField(max_length=255)
    operator = models.CharField(max_length=3, default='OR')
    indicator = models.ManyToManyField(Indicator, blank=True)
    observables = models.ManyToManyField('Observable', blank=True)
    observable_compositions = models.ManyToManyField('self', blank=True)

    def __unicode__(self):
        return u"%s" % (self.name) class File_Object(models.Model):
    file_meta = models.ManyToManyField(File_Meta_Object, blank=True)
    file_custom = models.ManyToManyField(File_Custom_Properties, blank=True)
    md5_hash = models.CharField(max_length=32, null=True, blank=True)
    sha256_hash = models.CharField(max_length=64, null=True, blank=True)
    observables = models.ManyToManyField(Observable)

    def __unicode__(self):
        if self.md5_hash:
            return u"%s" % (self.md5_hash)
        elif self.sha256_hash:
            return u"%s" % (self.sha256_hash)
        else:
            return u"File Object"

    class Meta:
        index_together = (("md5_hash", "sha256_hash"),) class TTP(models.Model):
    """ Tools, Tactics, and Procedures
    """
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    namespace = models.ManyToManyField('Namespace', blank=True)
    ttp_id = models.CharField(max_length=255)
    related_ttps = models.ManyToManyField('self', through='RelatedTTP', symmetrical=False, related_name='ttp_related_to_ttp', blank=True)

    def add_related_ttp(self, ttp, relationship):
        rel_ttp, rel_ttp_created = RelatedTTP.objects.get_or_create(from_ttp=self, to_ttp=ttp, relationship=relationship)
        return rel_ttp

    def __unicode__(self):
        return u"%s" % (self.name) class Address_Object(models.Model):
    address_value = models.CharField(max_length=255)
    category = models.CharField(max_length=255, default="ipv4-addr")
    condition = models.CharField(max_length=255, default="equals")
    observables = models.ManyToManyField(Observable)

    def __unicode__(self):
        if self.address_value:
            return u"%s" % (self.address_value)
        else:
            return u"Address Object"

    class Meta:
        unique_together = (("address_value", "category", "condition"),) class URI_Object(models.Model):
    uri_value = models.CharField(max_length=255)
    uri_type = models.CharField(max_length=255)
    condition = models.CharField(max_length=255, default="equals")
    observables = models.ManyToManyField(Observable)

    def __unicode__(self):
        if self.uri_value:
            return u"%s" % (self.uri_value)
        else:
            return u"URI Object"

    class Meta:
        unique_together = (("uri_value", "uri_type", "condition"),) class MalwareInstance(models.Model):
    ttp_ref = models.ForeignKey(TTP, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)

    def __unicode__(self):
        return u"%s" % (self.name) class AttackPattern(models.Model):
    ttp_ref = models.ForeignKey(TTP, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField(null=True, blank=True)
    short_description = models.CharField(max_length=255, null=True, blank=True)
    capec_id = models.CharField(max_length=255) def get_icon_for_namespace(namespace):
    """ Return the static path to the icon associated with given namespace
    """
    try:
        if namespace.count(':')>0:
            namespace = namespace.split(':')[0]
        icon = NamespaceIcon.objects.get(namespace=namespace)
    except Exception as e:
        return static('ns_icon/octalpus.png')
    return static('ns_icon/%s' % (icon.icon)) class PackageComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    package_reference = models.ForeignKey(Package, on_delete=models.CASCADE) class NamespaceIcon(models.Model):
    namespace = models.CharField(max_length=255, unique=True)
    icon = models.CharField(max_length=255)

    def __unicode__(self):
        return u"%s (%s)" % (self.namespace, self.icon) class ThreatActorComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    actor_reference = models.ForeignKey(ThreatActor, on_delete=models.CASCADE) class CampaignComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    campaign_reference = models.ForeignKey(Campaign, on_delete=models.CASCADE) class TTPComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    ttp_reference = models.ForeignKey(TTP, on_delete=models.CASCADE) class IndicatorComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    indicator_reference = models.ForeignKey(Indicator, on_delete=models.CASCADE) class ObservableComment(models.Model):
    ctext = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    creation_time = models.DateTimeField(auto_now_add=True)
    observable_reference = models.ForeignKey(Observable, on_delete=models.CASCADE) class Contact(models.Model):
    """Describe a contact person
    """
    firstname = models.CharField(max_length=255)
    lastname = models.CharField(max_length=255)
    phone = models.CharField(max_length=255, blank=True)
    email = models.EmailField(max_length=255)
    description = models.TextField(null=True, blank=True)

    class Meta:
        unique_together = (("firstname", "lastname", "email"),) class Handler(models.Model):
    """Describe an incident handler person
    """
    firstname = models.CharField(max_length=255)
    lastname = models.CharField(max_length=255)
    phone = models.CharField(max_length=255, blank=True)
    email = models.EmailField(max_length=255)
    description = models.TextField(null=True, blank=True)

    class Meta:
        unique_together = (("firstname", "lastname", "email"),) class Incident(models.Model):
    """Describe a security incident
    """
    incident_number = models.IntegerField(unique=True, default=random_incident_number)
    title = models.CharField(max_length=255, default="Unnamed Incident")
    description = models.TextField(null=True, blank=True)
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    status = models.ForeignKey(Incident_Status, on_delete=models.CASCADE)
    category = models.ForeignKey(Incident_Category, on_delete=models.CASCADE)
    affected_assets = models.ManyToManyField(Asset, blank=True)
    tasks = models.ManyToManyField(Task, blank=True)
    incident_handler = models.ManyToManyField(Handler, blank=True, related_name="incident_handler")
    contacts = models.ManyToManyField(Contact, blank=True, related_name="contacts")
    severity_choices = (
                ('h', 'High'),
                ('m', 'Medium'),
                ('l', 'Low'),
            )
    severity = models.CharField(max_length=2, choices=severity_choices, default='m')

    def __unicode__(self):
        return u"%s" % (self.title) class TemplateTask(models.Model):
    """Describe a template for a task to attach to an incident
    """
    name = models.CharField(max_length=255, default="Template Task")
    description = models.TextField(null=True, blank=True, default="Task Description") class TAXII_Remote_Server(models.Model):
    creation_time = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=255, help_text="""Name/Identifier""")
    host = models.CharField(max_length=255, help_text="""Hostname or IP address""")
    port = models.IntegerField(help_text="""Remote port""", default=80)
    protocol = models.CharField(max_length=5, help_text="""Protocol to use""", default="http")
    path = models.CharField(max_length=255, help_text="""Path to service""")
    version = models.CharField(max_length=5, help_text="""TAXII version to use""", default="1.1")
    auth_type = models.IntegerField(default=0, help_text="""Authentication to use""")
    last_discovery = models.DateTimeField(blank=True, null=True)
    # TODO: fields for authentication (foreign key)
    # TODO: proxy configuration

    def get_url(self):
        return "%s://%s:%i%s" % (self.protocol, self.host, self.port, self.path)

    def __unicode__(self):
        return u"%s (%s://%s:%i%s)" % (self.name, self.protocol, self.host, self.port, self.path)

    class Meta:
        unique_together = (("name", "host", "port", "protocol", "path"),) class TAXII_Remote_Collection(models.Model):
    creation_time = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    name = models.CharField(max_length=255, help_text="""name of the collection""", unique=True)
    begin_timestamp = models.DateTimeField(blank=True, null=True)
    end_timestamp = models.DateTimeField(blank=True, null=True)
    server = models.ForeignKey("TAXII_Remote_Server", on_delete=models.CASCADE)
    subscribed = models.BooleanField(default=False)
    collection_type = models.CharField(max_length=255, default="DATA-FEED")
    poll_period = models.IntegerField(default=24, help_text="""poll period in hours (e.g. 24 = every 24 hours)""")

    def __unicode__(self):
        return u"%s" % (self.name)
from rest_framework import serializers
from kraut_parser.models import Indicator, Indicator_Type, Observable, ThreatActor, Campaign, Confidence, Package, ObservableComposition, File_Object, TTP, Address_Object, URI_Object
from kraut_parser.models import MalwareInstance, AttackPattern
from kraut_intel.utils import get_icon_for_namespace
from kraut_intel.models import PackageComment, NamespaceIcon, ThreatActorComment, CampaignComment, TTPComment, IndicatorComment, ObservableComment
from kraut_incident.models import Contact, Handler, Incident, TemplateTask
from kraut_sharing.models import TAXII_Remote_Server, TAXII_Remote_Collection
import datetime

    def get_last_modified(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

################### MALWARE INSTANCE #####################

class MalwareInstanceSerializer(serializers.ModelSerializer):
    short_name = serializers.SerializerMethodField()
    creation_time = serializers.SerializerMethodField()
    last_modified = serializers.SerializerMethodField()
    subname = serializers.SerializerMethodField()
    mwitype = serializers.SerializerMethodField()

    class Meta:
        model = MalwareInstance
        fields = ('id', 'name', 'short_name', 'description', 'short_description', 'creation_time', 'last_modified', 'subname', 'mwitype')

    def get_short_name(self, obj):
        if len(obj.name)>55:
            return "%s ..." % (obj.name[:55])
        return obj.name

    def get_creation_time(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

    def get_last_modified(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

    def get_subname(self, obj):
        try:
            return obj.malwareinstancenames_set.first().name
        except:
            return "Unknown"

    def get_mwitype(self, obj):
        try:
            return obj.malwareinstancetypes_set.first()._type
        except:
            return "Unknown"

################### ATTACK PATTERN #####################

class AttackPatternSerializer(serializers.ModelSerializer):
    short_name = serializers.SerializerMethodField()
    creation_time = serializers.SerializerMethodField()
    last_modified = serializers.SerializerMethodField()

    class Meta:
        model = AttackPattern
        fields = ('id', 'name', 'short_name', 'description', 'short_description', 'creation_time', 'last_modified', 'capec_id')

    def get_short_name(self, obj):
        if len(obj.name)>55:
            return "%s ..." % (obj.name[:55])
        return obj.name

    def get_creation_time(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

    def get_last_modified(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

################### CAMPAIGN #####################

# Campaign Details
class CampaignSerializer(serializers.ModelSerializer):
    confidence = serializers.StringRelatedField(many=True)

    class Meta:
        model = Campaign
        fields = ('id', 'name', 'description', 'short_description', 'namespace', 'creation_time', 'last_modified', 'status', 'confidence', 'related_indicators', 'associated_campaigns')

# Campaign List
class CampSerializer(serializers.ModelSerializer):
    creation_time = serializers.SerializerMethodField()
    last_modified = serializers.SerializerMethodField()
    namespace = serializers.SerializerMethodField()
    namespace_icon = serializers.SerializerMethodField()
    confidence = serializers.SerializerMethodField()

    class Meta:
        model = Campaign
        fields = ('id', 'name', 'description', 'creation_time', 'last_modified', 'namespace', 'namespace_icon', 'confidence', 'status')

    def get_namespace_icon(self, obj):
        return get_icon_for_namespace(obj.namespace.last().namespace)

    def get_namespace(self, obj):
        return obj.namespace.last().namespace

    def get_creation_time(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

    def get_last_modified(self, obj):
        return obj.creation_time.strftime("%Y-%m-%d %H:%M:%S")

    def get_confidence(self, obj):
        try:
            return obj.confidence.first().value
        except:
            return "Unknown"

################### INDICATOR #####################

# Indicator Details
class IndicatorSerializer(serializers.ModelSerializer):
    indicator_types = serializers.StringRelatedField(many=True)

    class Meta:
        model = Indicator
        fields = ('id', 'name', 'description', 'short_description', 'namespace', 'indicator_types', 'confidence', 'related_indicators', 'creation_time', 'last_modified', 'indicator_composition_operator')

# Indicator List
class IndSerializer(serializers.ModelSerializer):
    creation_time = serializers.SerializerMethodField()
    last_modified = serializers.SerializerMethodField()
    namespace = serializers.SerializerMethodField()
    namespace_icon = serializers.SerializerMethodField()

    class Meta:

        model = Indicator