Compare commits

...

2 Commits

Author SHA1 Message Date
Hare Sudhan 0bb6dd34c3 update 2025-11-28 22:36:47 -05:00
Hare Sudhan 3cb6966dee pre-commit checks 2025-11-26 00:13:06 -05:00
20 changed files with 290 additions and 254 deletions
+9 -9
View File
@@ -5,12 +5,12 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "pip" # See documentation for possible values - package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
schedule: schedule:
interval: "weekly" interval: "weekly"
# Maintain dependencies for GitHub Actions # Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
+48 -47
View File
@@ -2,58 +2,59 @@ name: assign-labels
on: on:
workflow_run: workflow_run:
workflows: ["validate-atomics"] workflows:
- "validate-atomics"
types: types:
- completed - completed
jobs: jobs:
assign-labels: assign-labels:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: download-artifact - name: download-artifact
uses: actions/github-script@v8 uses: actions/github-script@v8
with: with:
script: | script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
run_id: context.payload.workflow_run.id, run_id: context.payload.workflow_run.id,
}); });
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "labels.json" return artifact.name == "labels.json"
})[0]; })[0];
let download = await github.rest.actions.downloadArtifact({ let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
artifact_id: matchArtifact.id, artifact_id: matchArtifact.id,
archive_format: 'zip', archive_format: 'zip',
}); });
let fs = require('fs'); let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/labels.zip`, Buffer.from(download.data)); fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/labels.zip`, Buffer.from(download.data));
- name: unzip-artifact - name: unzip-artifact
run: unzip labels.zip run: unzip labels.zip
- name: assign-labels-and-reviewers - name: assign-labels-and-reviewers
uses: actions/github-script@v8 uses: actions/github-script@v8
with: with:
script: | script: |-
let fs = require('fs'); let fs = require('fs');
const obj = JSON.parse(fs.readFileSync('./labels.json')); const obj = JSON.parse(fs.readFileSync('./labels.json'));
console.log(obj) console.log(obj)
if(obj.labels.length > 0){ if(obj.labels.length > 0){
await github.rest.issues.addLabels({ await github.rest.issues.addLabels({
issue_number: obj.pr, issue_number: obj.pr,
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
labels: obj.labels labels: obj.labels
}) })
} }
if(obj.maintainers.length > 0){ if(obj.maintainers.length > 0){
await github.rest.issues.addAssignees({ await github.rest.issues.addAssignees({
issue_number: obj.pr, issue_number: obj.pr,
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
assignees: obj.maintainers assignees: obj.maintainers
}); });
} }
+55 -54
View File
@@ -1,69 +1,70 @@
name: generate-docs name: generate-docs
on: on:
push: push:
branches: [ "master" ] branches:
- "master"
jobs: jobs:
generate-docs: generate-docs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout repo - name: checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
token: ${{ secrets.PROTECTED_BRANCH_PUSH_TOKEN }} token: ${{ secrets.PROTECTED_BRANCH_PUSH_TOKEN }}
- name: Install poetry - name: Install poetry
run: pipx install poetry run: pipx install poetry
- uses: actions/setup-python@v6 - uses: actions/setup-python@v6
with: with:
python-version: "3.11.2" python-version: "3.11.2"
cache: "poetry" cache: "poetry"
- name: Install dependencies - name: Install dependencies
run: poetry install --no-interaction run: poetry install --no-interaction
- name: Generate shields.io URL - name: Generate shields.io URL
run: poetry run python runner.py generate-counter run: poetry run python runner.py generate-counter
id: counter id: counter
working-directory: atomic_red_team working-directory: atomic_red_team
env: env:
PYTHONPATH: ${{ github.workspace }} PYTHONPATH: ${{ github.workspace }}
- name: Update README - name: Update README
run: | run: |
echo ${{ steps.counter.outputs.result }} echo ${{ steps.counter.outputs.result }}
sed -i "s|https://img.shields.io/badge/Atomics-.*-flat.svg|${{ steps.counter.outputs.result }}|" README.md sed -i "s|https://img.shields.io/badge/Atomics-.*-flat.svg|${{ steps.counter.outputs.result }}|" README.md
shell: bash shell: bash
- name: Generate and commit unique GUIDs for each atomic test - name: Generate and commit unique GUIDs for each atomic test
run: poetry run python runner.py generate-guids run: poetry run python runner.py generate-guids
working-directory: atomic_red_team working-directory: atomic_red_team
env: env:
PYTHONPATH: ${{ github.workspace }} PYTHONPATH: ${{ github.workspace }}
- name: setup ruby - name: setup ruby
uses: ruby/setup-ruby@v1 uses: ruby/setup-ruby@v1
with: with:
ruby-version: 3.0 ruby-version: 3.0
bundler-cache: true bundler-cache: true
- name: generate markdown docs for atomics - name: generate markdown docs for atomics
run: | run: |-
bin/generate-atomic-docs.rb bin/generate-atomic-docs.rb
echo "" echo ""
echo "" echo ""
git status git status
echo "" echo ""
echo "" echo ""
git diff-index HEAD -- git diff-index HEAD --
if git diff-index --quiet HEAD -- ; then if git diff-index --quiet HEAD -- ; then
echo "Not committing documentation because there are no changes" echo "Not committing documentation because there are no changes"
else else
git config credential.helper 'cache --timeout=120' git config credential.helper 'cache --timeout=120'
git config user.email "opensource@redcanary.com" git config user.email "opensource@redcanary.com"
git config user.name "Atomic Red Team doc generator" git config user.name "Atomic Red Team doc generator"
git add README.md git add README.md
git add atomics git add atomics
git commit -am "Generated docs from job=$GITHUB_JOB branch=$GITHUB_REF_NAME [ci skip]" git commit -am "Generated docs from job=$GITHUB_JOB branch=$GITHUB_REF_NAME [ci skip]"
git push origin $GITHUB_REF_NAME -f git push origin $GITHUB_REF_NAME -f
fi fi
+16 -16
View File
@@ -3,27 +3,27 @@ name: validate-python-file-changes
on: on:
pull_request: pull_request:
branches: branches:
- master - master
paths: paths:
- "atomic_red_team/**/*.py" - "atomic_red_team/**/*.py"
jobs: jobs:
validate-python-file-changes: validate-python-file-changes:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: checkout repo - name: checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install poetry - name: Install poetry
run: pipx install poetry run: pipx install poetry
- name: setup python3.11 - name: setup python3.11
uses: actions/setup-python@v6 uses: actions/setup-python@v6
id: setup-python id: setup-python
with: with:
python-version: "3.12.4" python-version: "3.12.4"
cache: "poetry" cache: "poetry"
- name: Install dependencies - name: Install dependencies
run: poetry install --no-interaction run: poetry install --no-interaction
- name: Run pytest - name: Run pytest
run: poetry run pytest atomic_red_team/tests run: poetry run pytest atomic_red_team/tests
+11 -11
View File
@@ -1,19 +1,19 @@
name: 'Close stale issues and PRs' name: 'Close stale issues and PRs'
on: on:
schedule: schedule:
- cron: '30 1 * * *' - cron: '30 1 * * *'
jobs: jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v10 - uses: actions/stale@v10
with: with:
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.' stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.' close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.' close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.'
days-before-issue-stale: 30 days-before-issue-stale: 30
days-before-pr-stale: 45 days-before-pr-stale: 45
days-before-issue-close: 10 days-before-issue-close: 10
days-before-pr-close: 10 days-before-pr-close: 10
+58 -58
View File
@@ -3,73 +3,73 @@ name: validate-atomics
on: on:
pull_request: pull_request:
branches: branches:
- master - master
jobs: jobs:
validate-atomics: validate-atomics:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout repo - name: checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install poetry - name: Install poetry
run: pipx install poetry run: pipx install poetry
- name: setup python3.11 - name: setup python3.11
uses: actions/setup-python@v6 uses: actions/setup-python@v6
id: setup-python id: setup-python
with: with:
python-version: "3.11.2" python-version: "3.11.2"
cache: "poetry" cache: "poetry"
- name: Install dependencies - name: Install dependencies
run: poetry install --no-interaction run: poetry install --no-interaction
- name: validate the format of atomics tests against the spec - name: validate the format of atomics tests against the spec
run: poetry run python runner.py validate run: poetry run python runner.py validate
working-directory: atomic_red_team working-directory: atomic_red_team
env: env:
PYTHONPATH: ${{ github.workspace }} PYTHONPATH: ${{ github.workspace }}
upload: upload:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout repo - name: checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install poetry - name: Install poetry
run: pipx install poetry run: pipx install poetry
- name: setup python3.11 - name: setup python3.11
uses: actions/setup-python@v6 uses: actions/setup-python@v6
id: setup-python id: setup-python
with: with:
python-version: "3.11.2" python-version: "3.11.2"
cache: "poetry" cache: "poetry"
- uses: actions/github-script@v8 - uses: actions/github-script@v8
id: get_pr_number id: get_pr_number
with: with:
script: | script: |
if (context.issue.number) { if (context.issue.number) {
// Return issue number if present // Return issue number if present
return context.issue.number; return context.issue.number;
} else { } else {
// Otherwise return issue number from commit // Otherwise return issue number from commit
return ( return (
await github.rest.repos.listPullRequestsAssociatedWithCommit({ await github.rest.repos.listPullRequestsAssociatedWithCommit({
commit_sha: context.sha, commit_sha: context.sha,
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
}) })
).data[0].number; ).data[0].number;
} }
result-encoding: string result-encoding: string
- name: Install dependencies - name: Install dependencies
run: poetry install --no-interaction --no-root run: poetry install --no-interaction --no-root
- name: save labels and reviewers into a file. - name: save labels and reviewers into a file.
run: | run: |
poetry run python runner.py generate-labels --pr '${{steps.get_pr_number.outputs.result}}' --token ${{ secrets.GITHUB_TOKEN }} poetry run python runner.py generate-labels --pr '${{steps.get_pr_number.outputs.result}}' --token ${{ secrets.GITHUB_TOKEN }}
working-directory: atomic_red_team working-directory: atomic_red_team
env: env:
PYTHONPATH: ${{ github.workspace }} PYTHONPATH: ${{ github.workspace }}
- uses: actions/upload-artifact@v5 - uses: actions/upload-artifact@v5
with: with:
name: labels.json name: labels.json
path: atomic_red_team/pr/ path: atomic_red_team/pr/
+8 -8
View File
@@ -3,18 +3,18 @@ name: validate-terraform
on: on:
pull_request: pull_request:
branches: branches:
- master - master
paths: paths:
- "**/*.tf" - "**/*.tf"
jobs: jobs:
validate-terraform: validate-terraform:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- uses: hashicorp/setup-terraform@v3 - uses: hashicorp/setup-terraform@v3
- name: Terraform fmt - name: Terraform fmt
id: fmt id: fmt
run: terraform fmt -recursive -check run: terraform fmt -recursive -check
continue-on-error: false continue-on-error: false
+21
View File
@@ -0,0 +1,21 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: check-yaml
- id: check-added-large-files
args:
- "--maxkb=10000"
- id: check-merge-conflict
- id: check-json
- id: mixed-line-ending
- id: fix-byte-order-marker
- id: debug-statements
- repo: https://github.com/google/yamlfmt
rev: v0.20.0
hooks:
- id: yamlfmt
args:
- "--verbose"
+14
View File
@@ -0,0 +1,14 @@
# yamlfmt configuration file
# See https://github.com/google/yamlfmt for more options
formatter:
indent: 2
trim_trailing_whitespace: true
eof_newline: true
force_array_style: block
retain_line_breaks_single: true
indentless_arrays: true
verbose: true
exclude:
- ".git/**"
+1 -1
View File
@@ -3,7 +3,7 @@ display_name: 'Brute Force: Password Spraying'
atomic_tests: atomic_tests:
- name: Password Spray all Domain Users - name: Password Spray all Domain Users
auto_generated_guid: 90bc2e54-6c84-47a5-9439-0a2a92b4b175 auto_generated_guid: 90bc2e54-6c84-47a5-9439-0a2a92b4b175
description: description: |
CAUTION! Be very careful to not exceed the password lockout threshold for users in the domain by running this test too frequently. CAUTION! Be very careful to not exceed the password lockout threshold for users in the domain by running this test too frequently.
This atomic attempts to map the IPC$ share on one of the Domain Controllers using a password of Spring2020 for each user in the %temp%\users.txt list. This atomic attempts to map the IPC$ share on one of the Domain Controllers using a password of Spring2020 for each user in the %temp%\users.txt list.
-1
View File
@@ -34,7 +34,6 @@ atomic_tests:
- name: DDEAUTO - name: DDEAUTO
auto_generated_guid: cf91174c-4e74-414e-bec0-8d60a104d181 auto_generated_guid: cf91174c-4e74-414e-bec0-8d60a104d181
description: | description: |
TrustedSec - Unicorn - https://github.com/trustedsec/unicorn TrustedSec - Unicorn - https://github.com/trustedsec/unicorn
SensePost DDEAUTO - https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/ SensePost DDEAUTO - https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/