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