/
build.gradle
406 lines (332 loc) · 11 KB
/
build.gradle
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
// This is the main dtf builder. If you've decided to build dtf
// from source, this may help you. You can think of building dtf
// in 5 steps:
//
// 1. Building Man Pages
// Man pages are generated by the Ruby gem ronn, so you'll need that.
// The man pages are built by "generateMans" task and will be asserted by
// the main .deb check. "cleanMans" to remove.
//
// 2. Building the included.tar Bundle
// This bundles and builds several Java based projects, including
// apktool, smali, axmlprinter, and abe. Should only need the
// included gradlew's for these. "generateIncluded" will build them
// all, and "cleanIncluded" to wipe away. This process uses 'make',
// so you'll probably need the 'build-essential' package. More details
// are in 'dtf-included/MakeFile'
//
// 3. Building the dtfClient
// This generates a output APK using the Android buildchain, so you'll
// need that. There are two outputs:
//
// 1. 'release' - A release-key signed version. You'll need to review
// how I'm dealing with keys in the 'dtf-client-app/app/build.gradle'
// file if you want to use the release APK. Use "buildReleaseApk"
// task to build.
// 2. 'debug' - Used for quick builds, using builtin keys, no ProGuard.
// I use this internally, you can if you want. Use "buildDebugApk"
// task to build.
//
// "cleanApk" task removes _any_ built APKs. If you're not careful, you
// may end up with both a debug and release APK in the .deb. Preference
// is always taken over a debug APK if found; you've been warned.
//
// 4. Building the Python package
// This task requires a number of small tests to be performed using
// flake8 and pylint. I chose to integrate these directly to keep the
// code clean. You can manually disable these if you'd like, but they
// are here to stay. "buildPython" generates the Python code that is
// needed.
//
// 5. Generating the .deb
// This is where all the asserts* I talk about come in to play. This final
// step runs the necessary checks to make sure eveything is OK, then a
// couple last minute checks, like checkBashisms + shellCheck on the
// 'bash-dtf' code. Unless you made heavy changes this shouldn't be an
// issue. The end-game task here is "makeDeb".
//
// Putting this all together, to generate a release ready, full-featured
// .deb file, use:
// $ ./gradlew generateMans \
// generateIncluded \
// buildReleaseApk \
// buildPython \
// makeDeb
//
// Misc 1: Testing dtf
// Testing is currently handled by a combination of offline tests with
// python-converage, python-runner, and venv, as well as additional Travis
// tests. The Travis tests are a bit more tricky, but to run offline tests
// and generate coverage, you can run the "doCoverage" task.
//
// Misc 2: Notes on cleaning
// Since there are so many components, I have a number of cleans you can use:
// clean - Just removes Python.
// cleanApk - Removes the APK(s).
// cleanFull - Removes /everything/.
//
// Enjoy dtf!
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.com.netflix.nebula:gradle-ospackage-plugin:3.6.1"
}
}
apply plugin: "nebula.ospackage"
// Populate version information
String versionContents = new File("VERSION").text.trim()
def values = versionContents.split('-')
project.ext.set("buildVersion", values[0])
project.ext.set("buildRelease", values[1])
String versionString = "dtf-" + values[0] + "-" + values[1]
if ( values.length == 3) {
project.ext.set("buildBranch", values[2])
project.ext.set("versionString", versionString + "." + values[2])
} else {
project.ext.set("buildBranch", "")
project.ext.set("versionString", versionString)
}
// Date
String currentDate = new Date().format( 'yyyy-MM-dd' )
project.ext.set("currentDate", currentDate)
// Task Definitions
task makeDeb(type:Deb) {
packageName = 'android-dtf'
version = project.buildVersion
release = project.buildRelease
maintainer = 'Jake Valletta <javallet@gmail.com>'
url = 'https://github.com/jakev/dtf'
summary = 'Android Device Testing Framework (dtf)'
packageDescription = 'Modular framework for discovering vulnerabilities on Android devices.'
packageGroup = 'main'
postUninstall file('deb-scripts/postuninstall')
postInstall file('deb-scripts/postinstall')
requires('python')
requires('python-pip')
into 'build/'
// Move the wheel to a tmp dir
from('python-dtf/dist/') {
fileMode 0640
into '/tmp/'
}
// Bash Completition
from('bash-dtf/') {
fileMode 0644
into '/etc/bash_completion.d/'
include '**/*.bash'
}
// dtf Bindings
from('dtf-binding/') {
fileMode 0755
into '/usr/local/bin'
}
// Binder Links
link('/usr/local/bin/dtf_aapt', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_abe', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_apktool', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_axmlprinter2', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_baksmali', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_busybox', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_shell', '/usr/local/bin/dtfbinder', 0755)
link('/usr/local/bin/dtf_smali', '/usr/local/bin/dtfbinder', 0755)
// Man pages
from('man/') {
into '/usr/local/man/man1/'
fileMode 0644
include '**/*.1'
}
from('man/') {
into '/usr/local/man/man7/'
fileMode 0644
include '**/*.7'
}
// Bash support
from('bash-dtf/') {
into '/usr/local/lib/android-dtf/bash/'
fileMode 0644
include '**/*.sh'
}
// dtfClient
from('dtf-client-app/app/build/outputs/apk/') {
into '/usr/local/lib/android-dtf/dtfClient/'
fileMode 0644
include '**/*.apk'
}
// Included-tools TAR.
from('dtf-included/build/') {
into '/usr/local/lib/android-dtf/'
fileMode 0644
include '**/*.tar'
}
// This will assert the APK.
doLast {
try {
if (new File("dtf-client-app/app/build/outputs/apk/").listFiles().count {} == 0) { }
} catch (Exception e) {
throw new GradleException('No client found. Use: build(Release|Debug)Apk')
}
}
}
// Run all tests
task doPythonTests() {}
task doBashTests() {}
// Build Python files
task buildPython(type:Exec) {
workingDir 'python-dtf'
commandLine 'python', 'setup.py', 'bdist_wheel'
}
// Clean the Python stuff
task cleanPython(type:Delete) {
delete 'build'
delete 'python-dtf/build'
delete 'python-dtf/dist'
delete "python-dtf/dtf.egg-info"
delete 'python-dtf/dtf/VERSION'
}
// Flake8 the Code
task doFlake(type:Exec) {
workingDir 'python-dtf'
commandLine 'flake8', './dtf'
}
// pylint the Code
task doLint(type:Exec) {
workingDir 'python-dtf'
commandLine 'pylint', './dtf', '--rcfile=./pylint.config'
}
// Run pytest suite
task doPytests(type:Exec) {
workingDir 'python-dtf'
commandLine 'python', 'setup.py', 'test'
}
// Generate Coverage information
task doCoverage(type:Exec) {
workingDir 'python-dtf'
commandLine 'sh', 'generate_coverage.sh'
}
// Run checkbashisms
task doCheckBashisms {
doLast {
exec {
workingDir 'bash-dtf'
commandLine 'bash', '-c', 'checkbashisms -f ./*.sh'
}
exec {
workingDir 'dtf-binding'
commandLine 'bash', '-c', 'checkbashisms -f ./dtfbinder'
}
}
}
// Run shellcheck
task doShellCheck {
doLast {
exec {
workingDir 'bash-dtf'
commandLine 'bash', '-c', 'shellcheck ./*.sh'
}
exec {
workingDir 'dtf-binding'
commandLine 'bash', '-c', 'shellcheck ./dtfbinder'
}
}
}
// Copy version file
task copyVersion(type:Copy) {
from('.')
into 'python-dtf/dtf/'
include('VERSION')
}
//// Man Pages
// Run `ronn` on man pages
task generateMans(type:Exec) {
workingDir 'man'
String commandString = new String("ronn ./*.ronn --date="
+ project.currentDate
+ " --organization=" + project.versionString
+ " --manual=\"dtf Manual\" --roff")
commandLine 'bash', '-c', commandString
}
// Remove generated man pages
task cleanMans(type:Delete) {
delete fileTree('man/') {
include '*.1'
include '*.7'
}
}
// Make sure man pages exist
task assertMans() {
doLast {
if (new File('man').listFiles().count { it.name ==~ /.*[1-9]$/ } == 0) {
throw new GradleException('man pages not found. Use: generateMans')
}
}
}
//// End Man Related
//// Included Releated
// Use make to start the process
task generateIncluded(type:Exec) {
workingDir 'dtf-included'
String commandString = new String("make fatTar")
commandLine 'bash', '-c', commandString
}
// Use make clean task to blow away included
task cleanIncluded(type:Exec) {
workingDir 'dtf-included'
String commandString = new String("make clean")
commandLine 'bash', '-c', commandString
}
task assertIncluded() {
doLast {
if (new File('dtf-included/build').listFiles().count { it.name ==~ /.*\.tar$/ } == 0) {
throw new GradleException('Included bundle not found. Use: generateIncluded')
}
}
}
//// End Included
//// dtfClient Releated
// Build release dtfClient APK
task buildReleaseApk(type:GradleBuild) {
buildFile = 'dtf-client-app/build.gradle'
tasks = ['assembleRelease']
}
// Build debug dtfClient APK
task buildDebugApk(type:GradleBuild) {
buildFile = 'dtf-client-app/build.gradle'
tasks = ['assembleDebug']
}
// Clean any APK
task cleanApk(type:GradleBuild) {
buildFile = 'dtf-client-app/build.gradle'
tasks = ['clean']
}
//// End dtfClient Related
// Remove generated API docs
task cleanApiDocs(type:Delete) {
delete 'api-docs'
}
// Clean up
clean {}
task cleanFull {}
clean.dependsOn("cleanPython")
cleanFull.dependsOn("cleanApk")
cleanFull.dependsOn("cleanIncluded")
cleanFull.dependsOn("cleanMans")
cleanFull.dependsOn("cleanPython")
// Task Dependencies
doPythonTests.dependsOn doLint
doPythonTests.dependsOn doFlake
// Prepare the python code
buildPython.dependsOn doPythonTests
buildPython.dependsOn copyVersion
doBashTests.dependsOn doCheckBashisms
doBashTests.dependsOn doShellCheck
// Building Debian
makeDeb.dependsOn buildPython
makeDeb.dependsOn assertMans
makeDeb.dependsOn assertIncluded
makeDeb.dependsOn doBashTests
// Used to run coverage tests
doCoverage.dependsOn buildPython