Skip to content

Commit

Permalink
Merge pull request #12 from instriq/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
htrgouvea authored Nov 29, 2024
2 parents 9ffe878 + f27790f commit 83b1f55
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 145 deletions.
35 changes: 19 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<p align="center">
<h3 align="center"><b>Sentra</b></h3>
<p align="center">The first autonomous source code posture risk score tool.</p>
<p align="center">The first autonomous source code posture risk score tool</p>
<p align="center">
<a href="https://github.com/instriq/sentra/blob/master/LICENSE.md">
<img src="https://img.shields.io/badge/license-MIT-blue.svg">
</a>
<a href="https://github.com/instriq/sentra/releases">
<img src="https://img.shields.io/badge/version-0.0.3-blue.svg">
</a>
<img src="https://github.com/instriq/sentra/actions/workflows/linter.yml/badge.svg">
<img src="https://github.com/instriq/sentra/actions/workflows/zarn.yml/badge.svg">
<img src="https://github.com/instriq/sentra/actions/workflows/security-gate.yml/badge.svg">
</p>
</p>

Expand All @@ -16,16 +22,6 @@ Sentra is a collection of Perl modules designed to help gain speed and increase

---

### Modules

| Name | Description |
|------|-------------|
| DependabotMetrics | Fetches and analyzes Dependabot alerts from GitHub repositories of a specified organization. |
| SearchFiles | Checks repositories for specific files and last update times. |
| SlackWebhook | An output forwarder for sending messages to Slack via webhooks. |

---

### Installation

