attackmap-analyzer-omeka-s 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- attackmap_analyzer_omeka_s-0.2.0/LICENSE +21 -0
- attackmap_analyzer_omeka_s-0.2.0/PKG-INFO +106 -0
- attackmap_analyzer_omeka_s-0.2.0/README.md +67 -0
- attackmap_analyzer_omeka_s-0.2.0/pyproject.toml +74 -0
- attackmap_analyzer_omeka_s-0.2.0/setup.cfg +4 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s/__init__.py +3 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s/acl.py +468 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s/analyzer.py +637 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s/phparray.py +451 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s/routes.py +627 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/PKG-INFO +106 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/SOURCES.txt +18 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/dependency_links.txt +1 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/entry_points.txt +2 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/requires.txt +9 -0
- attackmap_analyzer_omeka_s-0.2.0/src/attackmap_analyzer_omeka_s.egg-info/top_level.txt +1 -0
- attackmap_analyzer_omeka_s-0.2.0/tests/test_acl_and_api_key.py +578 -0
- attackmap_analyzer_omeka_s-0.2.0/tests/test_omeka_s_analyzer.py +170 -0
- attackmap_analyzer_omeka_s-0.2.0/tests/test_regex_budget.py +48 -0
- attackmap_analyzer_omeka_s-0.2.0/tests/test_signal_conformance.py +81 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matthew Davis and AttackMap Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: attackmap-analyzer-omeka-s
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Application-aware Omeka S analyzer plugin for AttackMap
|
|
5
|
+
Author: AttackMap Contributors
|
|
6
|
+
Author-email: Matthew Davis <mlaify@mlaify.io>
|
|
7
|
+
Maintainer-email: Matthew Davis <mlaify@mlaify.io>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/mlaify/attackmap-analyzer-omeka-s
|
|
10
|
+
Project-URL: Repository, https://github.com/mlaify/attackmap-analyzer-omeka-s
|
|
11
|
+
Project-URL: Issues, https://github.com/mlaify/attackmap-analyzer-omeka-s/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/mlaify/attackmap-analyzer-omeka-s/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: AttackMap core, https://github.com/mlaify/AttackMap
|
|
14
|
+
Keywords: security,static-analysis,appsec,defensive-security,attackmap,attackmap-plugin
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: Intended Audience :: System Administrators
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
+
Classifier: Topic :: Security
|
|
26
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
27
|
+
Classifier: Typing :: Typed
|
|
28
|
+
Requires-Python: >=3.11
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pydantic>=2.7.0
|
|
32
|
+
Provides-Extra: core
|
|
33
|
+
Requires-Dist: attackmap>=0.6.0; extra == "core"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
37
|
+
Requires-Dist: attackmap>=0.6.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# AttackMap Omeka S Analyzer
|
|
41
|
+
|
|
42
|
+
> [!IMPORTANT]
|
|
43
|
+
> **Active development, slow pace.** AttackMap is under active development, but
|
|
44
|
+
> progress may be slow until more contributors or co-maintainers join. Help is
|
|
45
|
+
> very welcome with the core engine, an analyzer, the macOS app, or the docs —
|
|
46
|
+
> see [CONTRIBUTING.md](CONTRIBUTING.md) or open an issue on
|
|
47
|
+
> [mlaify/AttackMap](https://github.com/mlaify/AttackMap/issues) to say hello.
|
|
48
|
+
> Security reports are still welcome at [security@mlaify.io](mailto:security@mlaify.io).
|
|
49
|
+
|
|
50
|
+
`attackmap-analyzer-omeka-s` is an application-aware analyzer module for AttackMap.
|
|
51
|
+
|
|
52
|
+
It focuses on Omeka S and emits structured scan signals for:
|
|
53
|
+
- likely admin, site, and API surfaces
|
|
54
|
+
- routes from Laminas-style module config, walked structurally: `child_routes` joined onto their parent (including a module's `'admin' => ['child_routes' => ...]` stub, joined onto Omeka core's `/admin`), `may_terminate`, Method verbs, Segment optional parts and Regex `spec`s (see [Routes](#routes)); navigation's `'route' => 'admin/my-module'` names a route and is not one
|
|
55
|
+
- per-route access from Omeka's ACL and admin login (see [Route access](#route-access)), recorded on `Route.auth` / `guards` / `guard_evidence`
|
|
56
|
+
- Omeka API key authentication (`key_identity` / `key_credential`) as a `protocol:omeka_api_key` `ProtocolHint`
|
|
57
|
+
- controller hints
|
|
58
|
+
- secret-shaped env var names (`getenv`, `$_ENV`) containing `SECRET`, `TOKEN`, `KEY`, `PASSWORD` or `PASSWD`, matched case-sensitively; `DB_HOST`-style connection settings are not secrets
|
|
59
|
+
- Omeka service usage (for example `Omeka\\Connection`)
|
|
60
|
+
- module extension points such as navigation and service manager factories
|
|
61
|
+
|
|
62
|
+
This module is intentionally heuristic and incremental.
|
|
63
|
+
|
|
64
|
+
## Detection
|
|
65
|
+
|
|
66
|
+
`detect()` looks at markers only and reads at most one small file (`composer.json`):
|
|
67
|
+
|
|
68
|
+
- `application/Module.php` (Omeka S core), `config/module.ini` (a module repo) or `modules/<Name>/config/module.ini`, by existence;
|
|
69
|
+
- `composer.json` named `omeka/omeka-s`, of type `omeka-s-module`, or requiring an `omeka/*` package.
|
|
70
|
+
|
|
71
|
+
A generic Laminas app (`module/` + `config/application.config.php`) is not Omeka S.
|
|
72
|
+
|
|
73
|
+
## Routes
|
|
74
|
+
|
|
75
|
+
Router config is read with a small PHP-array tokenizer (`phparray.py`, `routes.py`, copied from `attackmap-analyzer-php-laminas` so this plugin has no cross-plugin dependency; mlaify/AttackMap#259 tracks extracting shared PHP helpers). `child_routes` are joined, `may_terminate` is honored, Method children set the HTTP method, and Segment optional parts expand to the minimal form plus one more optional group per form (at most 4 paths per route). Laminas merges every module's config, so a module's stub (`'admin' => ['child_routes' => [...]]`, no type or route) joins the route of that name defined elsewhere in the repo, or else Omeka core's `top`, `site`, `admin`, `admin/site`, `admin/site/slug` and `api` routes (with their `__NAMESPACE__`, `__ADMIN__` and `__KEYAUTH__` defaults).
|
|
76
|
+
|
|
77
|
+
## Route access
|
|
78
|
+
|
|
79
|
+
Each route's `auth` is decided from Omeka's own checks:
|
|
80
|
+
|
|
81
|
+
- **`__ADMIN__` routes** (`/admin/...`, including module routes under `admin`) are `required`: `MvcListeners::redirectToLogin` sends anonymous visitors to the login page. Guards: `omeka:admin_login`, plus the ACL role guards below.
|
|
82
|
+
- **The ACL.** `$acl->allow(<roles>, <resources>, <privileges>[, <assertion>])` and `->deny(...)` are read from `Module.php` (`onBootstrap`, `attachListeners` and helpers) and `*AclFactory.php` (Omeka core). Resources are controller names (`'Omeka\Controller\Site\Item'`, `Controller\IndexController::class` resolved through `namespace`/`use`); the route's controller comes from its `controller` default, through `__NAMESPACE__` as Laminas' `ModuleRouteListener` does (`'item-set'` → `…\ItemSet`). The privilege is the action.
|
|
83
|
+
- **Lookup order** follows Laminas' `Acl::isAllowed`: the specific controller before the all-resources level (`null` resource); at each level the role's own rules, then all-roles rules; the privilege before all privileges; the last rule written for a slot wins. A `null`-resource rule is applied, as Laminas' `setRule` does, to every resource registered so far, and Omeka registers every controller before adding rules, so it overwrites earlier rules in the controllers' slots: `deny(null, 'X', 'show'); allow(null, null, 'show')` allows `show` on X. An all-roles, all-privileges deny on the controller continues to the all-resources level, as in Laminas. Two public principals are checked: the visitor (all-roles rules only) and `'guest'` (the Guest module's self-registration role, treated as public; `Acl::ROLE_*` constants resolve to their values, so `Acl::ROLE_GUEST` is `'guest'`). Role inheritance isn't modelled; Omeka adds its roles without parents.
|
|
84
|
+
- `anonymous`: the visitor or a guest is allowed. `guard_evidence` quotes the deciding rule, narrowed to the matched resource, and its location.
|
|
85
|
+
- `required`: both are denied by a rule (`omeka_acl:deny_anonymous`) or by Omeka's default deny. Omeka checks the role on every dispatch (`authorizeUserAgainstController`). Guards: `omeka_acl:requires_role(<role>)` for each role allowed, or `omeka_acl:default_deny`.
|
|
86
|
+
- `unknown`: a conditional rule (assertion) decides, a `:action` route's actions disagree, a rule's role or privilege list couldn't be read (a variable, constant or mixed array; for fixed actions too), or the per-repo budget (50,000 fresh decisions) is spent. An anonymous rule whose resource can't be resolved (`allow(null, $controllers)`), or a zero-argument `allow()` outside `*AclFactory.php`, turns every deny into `unknown`.
|
|
87
|
+
- **Registration.** Omeka adds only the keys of `controllers.invokables`/`factories` as ACL resources, and `authorizeUserAgainstController` lets through a controller that isn't a resource. A route to a controller *alias* is therefore `anonymous` (with that evidence); a route to a controller registered nowhere the analyzer saw is `unknown`.
|
|
88
|
+
- A `:controller` route (`/s/:site-slug/:controller`) is decided over every controller and alias under its `__NAMESPACE__`: `anonymous` or `required` only if all agree. Decisions are memoised per (controller, action) and per (namespace, action), with rules indexed per resource in program order (never expanded per privilege, so the index stays linear in the source).
|
|
89
|
+
- **Install and migration.** AclFactory's zero-argument `allow()` grants everything while Omeka isn't installed or needs a migration, when MvcListeners sends every request to `/install` or `/migrate`. Those controllers are never `required`: `unknown`, with a note.
|
|
90
|
+
- ACL decisions are only made in a repo with Omeka markers or ACL rules.
|
|
91
|
+
- **API key auth.** Routes whose defaults set `'__KEYAUTH__' => true` (Omeka's `/api`) accept `key_identity`/`key_credential` query parameters (`MvcListeners::authenticateApiKey`). Their `guard_evidence` says so, and a `protocol:omeka_api_key` `ProtocolHint` is emitted for the route file and for code that reads the parameters (`getQuery('key_identity')`). API keys are optional: `/api` is `anonymous` at the controller level (`allow(null, 'Omeka\Controller\Api')`), and the API adapters' own ACL decides per resource.
|
|
92
|
+
|
|
93
|
+
## Install
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
uv tool install attackmap --with attackmap-analyzer-omeka-s \
|
|
97
|
+
--index mlaify=https://pkg.mlaify.io/pypi/simple/ --index-strategy first-index
|
|
98
|
+
# or from source:
|
|
99
|
+
pip install git+https://github.com/mlaify/attackmap-analyzer-omeka-s.git
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Usage with AttackMap
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
attackmap analyze /path/to/repo --module omeka-s
|
|
106
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# AttackMap Omeka S Analyzer
|
|
2
|
+
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> **Active development, slow pace.** AttackMap is under active development, but
|
|
5
|
+
> progress may be slow until more contributors or co-maintainers join. Help is
|
|
6
|
+
> very welcome with the core engine, an analyzer, the macOS app, or the docs —
|
|
7
|
+
> see [CONTRIBUTING.md](CONTRIBUTING.md) or open an issue on
|
|
8
|
+
> [mlaify/AttackMap](https://github.com/mlaify/AttackMap/issues) to say hello.
|
|
9
|
+
> Security reports are still welcome at [security@mlaify.io](mailto:security@mlaify.io).
|
|
10
|
+
|
|
11
|
+
`attackmap-analyzer-omeka-s` is an application-aware analyzer module for AttackMap.
|
|
12
|
+
|
|
13
|
+
It focuses on Omeka S and emits structured scan signals for:
|
|
14
|
+
- likely admin, site, and API surfaces
|
|
15
|
+
- routes from Laminas-style module config, walked structurally: `child_routes` joined onto their parent (including a module's `'admin' => ['child_routes' => ...]` stub, joined onto Omeka core's `/admin`), `may_terminate`, Method verbs, Segment optional parts and Regex `spec`s (see [Routes](#routes)); navigation's `'route' => 'admin/my-module'` names a route and is not one
|
|
16
|
+
- per-route access from Omeka's ACL and admin login (see [Route access](#route-access)), recorded on `Route.auth` / `guards` / `guard_evidence`
|
|
17
|
+
- Omeka API key authentication (`key_identity` / `key_credential`) as a `protocol:omeka_api_key` `ProtocolHint`
|
|
18
|
+
- controller hints
|
|
19
|
+
- secret-shaped env var names (`getenv`, `$_ENV`) containing `SECRET`, `TOKEN`, `KEY`, `PASSWORD` or `PASSWD`, matched case-sensitively; `DB_HOST`-style connection settings are not secrets
|
|
20
|
+
- Omeka service usage (for example `Omeka\\Connection`)
|
|
21
|
+
- module extension points such as navigation and service manager factories
|
|
22
|
+
|
|
23
|
+
This module is intentionally heuristic and incremental.
|
|
24
|
+
|
|
25
|
+
## Detection
|
|
26
|
+
|
|
27
|
+
`detect()` looks at markers only and reads at most one small file (`composer.json`):
|
|
28
|
+
|
|
29
|
+
- `application/Module.php` (Omeka S core), `config/module.ini` (a module repo) or `modules/<Name>/config/module.ini`, by existence;
|
|
30
|
+
- `composer.json` named `omeka/omeka-s`, of type `omeka-s-module`, or requiring an `omeka/*` package.
|
|
31
|
+
|
|
32
|
+
A generic Laminas app (`module/` + `config/application.config.php`) is not Omeka S.
|
|
33
|
+
|
|
34
|
+
## Routes
|
|
35
|
+
|
|
36
|
+
Router config is read with a small PHP-array tokenizer (`phparray.py`, `routes.py`, copied from `attackmap-analyzer-php-laminas` so this plugin has no cross-plugin dependency; mlaify/AttackMap#259 tracks extracting shared PHP helpers). `child_routes` are joined, `may_terminate` is honored, Method children set the HTTP method, and Segment optional parts expand to the minimal form plus one more optional group per form (at most 4 paths per route). Laminas merges every module's config, so a module's stub (`'admin' => ['child_routes' => [...]]`, no type or route) joins the route of that name defined elsewhere in the repo, or else Omeka core's `top`, `site`, `admin`, `admin/site`, `admin/site/slug` and `api` routes (with their `__NAMESPACE__`, `__ADMIN__` and `__KEYAUTH__` defaults).
|
|
37
|
+
|
|
38
|
+
## Route access
|
|
39
|
+
|
|
40
|
+
Each route's `auth` is decided from Omeka's own checks:
|
|
41
|
+
|
|
42
|
+
- **`__ADMIN__` routes** (`/admin/...`, including module routes under `admin`) are `required`: `MvcListeners::redirectToLogin` sends anonymous visitors to the login page. Guards: `omeka:admin_login`, plus the ACL role guards below.
|
|
43
|
+
- **The ACL.** `$acl->allow(<roles>, <resources>, <privileges>[, <assertion>])` and `->deny(...)` are read from `Module.php` (`onBootstrap`, `attachListeners` and helpers) and `*AclFactory.php` (Omeka core). Resources are controller names (`'Omeka\Controller\Site\Item'`, `Controller\IndexController::class` resolved through `namespace`/`use`); the route's controller comes from its `controller` default, through `__NAMESPACE__` as Laminas' `ModuleRouteListener` does (`'item-set'` → `…\ItemSet`). The privilege is the action.
|
|
44
|
+
- **Lookup order** follows Laminas' `Acl::isAllowed`: the specific controller before the all-resources level (`null` resource); at each level the role's own rules, then all-roles rules; the privilege before all privileges; the last rule written for a slot wins. A `null`-resource rule is applied, as Laminas' `setRule` does, to every resource registered so far, and Omeka registers every controller before adding rules, so it overwrites earlier rules in the controllers' slots: `deny(null, 'X', 'show'); allow(null, null, 'show')` allows `show` on X. An all-roles, all-privileges deny on the controller continues to the all-resources level, as in Laminas. Two public principals are checked: the visitor (all-roles rules only) and `'guest'` (the Guest module's self-registration role, treated as public; `Acl::ROLE_*` constants resolve to their values, so `Acl::ROLE_GUEST` is `'guest'`). Role inheritance isn't modelled; Omeka adds its roles without parents.
|
|
45
|
+
- `anonymous`: the visitor or a guest is allowed. `guard_evidence` quotes the deciding rule, narrowed to the matched resource, and its location.
|
|
46
|
+
- `required`: both are denied by a rule (`omeka_acl:deny_anonymous`) or by Omeka's default deny. Omeka checks the role on every dispatch (`authorizeUserAgainstController`). Guards: `omeka_acl:requires_role(<role>)` for each role allowed, or `omeka_acl:default_deny`.
|
|
47
|
+
- `unknown`: a conditional rule (assertion) decides, a `:action` route's actions disagree, a rule's role or privilege list couldn't be read (a variable, constant or mixed array; for fixed actions too), or the per-repo budget (50,000 fresh decisions) is spent. An anonymous rule whose resource can't be resolved (`allow(null, $controllers)`), or a zero-argument `allow()` outside `*AclFactory.php`, turns every deny into `unknown`.
|
|
48
|
+
- **Registration.** Omeka adds only the keys of `controllers.invokables`/`factories` as ACL resources, and `authorizeUserAgainstController` lets through a controller that isn't a resource. A route to a controller *alias* is therefore `anonymous` (with that evidence); a route to a controller registered nowhere the analyzer saw is `unknown`.
|
|
49
|
+
- A `:controller` route (`/s/:site-slug/:controller`) is decided over every controller and alias under its `__NAMESPACE__`: `anonymous` or `required` only if all agree. Decisions are memoised per (controller, action) and per (namespace, action), with rules indexed per resource in program order (never expanded per privilege, so the index stays linear in the source).
|
|
50
|
+
- **Install and migration.** AclFactory's zero-argument `allow()` grants everything while Omeka isn't installed or needs a migration, when MvcListeners sends every request to `/install` or `/migrate`. Those controllers are never `required`: `unknown`, with a note.
|
|
51
|
+
- ACL decisions are only made in a repo with Omeka markers or ACL rules.
|
|
52
|
+
- **API key auth.** Routes whose defaults set `'__KEYAUTH__' => true` (Omeka's `/api`) accept `key_identity`/`key_credential` query parameters (`MvcListeners::authenticateApiKey`). Their `guard_evidence` says so, and a `protocol:omeka_api_key` `ProtocolHint` is emitted for the route file and for code that reads the parameters (`getQuery('key_identity')`). API keys are optional: `/api` is `anonymous` at the controller level (`allow(null, 'Omeka\Controller\Api')`), and the API adapters' own ACL decides per resource.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv tool install attackmap --with attackmap-analyzer-omeka-s \
|
|
58
|
+
--index mlaify=https://pkg.mlaify.io/pypi/simple/ --index-strategy first-index
|
|
59
|
+
# or from source:
|
|
60
|
+
pip install git+https://github.com/mlaify/attackmap-analyzer-omeka-s.git
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage with AttackMap
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
attackmap analyze /path/to/repo --module omeka-s
|
|
67
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "attackmap-analyzer-omeka-s"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Application-aware Omeka S analyzer plugin for AttackMap"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "Matthew Davis", email = "mlaify@mlaify.io"},
|
|
15
|
+
{name = "AttackMap Contributors"},
|
|
16
|
+
]
|
|
17
|
+
maintainers = [
|
|
18
|
+
{name = "Matthew Davis", email = "mlaify@mlaify.io"},
|
|
19
|
+
]
|
|
20
|
+
keywords = [
|
|
21
|
+
"security",
|
|
22
|
+
"static-analysis",
|
|
23
|
+
"appsec",
|
|
24
|
+
"defensive-security",
|
|
25
|
+
"attackmap",
|
|
26
|
+
"attackmap-plugin",
|
|
27
|
+
]
|
|
28
|
+
classifiers = [
|
|
29
|
+
"Development Status :: 4 - Beta",
|
|
30
|
+
"Intended Audience :: Developers",
|
|
31
|
+
"Intended Audience :: Information Technology",
|
|
32
|
+
"Intended Audience :: System Administrators",
|
|
33
|
+
"Operating System :: OS Independent",
|
|
34
|
+
"Programming Language :: Python :: 3",
|
|
35
|
+
"Programming Language :: Python :: 3.11",
|
|
36
|
+
"Programming Language :: Python :: 3.12",
|
|
37
|
+
"Programming Language :: Python :: 3.13",
|
|
38
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
39
|
+
"Topic :: Security",
|
|
40
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
41
|
+
"Typing :: Typed",
|
|
42
|
+
]
|
|
43
|
+
dependencies = [
|
|
44
|
+
"pydantic>=2.7.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
core = [
|
|
49
|
+
"attackmap>=0.6.0",
|
|
50
|
+
]
|
|
51
|
+
dev = [
|
|
52
|
+
"pytest>=8.0.0",
|
|
53
|
+
"build>=1.2.0",
|
|
54
|
+
"attackmap>=0.6.0",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[project.urls]
|
|
58
|
+
Homepage = "https://github.com/mlaify/attackmap-analyzer-omeka-s"
|
|
59
|
+
Repository = "https://github.com/mlaify/attackmap-analyzer-omeka-s"
|
|
60
|
+
Issues = "https://github.com/mlaify/attackmap-analyzer-omeka-s/issues"
|
|
61
|
+
Changelog = "https://github.com/mlaify/attackmap-analyzer-omeka-s/blob/main/CHANGELOG.md"
|
|
62
|
+
"AttackMap core" = "https://github.com/mlaify/AttackMap"
|
|
63
|
+
|
|
64
|
+
[project.entry-points."attackmap.analyzers"]
|
|
65
|
+
omeka_s = "attackmap_analyzer_omeka_s:OmekaSAnalyzer"
|
|
66
|
+
|
|
67
|
+
[tool.setuptools]
|
|
68
|
+
package-dir = {"" = "src"}
|
|
69
|
+
|
|
70
|
+
[tool.setuptools.packages.find]
|
|
71
|
+
where = ["src"]
|
|
72
|
+
|
|
73
|
+
[tool.pytest.ini_options]
|
|
74
|
+
testpaths = ["tests"]
|