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