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'
33 # Configure Nova Credentials
34 com = 'sudo hiera admin_password'
35 connect = connect.novaManager(com)
36 keypass = connect.keystonepass()
37 auth = v2.Password(auth_url='http://{0}:5000/v2.0'.format(INSTALLER_IP),
39 password=str(keypass).rstrip(),
41 sess = session.Session(auth=auth)
42 nova = client.Client(2, session=sess)
46 parser = argparse.ArgumentParser(description='OPNFV OpenSCAP Scanner')
47 parser.add_argument('--config', action='store', dest='cfgfile',
48 help='Config file', required=True)
49 args = parser.parse_args()
52 logger = ft_logger.Logger("security_scan").getLogger()
55 cfgparse = SafeConfigParser()
56 cfgparse.read(args.cfgfile)
59 def run_tests(host, nodetype):
60 port = cfgparse.get(nodetype, 'port')
61 user = cfgparse.get(nodetype, 'user')
62 user_key = cfgparse.get(nodetype, 'user_key')
63 logger.info("Host: {0} Selected Profile: {1}").format(host, nodetype)
64 logger.info("Creating temp file structure..")
65 createfiles(host, port, user, user_key)
66 logger.info("Installing OpenSCAP...")
67 install_pkg(host, port, user, user_key)
68 logger.info("Running scan...")
69 run_scanner(host, port, user, user_key, nodetype)
70 clean = cfgparse.get(nodetype, 'clean')
71 logger.info("Post installation tasks....")
72 post_tasks(host, port, user, user_key, nodetype)
74 logger.info("Cleaning down environment....")
75 logger.info("Removing OpenSCAP....")
76 removepkg(host, port, user, user_key, nodetype)
77 logger.info("Deleting tmp file and reports (remote)...")
78 cleandir(host, port, user, user_key, nodetype)
82 # Find compute nodes, active with network on ctlplane
83 for server in nova.servers.list():
84 if server.status == 'ACTIVE' and 'compute' in server.name:
85 networks = server.networks
87 for host in networks['ctlplane']:
88 run_tests(host, nodetype)
89 # Find controller nodes, active with network on ctlplane
90 elif server.status == 'ACTIVE' and 'controller' in server.name:
91 networks = server.networks
92 nodetype = 'controller'
93 for host in networks['ctlplane']:
94 run_tests(host, nodetype)
97 def createfiles(host, port, user, user_key):
100 localpath = os.getcwd() + '/scripts/createfiles.py'
101 remotepath = '/tmp/createfiles.py'
102 com = 'python /tmp/createfiles.py'
103 connect = connect.connectionManager(host, port, user, user_key,
104 localpath, remotepath, com)
105 tmpdir = connect.remotescript()
108 def install_pkg(host, port, user, user_key):
110 com = 'sudo yum -y install openscap-scanner scap-security-guide'
111 connect = connect.connectionManager(host, port, user, user_key, com)
115 def run_scanner(host, port, user, user_key, nodetype):
117 scantype = cfgparse.get(nodetype, 'scantype')
118 profile = cfgparse.get(nodetype, 'profile')
119 results = cfgparse.get(nodetype, 'results')
120 report = cfgparse.get(nodetype, 'report')
121 secpolicy = cfgparse.get(nodetype, 'secpolicy')
122 # Here is where we contruct the actual scan command
123 if scantype == 'xccdf':
124 cpe = cfgparse.get(nodetype, 'cpe')
125 com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
126 ' --report {2}/{4} --cpe {5} {6}'.format(oscapbin,
133 connect = connect.connectionManager(host, port, user, user_key, com)
135 elif scantype == 'oval':
136 com = '{0} oval eval --results {1}/{2} '
137 '--report {1}/{3} {4}'.format(oscapbin, tmpdir.rstrip(),
138 results, report, secpolicy)
139 connect = connect.connectionManager(host, port, user, user_key, com)
142 com = '{0} oval-collect '.format(oscapbin)
143 connect = connect.connectionManager(host, port, user, user_key, com)
147 def post_tasks(host, port, user, user_key, nodetype):
149 # Create the download folder for functest dashboard and download reports
150 reports_dir = cfgparse.get(nodetype, 'reports_dir')
151 dl_folder = os.path.join(reports_dir, host + "_" +
153 now().strftime('%Y-%m-%d_%H-%M-%S'))
154 os.makesdir(dl_folder, 0755)
155 report = cfgparse.get(nodetype, 'report')
156 results = cfgparse.get(nodetype, 'results')
157 reportfile = '{0}/{1}'.format(tmpdir.rstrip(), report)
158 connect = connect.connectionManager(host, port, user, user_key, dl_folder,
159 reportfile, report, results)
160 connect.download_reports()
163 def removepkg(host, port, user, user_key, nodetype):
165 com = 'sudo yum -y remove openscap-scanner scap-security-guide'
166 connect = connect.connectionManager(host, port, user, user_key, com)
170 def cleandir(host, port, user, user_key, nodetype):
172 com = 'sudo rm -r {0}'.format(tmpdir.rstrip())
173 connect = connect.connectionManager(host, port, user, user_key, com)
177 if __name__ == '__main__':