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
25 import functest.utils.functest_logger as ft_logger
28 __author__ = 'Luke Hinds (lhinds@redhat.com)'
29 __url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
32 INSTALLER_IP = os.getenv('INSTALLER_IP')
33 oscapbin = 'sudo /bin/oscap'
35 # Configure Nova Credentials
36 com = 'sudo hiera admin_password'
37 connect = connect.novaManager(com)
38 keypass = connect.keystonepass()
39 auth = v2.Password(auth_url='http://{0}:5000/v2.0'.format(INSTALLER_IP),
41 password=str(keypass).rstrip(),
43 sess = session.Session(auth=auth)
44 nova = client.Client(2, session=sess)
48 parser = argparse.ArgumentParser(description='OPNFV OpenSCAP Scanner')
49 parser.add_argument('--config', action='store', dest='cfgfile',
50 help='Config file', required=True)
51 args = parser.parse_args()
54 logger = ft_logger.Logger("security_scan").getLogger()
57 cfgparse = SafeConfigParser()
58 cfgparse.read(args.cfgfile)
61 def run_tests(host, nodetype):
62 port = cfgparse.get(nodetype, 'port')
63 user = cfgparse.get(nodetype, 'user')
64 user_key = cfgparse.get(nodetype, 'user_key')
65 logger.info("Host: {0} Selected Profile: {1}").format(host, nodetype)
66 logger.info("Creating temp file structure..")
67 createfiles(host, port, user, user_key)
68 logger.info("Installing OpenSCAP...")
69 install_pkg(host, port, user, user_key)
70 logger.info("Running scan...")
71 run_scanner(host, port, user, user_key, nodetype)
72 clean = cfgparse.get(nodetype, 'clean')
73 logger.info("Post installation tasks....")
74 post_tasks(host, port, user, user_key, nodetype)
76 logger.info("Cleaning down environment....")
77 logger.info("Removing OpenSCAP....")
78 removepkg(host, port, user, user_key, nodetype)
79 logger.info("Deleting tmp file and reports (remote)...")
80 cleandir(host, port, user, user_key, nodetype)
84 # Find compute nodes, active with network on ctlplane
85 for server in nova.servers.list():
86 if server.status == 'ACTIVE' and 'compute' in server.name:
87 networks = server.networks
89 for host in networks['ctlplane']:
90 run_tests(host, nodetype)
91 # Find controller nodes, active with network on ctlplane
92 elif server.status == 'ACTIVE' and 'controller' in server.name:
93 networks = server.networks
94 nodetype = 'controller'
95 for host in networks['ctlplane']:
96 run_tests(host, nodetype)
99 def createfiles(host, port, user, user_key):
102 localpath = os.getcwd() + '/scripts/createfiles.py'
103 remotepath = '/tmp/createfiles.py'
104 com = 'python /tmp/createfiles.py'
105 connect = connect.connectionManager(host, port, user, user_key,
106 localpath, remotepath, com)
107 tmpdir = connect.remotescript()
110 def install_pkg(host, port, user, user_key):
112 com = 'sudo yum -y install openscap-scanner scap-security-guide'
113 connect = connect.connectionManager(host, port, user, user_key, com)
117 def run_scanner(host, port, user, user_key, nodetype):
119 scantype = cfgparse.get(nodetype, 'scantype')
120 profile = cfgparse.get(nodetype, 'profile')
121 results = cfgparse.get(nodetype, 'results')
122 report = cfgparse.get(nodetype, 'report')
123 secpolicy = cfgparse.get(nodetype, 'secpolicy')
124 # Here is where we contruct the actual scan command
125 if scantype == 'xccdf':
126 cpe = cfgparse.get(nodetype, 'cpe')
127 com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
128 ' --report {2}/{4} --cpe {5} {6}'.format(oscapbin,
135 connect = connect.connectionManager(host, port, user, user_key, com)
137 elif scantype == 'oval':
138 com = '{0} oval eval --results {1}/{2} '
139 '--report {1}/{3} {4}'.format(oscapbin, tmpdir.rstrip(),
140 results, report, secpolicy)
141 connect = connect.connectionManager(host, port, user, user_key, com)
144 com = '{0} oval-collect '.format(oscapbin)
145 connect = connect.connectionManager(host, port, user, user_key, com)
149 def post_tasks(host, port, user, user_key, nodetype):
151 # Create the download folder for functest dashboard and download reports
152 reports_dir = cfgparse.get(nodetype, 'reports_dir')
153 dl_folder = os.path.join(reports_dir, host + "_" +
155 now().strftime('%Y-%m-%d_%H-%M-%S'))
156 os.makesdir(dl_folder, 0755)
157 report = cfgparse.get(nodetype, 'report')
158 results = cfgparse.get(nodetype, 'results')
159 reportfile = '{0}/{1}'.format(tmpdir.rstrip(), report)
160 connect = connect.connectionManager(host, port, user, user_key, dl_folder,
161 reportfile, report, results)
162 connect.download_reports()
165 def removepkg(host, port, user, user_key, nodetype):
167 com = 'sudo yum -y remove openscap-scanner scap-security-guide'
168 connect = connect.connectionManager(host, port, user, user_key, com)
172 def cleandir(host, port, user, user_key, nodetype):
174 com = 'sudo rm -r {0}'.format(tmpdir.rstrip())
175 connect = connect.connectionManager(host, port, user, user_key, com)
179 if __name__ == '__main__':