def comment(request): # user は STIPUser stip_user = request.user if request.method == 'POST': # 引数取得 package_id = request.POST['package_id'] # コメント投稿 post_comment(stip_user, package_id, request.POST['post'], stip_user) # 表示用 comments = rs.get_comment_from_rs(stip_user, package_id) feeds = [] for comment in comments: feeds.append( Feed.get_feeds_from_package_from_rs(stip_user, comment)) return render(request, 'feeds/partial_feed_comments.html', {'feeds': feeds}) else: # 引数取得 package_id = request.GET['package_id'] comments = rs.get_comment_from_rs(stip_user, package_id) feeds = [] for comment in comments: feeds.append( Feed.get_feeds_from_package_from_rs(stip_user, comment)) return render(request, 'feeds/partial_feed_comments.html', {'feeds': feeds})
def get_like_comment(request): package_id = request.GET['package_id'] # feed の like, comment 情報取得 # 投稿があることが確定しているので直接 cache からFeed 取得 feed = Feed.objects.get(package_id=package_id) Feed.add_like_comment_info(request.user, feed) rsp = {'likes': feed.likes, 'like': feed.like, 'comments': feed.comments} return JsonResponse(rsp)
def attach(request): file_id = request.POST['file_id'] attach_file_name = Feed.get_attach_file_name(file_id) attach_file_path = Feed.get_attach_file_path(file_id) # response作成 with open(attach_file_path, 'rb') as fp: response = HttpResponse(fp.read(), content_type='application/octet-stream') response['Content-Disposition'] = 'attachment; filename=%s' % ( attach_file_name) return response
def attach(request): file_id = request.POST['file_id'] attach_file_name = Feed.get_attach_file_name(file_id) attach_file_path = Feed.get_attach_file_path(file_id).encode('utf-8') # response作成 with open(attach_file_path, 'rb') as fp: response = HttpResponse(fp.read(), content_type='application/octet-stream') dl_file_name = urllib.parse.quote(attach_file_name) response[ 'Content-Disposition'] = "attachment; filename='{}'; filename*=UTF-8''{}".format( dl_file_name, dl_file_name) return response
def like(request): # Like元のパッケージID package_id = request.POST['package_id'] feed = Feed.get_feeds_from_package_id(request.user, package_id) # user は STIPUser stip_user = request.user # liker情報取得 likers = rs.get_likers_from_rs(stip_user, package_id) # すでにLikeされているか判定 # 自分自身の liker 文字列は instance_name + space + user_name myliker = '%s %s' % (SNSConfig.get_sns_identity_name(), stip_user.username) like = myliker in likers # Like/Unlike 用の STIX イメージ作成 feed_stix_like = FeedStixLike(feed, like, creator=stip_user) if like: # notify の unlike処理 stip_user.unotify_liked(package_id, feed.user) else: # notify の like処理 stip_user.notify_liked(package_id, feed.user) # 一時ファイルにstixの中身を書き出す tmp_file_path = write_like_comment_attach_stix( feed_stix_like.get_xml_content()) # RS に登録する rs.regist_ctim_rs(stip_user, feed_stix_like.file_name, tmp_file_path) os.remove(tmp_file_path) # 現在の Like 情報を取得する likers = rs.get_likers_from_rs(stip_user, package_id) return HttpResponse(len(likers))
def feeds(request): feeds = Feed.get_feeds(api_user=request.user, index=0, size=FEEDS_NUM_PAGES) # 最終更新時間 last_reload = str(datetime.datetime.now()) # anonymous以外の全ユーザを返却する users_list = STIPUser.objects.filter(is_active=True).exclude( username='******').order_by('username') if feeds: # feedsがあれば、 last_feedを一番最新のfeed id に指定する from_feed = feeds[0].package_id else: from_feed = None r = render( request, 'feeds/feeds.html', { 'feeds': feeds, 'jira': imported_jira, 'from_feed': from_feed, 'last_reload': last_reload, 'page': 1, 'users': users_list, 'sharing_groups': Group.objects.all(), }) r.set_cookie(key='username', value=str(request.user)) return r
def search(request): if 'q' in request.GET: querystring = request.GET.get('q').strip() if len(querystring) == 0: return redirect('/search/') try: search_type = request.GET.get('type') if search_type not in ['feed', 'users']: search_type = 'feed' except Exception: search_type = 'feed' count = {} results = {} results['feed'] = Feed.query(request.user, querystring) results['users'] = User.objects.filter( Q(username__icontains=querystring) | Q(screen_name__icontains=querystring)) count['feed'] = len(results['feed']) count['users'] = results['users'].count() return render( request, 'search/results.html', { 'hide_search': True, 'querystring': querystring, 'active': search_type, 'count': count, 'results': results[search_type], }) else: return render(request, 'search/search.html', {'hide_search': True})
def track_comments(request): # 引数取得 stip_user = request.user package_id = request.GET['package_id'] comments = rs.get_comment_from_rs(stip_user, package_id) feeds = [] for comment in comments: feeds.append(Feed.get_feeds_from_package_from_rs(stip_user, comment)) return render(request, 'feeds/partial_feed_comments.html', {'feeds': feeds})
def create_sighting_object(request): try: package_id = request.GET['package_id'] feed_id = request.GET['feed_id'] value_ = request.GET['value'] type_ = request.GET['type'] count = int(request.GET['count']) first_seen = request.GET['first_seen'] last_seen = request.GET['last_seen'] observable_id = request.GET['observable_id'] stip_user = request.user feed = Feed.get_feeds_from_package_id(stip_user, package_id) stix_file_path = Feed.get_cached_file_path(feed_id) stix2 = stip_sighting.convert_to_stix2_from_stix_file_path( stix_file_path) stix2 = stip_sighting.insert_sighting_object(stix2, type_, value_, observable_id, count, first_seen, last_seen, stip_user) stix2_str = stix2.serialize(True, ensure_ascii=False) _, stix2_file_path = tempfile.mkstemp() with open(stix2_file_path, 'w', encoding='utf-8') as fp: fp.write(stix2_str) # RS に登録する rs.regist_ctim_rs(feed.user, stix2.id, stix2_file_path) os.remove(stix2_file_path) file_name = '%s.json' % (stix2.id) output = io.StringIO() output.write(str(stix2_str)) response = HttpResponse(output.getvalue(), content_type='application/json') response['Content-Disposition'] = 'attachment; filename=%s' % ( file_name) return response except Exception as e: traceback.print_exc() return HttpResponseServerError(str(e))
def load(request): from_feed = request.GET.get('from_feed') page = int(request.GET.get('page')) feed_source = request.GET.get('feed_source') user_id = None if feed_source is not None: if feed_source != 'all': user_id = feed_source # from_feed 指定の STIXPacakge ID の produced 時間を取得する if from_feed != 'None': # from_feed が設定されている場合 package_from_feed = rs.get_package_info_from_package_id( request.user, from_feed) produced_str = package_from_feed['produced'] # RS から produced 時間より古い最新の Feed を取得する last_reload = Feed.get_datetime_from_string(produced_str) # Feed 取得する index = (page - 1) * FEEDS_NUM_PAGES feeds = Feed.get_feeds(api_user=request.user, last_reload=last_reload, user_id=user_id, index=index, size=FEEDS_NUM_PAGES) else: # from_feed が設定されていない場合 (投稿がない場合) feeds = [] html = '' csrf_token = (csrf(request)['csrf_token']) for feed in feeds: html = '{0}{1}'.format( html, render_to_string( 'feeds/partial_feed.html', { 'feed': feed, 'jira': imported_jira, 'user': request.user, 'csrf_token': csrf_token, })) return HttpResponse(html)
def check_via_poll(request): last_feed_datetime = get_datetime_from_string(request.GET.get('last_feed')) feed_source = request.GET.get('feed_source') feed_source = feed_source if feed_source is not None else 'all' username = request.GET.get('username') user = STIPUser.objects.get(username=username) feeds = Feed.get_feeds_after(last_feed_datetime=last_feed_datetime, api_user=user) if feed_source != 'all': feeds = feeds.filter(user__id=feed_source) count = len(feeds) return HttpResponse(count)
def download_stix_id(command_stix_id): wc = StipSnsBoot.get_slack_web_client() # cache の STIX を返却 stix_file_path = Feed.get_cached_file_path( command_stix_id.replace(':', '--')) file_name = '%s.xml' % (command_stix_id) post_slack_channel = SNSConfig.get_slack_bot_chnnel() wc.files_upload(initial_comment='', channels=post_slack_channel, file=open(stix_file_path, 'rb'), filename=file_name) return
def check(request): last_feed_datetime = get_datetime_from_string(request.GET.get('last_feed')) # feed_source は 全員のフィード取得の際は ALL,それ以外は STIPUserのid数値文字列 feed_source = request.GET.get('feed_source') user = None if feed_source != 'all': user = feed_source # 引数 rs 呼び出し用api_user,user(全員の場合はNone,それ以外はid STIP UserのID数値文字列) feeds = Feed.get_feeds_after(last_feed_datetime=last_feed_datetime, api_user=request.user, user_id=user) count = len(feeds) return HttpResponse(count)
def update(request): first_feed_datetime = get_datetime_from_string( request.GET.get('first_feed')) last_feed_datetime = get_datetime_from_string(request.GET.get('last_feed')) feed_source = request.GET.get('feed_source') feeds = Feed.get_feeds( range_big_datetime=first_feed_datetime, # 期間範囲指定の大きい方(新しい方)。この時間を含む range_small_datetime=last_feed_datetime, # 期間範囲指定の小さい方(古い方)。この時間を含む api_user=request.user) if feed_source != 'all': l = [] for feed in feeds: if feed.package_id == feed_source: l.append(feed) feeds = l dump = {} for feed in feeds: feed = Feed.add_like_comment_info(request.user, feed) dump[feed.pk] = {'likes': feed.likes, 'comments': feed.comments} data = json.dumps(dump) return HttpResponse(data, content_type='application/json')
def download_stix(request): feed_file_name_id = request.GET['feed_id'] # cache の STIX を返却 stix_file_path = Feed.get_cached_file_path(feed_file_name_id) # response作成 file_name = '%s.xml' % (feed_file_name_id) with open(stix_file_path, 'r', encoding='utf-8') as fp: output = io.StringIO() output.write(fp.read()) response = HttpResponse(output.getvalue(), content_type='application/xml') response['Content-Disposition'] = 'attachment; filename=%s' % ( file_name) return response
def profile(request, username): page_user = get_object_or_404(User, username=username) feeds = Feed.get_feeds(api_user=request.user, user_id=page_user.id, index=0, size=FEEDS_NUM_PAGES) from_feed = None if feeds: from_feed = feeds[0].package_id return render(request, 'core/profile.html', { 'page_user': page_user, 'feeds': feeds, 'from_feed': from_feed, 'page': 1 })
def post_comment(api_user, original_package_id, post, comment_user): # Feed 情報作成 origin_feed = Feed.get_feeds_from_package_id(api_user, original_package_id) # comment 作成 post = post.strip() if len(post) > 0: post = post[:10240] # Comment 用の STIX イメージ作成 feed_stix_comment = FeedStixComment(origin_feed, post, api_user) # 一時ファイルにstixの中身を書き出す tmp_file_path = write_like_comment_attach_stix( feed_stix_comment.get_xml_content()) # RS に登録する rs.regist_ctim_rs(api_user, feed_stix_comment.file_name, tmp_file_path) # 一時ファイルは削除 os.remove(tmp_file_path) # 通知 comment_user.notify_commented(original_package_id, origin_feed.user) notify_also_commented(original_package_id, origin_feed.user, comment_user)
def download_pdf(request): # 引数取得 feed_file_name_id = request.POST['feed_id'] package_id = request.POST['package_id'] # STIX 情報作成 feed_stix = get_feed_stix(feed_file_name_id) feed = Feed.get_feeds_from_package_id(request.user, package_id) # PDF 情報作成 feed_pdf = FeedPDF(feed, feed_stix.stix_package) # HttpResponse作成 file_name = '%s.pdf' % (feed_file_name_id) response = HttpResponse(content='application/pdf') # responseにPDF格納 feed_pdf.make_pdf_content(response, feed) response['Content-Disposition'] = 'attachment; filename=%s' % (file_name) response['Content-Type'] = 'application/pdf' return response
def _html_feeds(last_feed_datetime, user, csrf_token, feed_source='all'): user_id = None if feed_source != 'all': user_id = feed_source feeds = Feed.get_feeds_after(last_feed_datetime=last_feed_datetime, api_user=user, user_id=user_id) html = '' for feed in feeds: html = '{0}{1}'.format( html, render_to_string( 'feeds/partial_feed.html', { 'feed': feed, 'jira': imported_jira, 'user': user, 'csrf_token': csrf_token })) return html
def search(request): if 'q' in request.GET: query_string = request.GET.get('q').strip() if len(query_string) == 0: return redirect('/search/') try: search_type = request.GET.get('type') if search_type not in ['feed', 'users']: search_type = 'feed' except Exception: search_type = 'feed' feeds = Feed.query(request.user, query_string, size=FEEDS_NUM_PAGES) if feeds: from_feed = feeds[0].package_id else: from_feed = None else: query_string = None feeds = [] from_feed = None last_reload = str(datetime.datetime.now()) users_list = User.objects.filter(is_active=True).exclude( username='******').order_by('username') for i in range(len(feeds)): _, post = extract_tags(feeds[i].post) feeds[i].post = post r = render( request, 'search/search.html', { 'feeds': feeds, 'jira': imported_jira, 'from_feed': from_feed, 'last_reload': last_reload, 'page': 1, 'users': users_list, 'sharing_groups': Group.objects.all(), 'query_string': query_string, }) r.set_cookie(key='username', value=str(request.user)) return r
def get_feed_stix(feed_file_name_id): stix_file_path = Feed.get_cached_file_path(feed_file_name_id) return FeedStix(stix_file_path=stix_file_path)
def call_jira(request): try: # JIRA が import されていない場合は何もしない if imported_jira is None: rsp = {} return JsonResponse(rsp) # feed情報取得 feed_file_name_id = request.GET['feed_id'] package_id_arg = request.GET['package_id'] feed = Feed.get_feeds_from_package_id(request.user, package_id_arg) # JIRA instance proxies = System.get_request_proxies() j = JIRA(server=SNSConfig.get_jira_host(), proxies=proxies, basic_auth=(SNSConfig.get_jira_username(), SNSConfig.get_jira_password())) # issues作成 issue = j.create_issue(project=SNSConfig.get_jira_project(), summary=feed.title, description=feed.post, issuetype={'name': SNSConfig.get_jira_type()}) # 添付があればそれもつける for attach_file in feed.files.all(): file_path = Feed.get_attach_file_path(attach_file.package_id) j.add_attachment(issue=issue, attachment=file_path, filename=str(attach_file.file_name)) # STIX添付 stix_package = STIXPackage.from_xml(feed.stix_file_path) package_id = stix_package.id_ stix_file_name = '%s.xml' % (package_id) j.add_attachment(issue=issue, attachment=feed.stix_file_path, filename=stix_file_name) # CSV添付 # CSVの中身を取得する content = get_csv_content(feed_file_name_id) csv_attachment = io.StringIO() csv_attachment.write(content) csv_file_name = '%s.csv' % (package_id) j.add_attachment(issue=issue, attachment=csv_attachment, filename=csv_file_name) # PDF添付 feed_pdf = FeedPDF(feed, stix_package) pdf_attachment = io.BytesIO() feed_pdf.make_pdf_content(pdf_attachment, feed) pdf_file_name = '%s.pdf' % (package_id) j.add_attachment(issue=issue, attachment=pdf_attachment, filename=pdf_file_name) # isssue番号返却 url = SNSConfig.get_jira_host( ) + '/projects/' + SNSConfig.get_jira_project() + '/issues/' + str( issue) rsp = { 'issues': str(issue), 'url': url, } return JsonResponse(rsp) except Exception as e: traceback.print_exc() return HttpResponseServerError(str(e))
def post_common(request, user): # Feed作成 feed = Feed() # ManyToMany をクリアする feed.files.clear() feed.sharing_people.clear() # POSTデータ格納 if KEY_POST not in request.POST: raise Exception('No Post.') post = request.POST[KEY_POST] post = post.strip() if len(post) == 0: raise Exception('No Content.') # Title格納 if KEY_TITLE not in request.POST: raise Exception('No Title.') feed.title = request.POST[KEY_TITLE] # TLP格納 if KEY_TLP not in request.POST: raise Exception('No TLP.') feed.tlp = request.POST[KEY_TLP] # stix2 投稿か? is_stix2 = is_stix2_post(request) stix2_titles = [] stix2_contents = [] if KEY_STIX2_TITLES in request.POST: stix2_titles = json.loads(request.POST[KEY_STIX2_TITLES]) # 同一 language が複数に定義されている場合はエラー if is_duplicate_languages(stix2_titles): raise Exception('Duplicate Same Language Title') # stix2_titles から stix 1.x に格納する title を決める # default は 先頭 feed.title = stix2_titles[0]['title'] for stix2_title in stix2_titles: if stix2_title['language'] == request.user.language: feed.title = stix2_title['title'] break if KEY_STIX2_CONTENTS in request.POST: stix2_contents = json.loads(request.POST[KEY_STIX2_CONTENTS]) # 同一 language が複数に定義されている場合はエラー if is_duplicate_languages(stix2_contents): raise Exception('Duplicate Same Language Content') # stix2_contents から stix 1.x に格納する post を決める # default は 先頭 post = stix2_contents[0]['content'] for stix2_content in stix2_contents: if stix2_content['language'] == request.user.language: post = stix2_content['content'] break # anonymous投稿か? if KEY_ANONYMOUS in request.POST: # 投稿ユーザーはアノニマス feed.user = STIPUser.get_anonymous_user() else: feed.user = user # publication取得 if KEY_PUBLICATION in request.POST: publication = request.POST[KEY_PUBLICATION] else: publication = PUBLICATION_VALUE_ALL # referred_url 取得 if KEY_REFERRED_URL in request.POST: referred_url = request.POST[KEY_REFERRED_URL] if len(referred_url) == 0: referred_url = None else: referred_url = None feed.referred_url = referred_url group = None people = None # Sharing Rangeがgroup if publication == PUBLICATION_VALUE_GROUP: group = request.POST[KEY_GROUP] feed.sharing_range_type = const.SHARING_RANGE_TYPE_KEY_GROUP feed.sharing_group = Group.objects.get(en_name=group) # Sharing Rangeがpeople elif publication == PUBLICATION_VALUE_PEOPLE: feed.sharing_range_type = const.SHARING_RANGE_TYPE_KEY_PEOPLE people = request.POST[KEY_PEOPLE].split(',') feed.tmp_sharing_people = [] for user_id in people: # user_id は STIPUser の id stip_user = STIPUser.objects.get(id=user_id) # 一時的に sharing_people リストに格納 feed.tmp_sharing_people.append(stip_user) # Sharing Rangeがall elif publication == PUBLICATION_VALUE_ALL: feed.sharing_range_type = const.SHARING_RANGE_TYPE_KEY_ALL feed.save() # ファイル添付対応 for f in request.FILES.values(): attach_file = save_attach_file(f.name, f, feed.package_id) feed.files.add(attach_file) # indicators があるか if KEY_INDICATORS in request.POST: indicators = json.loads(request.POST[KEY_INDICATORS]) else: indicators = [] # ttps があるか if KEY_TTPS in request.POST: ttps = json.loads(request.POST[KEY_TTPS]) else: ttps = [] # threat_actors があるか if KEY_TAS in request.POST: tas = json.loads(request.POST[KEY_TAS]) else: tas = [] # POSTする save_post(request, feed, post, indicators, ttps, tas, is_stix2, stix2_titles, stix2_contents) return feed
def post(self, user, data): try: # msg分解 msg = email.message_from_string(data) # Subject取得 try: # content-type指定でdecode (subject_str, subject_type) = email.Header.decode_header(msg['Subject'])[0] subject = subject_str.decode(subject_type) except BaseException: # 存在しない場合はそのまま使用 subject = msg['Subject'] from ctirs.models import Feed # Feed作成 feed = Feed() # Title は Subject feed.title = subject # TLP は UserのデフォルトTLP feed.tlp = user.tlp # Use feed.user = user # 本文/Attachement取得 attachements = [] payloads = msg.get_payload() # 添付がある場合は list, ない場合はstr if isinstance(payloads, str): content_type = self.get_char_set_from_content_type( msg['Content-Type']) content_type = content_type.split(':')[0] if content_type is not None: body = payloads.decode(content_type) else: body = payloads elif isinstance(payloads, list): # bodyは payloads[0] body_payload = payloads[0] body = self.get_unicode_content(body_payload) # それ以降はattachement for index in range(1, len(payloads)): payload = payloads[index] attachements.append(payload) # Sharing Rangeはall feed.sharing_range_type = SHARING_RANGE_TYPE_KEY_ALL # 一旦Feedを保存しSTIXを作成する feed.save() # 添付ファイル処理 from feeds.views import save_post, save_attach_file for payload in attachements: file_name = self.get_file_name(payload) content = self.get_content(payload) # content を file stream にする import io o = io.BytesIO(content) attach_file = save_attach_file(file_name, o, feed.id) feed.files.add(attach_file) feed.save() # POSTする save_post(None, feed, body) except BaseException: import traceback traceback.print_exc() return