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.
18 from ConfigParser import SafeConfigParser
21 from functest.utils.functest_utils import FUNCTEST_REPO as FUNCTEST_REPO
22 from keystoneclient import session
23 from keystoneclient.auth.identity import v2
24 from novaclient import client
29 __author__ = 'Luke Hinds (lhinds@redhat.com)'
30 __url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
33 INSTALLER_IP = os.getenv('INSTALLER_IP')
34 oscapbin = 'sudo /bin/oscap'
35 functest_dir = '%s/testcases/security_scan/' % FUNCTEST_REPO
37 # Apex Spefic var needed to query Undercloud
38 if os.getenv('OS_AUTH_URL') is None:
39 connect.logger.error(" Enviroment variable OS_AUTH_URL is not set")
42 OS_AUTH_URL = os.getenv('OS_AUTH_URL')
45 parser = argparse.ArgumentParser(description='OPNFV OpenSCAP Scanner')
46 parser.add_argument('--config', action='store', dest='cfgfile',
47 help='Config file', required=True)
48 args = parser.parse_args()
51 cfgparse = SafeConfigParser()
52 cfgparse.read(args.cfgfile)
55 remotekey = cfgparse.get('undercloud', 'remotekey')
56 localkey = cfgparse.get('undercloud', 'localkey')
57 setup = connect.SetUp(remotekey, localkey)
61 # Configure Nova Credentials
62 com = 'sudo /usr/bin/hiera admin_password'
63 setup = connect.SetUp(com)
64 keypass = setup.keystonepass()
65 auth = v2.Password(auth_url=OS_AUTH_URL,
67 password=str(keypass).rstrip(),
69 sess = session.Session(auth=auth)
70 nova = client.Client(2, session=sess)
73 def run_tests(host, nodetype):
74 user = cfgparse.get(nodetype, 'user')
75 port = cfgparse.get(nodetype, 'port')
76 connect.logger.info("Host: {0} Selected Profile: {1}".format(host,
78 connect.logger.info("Checking internet for package installation...")
79 if internet_check(host, nodetype):
80 connect.logger.info("Internet Connection OK.")
81 connect.logger.info("Creating temp file structure..")
82 createfiles(host, port, user, localkey)
83 connect.logger.info("Installing OpenSCAP...")
84 install_pkg(host, port, user, localkey)
85 connect.logger.info("Running scan...")
86 run_scanner(host, port, user, localkey, nodetype)
87 clean = cfgparse.get(nodetype, 'clean')
88 connect.logger.info("Post installation tasks....")
89 post_tasks(host, port, user, localkey, nodetype)
91 connect.logger.info("Cleaning down environment....")
92 connect.logger.info("Removing OpenSCAP....")
93 removepkg(host, port, user, localkey, nodetype)
94 connect.logger.info("Deleting tmp file and reports (remote)...")
95 cleandir(host, port, user, localkey, nodetype)
97 connect.logger.error("Internet timeout. Moving on to next node..")
102 # Find compute nodes, active with network on ctlplane
103 for server in nova.servers.list():
104 if server.status == 'ACTIVE' and 'compute' in server.name:
105 networks = server.networks
107 for host in networks['ctlplane']:
108 run_tests(host, nodetype)
109 # Find controller nodes, active with network on ctlplane
110 elif server.status == 'ACTIVE' and 'controller' in server.name:
111 networks = server.networks
112 nodetype = 'controller'
113 for host in networks['ctlplane']:
114 run_tests(host, nodetype)
117 def internet_check(host, nodetype):
119 user = cfgparse.get(nodetype, 'user')
120 port = cfgparse.get(nodetype, 'port')
121 localpath = functest_dir + 'scripts/internet_check.py'
122 remotepath = '/tmp/internet_check.py'
123 com = 'python /tmp/internet_check.py'
124 testconnect = connect.ConnectionManager(host, port, user, localkey,
125 localpath, remotepath, com)
126 connectionresult = testconnect.remotescript()
127 if connectionresult.rstrip() == 'True':
133 def createfiles(host, port, user, localkey):
136 localpath = functest_dir + 'scripts/createfiles.py'
137 remotepath = '/tmp/createfiles.py'
138 com = 'python /tmp/createfiles.py'
139 connect = connect.ConnectionManager(host, port, user, localkey,
140 localpath, remotepath, com)
141 tmpdir = connect.remotescript()
144 def install_pkg(host, port, user, localkey):
146 com = 'sudo yum -y install openscap-scanner scap-security-guide'
147 connect = connect.ConnectionManager(host, port, user, localkey, com)
151 def run_scanner(host, port, user, localkey, nodetype):
153 scantype = cfgparse.get(nodetype, 'scantype')
154 profile = cfgparse.get(nodetype, 'profile')
155 results = cfgparse.get(nodetype, 'results')
156 report = cfgparse.get(nodetype, 'report')
157 secpolicy = cfgparse.get(nodetype, 'secpolicy')
158 # Here is where we contruct the actual scan command
159 if scantype == 'xccdf':
160 cpe = cfgparse.get(nodetype, 'cpe')
161 com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
162 ' --report {2}/{4} --cpe {5} {6}'.format(oscapbin,
169 connect = connect.ConnectionManager(host, port, user, localkey, com)
171 elif scantype == 'oval':
172 com = '{0} oval eval --results {1}/{2} '
173 '--report {1}/{3} {4}'.format(oscapbin, tmpdir.rstrip(),
174 results, report, secpolicy)
175 connect = connect.ConnectionManager(host, port, user, localkey, com)
178 com = '{0} oval-collect '.format(oscapbin)
179 connect = connect.ConnectionManager(host, port, user, localkey, com)
183 def post_tasks(host, port, user, localkey, nodetype):
185 # Create the download folder for functest dashboard and download reports
186 reports_dir = cfgparse.get(nodetype, 'reports_dir')
187 dl_folder = os.path.join(reports_dir, host + "_" +
189 now().strftime('%Y-%m-%d_%H-%M-%S'))
190 os.makedirs(dl_folder, 0755)
191 report = cfgparse.get(nodetype, 'report')
192 results = cfgparse.get(nodetype, 'results')
193 reportfile = '{0}/{1}'.format(tmpdir.rstrip(), report)
194 connect = connect.ConnectionManager(host, port, user, localkey, dl_folder,
195 reportfile, report, results)
196 connect.download_reports()
199 def removepkg(host, port, user, localkey, nodetype):
201 com = 'sudo yum -y remove openscap-scanner scap-security-guide'
202 connect = connect.ConnectionManager(host, port, user, localkey, com)
206 def cleandir(host, port, user, localkey, nodetype):
208 com = 'sudo rm -r {0}'.format(tmpdir.rstrip())
209 connect = connect.ConnectionManager(host, port, user, localkey, com)
213 if __name__ == '__main__':