-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathMakefile
More file actions
659 lines (547 loc) · 29 KB
/
Copy pathMakefile
File metadata and controls
659 lines (547 loc) · 29 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
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
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
MAKEFLAGS += --silent
SHELL=/bin/bash
D3FEND_VERSION ?=1.6.0
D3FEND_RELEASE_DATE ?="2026-08-31T00:12:00.000Z"
ATTACK_VERSION ?= 19.0
ATTACK_DATA_BASE_URL ?= https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master
ATTACK_ENTERPRISE_URL ?= $(ATTACK_DATA_BASE_URL)/enterprise-attack/enterprise-attack-$(ATTACK_VERSION).json
ATTACK_MOBILE_URL ?= $(ATTACK_DATA_BASE_URL)/mobile-attack/mobile-attack-$(ATTACK_VERSION).json
ATTACK_ICS_URL ?= $(ATTACK_DATA_BASE_URL)/ics-attack/ics-attack-$(ATTACK_VERSION).json
ATTACK_ITEM_URL_PREFIX ?= https://attack.mitre.org/techniques/
CAPEC_VERSION := 3.9
CAPEC_ARCHIVE_URL ?= https://capec.mitre.org/data/archive/capec_v$(CAPEC_VERSION).zip
CAPEC_ITEM_URL_PREFIX ?= https://capec.mitre.org/data/definitions/
SPARTA_VERSION := 4.0
SPARTA_STIX_URL ?= https://sparta.aerospace.org/download/STIX?f=sparta_data_v$(SPARTA_VERSION).json
SPARTA_ITEM_URL_PREFIX ?= https://sparta.aerospace.org/technique/
ATLAS_VERSION := 2026.06
ATLAS_STIX_URL ?= https://github.com/mitre-atlas/atlas-data/releases/download/v$(ATLAS_VERSION)/stix-atlas.json
ATLAS_ITEM_URL_PREFIX ?= https://atlas.mitre.org/techniques/
CWEC_URL ?= https://cwe.mitre.org/data/xml/cwec_latest.xml.zip
CWE_VERSION ?= current
CWE_ITEM_URL_PREFIX ?= https://cwe.mitre.org/data/definitions/
OCSF_VERSION ?= 1.8.0
OCSF_SCHEMA_DIR ?= data/ocsf-schema
OCSF_SCHEMA_ARCHIVE_URL ?= https://github.com/ocsf/ocsf-schema/archive/refs/tags/$(OCSF_VERSION).tar.gz
OCSF_SCHEMA_URL_PREFIX ?= https://schema.ocsf.io/
NIST_VERSION ?= 5
NIST_SOURCE_VERSION ?= Revision $(NIST_VERSION)
NIST_SOURCE ?= data/nist/NIST_SP-800-53_rev$(NIST_VERSION)_catalog.json
NIST_SOURCE_URL ?= https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev$(NIST_VERSION)/json/NIST_SP-800-53_rev$(NIST_VERSION)_catalog.json
NIST_ITEM_URL_PREFIX ?= https://csf.tools/reference/nist-sp-800-53/r$(NIST_VERSION)/
NIST_MAPPING_SOURCE ?= extensions/nist/sp800-53r5-control-catalog-d3fend-mapping.xlsx
NIST_MAPPING_SHEET ?= SP 800-53 Revision 5--d3fend
NIST_MAPPING_OUTPUT ?= build/sp800-53r5-control-to-d3fend-mapping.ttl
NIST_CATALOG_IRI ?= NIST_SP_800-53_R$(NIST_VERSION)
CCI_SOURCE_VERSION ?= 2025-01-23
CCI_MAPPING_VERSION ?= 2022-04-05
CCI_SOURCE_DIR ?= data/cci
CCI_SOURCE_ARCHIVE ?= $(CCI_SOURCE_DIR)/U_CCI_List.zip
CCI_SOURCE ?= $(CCI_SOURCE_DIR)/U_CCI_List.xml
CCI_SOURCE_URL ?= https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_CCI_List.zip
CCI_ITEM_URL ?= $(CCI_SOURCE_URL)
CCI_MAPPING_SOURCE ?= extensions/cci/CCI_Mapping.xlsx
CCI_MAPPING_SHEET ?= U_CCI_List
CCI_MAPPING_OUTPUT ?= build/cci-to-d3fend-mapping.ttl
JENA_VERSION := 5.6.0
JENA_PATH := "bin/jena/apache-jena-${JENA_VERSION}/bin"
PYTHON ?= python3.11
PIPENV ?= pipenv
JAVA ?= java
ROBOT_VERSION ?= 1.9.10
ROBOT_VERSIONED_JAR := bin/robot-$(ROBOT_VERSION).jar
ROBOT_URL ?= "https://github.com/ontodev/robot/releases/download/v$(ROBOT_VERSION)/robot.jar"
DOCKER_NO_CACHE ?= false
DOCKER_BUILD_NOCACHE_FLAG := $(if $(filter true,$(DOCKER_NO_CACHE)),--no-cache,)
ONTOLOGY_BASE_IMAGE ?= d3fend-ontology-base:latest
ONTOLOGY_IMAGE_TAG ?= d3fend-ontology:latest
ONTOLOGY_DOCKER_BUILD_ARGS ?= --build-arg BUILDKIT_INLINE_CACHE=1 --build-arg ROBOT_URL=$(ROBOT_URL)
# define standard colors
ifneq (,$(findstring xterm,${TERM}))
BLACK := $(shell tput -Txterm setaf 0)
RED := $(shell tput -Txterm setaf 1)
GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
LIGHTPURPLE := $(shell tput -Txterm setaf 4)
PURPLE := $(shell tput -Txterm setaf 5)
BLUE := $(shell tput -Txterm setaf 6)
WHITE := $(shell tput -Txterm setaf 7)
RESET := $(shell tput -Txterm sgr0)
else
BLACK := ""
RED := ""
GREEN := ""
YELLOW := ""
LIGHTPURPLE := ""
PURPLE := ""
BLUE := ""
WHITE := ""
RESET := ""
endif
START = echo "${BLUE}$@ started ${RESET}"
END = echo "${GREEN}$@ done ${RESET}"
FAIL = echo "${RED}$@ failed ${RESET}"
DB_LOCAL ?= "http://127.0.0.1:9899"
DB_PROD ?= "http://PRODUCTIONSERVER.local:9899"
DB_REST_PATH ?= "/blazegraph/namespace/d3fend/sparql"
DB_REST_PATH_INF ?= "/blazegraph/namespace/d3fend_inf/sparql"
DB_REST_PATH_BD ?= "/bigdata/namespace/d3fend/sparql"
DB_REST_PATH_BD_INF ?= "/bigdata/namespace/d3fend_inf/sparql"
DB_REST_PATH_TEST ?= "/bigdata/namespace/d3fend-test/sparql"
RD_DB_LOCAL ?= "http://127.0.0.1:12110"
RD_DB_PROD ?= "http://PRODUCTIONSERVER.local:9899"
RD_DB_REST_PATH ?= "/datastores/d3fend/content"
RD_DB_REST_PATH_INF ?= "/blazegraph/namespace/d3fend_inf/sparql"
RD_DB_REST_PATH_BD ?= "/bigdata/namespace/d3fend/sparql"
RD_DB_REST_PATH_BD_INF ?= "/bigdata/namespace/d3fend_inf/sparql"
RD_DB_REST_PATH_TEST ?= "/bigdata/namespace/d3fend-test/sparql"
db-delete-local:
@curl -s -o /dev/null -w "deleted ${DB_LOCAL}${DB_REST_PATH} %{http_code}\n" ${DB_LOCAL}${DB_REST_PATH} --data-urlencode "update=DROP ALL;"
@curl -s -o /dev/null -w "deleted ${DB_LOCAL}${DB_REST_PATH_INF} %{http_code}\n" ${DB_LOCAL}${DB_REST_PATH_INF} --data-urlencode "update=DROP ALL;"
db-delete-prod:
@curl -s -o /dev/null -w "deleted ${DB_PROD}${DB_REST_PATH} %{http_code}\n" ${DB_PROD}${DB_REST_PATH_BD} --data-urlencode "update=DROP ALL;"
@curl -s -o /dev/null -w "deleted ${DB_PROD}${DB_REST_PATH_BD_INF} %{http_code}\n" ${DB_PROD}${DB_REST_PATH_BD_INF} --data-urlencode "update=DROP ALL;"
db-load-local:
@curl -s -o /dev/null -w "loaded ${DB_LOCAL}${DB_REST_PATH} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file dist/public/d3fend.ttl ${DB_LOCAL}${DB_REST_PATH}
@curl -s -o /dev/null -w "loaded ${DB_LOCAL}${DB_REST_PATH_INF} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file dist/public/d3fend.ttl ${DB_LOCAL}${DB_REST_PATH_INF}
db-load-prod:
@curl -s -o /dev/null -w "loaded ${DB_PROD}${DB_REST_PATH} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file dist/public/d3fend.ttl ${DB_PROD}${DB_REST_PATH_BD}
@curl -s -o /dev/null -w "loaded ${DB_PROD}${DB_REST_PATH_INF} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file dist/public/d3fend.ttl ${DB_PROD}${DB_REST_PATH_BD_INF}
db-sync-prod: db-delete-prod db-load-prod
db-sync-local: db-delete-local db-load-local
db-load-prod-restore:
curl -D- -H 'Content-Type:application/x-turtle' -v -X POST --upload-file "BACKUPFILE".ttl ${DB_PROD}${DB_REST_PATH_BD}
@curl -s -o /dev/null -w "loaded ${DB_PROD}${DB_REST_PATH} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file "BACKUPFILE".ttl ${DB_PROD}${DB_REST_PATH}
@curl -s -o /dev/null -w "loaded ${DB_PROD}${DB_REST_PATH_INF} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file "BACKUPFILE".ttl ${DB_PROD}${DB_REST_PATH_INF}
# run make-onto again at end to rebuild the csv with latest data
db-sync-all: db-delete-local db-load-local db-delete-prod db-load-prod ## sync local and prod dbs with current ontology
rd_db-load-local:
@curl -i -X PATCH "admin:admin@localhost:12110/datastores/d3fend/content?operation=add-content-update-prefixes" -H "Content-Type:" -T dist/public/d3fend.ttl
#@curl -s -o /dev/null -w "loaded ${RD_DB_LOCAL}${RD_DB_REST_PATH} %{http_code}\n" -H 'Content-Type:' -X PATCH -T dist/public/d3fend.ttl ${RD_DB_LOCAL}${RD_DB_REST_PATH}
#@curl -s -o /dev/null -w "loaded ${RD_DB_LOCAL}${RD_DB_REST_PATH_INF} %{http_code}\n" -H 'Content-Type:application/x-turtle' -X POST --upload-file dist/public/d3fend.ttl ${RD_DB_LOCAL}${RD_DB_REST_PATH_INF}
clean: ## cleans all build artifacts
rm -rf build/
rm -rf dist/
rm -f reports/*
$(END)
install-system-deps:
yum install make -y
$(END)
install-python-deps:
PIPENV_PYTHON=$(PYTHON) $(PIPENV) install --dev
$(END)
update-python-deps: ## Update Python dependencies and refresh Pipfile.lock
PIPENV_PYTHON=$(PYTHON) $(PIPENV) update --dev --python $(PYTHON)
$(END)
update-deps: update-python-deps ## Update project dependency locks
$(END)
bindir:
mkdir -p bin bin/.library
$(END)
bin/jena: bindir
mkdir -p bin/jena
curl https://archive.apache.org/dist/jena/binaries/apache-jena-${JENA_VERSION}.tar.gz | tar xzf - -C bin/jena
$(END)
bin/robot: src/util/robot.sh | bindir ## install ROBOT launcher wrapper
cp src/util/robot.sh bin/robot
chmod +x bin/robot
$(END)
$(ROBOT_VERSIONED_JAR): | bindir
curl --fail --location $(ROBOT_URL) --output "$@.tmp"
mv "$@.tmp" "$@"
$(END)
bin/robot.jar: $(ROBOT_VERSIONED_JAR) | bindir
ln -sfn "$(notdir $<)" "$@"
$(END)
robot: bin/robot bin/robot.jar ## install the declared ROBOT wrapper and version
$(END)
install-deps: install-python-deps robot bin/jena ## install software deps
$(END)
docker-build-base-image: ## build the reusable ontology base image
@docker build $(DOCKER_BUILD_NOCACHE_FLAG) \
$(ONTOLOGY_DOCKER_BUILD_ARGS) \
--target ontology-base \
-t "$(ONTOLOGY_BASE_IMAGE)" .
docker-build-image: docker-build-base-image ## build the ontology image
@docker build $(DOCKER_BUILD_NOCACHE_FLAG) \
--cache-from "$(ONTOLOGY_BASE_IMAGE)" \
$(ONTOLOGY_DOCKER_BUILD_ARGS) \
-t "$(ONTOLOGY_IMAGE_TAG)" .
download-attack:
mkdir -p data
echo "Version: $(ATTACK_VERSION)"
curl -L $(ATTACK_ENTERPRISE_URL) -o data/enterprise-attack-$(ATTACK_VERSION).json
curl -L $(ATTACK_MOBILE_URL) -o data/mobile-attack-$(ATTACK_VERSION).json
curl -L $(ATTACK_ICS_URL) -o data/ics-attack-$(ATTACK_VERSION).json
$(END)
update-attack:
bash src/util/update_attack.sh $(ATTACK_VERSION) $(FRAMEWORKS)
$(END)
download-sparta:
mkdir -p data
echo "Version: $(SPARTA_VERSION)"
curl -L --insecure "$(SPARTA_STIX_URL)" -o data/sparta_data_v$(SPARTA_VERSION).json
$(END)
update-sparta:
bash src/util/update_sparta.sh $(SPARTA_VERSION)
$(END)
download-capec:
mkdir -p data
echo "Version: $(CAPEC_VERSION)"
curl -L $(CAPEC_ARCHIVE_URL) -o data/capec_v$(CAPEC_VERSION).zip
unzip -o data/capec_v$(CAPEC_VERSION).zip -d data
$(END)
update-capec:
bash src/util/update_capec.sh $(CAPEC_VERSION)
download-atlas:
mkdir -p data
echo "Version: $(ATLAS_VERSION)"
curl -L $(ATLAS_STIX_URL) -o data/stix-atlas.json
$(END)
update-atlas:
bash src/util/update_atlas.sh $(ATLAS_VERSION)
download-ocsf:
mkdir -p data
echo "Version: $(OCSF_VERSION)"
rm -rf $(OCSF_SCHEMA_DIR)
mkdir -p $(OCSF_SCHEMA_DIR)
curl -L $(OCSF_SCHEMA_ARCHIVE_URL) | tar xzf - -C $(OCSF_SCHEMA_DIR) --strip-components=1
$(END)
download-nist:
mkdir -p $(dir $(NIST_SOURCE))
echo "Version: $(NIST_SOURCE_VERSION)"
curl -L $(NIST_SOURCE_URL) -o $(NIST_SOURCE)
$(END)
download-cci:
mkdir -p $(CCI_SOURCE_DIR)
echo "Version: $(CCI_SOURCE_VERSION)"
curl -L $(CCI_SOURCE_URL) -o $(CCI_SOURCE_ARCHIVE)
unzip -o $(CCI_SOURCE_ARCHIVE) U_CCI_List.xml -d $(CCI_SOURCE_DIR)
$(END)
download-cwe:
$(MAKE) -C extensions/cwe download-cwe CWE_URL=$(CWEC_URL)
$(END)
download-data: download-attack download-sparta download-capec download-atlas download-cwe download-ocsf download-nist download-cci ## Download all external source data files
$(END)
update-puns:
bash src/util/update_puns.sh
$(END)
# See also how to configure one's own checks and labels for checks for report:
# http://robot.obolibrary.org/report#labels
# http://robot.obolibrary.org/report_queries/
#
# A copy of robot's default_profile.txt extracted from robot.jar and
# placed in src/queries/ as convenient reference. The report target is
# currently coded to not fail as some errors are not blockers
# yet. These reports are done immediately after adding ontology header
# annotations to output from Web Protege.
reports/default-robot-report.txt: build/d3fend-full.owl ## Generate d3fend-full-robot-report.txt on ontology source issues
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/custom-report-profile.txt \
--fail-on none > reports/default-robot-report.txt
$(END)
# Note: At present some definitions are d3f:definition; most are defacto rdfs:comment
reports/missing-d3fend-definition-report.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/missing-d3fend-definition-profile.txt \
--fail-on none > reports/missing-d3fend-definition-report.txt
$(END)
# Regression test, should not happen again.
reports/bogus-direct-subclassing-of-tactic-technique-report.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/bogus-direct-subclassing-of-tactic-technique-profile.txt \
--fail-on ERROR > reports/bogus-direct-subclassing-of-tactic-technique-report.txt
$(END)
reports/missing-rdfs-label-report.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/missing-rdfs-label-profile.txt \
--fail-on none > reports/missing-rdfs-label-report.txt
$(END)
reports/duplicate-labels.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/duplicate-labels-profile.txt \
--fail-on none > reports/duplicate-labels.txt
$(END)
reports/missing-attack-id-report.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/missing-attack-id-profile.txt \
--fail-on none > reports/missing-attack-id-report.txt
$(END)
reports/inconsistent-iri-report.txt: build/d3fend-full.owl
./bin/robot report -i build/d3fend-full.owl \
--profile src/queries/inconsistent-iri-profile.txt \
--fail-on none > reports/inconsistent-iri-report.txt
$(END)
reports/unallowed-thing-report.txt: reportsdir build/d3fend-public.owl
./bin/robot report -i build/d3fend-public.owl \
--profile src/queries/unallowed-thing-profile.txt \
--fail-on ERROR > reports/unallowed-thing-report.txt
$(END)
reports/missing-off-tech-artifacts-report.txt: build/d3fend-public.owl
./bin/robot query --format tsv -i build/d3fend-public.owl --query src/queries/missing-off-tech-artifacts.rq reports/missing-off-tech-artifacts-report.txt
$(END)
builddir:
mkdir -p build
$(END)
# TODO, we may be able to remove this target
build/d3fend-prefixes.json: builddir | robot ## create d3fend-specific prefix file for use with ROBOT
./bin/robot --noprefixes \
--add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" \
--add-prefix "rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#" \
--add-prefix "rdfs: http://www.w3.org/2000/01/rdf-schema#" \
--add-prefix "xsd: http://www.w3.org/2001/XMLSchema#" \
--add-prefix "owl: http://www.w3.org/2002/07/owl#" \
--add-prefix "skos: http://www.w3.org/2004/02/skos/core#" \
--add-prefix "dcterms: http://purl.org/dc/terms/" \
export-prefixes --output build/d3fend-prefixes.json
$(END)
build/d3fend-with-header.owl: src/ontology/d3fend-protege.ttl | robot
./bin/robot annotate --input src/ontology/d3fend-protege.ttl \
--version-iri "http://d3fend.mitre.org/ontologies/d3fend/${D3FEND_VERSION}/d3fend.owl" \
--typed-annotation "http://d3fend.mitre.org/ontologies/d3fend.owl#release-date" ${D3FEND_RELEASE_DATE} xsd:dateTime \
--annotation owl:versionInfo ${D3FEND_VERSION} \
--output build/d3fend-with-header.owl
$(END)
build/d3fend-with-links.owl: build/d3fend-with-header.owl ## converts d3f:has-link xsd:string to xsd:anyURI and fixes WebProtege ontology IRI to d3fend.mitre.org path.
./bin/robot query --input build/d3fend-with-header.owl \
--update src/queries/make-has-links-anyURI.rq \
--output build/d3fend-with-links.owl
$(END)
build/d3fend-trimmed-literals.owl: build/d3fend-with-links.owl
./bin/robot query --input build/d3fend-with-links.owl \
--update src/queries/trimming.rq \
--output build/d3fend-trimmed-literals.owl
$(END)
build/d3fend-res-as-prop.owl: build/d3fend-trimmed-literals.owl ## Extracts and translates just restrictions -> object property assertions
./bin/robot query --input build/d3fend-trimmed-literals.owl \
--query src/queries/restrictions-as-objectproperties.rq build/d3fend-res-as-prop.owl
$(END)
build/d3fend-full.owl: build/d3fend-res-as-prop.owl build/d3fend-trimmed-literals.owl ## Adds in object property assertions for class property restrictions
./bin/robot merge --input build/d3fend-trimmed-literals.owl \
--add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" \
--add-prefix "dcterms: http://purl.org/dc/terms/" \
--input build/d3fend-res-as-prop.owl \
--output build/d3fend-full.owl
$(END)
# NOTE: The hermit reasoner in Protege makes inferences as expected,
# but [in preliminary try] it did not pick up on transitive
# inferences nor modifies-part AFAICT. Deferred until after first
# public release of D3FEND.
#
# TODO When ready, add this back as final pre-public step and rewicker
# filenames to establish build chain dependency/sequencing.
#
# build/d3fend-materialized.owl: build/d3fend-full.owl
# ./bin/robot reason --reasoner hermit \
# --annotate-inferred-axioms true \
# --input build/d3fend-full.owl \
# --output build/d3fend-materialized.owl
# Must come before build/d3fend-public-no-private-annotations.owl because d3f:draft is a private annotation
build/d3fend-public-no-draft-kb-entries.owl: build/d3fend-full.owl
./bin/robot remove --input build/d3fend-full.owl \
--add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" \
--add-prefix "dcterms: http://purl.org/dc/terms/" \
--select "d3f:draft='true'^^xsd:boolean" \
--output build/d3fend-public-no-draft-kb-entries.owl
$(END)
build/d3fend-public-no-private-annotations.owl: build/d3fend-public-no-draft-kb-entries.owl
./bin/robot remove --input build/d3fend-public-no-draft-kb-entries.owl \
--add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" \
--add-prefix "dcterms: http://purl.org/dc/terms/" \
--term d3f:d3fend-private-annotation \
--select "self descendants instances" \
--preserve-structure false \
--output build/d3fend-public-no-private-annotations.owl
$(END)
build/d3fend-public.owl: build/d3fend-public-no-private-annotations.owl
./bin/robot remove --input build/d3fend-public-no-private-annotations.owl \
--add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" \
--add-prefix "dcterms: http://purl.org/dc/terms/" \
--term d3f:AnalysisCitation \
--term d3f:AssertionConfidence \
--term d3f:D3FENDAnalysisThing \
--term d3f:D3FENDAnalysis \
--term d3f:D3FENDAnalyst \
--term d3f:FormFactor \
--term d3f:License \
--term d3f:OSSupport \
--term d3f:Product \
--term d3f:ProductDeveloper \
--term d3f:SupportLevel \
--term d3f:TechniqueAssertion \
--select instances \
--output build/d3fend-public.owl
$(END)
build/d3fend.csv: build/d3fend-public.owl ## make D3FEND csv, not part of build or all targets
./bin/robot query --format csv -i build/d3fend-public.owl --query src/queries/csv_data.rq build/d3fend.csv
pipenv run python src/util/cleancsv.py
build/d3fend-architecture.owl: build/d3fend-full.owl
./bin/robot extract --method MIREOT \
--input build/d3fend-full.owl \
--branch-from-term "http://d3fend.mitre.org/ontologies/d3fend.owl#NetworkNode" \
--branch-from-term "http://d3fend.mitre.org/ontologies/d3fend.owl#Application" \
--output build/d3fend-architecture.owl
$(END)
build/d3fend-public-mapped.owl: build/d3fend-public.owl
./bin/robot merge --include-annotations true --input src/ontology/mappings/d3fend-ontology-mappings.ttl --input build/d3fend-public.owl --output build/d3fend-public-mapped.owl
$(END)
build/d3fend-public-cco.owl: build/d3fend-public.owl
./bin/robot merge --include-annotations true --input src/ontology/mappings/d3fend-cco.ttl --input build/d3fend-public.owl --output build/d3fend-public-cco.owl
$(END)
build/d3fend-public.ttl: build/d3fend-public.owl
./bin/robot convert --add-prefix "d3f: http://d3fend.mitre.org/ontologies/d3fend.owl#" --input build/d3fend-public.owl --output build/d3fend-public.ttl
build/d3fend-inferred-relationships.csv:
./bin/robot query --format csv -i build/d3fend-public.owl --query src/queries/def-to-off-with-prop-asserts-all.rq build/d3fend-inferred-relationships.csv
$(END)
build/cci-to-d3fend-mapping.ttl: build/d3fend-public.owl
pipenv run python extensions/cci/create_cci_mappings.py \
--source "$(CCI_MAPPING_SOURCE)" \
--sheet "$(CCI_MAPPING_SHEET)" \
--output "$(CCI_MAPPING_OUTPUT)" \
--mapping-version "$(CCI_MAPPING_VERSION)"
$(END)
build/sp800-53r5-control-to-d3fend-mapping.ttl: build/d3fend-public.owl
pipenv run python extensions/nist/create_nist_mappings.py \
--source "$(NIST_MAPPING_SOURCE)" \
--sheet "$(NIST_MAPPING_SHEET)" \
--output "$(NIST_MAPPING_OUTPUT)" \
--version "$(NIST_VERSION)" \
--catalog-iri "$(NIST_CATALOG_IRI)"
$(END)
build/extensions: build/d3fend-public.ttl build/cci-to-d3fend-mapping.ttl build/sp800-53r5-control-to-d3fend-mapping.ttl ## build D3FEND Extensions
cat build/d3fend-public.ttl > build/d3fend-public-with-controls.ttl
cat build/sp800-53r5-control-to-d3fend-mapping.ttl >> build/d3fend-public-with-controls.ttl
cat build/cci-to-d3fend-mapping.ttl >> build/d3fend-public-with-controls.ttl
pipenv run ttlfmt build/d3fend-public-with-controls.ttl
./bin/robot convert --input build/d3fend-public-with-controls.ttl --output build/d3fend-public-with-controls.owl
./bin/robot convert --input build/d3fend-public-with-controls.owl --output build/d3fend-public-with-controls.ttl
$(END)
build/ontology: builddir build/d3fend-full.owl build/d3fend-public.owl build/d3fend-public-mapped.owl build/d3fend-public-cco.owl reports/unallowed-thing-report.txt build/d3fend-architecture.owl build/d3fend-prefixes.json build/extensions ## run build and move to public folder, used to create output files, including JSON-LD, since robot doesn't support serializing to JSON-LD
$(END)
build: build/ontology build/d3fend.csv # build the D3FEND Ontology and Extensions
pipenv run python3 src/util/build.py extensions # expects a build/d3fend-public-with-controls.ttl file
$(END)
reportsdir:
mkdir -p reports/
$(END)
reports: robot reportsdir reports/default-robot-report.txt reports/missing-d3fend-definition-report.txt reports/bogus-direct-subclassing-of-tactic-technique-report.txt reports/missing-rdfs-label-report.txt reports/missing-attack-id-report.txt reports/inconsistent-iri-report.txt reports/missing-off-tech-artifacts-report.txt ## Generates all reports for ontology quality checks
$(END)
dashboard: reportsdir download-ocsf download-nist download-cci ## Generate static mapping dashboard artifacts in dist/dashboard
pipenv run python3 src/util/dashboard_report.py \
--ocsf-schema-dir $(OCSF_SCHEMA_DIR) \
--ocsf-schema-prefix $(OCSF_SCHEMA_URL_PREFIX) \
--ocsf-source-version $(OCSF_VERSION) \
--nist-source $(NIST_SOURCE) \
--nist-source-version "$(NIST_SOURCE_VERSION)" \
--nist-iri-version $(NIST_VERSION) \
--nist-item-url-prefix $(NIST_ITEM_URL_PREFIX) \
--cci-source $(CCI_SOURCE) \
--cci-source-version $(CCI_SOURCE_VERSION) \
--cci-mapping-version $(CCI_MAPPING_VERSION) \
--cci-item-url $(CCI_ITEM_URL) \
--attack-version $(ATTACK_VERSION) \
--attack-item-url-prefix $(ATTACK_ITEM_URL_PREFIX) \
--atlas-version $(ATLAS_VERSION) \
--atlas-item-url-prefix $(ATLAS_ITEM_URL_PREFIX) \
--sparta-version $(SPARTA_VERSION) \
--sparta-item-url-prefix $(SPARTA_ITEM_URL_PREFIX) \
--capec-version $(CAPEC_VERSION) \
--capec-item-url-prefix $(CAPEC_ITEM_URL_PREFIX) \
--cwe-version $(CWE_VERSION) \
--cwe-item-url-prefix $(CWE_ITEM_URL_PREFIX)
$(END)
REPORT_FILES = default-robot-report.txt \
missing-d3fend-definition-report.txt \
bogus-direct-subclassing-of-tactic-technique-report.txt \
missing-attack-id-report.txt \
inconsistent-iri-report.txt \
missing-off-tech-artifacts-report.txt
report-summary:
@echo "Error | Warn | Info | Report File" > reports/report-summary.txt
@echo "------|------|------|-------------" >> reports/report-summary.txt
@> reports/temp-summary.txt
@for file in $(REPORT_FILES); do \
error_count=$$(grep -c "ERROR" reports/$$file); \
warn_count=$$(grep -c "WARN" reports/$$file); \
info_count=$$(grep -c "INFO" reports/$$file); \
printf "%5s | %5s | %5s | %-20s\n" "$$error_count" "$$warn_count" "$$info_count" "reports/$$file" >> reports/temp-summary.txt; \
done
@sort -k1,1nr -k2,2nr -k3,3nr reports/temp-summary.txt >> reports/report-summary.txt
@rm reports/temp-summary.txt
# Add logic to list reports not covered by REPORT_FILES
@echo "" >> reports/report-summary.txt
@echo "" >> reports/report-summary.txt
@MISSING_REPORTS=""; \
for file in $$(ls reports/); do \
if [ "$$file" != "report-summary.txt" ]; then \
if ! echo "$(REPORT_FILES)" | grep -w "$$file" > /dev/null; then \
MISSING_REPORTS="$$MISSING_REPORTS reports/$$file"; \
fi; \
fi; \
done; \
if [ -n "$$MISSING_REPORTS" ]; then \
echo "Reports not included in the summary:" >> reports/report-summary.txt; \
for file in $$MISSING_REPORTS; do \
echo "$$file" >> reports/report-summary.txt; \
done; \
fi
distdir:
mkdir -p dist/public dist/private
$(END)
test-load-owl: reportsdir build/d3fend-public.owl ## Used to check d3fend.owl file as parseable and useable for DL profile.
./bin/robot validate-profile --profile DL --input build/d3fend-public-with-controls.owl --output reports/test-owl-validation.txt > reports/test-owl-validation-stdout.txt
$(END)
test-load-ttl: reportsdir build/d3fend-public.ttl ## Used to check d3fend.ttl file as parseable and useable for DL profile.
./bin/robot validate-profile --profile DL --input build/d3fend-public-with-controls.ttl --output reports/test-ttl-validation.txt > reports/test-ttl-validation-stdout.txt
$(END)
test-load-json: reportsdir ## Used to check d3fend.json (JSON-LD) file as parseable and useable for DL profile.
# ./bin/robot validate-profile --profile DL --input d3fend.json --output reports/json-validation.txt # JSON-LD serialized by RDFlib not read by ROBOT or Protege
@set -e; previous=$$(mktemp); trap 'rm -f "$$previous"' EXIT; \
cp build/d3fend-public-with-controls.json "$$previous"; \
pipenv run python3 src/util/build.py >/dev/null; \
pipenv run python3 -c 'import pathlib, sys; sys.exit(pathlib.Path(sys.argv[1]).read_bytes() != pathlib.Path(sys.argv[2]).read_bytes())' "$$previous" build/d3fend-public-with-controls.json
@pipenv run python3 -c 'from src.util.build import normalize_jsonld; value = {"@list": ["z", "a"]}; assert normalize_jsonld(value) == value'
@pipenv run python3 src/tests/test_load_json.py build/d3fend-public-with-controls.json > reports/test-load-json.txt
@JAVA="$(JAVA)" ${JENA_PATH}/rdfcompare build/d3fend-public-with-controls.owl build/d3fend-public-with-controls.ttl RDFXML TURTLE | grep -q "models are equal"
@JAVA="$(JAVA)" ${JENA_PATH}/rdfcompare build/d3fend-public-with-controls.ttl build/d3fend-public-with-controls.json TURTLE JSON-LD | grep -q "models are equal"
$(END)
test-load-full: reportsdir ## Used to check d3fend-full.owl as parseable and useable for DL profile.
./bin/robot validate-profile --profile DL --input build/d3fend-full.owl --output reports/test-owl-validation.txt > reports/test-owl-validation-stdout.txt
$(END)
test-jena: reportsdir ## Used to check d3fend-full.owl as parseable and useable for jena libraries
@JAVA="$(JAVA)" ${JENA_PATH}/riot --validate build/d3fend-public-with-controls.owl > reports/test-owl-jena-validation.txt
$(END)
test-reasoner:
./bin/robot reason --reasoner ELK --input build/d3fend-public-with-controls.ttl -D reports/test-reasoner-results.ttl
test: robot test-load-owl test-load-ttl test-load-json test-load-full test-jena test-reasoner ## Checks all ontology build files as parseable and DL-compatible.
$(END)
dist: distdir
cp build/d3fend-full.owl dist/private/d3fend-full.owl
cp build/d3fend-public-mapped.owl dist/public/d3fend-mapped.owl
cp build/d3fend-public-with-controls.ttl dist/public/d3fend.ttl # For now, roll in the CCI & NIST controls extensions to base .ttl release
# TODO: Sadly some ontology tooling, possibly owlapi or robot, changing input files, thus we add a step here
pipenv run ttlfmt dist/public/d3fend.ttl
cp build/d3fend-public-with-controls.owl dist/public/d3fend.owl # For now, roll in the CCI & NIST controls extensions to base .owl release
cp build/d3fend-public-with-controls.json dist/public/d3fend.json
@cp build/d3fend.csv dist/public/d3fend.csv || echo "${RED}WARNING: build/d3fend.csv not found to include in dist. Manually run: ${YELLOW} make build/d3fend.csv ${RESET} ${RESET}"
cp build/d3fend-architecture.owl dist/public/d3fend-architecture.owl
cp build/d3fend-public-cco.owl dist/public/d3fend-cco.owl
chmod 644 dist/public/d3fend.ttl dist/public/d3fend.owl
$(END)
#all: build build/d3fend.csv extensions dist test ## build all, check for unallowed content, and test load files
all: build extensions test dist ## build all, check for unallowed content, and test load files
$(END)
print-new-techniques: build/d3fend.csv ## compare local build against current public version
diff -y -W 500 build/d3fend.csv <(curl -s https://d3fend.mitre.org/ontologies/d3fend.csv) | grep \< | sed "s/\<//g"
$(END)
help: ##print out this message
@grep -E '^[^@]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
format: ## Format ttl to canonical, stable format for effective diffing (accomplished before any commits)
pipenv run ttlfmt src/ontology/d3fend-protege.ttl
# requires `make install-python-deps`
pre-commit-install:
pipenv run pre-commit install
pre-commit:
pipenv run pre-commit run --all-files
.PHONY: all help clean build dist test robot
.DEFAULT_GOAL := help