From 3f48d4470fd124438e04323b3b21353a7edde9e8 Mon Sep 17 00:00:00 2001 From: Cameron Dunn Date: Tue, 24 Oct 2023 16:13:23 -0700 Subject: [PATCH 1/5] better filtering for changed rules --- .github/workflows/rule-validate.yml | 152 +++++++++++++++++++--------- 1 file changed, 103 insertions(+), 49 deletions(-) diff --git a/.github/workflows/rule-validate.yml b/.github/workflows/rule-validate.yml index dc15f63eeba..64d8f08bfc0 100644 --- a/.github/workflows/rule-validate.yml +++ b/.github/workflows/rule-validate.yml @@ -11,7 +11,7 @@ concurrency: # For pull_request_target workflows we want to use head_ref -- the branch triggering the workflow. Otherwise, # use ref, which is the branch for a push event. group: ${{ github.event_name == 'pull_request_target' && github.head_ref || github.ref }} - cancel-in-progress: true + cancel-in-progress: ${{ github.event_name == 'pull_request_target' }} jobs: tests: @@ -26,7 +26,7 @@ jobs: uses: mikefarah/yq@v4.27.3 - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} @@ -42,52 +42,52 @@ jobs: pip install -r scripts/generate-rule-ids/requirements.txt python scripts/generate-rule-ids/main.py - - name: Validate Rules - run: | - for f in *-rules/*.yml - do - echo "Processing $f" - http_code=$(yq -o=json eval 'del(.type)' "$f" | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) - echo '' >> response.txt - cat response.txt - if [[ "$http_code" != "200" ]]; then - echo "Unexpected response $http_code" - exit 1 - fi - done - - - name: Validate Insights and Signals - run: | - for f in {insights,signals}/**/*.yml - do - echo "Processing $f" - http_code=$(yq eval 'del(.type) | .source = "length([\n\n" + .source + "\n]) >= 0"' "$f" -o=json | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) - echo '' >> response.txt - cat response.txt - if [[ "$http_code" != "200" ]]; then - echo "Unexpected response $http_code" - exit 1 - fi - done - - - name: Verify no .yaml files exist - run: | - ! /bin/sh -c 'ls **/*.yaml' - - - name: Commit & Push Results, if needed - run: | - rm response.txt - - if [ -z "$(git status --porcelain)" ]; then - echo "No files changed, nothing to do" - exit 0 - fi - - git config user.name 'ID Generator' - git config user.email 'hello@sublimesecurity.com' - git add **/*.yml - git commit -m "Auto add rule ID" - git push origin ${{ github.head_ref }} +# - name: Validate Rules +# run: | +# for f in *-rules/*.yml +# do +# echo "Processing $f" +# http_code=$(yq -o=json eval 'del(.type)' "$f" | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) +# echo '' >> response.txt +# cat response.txt +# if [[ "$http_code" != "200" ]]; then +# echo "Unexpected response $http_code" +# exit 1 +# fi +# done +# +# - name: Validate Insights and Signals +# run: | +# for f in {insights,signals}/**/*.yml +# do +# echo "Processing $f" +# http_code=$(yq eval 'del(.type) | .source = "length([\n\n" + .source + "\n]) >= 0"' "$f" -o=json | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) +# echo '' >> response.txt +# cat response.txt +# if [[ "$http_code" != "200" ]]; then +# echo "Unexpected response $http_code" +# exit 1 +# fi +# done + +# - name: Verify no .yaml files exist +# run: | +# ! /bin/sh -c 'ls **/*.yaml' +# +# - name: Commit & Push Results, if needed +# run: | +# rm response.txt +# +# if [ -z "$(git status --porcelain)" ]; then +# echo "No files changed, nothing to do" +# exit 0 +# fi +# +# git config user.name 'ID Generator' +# git config user.email 'hello@sublimesecurity.com' +# git add **/*.yml +# git commit -m "Auto add rule ID" +# git push origin ${{ github.head_ref }} - name: Get the head SHA id: get_head @@ -100,14 +100,68 @@ jobs: files: "detection-rules/**" recover_deleted_files: true + - name: Get base ref + id: get_base_ref + run: | + if [ ${{ github.event_name }} == 'pull_request_target' ]; then + # Detect changes based on whatever we're merging into. + echo "##[set-output name=ref;]${{ github.base_ref }}" + elif [ ${{ github.event_name }} == 'push' ]; then + # Detect changes based on the previous commit + echo "##[set-output name=ref;]$(git rev-parse HEAD^)" + elif [ ${{ github.event_name }} == 'workflow_dispatch' ]; then + # Run on a target, so run for all rules. + echo "##[set-output name=run_all;]true" + fi + + - name: Checkout base + uses: actions/checkout@v4 + if: ${{ steps.get_base_ref.outputs.run_all != 'true' }} + with: + ref: ${{ steps.get_base_ref.outputs.ref }} + repository: sublime-security/sublime-rules + depth: 0 + path: sr-main + + - name: Rename files in sr-main based on rule id + if: ${{ steps.get_base_ref.outputs.run_all != 'true' }} + run: | + cd sr-main/detection-rules + + for file in *.yml + do + id=$(yq '.id' "$file") + mv "$file" "${id}.yml" + done + + - name: "Find updated rule IDs" id: find_ids run: | - for file in ${{ steps.changed-files.outputs.all_changed_and_modified_files }}; do + for file in detection-rules/*.yml; do echo "$file was changed" rule_id=$(yq '.id' $file) + if [ ${{ steps.get_base_ref.outputs.run_all != 'true' }} ]; then + altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") + continue + fi + echo "$file has rule ID $rule_id" + new_source=$(yq '.source' "$file") + old_source=$(yq '.source' "sr-main/detection-rules/$rule_id.yml" || echo '') + echo $old_source + + # We only need to care when rule source is changed. This will handle renames, tag changes, etc. + if [ "$new_source" != "$old_source" ]; then + echo "$file has altered source" + altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") + fi + done + + for file in ${{ steps.changed-files.outputs.deleted_files }}; do + rule_id=$(yq '.id' $file) + echo "$file has rule ID $rule_id and was deleted" altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") done From 0500de6a8e0dcfa9c72c91e9b3718105e92780ce Mon Sep 17 00:00:00 2001 From: Cameron Dunn Date: Tue, 24 Oct 2023 21:19:12 -0700 Subject: [PATCH 2/5] clean/fix --- .github/workflows/rule-validate.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/rule-validate.yml b/.github/workflows/rule-validate.yml index 64d8f08bfc0..47a8ca549bb 100644 --- a/.github/workflows/rule-validate.yml +++ b/.github/workflows/rule-validate.yml @@ -139,10 +139,9 @@ jobs: id: find_ids run: | for file in detection-rules/*.yml; do - echo "$file was changed" rule_id=$(yq '.id' $file) - if [ ${{ steps.get_base_ref.outputs.run_all != 'true' }} ]; then + if [ ${{ steps.get_base_ref.outputs.run_all }} = 'true']; then altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") continue fi @@ -150,7 +149,6 @@ jobs: echo "$file has rule ID $rule_id" new_source=$(yq '.source' "$file") old_source=$(yq '.source' "sr-main/detection-rules/$rule_id.yml" || echo '') - echo $old_source # We only need to care when rule source is changed. This will handle renames, tag changes, etc. if [ "$new_source" != "$old_source" ]; then From 3b36565d449cb3fa90d5d21e1c87b8b31f5c2dae Mon Sep 17 00:00:00 2001 From: Cameron Dunn Date: Tue, 24 Oct 2023 21:41:51 -0700 Subject: [PATCH 3/5] ] --- .github/workflows/rule-validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rule-validate.yml b/.github/workflows/rule-validate.yml index 47a8ca549bb..b0ba5e0b957 100644 --- a/.github/workflows/rule-validate.yml +++ b/.github/workflows/rule-validate.yml @@ -141,7 +141,7 @@ jobs: for file in detection-rules/*.yml; do rule_id=$(yq '.id' $file) - if [ ${{ steps.get_base_ref.outputs.run_all }} = 'true']; then + if [ ${{ steps.get_base_ref.outputs.run_all }} = 'true' ]; then altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") continue fi From 6cc418d077dd4491421ac48a4a64e9df20b4272e Mon Sep 17 00:00:00 2001 From: Cameron Dunn Date: Tue, 24 Oct 2023 21:54:41 -0700 Subject: [PATCH 4/5] cleanup --- .github/workflows/rule-validate.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rule-validate.yml b/.github/workflows/rule-validate.yml index b0ba5e0b957..ce374580c5e 100644 --- a/.github/workflows/rule-validate.yml +++ b/.github/workflows/rule-validate.yml @@ -103,13 +103,13 @@ jobs: - name: Get base ref id: get_base_ref run: | - if [ ${{ github.event_name }} == 'pull_request_target' ]; then + if [[ "${{ github.event_name }}" == 'pull_request_target' ]]; then # Detect changes based on whatever we're merging into. echo "##[set-output name=ref;]${{ github.base_ref }}" - elif [ ${{ github.event_name }} == 'push' ]; then + elif [[ "${{ github.event_name }}" == 'push' ]]; then # Detect changes based on the previous commit echo "##[set-output name=ref;]$(git rev-parse HEAD^)" - elif [ ${{ github.event_name }} == 'workflow_dispatch' ]; then + elif [[ "${{ github.event_name }}" == 'workflow_dispatch' ]]; then # Run on a target, so run for all rules. echo "##[set-output name=run_all;]true" fi @@ -141,25 +141,24 @@ jobs: for file in detection-rules/*.yml; do rule_id=$(yq '.id' $file) - if [ ${{ steps.get_base_ref.outputs.run_all }} = 'true' ]; then + if [[ "${{ steps.get_base_ref.outputs.run_all }}" == "true" ]]; then altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") continue fi - echo "$file has rule ID $rule_id" new_source=$(yq '.source' "$file") old_source=$(yq '.source' "sr-main/detection-rules/$rule_id.yml" || echo '') # We only need to care when rule source is changed. This will handle renames, tag changes, etc. - if [ "$new_source" != "$old_source" ]; then - echo "$file has altered source" + if [[ "$new_source" != "$old_source" ]]; then + echo "$file ($rule_id) has altered source" altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") fi done for file in ${{ steps.changed-files.outputs.deleted_files }}; do rule_id=$(yq '.id' $file) - echo "$file has rule ID $rule_id and was deleted" + echo "$file ($rule_id) was deleted" altered_rule_ids=$(echo "$rule_id"" ""$altered_rule_ids") done From 08768668f975d3b3d51fcae719ab24d89bb43edb Mon Sep 17 00:00:00 2001 From: Cameron Dunn Date: Tue, 24 Oct 2023 22:07:03 -0700 Subject: [PATCH 5/5] restore --- .github/workflows/rule-validate.yml | 92 ++++++++++++++--------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.github/workflows/rule-validate.yml b/.github/workflows/rule-validate.yml index ce374580c5e..c98120c8aba 100644 --- a/.github/workflows/rule-validate.yml +++ b/.github/workflows/rule-validate.yml @@ -42,52 +42,52 @@ jobs: pip install -r scripts/generate-rule-ids/requirements.txt python scripts/generate-rule-ids/main.py -# - name: Validate Rules -# run: | -# for f in *-rules/*.yml -# do -# echo "Processing $f" -# http_code=$(yq -o=json eval 'del(.type)' "$f" | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) -# echo '' >> response.txt -# cat response.txt -# if [[ "$http_code" != "200" ]]; then -# echo "Unexpected response $http_code" -# exit 1 -# fi -# done -# -# - name: Validate Insights and Signals -# run: | -# for f in {insights,signals}/**/*.yml -# do -# echo "Processing $f" -# http_code=$(yq eval 'del(.type) | .source = "length([\n\n" + .source + "\n]) >= 0"' "$f" -o=json | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) -# echo '' >> response.txt -# cat response.txt -# if [[ "$http_code" != "200" ]]; then -# echo "Unexpected response $http_code" -# exit 1 -# fi -# done - -# - name: Verify no .yaml files exist -# run: | -# ! /bin/sh -c 'ls **/*.yaml' -# -# - name: Commit & Push Results, if needed -# run: | -# rm response.txt -# -# if [ -z "$(git status --porcelain)" ]; then -# echo "No files changed, nothing to do" -# exit 0 -# fi -# -# git config user.name 'ID Generator' -# git config user.email 'hello@sublimesecurity.com' -# git add **/*.yml -# git commit -m "Auto add rule ID" -# git push origin ${{ github.head_ref }} + - name: Validate Rules + run: | + for f in *-rules/*.yml + do + echo "Processing $f" + http_code=$(yq -o=json eval 'del(.type)' "$f" | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) + echo '' >> response.txt + cat response.txt + if [[ "$http_code" != "200" ]]; then + echo "Unexpected response $http_code" + exit 1 + fi + done + + - name: Validate Insights and Signals + run: | + for f in {insights,signals}/**/*.yml + do + echo "Processing $f" + http_code=$(yq eval 'del(.type) | .source = "length([\n\n" + .source + "\n]) >= 0"' "$f" -o=json | curl -H "Content-Type: application/json" -X POST --data-binary @- -o response.txt -w "%{http_code}" --silent https://playground.sublimesecurity.com/v1/rules/validate) + echo '' >> response.txt + cat response.txt + if [[ "$http_code" != "200" ]]; then + echo "Unexpected response $http_code" + exit 1 + fi + done + + - name: Verify no .yaml files exist + run: | + ! /bin/sh -c 'ls **/*.yaml' + + - name: Commit & Push Results, if needed + run: | + rm response.txt + + if [ -z "$(git status --porcelain)" ]; then + echo "No files changed, nothing to do" + exit 0 + fi + + git config user.name 'ID Generator' + git config user.email 'hello@sublimesecurity.com' + git add **/*.yml + git commit -m "Auto add rule ID" + git push origin ${{ github.head_ref }} - name: Get the head SHA id: get_head