UNCLASSIFIED

Commit d365bef1 authored by Taylor Biggs's avatar Taylor Biggs
Browse files

Merge branch 'python-app-container' into 'master'

Python for CSV Generation and Whitelisting

See merge request !26
parents 98ed9d55 28e7ec6d
*.pyc
python/index.html-og
/.project
/.pydevproject
/.pydevproject
\ No newline at end of file
FROM fedora:latest
LABEL version="1.0"
LABEL description="idk maybe later"
USER 0
EXPOSE 8000
EXPOSE 80
ADD app.py helpers.py report_helpers.py s3_helpers.py requirements.txt start.sh /
ADD index.html style.css scripts.js loading.gif img-safe.svg /var/www/html/
ADD bootstrap /var/www/html/bootstrap
# RUN yum install -y python3-tkinter
RUN yum install -y httpd \
&& pip3 install -r requirements.txt \
&& chmod 777 /var/www/html/ \
&& chmod 777 /start.sh \
&& echo "ServerName localhost" >> /etc/httpd/conf/httpd.conf
CMD ["/bin/bash", "/start.sh"]
# DEMO TESTING BUILD
# Building
<code> docker build . </code>
# Running
1. Need to forward ports for httpd server (tcp 80) and flask app (tcp 8000)
2. Need to forward environment variable for GITLAB_KEY to access gitlab API
<code> docker run -dit -e GITLAB_KEY=??????? -p 1234:80 -p 8000:8000 image_name </code>
# To Do
1. Add Remediation capability for authenticated user
2. Consider whitelist edgecases
#!/usr/bin/python3
from flask import Flask, request, send_file, make_response
from flask_restful import Api
import helpers
import s3_helpers
import report_helpers
import git_helpers
from flask_cors import CORS
app = Flask(__name__)
api = Api(app)
CORS(app)
DCCSCR_WHITELIST_PROJECT_ID = 143
@app.route('/get', methods=['GET', 'POST'])
def get_all_the_things():
image_name = request.args.get('name')
image_ver = request.args.get('ver')
proj = git_helpers.init(DCCSCR_WHITELIST_PROJECT_ID)
return helpers.get_all_the_things_json(proj, image_name, image_ver)
@app.route('/get_all_whitelists')
def get_all_whitelists():
return str(git_helpers.get_all_filename_and_refs_json(git_helpers.init(DCCSCR_WHITELIST_PROJECT_ID)))
@app.route('/last_runs', methods=['GET', 'POST'])
def get_last_run():
map_url = request.args.get('url')
return s3_helpers.get_last_n_runs(map_url, 5)
@app.route('/compare', methods=['GET', 'POST'])
def compare():
url = request.args.get('url')
return report_helpers.do_all_the_things(url)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port='8000')
This diff is collapsed.
/*!
* Bootstrap Responsive v2.3.2
*
* Copyright 2013 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world by @mdo and @fat.
*/.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import report_helpers
import csv
import json
debug = 0
path_to_oscap_file = ""
path_to_oval_file = ""
path_to_twistlock_file = ""
path_to_anchore_sec_file = ""
path_to_anchore_gates_file = ""
def main():
generate_all_reports(
path_to_oscap_file,
path_to_oval_file,
path_to_twistlock_file,
path_to_anchore_sec_file,
path_to_anchore_gates_file,
path_for_output
)
csv_dir = path_for_output
def generate_all_reports(oscap, oval, twistlock, anchore_sec, anchore_gates):
oscap_fail_count = generate_oscap_report(oscap)
oval_fail_count = generate_oval_report(oval)
twist_fail_count = generate_twistlock_report(twistlock)
anc_sec_count = generate_anchore_sec_report(anchore_sec)
anc_gate_count = generate_anchore_gates_report(anchore_gates)
generate_summary_report(oscap_fail_count[0],
oscap_fail_count[1],
oval_fail_count,
twist_fail_count,
anc_sec_count,
anc_gate_count
)
if debug:
print("OSCAP FAILS: " + str(oscap_fail_count[0]))
print("OSCAP NOT CHECKED: " + str(oscap_fail_count[1]))
print("OVAL FAILS: " + str(oval_fail_count))
print("TWISTLOCK FAILS: " + str(twist_fail_count))
print("ANCHORE SEC FAILS: " + str(anc_sec_count))
print("ANCHORE GATE FAILS: " + str(anc_gate_count))
# SUMMARY REPORT
def generate_summary_report(of, onc, ovf, tlf, asf, agf):
sum_data = open(csv_dir + '/summary.csv', 'w')
csv_writer = csv.writer(sum_data)
csv_writer.writerow(['DRAFT'])
csv_writer.writerow(['UNCLASSIFIED//FOUO'])
header = ['Scan', 'Automated Findings', 'Manual Checks', 'Total']
osl = ['OpenSCAP - DISA Compliance', of, onc, of+onc]
ovf = ['OpenSCAP - OVAL Results', int(ovf or 0), 0, int(ovf or 0)]
ancl = ['Anchore CVE Results', int(asf or 0), 0, int(asf or 0)]
ancc = ['Anchore Compliance Results', int(agf or 0), 0, int(agf or 0)]
twl = ['Twistlock Vulnerability Results', int(tlf or 0), 0, int(tlf or 0)]
csv_writer.writerow("")
csv_writer.writerow(header)
csv_writer.writerow(osl)
csv_writer.writerow(ovf)
csv_writer.writerow(twl)
csv_writer.writerow(ancl)
csv_writer.writerow(ancc)
csv_writer.writerow(['Totals',
osl[1]+ovf[1]+ancl[1]+ancc[1]+twl[1],
osl[2]+ovf[2]+ancl[2]+ancc[2]+twl[2],
osl[3]+ovf[3]+ancl[3]+ancc[3]+twl[3]
])
csv_writer.writerow("")
csv_writer.writerow(['Notes'])
csv_writer.writerow(['Anchore Results are based on an older version of CVSS, and will be supporting the newer (CVSS 3.0) in a future release'])
csv_writer.writerow("")
csv_writer.writerow(['Scans performed', ]) # need date scanned
csv_writer.writerow(['On container layer sha256:', ]) # need container sha
# OSCAP CSV
def generate_oscap_report(oscap):
oscap_cves = report_helpers.get_oscap_full(oscap)
oscap_data = open(csv_dir + '/oscap.csv', 'w')
csv_writer = csv.writer(oscap_data)
count = 0
fail_count = 0
nc_count = 0
for line in oscap_cves:
if count == 0:
header = line.keys()
csv_writer.writerow(header)
count += 1
if line['result'] == 'fail':
fail_count+=1
elif line['result'] == 'notchecked':
nc_count+=1
csv_writer.writerow(line.values())
oscap_data.close()
return fail_count, nc_count
# OVAL CSV
def generate_oval_report(oval):
oval_cves = report_helpers.get_oval_full(oval)
oval_data = open(csv_dir + '/oval.csv', 'w')
csv_writer = csv.writer(oval_data)
count = 0
fail_count = 0
for line in oval_cves:
if count == 0:
header = line.keys()
csv_writer.writerow(header)
count += 1
if line['result'] == 'true':
fail_count+=1
csv_writer.writerow(line.values())
oval_data.close()
return fail_count
# TWISTLOCK CSV
def generate_twistlock_report(twistlock):
tl_cves = report_helpers.get_twistlock_full(twistlock)
tl_data = open(csv_dir + '/tl.csv', 'w')
csv_writer = csv.writer(tl_data)
count = 0
for line in tl_cves:
if count == 0:
header = line.keys()
csv_writer.writerow(header)
count += 1
csv_writer.writerow(line.values())
tl_data.close()
return len(tl_cves)
# ANCHORE SECURITY CSV
def generate_anchore_sec_report(anchore_sec):
anchore_cves = report_helpers.get_anchore_full(anchore_sec)
anchore_data = open(csv_dir + '/anchore_security.csv', 'w')
csv_writer = csv.writer(anchore_data)
count = 0
for line in anchore_cves:
if count == 0:
header = line.keys()
csv_writer.writerow(header)
count += 1
csv_writer.writerow(line.values())
anchore_data.close()
# ANCHORE GATES CSV
def generate_anchore_gates_report(anchore_gates):
anchore_g = report_helpers.get_anchore_gates_full(anchore_gates)
anchore_data = open(csv_dir + '/anchore_gates.csv', 'w')
csv_writer = csv.writer(anchore_data)
count = 0
stop_count = 0
for line in anchore_g:
if count == 0:
header = line.__dict__.keys()
csv_writer.writerow(header)
count+=1
if line.gate_action == "stop":
stop_count+=1
csv_writer.writerow(line.__dict__.values())
anchore_data.close()
return stop_count
if __name__ == "__main__":
main() # with if
import gitlab
import json
import helpers
import os
gitlab_url = "https://dccscr.dsop.io"
gitlab_key = os.environ['GITLAB_KEY']
def main():
print("git_helpers.py")
# working
def get_whitelist_file_contents(proj, item_path, item_ref):
f = proj.files.get(file_path=item_path, ref=item_ref)
try:
contents = json.loads(f.decode())
except ValueError as error:
print("JSON object issue: %s") % error
return contents
def get_complete_whitelist_for_image(proj, im_name, im_tag):
all_wls = get_whitelist_filenames(proj)
total_wl = []
for item in all_wls:
contents = get_whitelist_file_contents(proj, item['filename'], item['ref'])
par_image = contents['image_parent_name']
par_tag = contents['image_parent_tag']
if contents['image_name'] == im_name and contents['image_tag'] == im_tag:
for x in get_whitelist_for_image(proj, im_name, im_tag):
x.set_whitelist_source(im_name)
total_wl.append(x)
if len(par_image) > 0 and len(par_tag) > 0:
for y in get_complete_whitelist_for_image(proj, par_image, par_tag):
y.set_whitelist_source(par_image)
total_wl.append(y)
return total_wl
# working
def get_whitelist_for_image(proj, im_name, im_tag):
all_wls = get_whitelist_filenames(proj)
wl = []
for item in all_wls:
contents = get_whitelist_file_contents(proj, item['filename'], item['ref'])
if contents['image_name'] == im_name and contents['image_tag'] == im_tag:
for v in contents['whitelisted_vulnerabilities']:
tar = helpers.Vuln(v)
wl.append(tar)
return wl
def get_whitelist_path_ref(proj, im_name, im_tag):
all_wls = get_whitelist_filenames(proj)
for item in all_wls:
wl = get_whitelist_file_contents(proj, item['filename'], item['ref'])
if wl['image_name'] == im_name and wl['image_tag'] == im_tag:
return item['filename'], item['ref']
return False
# working
def does_image_exist(proj, im_name, im_tag):
all_wls = get_whitelist_filenames(proj)
for item in all_wls:
wl = get_whitelist_file_contents(proj, item['filename'], item['ref'])
if wl['image_name'] == im_name and wl['image_tag'] == im_tag:
return True
return False
def get_whitelist_filenames(project):
wl_fns = project.search('blobs', 'authorized_approvers')
return_list = []
for wl_fn in wl_fns:
if "greylist" in wl_fn['filename']:
return_list.append(wl_fn)
return return_list
def get_all_filename_and_refs_json(project):
wl_fns = project.search('blobs', 'authorized_approvers')
filename_list = list()
for file in wl_fns:
filename_list.append((file['filename'], file['ref']))
return json.dumps(filename_list)
def init(pid):
gl = gitlab.Gitlab(gitlab_url, private_token=gitlab_key)
gl.auth()
return gl.projects.get(pid)
def set_default(obj):
if isinstance(obj, set):
return list(obj)
raise TypeError
if __name__ == "__main__":
main() # with if
\ No newline at end of file
import gitlab
import json
import git_helpers
import os
from pprint import pprint
gitlab_url = "https://dccscr.dsop.io"
gitlab_key = os.environ['GITLAB_KEY']
dccscr_project_id = 143
SAMPLE_IMAGE_NAME = "openjdk"
SAMPLE_IMAGE_VERSION = "1.8"
def main():
proj = git_helpers.init(dccscr_project_id)
# gl = git_helpers.get_all_filename_and_refs_json(proj)
# print(get_all_the_things_json(proj, SAMPLE_IMAGE_NAME, SAMPLE_IMAGE_VERSION))
print(git_helpers.get_all_filename_and_refs_json(proj))
class Vuln:
vuln_id = ""
vuln_desc = ""
vuln_source = ""
whitelist_source = ""
status = ""
approved_date = ""
approved_by = ""
justification = ""
def __repr__(self):
return "Vuln: " + self.vulnerability + " - " + self.vuln_source + " - " + self.whitelist_source + " - "+ self.status + " - " + self.approved_by
def __str__(self):
return "Vuln: " + self.vulnerability + " - " + self.vuln_source + " - " + self.whitelist_source + " - "+ self.status + " - " + self.approved_by
def __init__(self, v):
self.vulnerability = v['vulnerability']
self.vuln_description = v['vuln_description']
self.vuln_source = v['vuln_source']
self.status = v['status']
self.approved_date = v['approved_date']
self.approved_by = v['approved_by']
self.justification = v['justification']
# def __init__(self, vid, desc, source, stat, date, by, just):
# self.vulnerability = vid
# self.vuln_description = desc
# self.vuln_source = source
# self.status = stat
# self.approved_date = date
# self.approved_by = by
# self.justification = just
def set_whitelist_source(self, val):
self.whitelist_source = val
class AnchoreGate:
image_id = ""
repo_tag = ""
trigger_id = ""
gate = ""
trigger = ""
check_output = ""
gate_action = ""
# whitelisted = ""
policy_id = ""
matched_rule_id = ""
whitelist_id = ""
whitelist_name = ""
def __init__(self, g):
self.image_id = g[0]
self.repo_tag = g[1]
self.trigger_id = g[2]
self.gate = g[3]
self.trigger = g[4]
self.check_output = g[5]
self.gate_action = g[6]
# self.whitelisted = g[7]
self.policy_id = g[8]
if g[7]:
self.matched_rule_id = g[7]['matched_rule_id']
self.whitelist_id = g[7]['whitelist_id']
self.whitelist_name = g[7]['whitelist_name']
# working
def get_all_the_things_json(proj, im_name, im_ver):
first_call = git_helpers.get_whitelist_path_ref(proj, im_name, im_ver)
if first_call:
fn = first_call[0]
ver = first_call[1]
contents = git_helpers.get_whitelist_file_contents(proj, fn, ver)
contents['complete_whitelist'] = []
# contents['complete_whitelist'] = git_helpers.get_complete_whitelist_for_image(proj, im_name, im_ver)
complete_wl = git_helpers.get_complete_whitelist_for_image(proj, im_name, im_ver)
for x in complete_wl:
contents['complete_whitelist'].append(x.__dict__)
# contents['complete_whitelist'] = json.dumps(.__dict__)
# app_json = json.dumps(contents, default=git_helpers.set_default)
return json.dumps(contents)
else:
return im_name, im_ver, "not found."
if __name__ == "__main__":
main() # with if
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:lucid="lucid" width="520" height="660"><g transform="translate(-220 -60)" lucid:page-tab-id="0_0"><path d="M240 80h480v620H240z" fill="url(#a)"/><defs><image width="1" height="1" id="b" xlink:href="data:image/png;base64,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" preserveAspectRatio="none"/><pattern id="a" patternUnits="userSpaceOnUse" x="240" y="80" width="480" height="620"><use xlink:href="#b" transform="translate(-4.712812960235624, 19.808541973490378) scale(480,574.7275405007364)"/></pattern></defs></g></svg>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment