...
 
Commits (12)
#!/usr/bin/python
#!/usr/local/autopkg/python
#
# Copyright 2013 The Pennsylvania State University.
#
......@@ -8,7 +8,13 @@ AutoPkgBESEngine.py
Created by Matt Hansen (mah60@psu.edu) on 2013-10-08.
AutoPkg Processor for BES (BigFix) XML Tasks and Fixlets
Updated by Rusty Myers (rzm102@psu.edu) on 2020-02-21.
Adding support for python3
"""
from __future__ import absolute_import
import os
import base64
import hashlib
......@@ -22,7 +28,7 @@ from collections import OrderedDict
import requests
from lxml import etree
from FoundationPlist import FoundationPlist
import plistlib
from autopkglib import Processor, ProcessorError, get_autopkg_version
......@@ -127,10 +133,18 @@ class AutoPkgBESEngine(Processor):
Return a direct url for a download link and spoof the User-Agent.
"""
useragentsplist = ('/Applications/Safari.app'
'/Contents/Resources/UserAgents.plist')
useragent = FoundationPlist.readPlist(useragentsplist)[0]['user-agent']
useragentsplist = ('/Applications/Safari.app/Contents/Resources/UserAgents.plist')
# Source: https://github.com/autopkg/autopkg/blob/34874d2f1f91dadfdafaaf5aba63f8231936657f/Code/autopkglib/PlistEditor.py
useragents = ""
if not useragentsplist:
return {}
try:
with open(useragentsplist, "rb") as f:
useragents = plistlib.load(f)
except Exception as err:
raise ProcessorError("Could not read user agent plist: {err}")
useragent = useragents[0]['user-agent']
headers = {'User-Agent' : useragent.encode('ascii')}
request = requests.head(url, headers=headers)
......@@ -147,19 +161,34 @@ class AutoPkgBESEngine(Processor):
size = self.get_size(file_path)
return "prefetch %s sha1:%s size:%d %s sha256:%s" % (file_name, sha1,
size, url, sha256)
def get_sha1(self, file_path=""):
if not file_path:
file_path = self.env.get("bes_softwareinstaller", self.env.get("pathname"))
return hashlib.sha1(file(file_path).read()).hexdigest()
def get_sha256(self, file_path=""):
if not file_path:
file_path = self.env.get("bes_softwareinstaller", self.env.get("pathname"))
return hashlib.sha256(file(file_path).read()).hexdigest()
size, url.decode(), sha256)
def get_sha1(self, filename=""):
if not filename:
filename = self.env.get("bes_softwareinstaller", self.env.get("pathname"))
h = hashlib.sha1()
with open(filename, 'rb') as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
#https://stackoverflow.com/questions/22058048/hashing-a-file-in-python
def get_sha256(self, filename=""):
if not filename:
filename = self.env.get("bes_softwareinstaller", self.env.get("pathname"))
h = hashlib.sha256()
with open(filename, 'rb') as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
def get_size(self, file_path=""):
if not file_path:
......@@ -174,7 +203,7 @@ class AutoPkgBESEngine(Processor):
#content_type = r.headers['Content-Type']
content_type = "image/%s" % r.url.split('.')[-1]
return "data:%s;base64,%s" % (content_type, b64content)
return "data:%s;base64,%s" % (content_type, b64content.decode())
def new_node(self, element_name, node_text="", element_attributes={}):
"""
......@@ -291,18 +320,17 @@ class AutoPkgBESEngine(Processor):
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = proc.communicate(relevance)
out, err = proc.communicate(relevance.encode())
output = {}
for line in out.strip().split('\n'):
for line in out.decode().strip().split('\n'):
output[line.split(':')[0].strip()] = line.split(':')[1].strip()
if output.get('E', None):
self.output("Relevance Error: {%s} -- %s" %
(relevance,
output.get('E')))
(relevance, output.get('E')))
return True
except Exception, error:
except Exception as error:
self.output("Relevance Error: (%s) -- %s" % (QNA, error))
return True
......@@ -347,7 +375,7 @@ class AutoPkgBESEngine(Processor):
bes_relevance = self.env.get("bes_relevance")
if skipPrefetch != True:
bes_filename = self.env.get("bes_filename", url.split('/')[-1])
bes_filename = self.env.get("bes_filename", url.decode().split('/')[-1])
bes_filename = bes_filename.strip().replace(' ', '_')
bes_prefetch = self.env.get("bes_prefetch",
......@@ -357,7 +385,7 @@ class AutoPkgBESEngine(Processor):
bes_description = self.env.get("bes_description",
'This task will deploy %s %s.<BR><BR>'
'This task is applicable on Mac OS X' %
'This task is applicable on macOS' %
(bes_displayname, bes_version))
bes_actions = self.env.get("bes_actions",
......@@ -457,7 +485,7 @@ class AutoPkgBESEngine(Processor):
# Add Additional MIME Fields
if bes_additionalmimefields:
for name, value in bes_additionalmimefields.iteritems():
for name, value in bes_additionalmimefields.items():
node.append(self.new_mime(name, value))
# Add Modification Time
......@@ -468,7 +496,7 @@ class AutoPkgBESEngine(Processor):
# Append Default Action
bes_ssaaction_copy = None
for action in sorted(bes_actions.iterkeys()):
for action in sorted(bes_actions.keys()):
if bes_actions[action].get('ActionName', None) == bes_ssaaction:
bes_ssaaction_copy = bes_actions[action]
......@@ -478,7 +506,7 @@ class AutoPkgBESEngine(Processor):
bes_actions.pop(action, None)
# Append Actions
for action in sorted(bes_actions.iterkeys()):
for action in sorted(bes_actions.keys()):
node.append(self.new_action(bes_actions[action]))
# Append SSA Action
......
#!/usr/bin/python
#!/usr/local/autopkg/python
# encoding: utf-8
#
# Copyright 2013 The Pennsylvania State University.
......@@ -9,7 +9,12 @@ BESImporter.py
Created by Matt Hansen (mah60@psu.edu) on 2013-11-04.
AutoPkg Processor for importing tasks using the BigFix RESTAPI
Updated by Rusty Myers (rzm102@psu.edu) on 2020-02-21.
Adding support for python3
"""
from __future__ import absolute_import
import besapi
......@@ -42,7 +47,7 @@ class BESImporter(Processor):
"description":
"Task ID to import (overwrite), performs HTTP PUT."
},
"BES_ROOTSERVER": {
"BES_ROOT_SERVER": {
"required": True,
"description":
"URL to BES root server. e.g https://bes.domain.tld:52311/api"
......@@ -80,12 +85,12 @@ class BESImporter(Processor):
BES_USERNAME = self.env.get("BES_USERNAME")
BES_PASSWORD = self.env.get("BES_PASSWORD")
BES_ROOTSERVER = self.env.get("BES_ROOTSERVER")
BES_ROOT_SERVER = self.env.get("BES_ROOT_SERVER")
# BES Console Connection
B = besapi.BESConnection(BES_USERNAME,
BES_PASSWORD,
BES_ROOTSERVER,
BES_ROOT_SERVER,
verify=False)
# PUT, update task
......@@ -100,7 +105,7 @@ class BESImporter(Processor):
bes_taskid, task().Task.Title))
self.output("Importing: '%s' to %s/tasks/custom/%s" %
(bes_file, BES_ROOTSERVER, bes_customsite))
(bes_file, BES_ROOT_SERVER, bes_customsite))
with open(bes_file, 'r') as file_handle:
upload_result = B.put('task/custom/%s/%s' % (bes_customsite,
......@@ -146,7 +151,7 @@ class BESImporter(Processor):
if not duplicate_task:
self.output("Importing: '%s' to %s/tasks/custom/%s" %
(bes_file, BES_ROOTSERVER, bes_customsite))
(bes_file, BES_ROOT_SERVER, bes_customsite))
# Upload task
with open(bes_file, 'r') as file_handle:
......
#!/usr/bin/python
#!/usr/local/autopkg/python
# encoding: utf-8
#
# Copyright 2014 The Pennsylvania State University.
......@@ -9,10 +9,15 @@ BESRelevanceProvider.py
Created by Matt Hansen (mah60@psu.edu) on 2014-02-19.
AutoPkg Processor for retreiving relevance data for tasks.
Updated by Rusty Myers (rzm102@psu.edu) on 2020-02-21.
Adding support for python3
"""
from __future__ import absolute_import
import os
import hashlib
import os
import subprocess
from autopkglib import Processor, ProcessorError
......@@ -25,7 +30,7 @@ class BESRelevanceProvider(Processor):
description = "Retreives arbitrary relevance data using the QnA utility."
input_variables = {
"bes_filepath": {
"required": True,
"required": False,
"description":
"Path to a file for relevance data. Defaults to %pathname%."
},
......@@ -53,6 +58,10 @@ class BESRelevanceProvider(Processor):
"description":
"The resulting file size of the %bes_filepath%."
},
"bes_sha256": {
"description":
"The resulting file size of the %bes_filepath%."
},
}
__doc__ = description
......@@ -63,11 +72,12 @@ class BESRelevanceProvider(Processor):
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = proc.communicate(relevance)
out, err = proc.communicate(relevance.encode())
output = {}
for line in out.strip().split('\n'):
output[line.split(':')[0].strip()] = line.split(':')[1].strip()
for line in out.decode().strip().split('\n'):
line_split = line.split(': ')
output[line_split[0]] = ''.join(line_split[1:])
if output.get('E', None):
self.output("Relevance Error: {%s} -- %s" %
......@@ -75,32 +85,67 @@ class BESRelevanceProvider(Processor):
return None
else:
return output.get('A', None)
except Exception, error:
except BaseException as error:
self.output("QnA Error: (%s) -- %s" % (QNA, error))
return None
#https://stackoverflow.com/questions/22058048/hashing-a-file-in-python
def sha256sum(self, filename):
h = hashlib.sha256()
with open(filename, 'rb') as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
def sha1sum(self, filename):
h = hashlib.sha1()
with open(filename, 'rb') as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
def main(self):
# Assign BES Console Variables
bes_filepath = self.env.get("bes_filepath", self.env.get("pathname"))
bes_filepath = self.env.get("bes_filepath", None)
bes_relevance = self.env.get("bes_relevance", None)
if os.path.isfile(bes_filepath):
if not os.path.isfile(QNA):
self.output("QnA utility not found at [%s]."
"\n\n Run `autopkg install QnA`" % QNA)
self.env['bes_sha1'] = hashlib.sha1(file(
bes_filepath).read()).hexdigest()
if bes_filepath and os.path.isfile(bes_filepath):
self.env['bes_sha1'] = self.sha1sum(bes_filepath)
self.env['bes_size'] = str(os.path.getsize(bes_filepath))
self.env['bes_sha256'] = self.sha256sum(bes_filepath)
self.env['bes_sha1_short'] = str(self.env.get("bes_sha1"))[-5:]
self.output("bes_sha1 = %s, bes_size = %s, bes_sha1_short = %s" %
(self.env.get("bes_sha1"),
self.env.get("bes_size"),
self.env.get("bes_sha1_short")))
self.output("bes_sha1 = %s, bes_size = %s, "
"bes_sha256 = %s, bes_sha1_short = %s" %
(self.env.get("bes_sha1"),
self.env.get("bes_size"),
self.env.get("bes_sha256"),
self.env.get("bes_sha1_short")))
if bes_relevance:
output_var_name = self.env.get("output_var_name",
output_var_name = self.env.get("output_var_name",
"bes_relevance_result")
self.output(bes_relevance)
relevance_result = self.eval_relevance(bes_relevance)
if relevance_result is not None:
self.env[output_var_name] = relevance_result
elif output_var_name not in self.env:
self.env[output_var_name] = None
self.env[output_var_name] = self.eval_relevance(bes_relevance)
self.output("%s = %s" %
(output_var_name,
self.env.get(output_var_name)))
......
#!/usr/bin/python
#!/usr/local/autopkg/python
# encoding: utf-8
#
# Copyright 2015 The Pennsylvania State University.
......@@ -9,8 +9,12 @@ BESTemplater.py
Created by Matt Hansen (mah60@psu.edu) on 2015-04-30.
AutoPkg Processor for importing tasks using the BigFix RESTAPI
"""
Updated by Rusty Myers (rzm102@psu.edu) on 2020-02-21.
Work in progress. Does not support Python3.
"""
from __future__ import absolute_import
import os
import sys
......
#!/usr/bin/python
#!/usr/local/autopkg/python
# encoding: utf-8
#
# Copyright 2013 The Pennsylvania State University.
......@@ -9,10 +9,16 @@ BESUploader.py
Created by Matt Hansen (mah60@psu.edu) on 2013-11-06.
AutoPkg Processor for uploading files using the BigFix REST API
Updated by Rusty Myers (rzm102@psu.edu) on 2020-02-21.
Adding support for python3
"""
from __future__ import absolute_import
import os, ssl
import urllib2
import urllib
import base64
import sys
from xml.dom import minidom
......@@ -87,7 +93,7 @@ class BESUploader(Processor):
def send_api_request(self, api_url, auth_string, bes_file=None):
"""Send generic BES API request"""
# self.output("Sending BES API Request")
request = urllib2.Request(api_url)
request = urllib.request(api_url)
request.add_header("Authorization", "Basic %s" % auth_string)
request.add_header("Content-Type", "application/xml")
......@@ -95,7 +101,7 @@ class BESUploader(Processor):
# Read bes_file contents and add to request
if bes_file:
bes_data = open(bes_file).read()
request.add_data(bes_data)
request.data(bes_data)
request.add_header("Content-Disposition",
'attachment; filename="%s"' %
os.path.basename(bes_file))
......@@ -105,13 +111,13 @@ class BESUploader(Processor):
# self.output(request.get_full_url())
# self.output(request.get_method())
# self.output(request)
return urllib2.urlopen(request)
return urllib.request.urlopen(request)
except urllib2.HTTPError, error:
except urllib.error.HTTPError as error:
self.output("HTTPError: [%s] %s" % (error.code, error.read()))
sys.exit(1)
except urllib2.URLError, error:
except urllib.error.URLError as error:
self.output("URLError: %s" % (error.args))
sys.exit(1)
......
AutoPkg BESEngine
=======
##Update for Python3 and AutoPkg 2.0
AutoPkg 2.0 has started to ship with it's own install of python3, which means that installing modules for python system
wide or into user spaces won't work as expected.
The AutoPkgBESEngine requires the additon of the following modules to the AutoPkg Python Framework, as well as the besapi folder:
requests (BESImporter.py)
-> urllib3 (requests)
-> chardet (requests)
-> idna (requests)
lxml (AutoPkgBESEngine.py)
One option is to place the folders from the "modules" folder in the repo into the "/Library/AutoPkg/Python3/Python.framework/Versions/Current/lib/python3.7/site-packages/" folder.
See [Installing Additional Modules](https://github.com/munki/munki/wiki/Customizing-Python-for-Munki-4#installing-additional-python-modules) from AutoPkg wiki for more information.
-----------
AutoPkgBESEngine is a collection of shared processors for [AutoPkg](https://github.com/autopkg/autopkg) used to automatically create and import software deployment tasks into a [IBM Endpoint Manager](http://www.ibm.com/software/tivoli/solutions/endpoint-manager/) console.
AutoPkgBESEngine.py - AutoPkg Processor for BES (BigFix) XML Tasks and Fixlets
......