audnet 0.1.2__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.
- audnet-0.1.2/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
- audnet-0.1.2/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- audnet-0.1.2/.github/PULL_REQUEST_TEMPLATE.md +24 -0
- audnet-0.1.2/.github/labeler.yml +72 -0
- audnet-0.1.2/.github/workflows/auto-close-issues.yml +43 -0
- audnet-0.1.2/.github/workflows/ci.yml +101 -0
- audnet-0.1.2/.github/workflows/issue-labeler.yml +74 -0
- audnet-0.1.2/.github/workflows/labeler.yml +21 -0
- audnet-0.1.2/.github/workflows/publish.yml +68 -0
- audnet-0.1.2/.github/workflows/size-label.yml +26 -0
- audnet-0.1.2/.gitignore +27 -0
- audnet-0.1.2/.pre-commit-config.yaml +36 -0
- audnet-0.1.2/CHANGELOG.md +86 -0
- audnet-0.1.2/CONTRIBUTING.md +122 -0
- audnet-0.1.2/LICENSE +21 -0
- audnet-0.1.2/PKG-INFO +826 -0
- audnet-0.1.2/README.md +790 -0
- audnet-0.1.2/SECURITY.md +121 -0
- audnet-0.1.2/benchmarks/bench_collectors.py +176 -0
- audnet-0.1.2/pyproject.toml +107 -0
- audnet-0.1.2/src/audnet/__init__.py +8 -0
- audnet-0.1.2/src/audnet/cli.py +222 -0
- audnet-0.1.2/src/audnet/collector.py +180 -0
- audnet-0.1.2/src/audnet/collector_async.py +199 -0
- audnet-0.1.2/src/audnet/compliance.py +250 -0
- audnet-0.1.2/src/audnet/config.py +113 -0
- audnet-0.1.2/src/audnet/exceptions.py +25 -0
- audnet-0.1.2/src/audnet/models.py +105 -0
- audnet-0.1.2/src/audnet/parser.py +67 -0
- audnet-0.1.2/src/audnet/reporter.py +61 -0
- audnet-0.1.2/src/audnet/templates/__init__.py +0 -0
- audnet-0.1.2/src/audnet/textfsm_templates/__init__.py +0 -0
- audnet-0.1.2/src/audnet/textfsm_templates/cisco_ios_show_cdp_neighbors_detail.textfsm +12 -0
- audnet-0.1.2/src/audnet/textfsm_templates/cisco_ios_show_interface_status.textfsm +10 -0
- audnet-0.1.2/src/audnet/textfsm_templates/cisco_ios_show_ip_interface_brief.textfsm +10 -0
- audnet-0.1.2/src/audnet/textfsm_templates/cisco_ios_show_running_config.textfsm +4 -0
- audnet-0.1.2/src/audnet/textfsm_templates/cisco_ios_show_version.textfsm +9 -0
- audnet-0.1.2/src/audnet/vendor_registry.py +165 -0
- audnet-0.1.2/tests/__init__.py +1 -0
- audnet-0.1.2/tests/conftest.py +34 -0
- audnet-0.1.2/tests/test_cli.py +973 -0
- audnet-0.1.2/tests/test_collector.py +709 -0
- audnet-0.1.2/tests/test_collector_async.py +206 -0
- audnet-0.1.2/tests/test_compliance.py +847 -0
- audnet-0.1.2/tests/test_config.py +250 -0
- audnet-0.1.2/tests/test_exceptions.py +39 -0
- audnet-0.1.2/tests/test_integration.py +259 -0
- audnet-0.1.2/tests/test_logging.py +105 -0
- audnet-0.1.2/tests/test_models.py +160 -0
- audnet-0.1.2/tests/test_parser.py +181 -0
- audnet-0.1.2/tests/test_reporter.py +102 -0
- audnet-0.1.2/tests/test_vendor_registry.py +153 -0
- audnet-0.1.2/tests/test_version.py +11 -0
- audnet-0.1.2/uv.lock +1579 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Describe the bug**
|
|
8
|
+
A clear and concise description of what the bug is.
|
|
9
|
+
|
|
10
|
+
**To Reproduce**
|
|
11
|
+
Steps to reproduce the behavior:
|
|
12
|
+
1. Run `audnet ...`
|
|
13
|
+
2. ...
|
|
14
|
+
3. See error
|
|
15
|
+
|
|
16
|
+
**Expected behavior**
|
|
17
|
+
A clear and concise description of what you expected to happen.
|
|
18
|
+
|
|
19
|
+
**Screenshots**
|
|
20
|
+
If applicable, add screenshots.
|
|
21
|
+
|
|
22
|
+
**Environment:**
|
|
23
|
+
- OS: [e.g. Ubuntu 24.04]
|
|
24
|
+
- Python: [e.g. 3.12]
|
|
25
|
+
- audnet: [e.g. v0.1.0]
|
|
26
|
+
|
|
27
|
+
**Additional context**
|
|
28
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Is your feature request related to a problem? Please describe.**
|
|
8
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
9
|
+
|
|
10
|
+
**Describe the solution you'd like**
|
|
11
|
+
A clear and concise description of what you want to happen.
|
|
12
|
+
|
|
13
|
+
**Describe alternatives you've considered**
|
|
14
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
15
|
+
|
|
16
|
+
**Additional context**
|
|
17
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? -->
|
|
4
|
+
|
|
5
|
+
## Related Issues
|
|
6
|
+
|
|
7
|
+
<!-- Link issues that this PR closes. Use one of: -->
|
|
8
|
+
<!-- Closes #123, Fixes #456, Resolves #789 -->
|
|
9
|
+
|
|
10
|
+
## Type of Change
|
|
11
|
+
|
|
12
|
+
- [ ] Bug fix (non-breaking change that fixes an issue)
|
|
13
|
+
- [ ] New feature (non-breaking change that adds functionality)
|
|
14
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
|
15
|
+
- [ ] Documentation update
|
|
16
|
+
- [ ] CI / tooling
|
|
17
|
+
|
|
18
|
+
## Checklist
|
|
19
|
+
|
|
20
|
+
- [ ] Tests added or updated
|
|
21
|
+
- [ ] Lint + type checks pass (`ruff check src/ tests/`, `mypy src/`)
|
|
22
|
+
- [ ] Full test suite passes
|
|
23
|
+
- [ ] CHANGELOG.md updated if applicable
|
|
24
|
+
- [ ] README.md updated if applicable
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Auto-label configuration for PRs based on changed paths
|
|
2
|
+
# Format for actions/labeler@v5
|
|
3
|
+
|
|
4
|
+
enhancement:
|
|
5
|
+
- changed-files:
|
|
6
|
+
- any-glob-to-any-file:
|
|
7
|
+
- src/**/*
|
|
8
|
+
- '!src/**/.github/**/*'
|
|
9
|
+
|
|
10
|
+
bug:
|
|
11
|
+
- changed-files:
|
|
12
|
+
- any-glob-to-any-file:
|
|
13
|
+
- src/**/*
|
|
14
|
+
- '!src/**/.github/**/*'
|
|
15
|
+
- '**/fix*'
|
|
16
|
+
- '**/bug*'
|
|
17
|
+
|
|
18
|
+
chore:
|
|
19
|
+
- changed-files:
|
|
20
|
+
- any-glob-to-any-file:
|
|
21
|
+
- .github/**/*
|
|
22
|
+
- '*.lock'
|
|
23
|
+
- uv.lock
|
|
24
|
+
|
|
25
|
+
documentation:
|
|
26
|
+
- changed-files:
|
|
27
|
+
- any-glob-to-any-file:
|
|
28
|
+
- '**/*.md'
|
|
29
|
+
- docs/**/*
|
|
30
|
+
- .github/ISSUE_TEMPLATE/**/*
|
|
31
|
+
|
|
32
|
+
security:
|
|
33
|
+
- changed-files:
|
|
34
|
+
- any-glob-to-any-file:
|
|
35
|
+
- src/audnet/reporter.py
|
|
36
|
+
- src/audnet/collector.py
|
|
37
|
+
- pyproject.toml
|
|
38
|
+
|
|
39
|
+
collector:
|
|
40
|
+
- changed-files:
|
|
41
|
+
- any-glob-to-any-file:
|
|
42
|
+
- src/audnet/collector.py
|
|
43
|
+
|
|
44
|
+
cli:
|
|
45
|
+
- changed-files:
|
|
46
|
+
- any-glob-to-any-file:
|
|
47
|
+
- src/audnet/cli.py
|
|
48
|
+
|
|
49
|
+
compliance:
|
|
50
|
+
- changed-files:
|
|
51
|
+
- any-glob-to-any-file:
|
|
52
|
+
- src/audnet/compliance.py
|
|
53
|
+
|
|
54
|
+
parser:
|
|
55
|
+
- changed-files:
|
|
56
|
+
- any-glob-to-any-file:
|
|
57
|
+
- src/audnet/parser.py
|
|
58
|
+
|
|
59
|
+
models:
|
|
60
|
+
- changed-files:
|
|
61
|
+
- any-glob-to-any-file:
|
|
62
|
+
- src/audnet/models.py
|
|
63
|
+
|
|
64
|
+
config:
|
|
65
|
+
- changed-files:
|
|
66
|
+
- any-glob-to-any-file:
|
|
67
|
+
- src/audnet/config.py
|
|
68
|
+
|
|
69
|
+
tests:
|
|
70
|
+
- changed-files:
|
|
71
|
+
- any-glob-to-any-file:
|
|
72
|
+
- tests/**/*
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Auto Close Issues
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [closed]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
close-linked-issues:
|
|
9
|
+
if: github.event.pull_request.merged == true
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
issues: write
|
|
13
|
+
pull-requests: read
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/github-script@v7
|
|
16
|
+
with:
|
|
17
|
+
script: |
|
|
18
|
+
const pr = context.payload.pull_request;
|
|
19
|
+
const body = pr.body || '';
|
|
20
|
+
|
|
21
|
+
const issueRegex = /(?:close[sd]?|fix(?:es|ed)?|resolve[sd]?)\s+#(\d+)/gi;
|
|
22
|
+
const matches = [...body.matchAll(issueRegex)];
|
|
23
|
+
|
|
24
|
+
if (matches.length === 0) {
|
|
25
|
+
console.log('No linked issues found in PR body.');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const match of matches) {
|
|
30
|
+
const issueNumber = parseInt(match[1]);
|
|
31
|
+
try {
|
|
32
|
+
await github.rest.issues.update({
|
|
33
|
+
owner: context.repo.owner,
|
|
34
|
+
repo: context.repo.repo,
|
|
35
|
+
issue_number: issueNumber,
|
|
36
|
+
state: 'closed',
|
|
37
|
+
state_reason: 'completed'
|
|
38
|
+
});
|
|
39
|
+
console.log(`Closed issue #${issueNumber}`);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.log(`Could not close #${issueNumber}: ${e.message}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master, main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.14"
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
version: "latest"
|
|
28
|
+
|
|
29
|
+
- name: Create venv and install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
uv venv
|
|
32
|
+
uv pip install -e ".[dev]"
|
|
33
|
+
|
|
34
|
+
- name: Lint with ruff
|
|
35
|
+
run: uv run ruff check src/ tests/
|
|
36
|
+
|
|
37
|
+
- name: Type check with mypy
|
|
38
|
+
run: uv run mypy src/
|
|
39
|
+
|
|
40
|
+
security:
|
|
41
|
+
needs: lint
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- name: Set up Python
|
|
47
|
+
uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: "3.14"
|
|
50
|
+
|
|
51
|
+
- name: Install uv
|
|
52
|
+
uses: astral-sh/setup-uv@v5
|
|
53
|
+
with:
|
|
54
|
+
version: "latest"
|
|
55
|
+
|
|
56
|
+
- name: Create venv and install dependencies
|
|
57
|
+
run: |
|
|
58
|
+
uv venv
|
|
59
|
+
uv pip install -e ".[dev]"
|
|
60
|
+
|
|
61
|
+
- name: Run Bandit security scan
|
|
62
|
+
run: uv run bandit -r src/ -c pyproject.toml
|
|
63
|
+
|
|
64
|
+
- name: Run pip-audit dependency check
|
|
65
|
+
uses: nick-fields/retry@v3
|
|
66
|
+
with:
|
|
67
|
+
timeout_minutes: 5
|
|
68
|
+
max_attempts: 3
|
|
69
|
+
retry_wait_seconds: 30
|
|
70
|
+
command: uv run pip-audit --ignore-vuln CVE-2026-44405 --ignore-vuln PYSEC-2026-196
|
|
71
|
+
|
|
72
|
+
test:
|
|
73
|
+
needs: security
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
strategy:
|
|
76
|
+
matrix:
|
|
77
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
78
|
+
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
|
|
82
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
83
|
+
uses: actions/setup-python@v5
|
|
84
|
+
with:
|
|
85
|
+
python-version: ${{ matrix.python-version }}
|
|
86
|
+
|
|
87
|
+
- name: Install uv
|
|
88
|
+
uses: astral-sh/setup-uv@v5
|
|
89
|
+
with:
|
|
90
|
+
version: "latest"
|
|
91
|
+
|
|
92
|
+
- name: Create venv and install dependencies
|
|
93
|
+
run: |
|
|
94
|
+
uv venv
|
|
95
|
+
uv pip install -e ".[dev]"
|
|
96
|
+
|
|
97
|
+
- name: Run tests
|
|
98
|
+
run: uv run pytest tests/ -v --tb=short
|
|
99
|
+
|
|
100
|
+
- name: Coverage report
|
|
101
|
+
run: uv run pytest tests/ --cov=audnet --cov-report=term-missing --cov-fail-under=90
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Auto Label Issues
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issues:
|
|
5
|
+
types: [opened, edited]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
label:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
issues: write
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/github-script@v7
|
|
14
|
+
with:
|
|
15
|
+
script: |
|
|
16
|
+
const issue = context.payload.issue;
|
|
17
|
+
const title = issue.title.toLowerCase();
|
|
18
|
+
const body = (issue.body || '').toLowerCase();
|
|
19
|
+
let labelsToAdd = [];
|
|
20
|
+
|
|
21
|
+
// Keyword-based labeling (production pattern)
|
|
22
|
+
if (title.includes('fix') || title.includes('bug') || body.includes('bug')) {
|
|
23
|
+
labelsToAdd.push('bug');
|
|
24
|
+
}
|
|
25
|
+
if (title.includes('feat') || title.includes('enhance') || body.includes('feature')) {
|
|
26
|
+
labelsToAdd.push('enhancement');
|
|
27
|
+
}
|
|
28
|
+
if (title.includes('docs') || title.includes('documentation') || body.includes('readme')) {
|
|
29
|
+
labelsToAdd.push('documentation');
|
|
30
|
+
}
|
|
31
|
+
if (title.includes('security') || body.includes('secret') || body.includes('password')) {
|
|
32
|
+
labelsToAdd.push('security');
|
|
33
|
+
}
|
|
34
|
+
if (title.includes('performance') || title.includes('slow')) {
|
|
35
|
+
labelsToAdd.push('performance');
|
|
36
|
+
}
|
|
37
|
+
if (title.includes('refactor') || title.includes('clean')) {
|
|
38
|
+
labelsToAdd.push('refactor');
|
|
39
|
+
}
|
|
40
|
+
if (title.includes('chore') || title.includes('ci') || title.includes('test')) {
|
|
41
|
+
labelsToAdd.push('chore');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Remove duplicates
|
|
45
|
+
labelsToAdd = [...new Set(labelsToAdd)];
|
|
46
|
+
|
|
47
|
+
if (labelsToAdd.length > 0) {
|
|
48
|
+
// Ensure each label exists (create if missing) - robust production fix
|
|
49
|
+
for (const label of labelsToAdd) {
|
|
50
|
+
try {
|
|
51
|
+
await github.rest.issues.getLabel({
|
|
52
|
+
owner: context.repo.owner,
|
|
53
|
+
repo: context.repo.repo,
|
|
54
|
+
name: label
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error.status === 404) {
|
|
58
|
+
await github.rest.issues.createLabel({
|
|
59
|
+
owner: context.repo.owner,
|
|
60
|
+
repo: context.repo.repo,
|
|
61
|
+
name: label,
|
|
62
|
+
color: '0366d6' // GitHub blue
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await github.rest.issues.addLabels({
|
|
69
|
+
owner: context.repo.owner,
|
|
70
|
+
repo: context.repo.repo,
|
|
71
|
+
issue_number: issue.number,
|
|
72
|
+
labels: labelsToAdd
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Auto Labeler
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
label:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pull-requests: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Label PR based on changed files
|
|
17
|
+
uses: actions/labeler@v5
|
|
18
|
+
with:
|
|
19
|
+
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
20
|
+
configuration-path: .github/labeler.yml
|
|
21
|
+
sync-labels: true
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ['v*']
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write # needed for creating GitHub Releases
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build-and-publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment:
|
|
14
|
+
name: pypi
|
|
15
|
+
url: https://pypi.org/p/audnet
|
|
16
|
+
permissions:
|
|
17
|
+
id-token: write # required for PyPI Trusted Publishing (OIDC)
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0 # required for hatch-vcs to determine version from tags
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.14"
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v5
|
|
31
|
+
with:
|
|
32
|
+
version: "latest"
|
|
33
|
+
|
|
34
|
+
- name: Build wheel and sdist
|
|
35
|
+
run: uv build
|
|
36
|
+
|
|
37
|
+
- name: Publish to PyPI
|
|
38
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
39
|
+
|
|
40
|
+
- name: Extract changelog section for this version
|
|
41
|
+
id: changelog
|
|
42
|
+
run: |
|
|
43
|
+
VERSION="${GITHUB_REF_NAME#v}"
|
|
44
|
+
# Extract the section for this version from CHANGELOG.md
|
|
45
|
+
NOTES=$(python3 -c "
|
|
46
|
+
import re, sys
|
|
47
|
+
version = '${VERSION}'
|
|
48
|
+
with open('CHANGELOG.md') as f:
|
|
49
|
+
content = f.read()
|
|
50
|
+
# Find the section for this version
|
|
51
|
+
pattern = rf'## \[{re.escape(version)}\].*?(?=\n## \[|\Z)'
|
|
52
|
+
match = re.search(pattern, content, re.DOTALL)
|
|
53
|
+
if match:
|
|
54
|
+
print(match.group(0).strip())
|
|
55
|
+
else:
|
|
56
|
+
print(f'Version {version} release.')
|
|
57
|
+
")
|
|
58
|
+
echo "notes<<EOF" >> "$GITHUB_OUTPUT"
|
|
59
|
+
echo "$NOTES" >> "$GITHUB_OUTPUT"
|
|
60
|
+
echo "EOF" >> "$GITHUB_OUTPUT"
|
|
61
|
+
|
|
62
|
+
- name: Create GitHub Release
|
|
63
|
+
uses: softprops/action-gh-release@v2
|
|
64
|
+
with:
|
|
65
|
+
body: ${{ steps.changelog.outputs.notes }}
|
|
66
|
+
files: dist/*
|
|
67
|
+
draft: false
|
|
68
|
+
prerelease: false
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Size Label
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
size-label:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pull-requests: write
|
|
13
|
+
issues: write
|
|
14
|
+
steps:
|
|
15
|
+
- uses: pascalgn/size-label-action@v0.5.5
|
|
16
|
+
env:
|
|
17
|
+
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
|
18
|
+
with:
|
|
19
|
+
sizes: >
|
|
20
|
+
{
|
|
21
|
+
"size/XS": 0,
|
|
22
|
+
"size/S": 10,
|
|
23
|
+
"size/M": 50,
|
|
24
|
+
"size/L": 200,
|
|
25
|
+
"size/XL": 500
|
|
26
|
+
}
|
audnet-0.1.2/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
|
|
14
|
+
# Testing
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# Generated reports (created by running audnet)
|
|
20
|
+
audit_report.*
|
|
21
|
+
|
|
22
|
+
# User data — never commit real device inventories or baselines with credentials
|
|
23
|
+
inventories/
|
|
24
|
+
baselines/
|
|
25
|
+
|
|
26
|
+
# Agent working files
|
|
27
|
+
.hermes/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-added-large-files
|
|
10
|
+
args: ['--maxkb=500']
|
|
11
|
+
- id: debug-statements
|
|
12
|
+
- id: mixed-line-ending
|
|
13
|
+
|
|
14
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
|
+
rev: v0.11.7
|
|
16
|
+
hooks:
|
|
17
|
+
- id: ruff
|
|
18
|
+
args: [--fix]
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
22
|
+
rev: v1.15.0
|
|
23
|
+
hooks:
|
|
24
|
+
- id: mypy
|
|
25
|
+
pass_filenames: false
|
|
26
|
+
args: [src/]
|
|
27
|
+
additional_dependencies:
|
|
28
|
+
- netmiko>=4.3.0
|
|
29
|
+
- textfsm>=1.1.0
|
|
30
|
+
- jinja2>=3.1.0
|
|
31
|
+
- pyyaml>=6.0
|
|
32
|
+
- pydantic>=2.0
|
|
33
|
+
- typer>=0.12.0
|
|
34
|
+
- rich>=13.0
|
|
35
|
+
- structlog>=24.0
|
|
36
|
+
- tenacity>=8.5.0
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-06-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release: network security & compliance auditor with SSH-based device collection
|
|
13
|
+
- Parallel SSH collector (`collector.py`) using Netmiko + ThreadPoolExecutor with configurable concurrency
|
|
14
|
+
- Async collector prototype (`collector_async.py`) using asyncio + asyncssh for large-scale performance
|
|
15
|
+
- TextFSM parser with vendor-aware template selection for structured CLI output
|
|
16
|
+
- Pattern-based compliance engine with 4 security rules (SSH, NTP, syslog, interface) and per-vendor overrides
|
|
17
|
+
- Vendor registry/dispatch pattern (`VendorProfile`, `register_vendor()`) for multi-vendor support
|
|
18
|
+
- Jinja2 report generator producing Markdown and HTML audit reports
|
|
19
|
+
- Typer CLI with `--device`, `--check`, `--json`, `--dry-run`, `--strict`, `--verbose`, `--version` flags
|
|
20
|
+
- YAML inventory loader with environment variable resolution for credential management
|
|
21
|
+
- Pydantic models for baseline schema validation
|
|
22
|
+
- Structured exception hierarchy with retry logic for transient SSH failures
|
|
23
|
+
- SSH key-based authentication support
|
|
24
|
+
- `structlog` with secret redaction for safe logging
|
|
25
|
+
- Plaintext password detection with `--strict` mode for CI/CD pipelines
|
|
26
|
+
- Pre-commit hooks: ruff, mypy strict, bandit, and formatting checks
|
|
27
|
+
- GitHub Actions CI: lint, security scan (bandit + pip-audit), and multi-version testing (3.12/3.13/3.14)
|
|
28
|
+
- GitHub Actions auto-close workflow for linked issues on PR merge
|
|
29
|
+
- Comprehensive test suite: 208 tests, 98.61% coverage
|
|
30
|
+
- Sample device inventory and security baseline configuration
|
|
31
|
+
- Documentation: README with usage examples, SECURITY.md, CONTRIBUTING.md, CHANGELOG.md
|
|
32
|
+
|
|
33
|
+
### Security
|
|
34
|
+
|
|
35
|
+
- Passwords stored as `SecretStr` (Pydantic), never rendered in logs or output
|
|
36
|
+
- Structlog processor redacts sensitive keys (`password`, `key_file`, `secret`, `passwd`, `token`)
|
|
37
|
+
- `--strict` mode enforces env-var-only passwords in CI/CD pipelines
|
|
38
|
+
|
|
39
|
+
## [0.1.2] - 2026-06-12
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- Renamed package from `net-audit` / `net_audit` to `audnet` everywhere: Python package, CLI entry point, PyPI project name, env vars (`AUDNET_PASSWORD`), docs, badges (#108, #109)
|
|
44
|
+
- Renamed GitHub repository from `islam666/net-audit` to `islam666/Audnet`
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- CI badge URL updated to match renamed repo
|
|
49
|
+
- Release badge URL updated to match renamed repo
|
|
50
|
+
- Labeler config paths updated from `src/net_audit/` to `src/audnet/`
|
|
51
|
+
- Sample SSH key filename in inventory updated to `audnet_id_ed25519`
|
|
52
|
+
|
|
53
|
+
## [Unreleased]
|
|
54
|
+
|
|
55
|
+
## [0.1.1] - 2026-06-12
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- `--async` flag for asyncio-based collector (asyncssh) — recommended for >20 devices (#88)
|
|
60
|
+
- `--no-fail` flag to exit with code 0 even when compliance checks fail (default: exit code 1 on failures) (#78)
|
|
61
|
+
- Hostname parsing from `show version` output (#73)
|
|
62
|
+
- Serial number parsing from `show version` output (#72)
|
|
63
|
+
- PyPI publish workflow — automated build and publish to PyPI on `v*` tags via Trusted Publishing (OIDC) (#90)
|
|
64
|
+
- PyPI version and Python version badges in README (#90)
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- Strict mode now also checks `secret`, `passwd`, and `token` fields for plaintext passwords (#76)
|
|
69
|
+
- `CheckConfig` model missing `vendor_patterns` field — added with proper validation (#85)
|
|
70
|
+
- SSH host key verification not configurable in async collector (#84)
|
|
71
|
+
- Invalid device entries in inventory no longer abort entire load — skipped with warning (#83)
|
|
72
|
+
- Device order not preserved in `collect_all` results — now maintains insertion order (#82)
|
|
73
|
+
- Missing vendor TextFSM templates silently returned empty results — now raises `ParseError` (#81)
|
|
74
|
+
- `connect_timeout` passed as string instead of int in async collector (#79)
|
|
75
|
+
- Report templates not lazy-loaded — now loaded on demand with proper error handling (#77)
|
|
76
|
+
- Extra TextFSM fields in `ParsedVersion` caused validation errors — now ignored (#75)
|
|
77
|
+
- Baseline `check_name` not propagated to `ComplianceResult` — now correctly set (#74)
|
|
78
|
+
- `_check_no_open_ports` backward walk logic replaced with forward-scan interface tracking for correctness (#87)
|
|
79
|
+
- Magic slot indices in parser replaced with `Slot` enum for type safety (#86)
|
|
80
|
+
|
|
81
|
+
### Documentation
|
|
82
|
+
|
|
83
|
+
- Added quick-install section to README (#53)
|
|
84
|
+
- Added quick start guide (#80)
|
|
85
|
+
- Added GitHub Release badge to README (#51)
|
|
86
|
+
- Updated CONTRIBUTING.md release process to reflect automated PyPI publish (#90)
|