Skip to content

Commit

Permalink
Version 2.3.0 (#36)
Browse files Browse the repository at this point in the history
* [#19] [Feature] GitHub repositories backup (#26)

* chore: #19 - prepare for feature

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* chore: project - clean up

- Fixed typos

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* feat: #19 - dump of repositories of organisation

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* [#27] [Feature] Diver - Extract email addresses (#31)

* chore: project - improve README and THIRD-PARTY

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* chore: project - rename bad command parameter

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* fix: Shell scripts - temp log file not found

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* feat: #27 - extract email adresses from Git history

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* doc: README - improve section for backup-all-repositories-from-org

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* Small improvements for doc and scripts (#33)

* doc: proejct - improve README with keywords

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* feat: #27 - keep unique email address

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>

* feat: #20 - check for vulnerability alerts in organisation projects (#35)

Signed-off-by: Pierre-Yves Lapersonne <[email protected]>
  • Loading branch information
pylapp authored Feb 25, 2022
1 parent f0feb36 commit 0d5eff2
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 11 deletions.
17 changes: 10 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
# CHANGELOG

## Version 2.2.0
## Version 2.3.0

### Features (github)
### Features

- [#19](https://github.com/Orange-OpenSource/floss-toolbox/issues/19) Backup of repositories
- [#20](https://github.com/Orange-OpenSource/floss-toolbox/issues/20) Find repositories with vulnerabilities (Dependabot)

### Features (diver)
## Version 2.2.0

### Features

- [#19](https://github.com/Orange-OpenSource/floss-toolbox/issues/19) Backup of repositories
- [#27](https://github.com/Orange-OpenSource/floss-toolbox/issues/27) Extract email addresses

## Version 2.1.0

### Features (diver):
### Features

- [#13](https://github.com/Orange-OpenSource/floss-toolbox/issues/13) List all contributors of a Git repository using Git history

## Version 2.0.0

### Features (github):
### Features

- [#4](https://github.com/Orange-OpenSource/floss-toolbox/issues/4) Get all members of GitHub organization
- [#4](https://github.com/Orange-OpenSource/floss-toolbox/issues/4) Get members who don't have 2FA enabled
Expand All @@ -34,7 +37,7 @@

## Version 1.0.0

### Features (diver):
### Features

- Find contributors in files using a base of words and producing logs
- Find contributors in git logs
Expand Down
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# floss-toolbox (version 2.2.0)
# floss-toolbox (version 2.3.0)

Toolbox to help developers and open source referents to have cleaner projects in GitHub organizations.

Expand Down Expand Up @@ -373,4 +373,25 @@ _So imagine a python eating ruby gems in a shell. Gorgeous isn't it?_
You need to define in the _configuration.rb_ files the Github organisation at **GITHUB_ORGANIZATION_NAME**.
You have to also define the location to store clones at **REPOSITORIES_CLONE_LOCATION_PATH**

**You should also have your _git_ environment ready, i.e. add your SSH private key if you clone by SSH for example.**

### Check if there are vulnerabilities alerts in organisation repositories

_Keywords: #organisation #GitHub #repositories #Dependabot #vulnerabilities_

This feature allows to check in all repositories of the GitHub organisation if there are projects witch vulnerabilities alerts.

Run the following command:
```shell
bash GitHubWizard.sh vulnerabilities-alerts-for-all-repositories
```

This script will trigger the _gh_ client which may ask you to athenticate to the GitHub API.
Then the Shell script will pick configuration details from the Ruby configuration file; and triggers another Shell script for the data process. A Python code will be called too.

The Python code will process JSON data, the Sheel script will make a CURL request to to GraphQL API.

You need to define in the _configuration.rb_ files the Github organisation at **GITHUB_ORGANIZATION_NAME**.
You have to also define the location to store clones at **REPOSITORIES_CLONE_LOCATION_PATH**

**You should also have your _git_ environment ready, i.e. add your SSH private key if you clone by SSH for example.**
6 changes: 3 additions & 3 deletions toolbox/github/utils/GitHubFacade.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env ruby
# Software Name: floss-toolbox
# SPDX-FileCopyrightText: Copyright (c) 2021 Orange
# SPDX-FileCopyrightText: Copyright (c) 2021-2022 Orange
# SPDX-License-Identifier: Apache-2.0
#
# This software is distributed under the Apache 2.0 license.
#
# Author: Pierre-Yves LAPERSONNE <pierreyves(dot)lapersonne(at)orange(dot)com> et al.

# Version.............: 1.0.0
# Version.............: 1.1.0
# Since...............: 26/04/2021
# Description.........: Received from arguments a feature to launch using GitHub API.
# Loads configuration elements from configuration.rb, writes outputs using FileManager.rb and calls GitHubWrapper.rb for requests
Expand Down Expand Up @@ -51,7 +51,7 @@
end
feature_to_run=ARGV[0]

if feature_to_run != "get-members-2fa-disabled" && feature_to_run != "get-all-members" && feature_to_run != "get-members-without-company" && feature_to_run != "get-projects-without-team" && feature_to_run != "get-users-with-bad-email" && feature_to_run != "get-users-with-bad-fullname" && feature_to_run != "get-projects-conformity" && feature_to_run != "get-projects-without-licenses" && feature_to_run != "get-empty-projects" && feature_to_run != "set-users-permissions-to-push" && feature_to_run != "set-teams-permissions-to-push"
if feature_to_run != "get-members-2fa-disabled" && feature_to_run != "get-all-members" && feature_to_run != "get-members-without-company" && feature_to_run != "get-projects-without-team" && feature_to_run != "get-users-with-bad-email" && feature_to_run != "get-users-with-bad-fullname" && feature_to_run != "get-projects-conformity" && feature_to_run != "get-projects-without-licenses" && feature_to_run != "get-empty-projects" && feature_to_run != "set-users-permissions-to-push" && feature_to_run != "set-teams-permissions-to-push"
Log.error "Unknown feature. Exit now."
exit $EXIT_UNKNOWN_FEATURE
end
Expand Down
208 changes: 208 additions & 0 deletions toolbox/github/utils/check-vulnerabilities-from-github.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/bin/bash
# Software Name: floss-toolbox
# SPDX-FileCopyrightText: Copyright (c) 2021-2022 Orange
# SPDX-License-Identifier: Apache-2.0
#
# This software is distributed under the Apache 2.0 license.
#
# Author: Pierre-Yves LAPERSONNE <pierreyves(dot)lapersonne(at)orange(dot)com> et al.

# Since...............: 25/02/2022
# Description.........: Received from arguments a GitHub organisation name and a GitHub personal token path to dump check if vulnerabilities alert exists

#set -euxo pipefail
VERSION="1.0.0"

# Config
# ------

EXIT_OK=0
EXIT_BAD_ARGUMENTS=1
EXIT_BAD_SETUP=2

URL_EXTRACTER_FILE="./utils/extract-repos-field-from-json.py"
VULNERABILITY_PARSER="./utils/count-vulnerabilities-nodes.py"
GITHB_ORGANISATION_VULNERABILITIES_RESULTS="$$_github-organisation-repositories-vulnerabilities-count.csv"

# Functions
# ---------

UsageAndExit(){
echo "check-vulnerabilities-from-github.sh - Version $VERSION"
echo "USAGE:"
echo "bash check-vulnerabilities-from-github.sh ORGANISATION KEY TOKEN"
echo "with ORGANISATION: GitHub organisation name"
echo "with KEY: JSON key to sue use cloning URL"
echo "with TOKEN: personal access token fir requests"
echo "About exit codes:"
echo -e "\t 0................: Normal exit"
echo -e "\t 1................: Bad arguments given to the script"
echo -e "\t 2................: File URL_EXTRACTER_FILE is not defined. Impossible to extract URL from API results."
exit $EXIT_OK
}

# Check setup
# -----------

if [ "$#" -eq 0 ]; then
UsageAndExit
exit $EXIT_OK
fi

if [ "$#" -ne 3 ]; then
echo "ERROR: Bad arguments number. Exits now"
UsageAndExit
exit $EXIT_BAD_ARGUMENTS
fi

if [ ! -f "$URL_EXTRACTER_FILE" ]; then
echo "ERROR: Bad set up for URL extracter. Exits now"
UsageAndExit
exit $EXIT_BAD_SETUP
fi

if [ -f "VULNERABILITY_PARSER" ]; then
echo "ERROR: Bad set up vulnerability parser. Exits now"
UsageAndExit
exit $EXIT_BAD_SETUP
fi

organisation_name=$1
if [ -z "$organisation_name" ]; then
echo "ERROR: No organisation name defined. Exits now."
UsageAndExit
exit $EXIT_BAD_ARGUMENTS
fi

cloning_url_key=$2
if [ -z "$cloning_url_key" ]; then
echo "ERROR: No JSON key for URL. Exits now."
UsageAndExit
exit $EXIT_BAD_ARGUMENTS
fi

personal_access_token=$3
if [ -z "$personal_access_token" ]; then
echo "ERROR: No personal access token defined. Exits now."
UsageAndExit
exit $EXIT_BAD_ARGUMENTS
fi

# Run
# ---

echo "-------------------------------------------------------"
echo "check-vulnerabilities-from-github.sh - Version $VERSION"
echo "-------------------------------------------------------"

# Step 1 - Authenticate to GitHub using gh

echo "Authenticating to GitHub using gh client..."
gh auth login
echo "Authentication done."

# Step 2 - Get repositories URL

echo "Get repositories URL..."
repositories_list_raw_temp_file=".repos-raw.json"
repositories_list_clean_temp_file=".repos-clean.json"
gh api -X GET "orgs/$organisation_name/repos" -F per_page=500 --paginate > $repositories_list_raw_temp_file
cat $repositories_list_raw_temp_file | sed -e "s/\]\[/,/g" > $repositories_list_clean_temp_file # Need to replace '][' by ',' because of pagination
rm -f $repositories_list_raw_temp_file
echo "All repositories URL got."

# Step 3 - Extract cloning URL

url_for_cloning=".url-for-cloning.txt"
echo "Extract cloning from results (using '$cloning_url_key' as JSON key)..."
python3 "$URL_EXTRACTER_FILE" --field $cloning_url_key --source $repositories_list_clean_temp_file > $url_for_cloning
rm -f $repositories_list_clean_temp_file
echo "Extraction done."

# Step 4 - Create workspace directory

dir_before_dump=`pwd`
echo "Creating workspace directory..."
directory_name=$(date '+%Y-%m-%d')
cd "$repositories_location"
if [ -d "$directory_name" ]; then
echo "Removing old directory with the same name"
yes | rm -rf $directory_name
fi
mkdir $directory_name
cd $directory_name
echo "Dump directory created with name '$directory_name' at location `pwd`."

# Step 5 - For each repository, check it

number_of_url=`cat "$dir_before_dump/$url_for_cloning" | wc | awk {'print $1 '}`
cpt=1
echo "Dumping of $number_of_url repositories..."
github_request_result_file_raw=".vulnerabilities-github.txt"
github_request_result_file_json=".vulnerabilities-github.json"

echo "status;project name;count of alerts" > $GITHB_ORGANISATION_VULNERABILITIES_RESULTS
cpt_clean_repo=0
cpt_dirty_repo=0
while read url_line; do

# Step 5.1 - Get repo name
# We assume URL are like "[email protected]:org/repo.js.git"
repo_name=`echo "$url_line" | cut -d"/" -f 2 | awk -F".git" '{print $1}'`
echo "Checking ($cpt / $number_of_url) '$repo_name'..."
cpt=$((cpt+1))

# Step 5.2 - Request GitHub API
graphqlScript='query { repository(name: \"'"$repo_name"'\", owner: \"'"$organisation_name"'\") {
vulnerabilityAlerts(first: 100) {
nodes {
createdAt
dismissedAt
securityVulnerability {
package {
name
}
advisory {
description
}
}
}
}
}
}'
script="$(echo $graphqlScript)"

curl -s -i -H 'Content-Type: application/json' \
-H "Authorization: bearer $personal_access_token" \
-X POST -d "{ \"query\": \"$script\"}" https://api.github.com/graphql -o "$github_request_result_file_raw"

# Step 5.3 - Process result file

# We suppose in response paylaod we have the usefull line like
# {"data":{"repository":{"vulnerabilityAlerts":{"nodes":[]}}}}
cat $github_request_result_file_raw | grep vulnerabilityAlerts > "$github_request_result_file_json"
count=`python3 "../$VULNERABILITY_PARSER" --file "$github_request_result_file_json"`

# Step 5.4 - Build final file
if [ "$count" -eq "0" ]; then
echo "😊;$repo_name;$count" >> $GITHB_ORGANISATION_VULNERABILITIES_RESULTS
cpt_clean_repo=$((cpt_clean_repo+1))
else
echo "🚨;$repo_name;$count" >> $GITHB_ORGANISATION_VULNERABILITIES_RESULTS
echo "🚨 WARNING: Project '$repo_name' has '$count' vulnerability alerts on GitHub!"
cpt_dirty_repo=$((cpt_dirty_repo+1))
fi

done < "$dir_before_dump/$url_for_cloning"

echo "GitHub organisation name.............: '$organisation_name'"
echo "Total number of projects.............: '$number_of_url'"
echo "Number of projects with alerts.......: '$cpt_dirty_repo'"
echo "Number of projects without alerts....: '$cpt_clean_repo'"

rm "$github_request_result_file_raw"
rm "$github_request_result_file_json"
cd "$dir_before_dump"
rm -f $url_for_cloning

echo "Check done!"
42 changes: 42 additions & 0 deletions toolbox/github/utils/count-vulnerabilities-nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/python3
# Software Name: floss-toolbox
# SPDX-FileCopyrightText: Copyright (c) 2022 Orange
# SPDX-License-Identifier: Apache-2.0
#
# This software is distributed under the Apache 2.0 license.
#
# Author: Pierre-Yves LAPERSONNE <pierreyves(dot)lapersonne(at)orange(dot)com> et al.

# Version.............: 1.0.0
# Since...............: 25/02/2022
# Description.........: In the given JSON file, produced by GitHub GraphQL API request file, count and return the number of vulnerabilities nodes
#
# Usage: python3 count-vulnerabilities-nodes.py --file file_name
#

import argparse
import json
import sys

# Check arguments
# ---------------

parser = argparse.ArgumentParser(description='In the given JSON file, produced by GitHub GraphQL API request file; count and return the number of vulnerabilities nodes.')
required_args = parser.add_argument_group('Required arguments')
required_args.add_argument('-f', '--file', help='The JSON file to process', required=True)
args = parser.parse_args()

file_name = args.file

# Extraction
# ----------

with open(file_name, 'r', encoding='utf-8') as f:
entries = json.load(f)
f.close()

vulnerabilitiy_nodes = entries["data"]["repository"]["vulnerabilityAlerts"]["nodes"]
vulnerabilitiy_nodes_count=len(vulnerabilitiy_nodes)

print(vulnerabilitiy_nodes_count)
sys.exit(0)

0 comments on commit 0d5eff2

Please sign in to comment.