3 # Copyright (c) 2016 Red Hat
4 # Luke Hinds (lhinds@redhat.com)
5 # This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # 0.1: This script installs OpenSCAP on the remote host, and scans the
12 # nominated node. Post scan a report is downloaded and if '--clean' is passed
13 # all trace of the scan is removed from the remote system.
20 from ConfigParser import SafeConfigParser
21 from keystoneclient.auth.identity import v2
22 from keystoneclient import session
23 from novaclient import client
26 __author__ = 'Luke Hinds (lhinds@redhat.com)'
27 __url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
30 INSTALLER_IP = os.getenv('INSTALLER_IP')
31 oscapbin = 'sudo /bin/oscap'
34 parser = argparse.ArgumentParser(description='OPNFV OpenSCAP Scanner')
35 parser.add_argument('--config', action='store', dest='cfgfile',
36 help='Config file', required=True)
37 args = parser.parse_args()
40 cfgparse = SafeConfigParser()
41 cfgparse.read(args.cfgfile)
44 remotekey = cfgparse.get('undercloud', 'remotekey')
45 localkey = cfgparse.get('undercloud', 'localkey')
46 setup = connect.SetUp(remotekey, localkey)
50 # Configure Nova Credentials
51 com = 'sudo hiera admin_password'
52 setup = connect.SetUp(com)
53 keypass = setup.keystonepass()
54 auth = v2.Password(auth_url='http://{0}:5000/v2.0'.format(INSTALLER_IP),
56 password=str(keypass).rstrip(),
58 sess = session.Session(auth=auth)
59 nova = client.Client(2, session=sess)
62 def run_tests(host, nodetype):
63 user = cfgparse.get(nodetype, 'user')
64 port = cfgparse.get(nodetype, 'port')
65 connect.logger.info("Host: {0} Selected Profile: {1}".format(host,
67 connect.logger.info("Creating temp file structure..")
68 createfiles(host, port, user, localkey)
69 connect.logger.info("Installing OpenSCAP...")
70 install_pkg(host, port, user, localkey)
71 connect.logger.info("Running scan...")
72 run_scanner(host, port, user, localkey, nodetype)
73 clean = cfgparse.get(nodetype, 'clean')
74 connect.logger.info("Post installation tasks....")
75 post_tasks(host, port, user, localkey, nodetype)
77 connect.logger.info("Cleaning down environment....")
78 connect.logger.info("Removing OpenSCAP....")
79 removepkg(host, port, user, localkey, nodetype)
80 connect.logger.info("Deleting tmp file and reports (remote)...")
81 cleandir(host, port, user, localkey, nodetype)
85 # Find compute nodes, active with network on ctlplane
86 for server in nova.servers.list():
87 if server.status == 'ACTIVE' and 'compute' in server.name:
88 networks = server.networks
90 for host in networks['ctlplane']:
91 run_tests(host, nodetype)
92 # Find controller nodes, active with network on ctlplane
93 elif server.status == 'ACTIVE' and 'controller' in server.name:
94 networks = server.networks
95 nodetype = 'controller'
96 for host in networks['ctlplane']:
97 run_tests(host, nodetype)
100 def createfiles(host, port, user, localkey):
103 localpath = os.getcwd() + '/scripts/createfiles.py'
104 remotepath = '/tmp/createfiles.py'
105 com = 'python /tmp/createfiles.py'
106 connect = connect.ConnectionManager(host, port, user, localkey,
107 localpath, remotepath, com)
108 tmpdir = connect.remotescript()
111 def install_pkg(host, port, user, localkey):
113 com = 'sudo yum -y install openscap-scanner scap-security-guide'
114 connect = connect.ConnectionManager(host, port, user, localkey, com)
118 def run_scanner(host, port, user, localkey, nodetype):
120 scantype = cfgparse.get(nodetype, 'scantype')
121 profile = cfgparse.get(nodetype, 'profile')
122 results = cfgparse.get(nodetype, 'results')
123 report = cfgparse.get(nodetype, 'report')
124 secpolicy = cfgparse.get(nodetype, 'secpolicy')
125 # Here is where we contruct the actual scan command
126 if scantype == 'xccdf':
127 cpe = cfgparse.get(nodetype, 'cpe')
128 com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
129 ' --report {2}/{4} --cpe {5} {6}'.format(oscapbin,
136 connect = connect.ConnectionManager(host, port, user, localkey, com)
138 elif scantype == 'oval':
139 com = '{0} oval eval --results {1}/{2} '
140 '--report {1}/{3} {4}'.format(oscapbin, tmpdir.rstrip(),
141 results, report, secpolicy)
142 connect = connect.ConnectionManager(host, port, user, localkey, com)
145 com = '{0} oval-collect '.format(oscapbin)
146 connect = connect.ConnectionManager(host, port, user, localkey, com)
150 def post_tasks(host, port, user, localkey, nodetype):
152 # Create the download folder for functest dashboard and download reports
153 reports_dir = cfgparse.get(nodetype, 'reports_dir')
154 dl_folder = os.path.join(reports_dir, host + "_" +
156 now().strftime('%Y-%m-%d_%H-%M-%S'))
157 os.makedirs(dl_folder, 0755)
158 report = cfgparse.get(nodetype, 'report')
159 results = cfgparse.get(nodetype, 'results')
160 reportfile = '{0}/{1}'.format(tmpdir.rstrip(), report)
161 connect = connect.ConnectionManager(host, port, user, localkey, dl_folder,
162 reportfile, report, results)
163 connect.download_reports()
166 def removepkg(host, port, user, localkey, nodetype):
168 com = 'sudo yum -y remove openscap-scanner scap-security-guide'
169 connect = connect.ConnectionManager(host, port, user, localkey, com)
173 def cleandir(host, port, user, localkey, nodetype):
175 com = 'sudo rm -r {0}'.format(tmpdir.rstrip())
176 connect = connect.ConnectionManager(host, port, user, localkey, com)
180 if __name__ == '__main__':