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.
19 from ConfigParser import SafeConfigParser
22 from keystoneclient import session
23 from keystoneclient.auth.identity import v2
24 from novaclient import client
27 import functest.utils.functest_utils as ft_utils
30 __author__ = 'Luke Hinds (lhinds@redhat.com)'
31 __url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
34 INSTALLER_IP = os.getenv('INSTALLER_IP')
35 oscapbin = 'sudo /bin/oscap'
36 functest_dir = '%s/testcases/security_scan/' % ft_utils.FUNCTEST_REPO
38 # Apex Spefic var needed to query Undercloud
39 if os.getenv('OS_AUTH_URL') is None:
40 connect.logger.error(" Enviroment variable OS_AUTH_URL is not set")
43 OS_AUTH_URL = os.getenv('OS_AUTH_URL')
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 cfgparse = SafeConfigParser()
53 cfgparse.read(args.cfgfile)
56 remotekey = cfgparse.get('undercloud', 'remotekey')
57 localkey = cfgparse.get('undercloud', 'localkey')
58 setup = connect.SetUp(remotekey, localkey)
62 # Configure Nova Credentials
63 com = 'sudo /usr/bin/hiera admin_password'
64 setup = connect.SetUp(com)
65 keypass = setup.keystonepass()
66 auth = v2.Password(auth_url=OS_AUTH_URL,
68 password=str(keypass).rstrip(),
70 sess = session.Session(auth=auth)
71 nova = client.Client(2, session=sess)
74 def run_tests(host, nodetype):
75 user = cfgparse.get(nodetype, 'user')
76 port = cfgparse.get(nodetype, 'port')
77 connect.logger.info("Host: {0} Selected Profile: {1}".format(host,
79 connect.logger.info("Checking internet for package installation...")
80 if internet_check(host, nodetype):
81 connect.logger.info("Internet Connection OK.")
82 connect.logger.info("Creating temp file structure..")
83 createfiles(host, port, user, localkey)
84 connect.logger.debug("Installing OpenSCAP...")
85 install_pkg(host, port, user, localkey)
86 connect.logger.debug("Running scan...")
87 run_scanner(host, port, user, localkey, nodetype)
88 clean = cfgparse.get(nodetype, 'clean')
89 connect.logger.info("Post installation tasks....")
90 post_tasks(host, port, user, localkey, nodetype)
92 connect.logger.info("Cleaning down environment....")
93 connect.logger.debug("Removing OpenSCAP....")
94 removepkg(host, port, user, localkey, nodetype)
95 connect.logger.info("Deleting tmp file and reports (remote)...")
96 cleandir(host, port, user, localkey, nodetype)
98 connect.logger.error("Internet timeout. Moving on to next node..")
103 # Find compute nodes, active with network on ctlplane
104 for server in nova.servers.list():
105 if server.status == 'ACTIVE' and 'compute' in server.name:
106 networks = server.networks
108 for host in networks['ctlplane']:
109 run_tests(host, nodetype)
110 # Find controller nodes, active with network on ctlplane
111 elif server.status == 'ACTIVE' and 'controller' in server.name:
112 networks = server.networks
113 nodetype = 'controller'
114 for host in networks['ctlplane']:
115 run_tests(host, nodetype)
118 def internet_check(host, nodetype):
120 user = cfgparse.get(nodetype, 'user')
121 port = cfgparse.get(nodetype, 'port')
122 localpath = functest_dir + 'scripts/internet_check.py'
123 remotepath = '/tmp/internet_check.py'
124 com = 'python /tmp/internet_check.py'
125 testconnect = connect.ConnectionManager(host, port, user, localkey,
126 localpath, remotepath, com)
127 connectionresult = testconnect.remotescript()
128 if connectionresult.rstrip() == 'True':
134 def createfiles(host, port, user, localkey):
137 localpath = functest_dir + 'scripts/createfiles.py'
138 remotepath = '/tmp/createfiles.py'
139 com = 'python /tmp/createfiles.py'
140 connect = connect.ConnectionManager(host, port, user, localkey,
141 localpath, remotepath, com)
142 tmpdir = connect.remotescript()
145 def install_pkg(host, port, user, localkey):
147 com = 'sudo yum -y install openscap-scanner scap-security-guide'
148 connect = connect.ConnectionManager(host, port, user, localkey, com)
152 def run_scanner(host, port, user, localkey, nodetype):
154 scantype = cfgparse.get(nodetype, 'scantype')
155 profile = cfgparse.get(nodetype, 'profile')
156 results = cfgparse.get(nodetype, 'results')
157 report = cfgparse.get(nodetype, 'report')
158 secpolicy = cfgparse.get(nodetype, 'secpolicy')
159 # Here is where we contruct the actual scan command
160 if scantype == 'xccdf':
161 cpe = cfgparse.get(nodetype, 'cpe')
162 com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
163 ' --report {2}/{4} --cpe {5} {6}'.format(oscapbin,
170 connect = connect.ConnectionManager(host, port, user, localkey, com)
172 elif scantype == 'oval':
173 com = '{0} oval eval --results {1}/{2} '
174 '--report {1}/{3} {4}'.format(oscapbin, tmpdir.rstrip(),
175 results, report, secpolicy)
176 connect = connect.ConnectionManager(host, port, user, localkey, com)
179 com = '{0} oval-collect '.format(oscapbin)
180 connect = connect.ConnectionManager(host, port, user, localkey, com)
184 def post_tasks(host, port, user, localkey, nodetype):
186 # Create the download folder for functest dashboard and download reports
187 reports_dir = cfgparse.get(nodetype, 'reports_dir')
188 dl_folder = os.path.join(reports_dir, host + "_" +
190 now().strftime('%Y-%m-%d_%H-%M-%S'))
191 os.makedirs(dl_folder, 0755)
192 report = cfgparse.get(nodetype, 'report')
193 results = cfgparse.get(nodetype, 'results')
194 reportfile = '{0}/{1}'.format(tmpdir.rstrip(), report)
195 connect = connect.ConnectionManager(host, port, user, localkey, dl_folder,
196 reportfile, report, results)
197 connect.download_reports()
200 def removepkg(host, port, user, localkey, nodetype):
202 com = 'sudo yum -y remove openscap-scanner scap-security-guide'
203 connect = connect.ConnectionManager(host, port, user, localkey, com)
207 def cleandir(host, port, user, localkey, nodetype):
209 com = 'sudo rm -r {0}'.format(tmpdir.rstrip())
210 connect = connect.ConnectionManager(host, port, user, localkey, com)
214 if __name__ == '__main__':