-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathSantaUnsignedSha.py
More file actions
executable file
·123 lines (108 loc) · 4.63 KB
/
SantaUnsignedSha.py
File metadata and controls
executable file
·123 lines (108 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/local/autopkg/python
# -*- coding: utf-8 -*-
#
# Copyright 2016 Allister Banks, mostly stolen from Hannes Juutilainen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""See docstring for SantaCertSha class"""
from __future__ import absolute_import
import hashlib
import os
from stat import S_IXOTH
from autopkglib import ProcessorError
from autopkglib.DmgMounter import DmgMounter
__all__ = ["SantaUnsignedSha"]
class SantaUnsignedSha(DmgMounter):
#pylint disable=line-too-long
"""Gets sha256 from unsigned binaries to inject into Munki pkginfo via
preflight script, which therefore auto-whitelists via santactl rule verb.
Checks if binaries aren't 0 bytes/executable, but you should verify path
remains valid. Assumes you will use MunkiPkgInfoMerger in the subsequent
step with preinstall key to merge script into pkginfo.
"""
input_variables = {
"input_paths": {
"required": True,
"description":
("File paths to unsigned binaries to grab sha from. Pkg payloads must be expanded."
"Can point to a path inside a .dmg, which will be mounted."),
},
}
output_variables = {
"preinstall_script": {
"description":
"Assembled preinstall script for whitelisting binaries to be merged"
"into Munki pkginfo. Assumes santactl is present/at default path on clients",
},
}
description = __doc__
def check_and_hash(self, path):
"""
Uses hashlib's sha256 algorithm to fingerprint path after checking zero size
and execute bit is set, returns sha if passes check, bool False if not
"""
binary_sha = False
mode = os.stat(path).st_mode
size = os.stat(path).st_size
if size != 0 and (mode & S_IXOTH):
try:
with open(path, 'rb') as sha_me:
binary_sha = hashlib.sha256(sha_me.read()).hexdigest()
except Exception as error:
raise ProcessorError(
"Encoutered error %s getting sha256 from path, %s" % (error, path))
return binary_sha
def gen_preinstall(self, shas_forwlist):
"""builds & returns preinstall script as multi-line string with whitelist commands"""
preinstall_temp = """#!/bin/bash
# Adds new unsigned binaries sha256 to santa whitelist, bails if santactl not present
[[ ! -f "/Library/Extensions/santa-driver.kext/Contents/MacOS/santactl" ]] && exit 0
"""
whitelist_str = "\n/usr/local/bin/santactl rule --whitelist --sha256 "
for sha in shas_forwlist:
preinstall_temp += whitelist_str + sha
preinstall_temp += "\nexit 0"
return preinstall_temp
def main(self):
# Check if we're trying to read something inside a dmg.
input_paths = self.env['input_paths']
shas_forwlist = []
dmg_paths = []
for input_path in input_paths:
(dmg_path, dmg, dmg_source_path) = self.parsePathForDMG(input_path)
if dmg:
dmg_paths.append(input_path)
mount_point = self.mount(dmg_path)
else:
sha = self.check_and_hash(input_path)
shas_forwlist.append(sha)
for input_path in dmg_paths:
try:
# Mount dmg and copy path inside.
input_path = os.path.join(mount_point, dmg_source_path)
# check is executable and not 0 bytes
sha = self.check_and_hash(input_path)
self.output("Here's some sha %s" % sha)
shas_forwlist.append(sha)
except Exception as error:
raise ProcessorError("Error processing path '%s', '%s'" % (input_path, error))
if dmg:
self.unmount(dmg_path)
if len(shas_forwlist) > 0:
preinstall = self.gen_preinstall(shas_forwlist)
self.env["preinstall_script"] = preinstall
else:
raise ProcessorError("Could not build list of binary shas from input")
if __name__ == '__main__':
PROCESSOR = SantaUnsignedSha()
PROCESSOR.execute_shell()