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