```bash
Expand All @@ -43,18 +39,25 @@ $ cpanm --installdeps .
```
$ perl sentra.pl
Sentra v0.0.1
Sentra v0.0.3
Core Commands
==============
Command Description
------- -----------
-o, --org Specify the name of the organization
-t, --token Set the GitHub Token to use during actions
-w, --webhook Set the webhook address for Slack
-m, --message Message to send via Slack webhook
-mt, --maintained Check last commit date of repositories
-d, --dependency Check for dependabot.yaml file in repositories
-p, --per_page Set the number of items per page in API requests (default: 100)
-M, --metrics See some metrics based on GHAS
-w, --webhook Set the webhook address for Slack
-m, --message Message to send via Slack webhook
```

---

### Workflows examples

```yaml
```

---
Expand All @@ -67,4 +70,4 @@ Your contributions and suggestions are heartily ♥ welcome. [See here the contr

### License

This work is licensed under [MIT License.](/LICENSE.md)
This work is licensed under [MIT License.](/LICENSE.md)
62 changes: 15 additions & 47 deletions lib/Sentra/Engine/DependabotMetrics.pm
Original file line number Diff line number Diff line change
@@ -1,42 +1,17 @@
package Sentra::Engine::DependabotMetrics {
use strict;
use warnings;
use Mojo::UserAgent;
use Mojo::JSON qw(decode_json);
use JSON;
use Sentra::Utils::UserAgent;
use Sentra::Utils::Repositories_List;

sub new {
my ($class, $org, $token, $per_page) = @_;

my $userAgent = Mojo::UserAgent -> new();
my $userAgent = Sentra::Utils::UserAgent -> new($token);
my @repositories_list = Sentra::Utils::Repositories_List -> new($org, $token);

my $headers = {
'X-GitHub-Api-Version' => '2022-11-28',
'Accept' => 'application/vnd.github+json',
'User-Agent' => 'Sentra 0.0.3',
'Authorization' => "Bearer $token"
};

my @repos;
my $repo_page = 1;

while (1) {
my $repo_url = "https://api.github.com/orgs/$org/repos?per_page=$per_page&page=$repo_page";
my $repo_tx = $userAgent -> get($repo_url => $headers);
my $res = $repo_tx -> result or return "Error fetching repositories: " . $repo_tx->error->{message} . "\n";

$res->is_success or return "Error fetching repositories: " . $res->message . "\n";

my $repo_data = $res -> json;

last unless @$repo_data;

push @repos, map { "$org/$_->{name}" } grep { !$_->{archived} } @$repo_data;

$repo_page++;
}

return "Error when trying to request information from GitHub, please review the parameters provided." unless @repos;

my $output = "";
my $total_alerts = 0;

my %severity_count = (
Expand All @@ -46,32 +21,25 @@ package Sentra::Engine::DependabotMetrics {
critical => 0
);

for my $repo (@repos) {
foreach my $repository (@repositories_list) {
my $alert_page = 1;

while (1) {
my $alert_url = "https://api.github.com/repos/$repo/dependabot/alerts?state=open&per_page=$per_page&page=$alert_page";
my $alert_tx = $userAgent -> get($alert_url => $headers);
my $res = $alert_tx->result or return "Error fetching alerts for $repo: " . $alert_tx->error->{message} . "\n";
my $alert_url = "https://api.github.com/repos/$repository/dependabot/alerts?state=open&per_page=$per_page&page=$alert_page";
my $request = $userAgent -> get($alert_url);

$res->is_success or return "Error fetching alerts for $repo: " . $res->message . "\n";

my $alert_data = $res -> json;
if ($request -> code() == 200) {
my $alert_data = decode_json($request -> content());

last unless @$alert_data;

$total_alerts += scalar @$alert_data;

for my $alert (@$alert_data) {
my $severity = $alert -> {security_vulnerability}{severity} || 'unknown';

$severity_count{$severity}++ if exists $severity_count{$severity};
}

$alert_page++;
}
}
}

my $output = "";

$output .= "Severity $_: $severity_count{$_}\n" for keys %severity_count;
$output .= "Total DependaBot Alerts: $total_alerts\n";
Expand Down
53 changes: 17 additions & 36 deletions lib/Sentra/Engine/Maintained.pm
Original file line number Diff line number Diff line change
@@ -1,56 +1,37 @@
package Sentra::Engine::Maintained {
use strict;
use warnings;
use Mojo::UserAgent;
use Mojo::JSON qw(decode_json);
use JSON;
use DateTime;
use DateTime::Format::ISO8601;
use Sentra::Utils::UserAgent;
use Sentra::Utils::Repositories_List;

sub new {
my ($class, $org, $token, $per_page) = @_;

my $userAgent = Mojo::UserAgent -> new();
my $output = '';
my $userAgent = Sentra::Utils::UserAgent -> new($token);
my @repositories_list = Sentra::Utils::Repositories_List -> new($org, $token);

my $headers = {
'Authorization' => "Bearer $token",
'Accept' => 'application/vnd.github+json',
'X-GitHub-Api-Version' => '2022-11-28'
};
foreach my $repository (@repositories_list) {
my $get_commits = $userAgent -> get("https://api.github.com/repos/$repository/commits");

my $output = '';

my $repo_url = "https://api.github.com/orgs/$org/repos?per_page=$per_page";
my $repo_tx = $userAgent -> get($repo_url => $headers);

my $res = $repo_tx -> result or return "Error fetching repositories: " . $repo_tx->error->{message} . "\n";
$res -> is_success or return "Error fetching repositories: " . $res->message . "\n";

my $repos = $res->json;

for my $repo (@$repos) {
next if $repo -> {archived};

my $full_name = "$org/$repo->{name}";


my $commits_url = "https://api.github.com/repos/$full_name/commits";
my $commits_tx = $userAgent->get($commits_url => $headers);
my $commits_res = $commits_tx->result;

if ($commits_res && $commits_res->is_success) {
my $commits = $commits_res->json;

if ($get_commits -> code() == 200) {
my $commits = decode_json($get_commits -> content());

if (@$commits) {
my $last_commit_date_str = $commits->[0]{commit}{committer}{date};
my $last_commit_date = DateTime::Format::ISO8601->parse_datetime($last_commit_date_str);

$output .= "The repository https://github.com/$full_name has not been updated for more than 90 days.\n"
if DateTime -> now -> subtract(days => 90) > $last_commit_date;
my $last_commit_date = DateTime::Format::ISO8601 -> parse_datetime($last_commit_date_str);

if (DateTime -> now -> subtract(days => 90) > $last_commit_date) {
$output .= "The repository https://github.com/$repository has not been updated for more than 90 days.\n";
}
}
}
}

return $output || "No issues found.";
return $output;
}
}

Expand Down
45 changes: 14 additions & 31 deletions lib/Sentra/Engine/SearchFiles.pm
Original file line number Diff line number Diff line change
@@ -1,44 +1,27 @@
package Sentra::Engine::SearchFiles {
use strict;
use warnings;
use Mojo::UserAgent;
use Mojo::JSON qw(decode_json);
use JSON;
use Sentra::Utils::UserAgent;
use Sentra::Utils::Repositories_List;

sub new {
my ($class, $org, $token, $per_page) = @_;

my $userAgent = Mojo::UserAgent -> new();
my $output = '';
my $userAgent = Sentra::Utils::UserAgent -> new($token);
my @repositories_list = Sentra::Utils::Repositories_List -> new($org, $token);

my $headers = {
'Authorization' => "Bearer $token",
'Accept' => 'application/vnd.github+json',
'X-GitHub-Api-Version' => '2022-11-28'
};

my $output = '';

my $repo_url = "https://api.github.com/orgs/$org/repos?per_page=$per_page";
my $repo_tx = $userAgent -> get($repo_url => $headers);

my $res = $repo_tx->result or return "Error fetching repositories: " . $repo_tx->error->{message} . "\n";
$res->is_success or return "Error fetching repositories: " . $res->message . "\n";

my $repos = $res->json;

for my $repo (@$repos) {
next if $repo -> {archived};

my $full_name = "$org/$repo->{name}";

my $dependabot_url = "https://api.github.com/repos/$full_name/contents/.github/dependabot.yaml";
my $dependabot_tx = $userAgent->get($dependabot_url => $headers);

if ($dependabot_tx->result->code == 404) {
$output .= "The dependabot.yml file was not found in this repository: https://github.com/$full_name\n";
}
foreach my $repository (@repositories_list) {
my $dependabot_url = "https://api.github.com/repos/$repository/contents/.github/dependabot.yaml";
my $request = $userAgent -> get($dependabot_url);

if ($request -> code == 404) {
$output .= "The dependabot.yml file was not found in this repository: https://github.com/$repository\n";
}
}

return $output || "No issues found.";
return $output;
}
}

Expand Down
8 changes: 4 additions & 4 deletions lib/Sentra/Engine/SlackWebhook.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ package Sentra::Engine::SlackWebhook {
my $userAgent = Mojo::UserAgent -> new();
my $payload = encode_json({text => $message});

my $tx = $userAgent -> post($webhook => {
my $text = $userAgent -> post($webhook => {
'Content-Type' => 'application/json'
} => $payload);

my $res = $tx -> result;
my $res = $text -> result;

unless ($res) {
my $err = $tx->error;
my $err = $text -> error;
return "Failed to send message: [" . ($err->{message} || "Unknown error") . "]\n";
}

return "Failed to send message: [" . $res->message . "]\n" unless $res->is_success;
return "Failed to send message: [" . $res->message . "]\n" unless $res -> is_success;

return "Message sent successfully! [" . $res->body . "]\n";
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Sentra/Utils/Helper.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ package Sentra::Utils::Helper {
\r\t------- -----------
\r\t-o, --org Specify the name of the organization
\r\t-t, --token Set the GitHub Token to use during actions
\r\t-mt, --maintained Check last commit date of repositories
\r\t-d, --dependency Check for dependabot.yaml file in repositories
\r\t-mt, --maintained Get alerts about repositories with a last commit date greater than 90 days old
\r\t-d, --dependency Check if repositories has dependabot.yaml file
\r\t-M, --metrics See some metrics based on GHAS
\r\t-w, --webhook Set the webhook address for Slack
\r\t-m, --message Message to send via Slack webhook\n\n";
Expand Down
37 changes: 37 additions & 0 deletions lib/Sentra/Utils/Repositories_List.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package Sentra::Utils::Repositories_List {
use strict;
use warnings;
use JSON;
use Sentra::Utils::UserAgent;

sub new {
my ($self, $org, $token) = @_;

my @repos;
my $page = 1;
my $userAgent = Sentra::Utils::UserAgent -> new($token);

while (1) {
my $url = "https://api.github.com/orgs/$org/repos?per_page=100&page=$page";
my $response = $userAgent -> get($url);

if ($response -> code() == 200) {
my $data = decode_json($response -> content());

if (scalar(@$data) == 0) {
last;
}

for my $repo (@$data) {
push @repos, "$org/$repo->{name}" unless $repo->{archived};
}

$page++;
}
}

return @repos;
}
}

1;
28 changes: 28 additions & 0 deletions lib/Sentra/Utils/UserAgent.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package Sentra::Utils::UserAgent {
use strict;
use warnings;
use LWP::UserAgent;

sub new {
my ($self, $token) = @_;

my $userAgent = LWP::UserAgent -> new(
timeout => 5,
ssl_opts => {
verify_hostname => 0,
SSL_verify_mode => 0
},
agent => "Sentra 0.0.3"
);

$userAgent -> default_headers -> header (
'X-GitHub-Api-Version' => '2022-11-28',
'Accept' => 'application/vnd.github+json',
'Authorization' => "Bearer $token"
);

return $userAgent;
}
}

1;
Loading

0 comments on commit 83b1f55

Please sign in to comment.