bugfix for finding tempest failed testcase
[functest.git] / functest / opnfv_tests / security_scan / security_scan.py
1 #!/usr/bin/python
2 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
14
15
16 import datetime
17 import os
18 import sys
19 from ConfigParser import SafeConfigParser
20
21 import argparse
22 from keystoneclient import session
23 from keystoneclient.auth.identity import v2
24 from novaclient import client
25
26 import connect
27 import functest.utils.functest_constants as ft_constants
28
29 __version__ = 0.1
30 __author__ = 'Luke Hinds (lhinds@redhat.com)'
31 __url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
32
33 # Global vars
34 INSTALLER_IP = ft_constants.CI_INSTALLER_IP
35 oscapbin = 'sudo /bin/oscap'
36 functest_dir = '%s/security_scan/' % ft_constants.FUNCTEST_TEST_DIR
37
38 # Apex Spefic var needed to query Undercloud
39 if ft_constants.OS_AUTH_URL is None:
40     connect.logger.error(" Enviroment variable OS_AUTH_URL is not set")
41     sys.exit(0)
42 else:
43     OS_AUTH_URL = ft_constants.OS_AUTH_URL
44
45 # args
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()
50
51 # Config Parser
52 cfgparse = SafeConfigParser()
53 cfgparse.read(args.cfgfile)
54
55 #  Grab Undercloud key
56 remotekey = cfgparse.get('undercloud', 'remotekey')
57 localkey = cfgparse.get('undercloud', 'localkey')
58 setup = connect.SetUp(remotekey, localkey)
59 setup.getockey()
60
61
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,
67                    username='admin',
68                    password=str(keypass).rstrip(),
69                    tenant_name='admin')
70 sess = session.Session(auth=auth)
71 nova = client.Client(2, session=sess)
72
73
74 class GlobalVariables:
75     tmpdir = ""
76
77
78 def run_tests(host, nodetype):
79     user = cfgparse.get(nodetype, 'user')
80     port = cfgparse.get(nodetype, 'port')
81     connect.logger.info("Host: {0} Selected Profile: {1}".format(host,
82                                                                  nodetype))
83     connect.logger.info("Checking internet for package installation...")
84     if internet_check(host, nodetype):
85         connect.logger.info("Internet Connection OK.")
86         connect.logger.info("Creating temp file structure..")
87         createfiles(host, port, user, localkey)
88         connect.logger.debug("Installing OpenSCAP...")
89         install_pkg(host, port, user, localkey)
90         connect.logger.debug("Running scan...")
91         run_scanner(host, port, user, localkey, nodetype)
92         clean = cfgparse.get(nodetype, 'clean')
93         connect.logger.info("Post installation tasks....")
94         post_tasks(host, port, user, localkey, nodetype)
95         if clean:
96             connect.logger.info("Cleaning down environment....")
97             connect.logger.debug("Removing OpenSCAP....")
98             removepkg(host, port, user, localkey, nodetype)
99             connect.logger.info("Deleting tmp file and reports (remote)...")
100             cleandir(host, port, user, localkey, nodetype)
101     else:
102         connect.logger.error("Internet timeout. Moving on to next node..")
103         pass
104
105
106 def nova_iterate():
107     # Find compute nodes, active with network on ctlplane
108     for server in nova.servers.list():
109         if server.status == 'ACTIVE' and 'compute' in server.name:
110             networks = server.networks
111             nodetype = 'compute'
112             for host in networks['ctlplane']:
113                 run_tests(host, nodetype)
114         # Find controller nodes, active with network on ctlplane
115         elif server.status == 'ACTIVE' and 'controller' in server.name:
116             networks = server.networks
117             nodetype = 'controller'
118             for host in networks['ctlplane']:
119                 run_tests(host, nodetype)
120
121
122 def internet_check(host, nodetype):
123     import connect
124     user = cfgparse.get(nodetype, 'user')
125     port = cfgparse.get(nodetype, 'port')
126     localpath = functest_dir + 'scripts/internet_check.py'
127     remotepath = '/tmp/internet_check.py'
128     com = 'python /tmp/internet_check.py'
129     testconnect = connect.ConnectionManager(host, port, user, localkey,
130                                             localpath, remotepath, com)
131     connectionresult = testconnect.remotescript()
132     if connectionresult.rstrip() == 'True':
133         return True
134     else:
135         return False
136
137
138 def createfiles(host, port, user, localkey):
139     import connect
140     localpath = functest_dir + 'scripts/createfiles.py'
141     remotepath = '/tmp/createfiles.py'
142     com = 'python /tmp/createfiles.py'
143     connect = connect.ConnectionManager(host, port, user, localkey,
144                                         localpath, remotepath, com)
145     GlobalVariables.tmpdir = connect.remotescript()
146
147
148 def install_pkg(host, port, user, localkey):
149     import connect
150     com = 'sudo yum -y install openscap-scanner scap-security-guide'
151     connect = connect.ConnectionManager(host, port, user, localkey, com)
152     connect.remotecmd()
153
154
155 def run_scanner(host, port, user, localkey, nodetype):
156     import connect
157     scantype = cfgparse.get(nodetype, 'scantype')
158     profile = cfgparse.get(nodetype, 'profile')
159     results = cfgparse.get(nodetype, 'results')
160     report = cfgparse.get(nodetype, 'report')
161     secpolicy = cfgparse.get(nodetype, 'secpolicy')
162     # Here is where we contruct the actual scan command
163     if scantype == 'xccdf':
164         cpe = cfgparse.get(nodetype, 'cpe')
165         com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
166               ' --report {2}/{4}' \
167               ' --cpe {5} {6}'.format(oscapbin,
168                                       profile,
169                                       GlobalVariables.tmpdir.rstrip(),
170                                       results,
171                                       report,
172                                       cpe,
173                                       secpolicy)
174         connect = connect.ConnectionManager(host, port, user, localkey, com)
175         connect.remotecmd()
176     elif scantype == 'oval':
177         com = '{0} oval eval --results {1}/{2} '
178         '--report {1}/{3} {4}'.format(oscapbin,
179                                       GlobalVariables.tmpdir.rstrip(),
180                                       results, report, secpolicy)
181         connect = connect.ConnectionManager(host, port, user, localkey, com)
182         connect.remotecmd()
183     else:
184         com = '{0} oval-collect '.format(oscapbin)
185         connect = connect.ConnectionManager(host, port, user, localkey, com)
186         connect.remotecmd()
187
188
189 def post_tasks(host, port, user, localkey, nodetype):
190     import connect
191     # Create the download folder for functest dashboard and download reports
192     reports_dir = cfgparse.get(nodetype, 'reports_dir')
193     dl_folder = os.path.join(reports_dir, host + "_" +
194                              datetime.datetime.
195                              now().strftime('%Y-%m-%d_%H-%M-%S'))
196     os.makedirs(dl_folder, 0755)
197     report = cfgparse.get(nodetype, 'report')
198     results = cfgparse.get(nodetype, 'results')
199     reportfile = '{0}/{1}'.format(GlobalVariables.tmpdir.rstrip(), report)
200     connect = connect.ConnectionManager(host, port, user, localkey, dl_folder,
201                                         reportfile, report, results)
202     connect.download_reports()
203
204
205 def removepkg(host, port, user, localkey, nodetype):
206     import connect
207     com = 'sudo yum -y remove openscap-scanner scap-security-guide'
208     connect = connect.ConnectionManager(host, port, user, localkey, com)
209     connect.remotecmd()
210
211
212 def cleandir(host, port, user, localkey, nodetype):
213     import connect
214     com = 'sudo rm -r {0}'.format(GlobalVariables.tmpdir.rstrip())
215     connect = connect.ConnectionManager(host, port, user, localkey, com)
216     connect.remotecmd()
217
218
219 if __name__ == '__main__':
220     nova_iterate()