Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor Code and Dependencies modules, fix severity counting, and update README #11

Merged
merged 5 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Core Commands
Command Description
------- -----------
-t, --token GitHub token
-r, --repo GitHub repository, organization/repository-name
-r, --repo GitHub repository, organization/repository-name
-c, --critical Critical severity limit
-h, --high High severity limit
-m, --medium Medium severity limit
Expand Down Expand Up @@ -122,4 +122,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)
86 changes: 43 additions & 43 deletions lib/SecurityGate/Engine/Code.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,55 @@ package SecurityGate::Engine::Code {
use Mojo::JSON;

sub new {
my ($class, $token, $repository, $severity_limits) = @_;
my $alerts_endpoint = "https://api.github.com/repos/$repository/code-scanning/alerts";

my $userAgent = Mojo::UserAgent -> new();
my $alerts_request = $userAgent -> get($alerts_endpoint, {Authorization => "Bearer $token"}) -> result();

if ($alerts_request -> code() == 200) {
my $alerts_data = $alerts_request -> json();
my $open_alerts = 0;
my %severity_counts = map {$_ => 0} keys %$severity_limits;

foreach my $alert (@$alerts_data) {
if ($alert -> {state} eq "open") {
$open_alerts++;

my $severity = $alert -> {rule} -> {severity};
$severity_counts{$severity}++ if exists $severity_counts{$severity};
}
}
my ($class, $token, $repository, $severity_limits) = @_;
my $alerts_endpoint = "https://api.github.com/repos/$repository/code-scanning/alerts";

print "[!] Total of open code scanning alerts: $open_alerts\n";

foreach my $severity (keys %severity_counts) {
print "[-] $severity: $severity_counts{$severity}\n";
}
my $userAgent = Mojo::UserAgent->new();
my $alerts_request = $userAgent->get($alerts_endpoint, {Authorization => "Bearer $token"})->result();

my $threshold_exceeded = 0;

foreach my $severity (keys %severity_counts) {
if ($severity_counts{$severity} > $severity_limits -> {$severity}) {
print "[+] More than $severity_limits->{$severity} $severity code scanning alerts found.\n";

$threshold_exceeded = 1;
}
}
if ($alerts_request->code() == 200) {
my $alerts_data = $alerts_request->json();
my $open_alerts = 0;
my %severity_counts = map {$_ => 0} keys %$severity_limits;

foreach my $alert (@$alerts_data) {
if ($alert->{state} eq "open") {
$open_alerts++;

my $severity = $alert->{rule}->{security_severity_level} // 'unknown';
$severity_counts{$severity}++ if exists $severity_counts{$severity};
}
}

print "\n[!] Total of open code scanning alerts: $open_alerts\n\n";

if ($threshold_exceeded) {
return 1;
foreach my $severity (keys %severity_counts) {
print "[-] $severity: $severity_counts{$severity}\n";
}

print "\n";

my $threshold_exceeded = 0;

foreach my $severity (keys %severity_counts) {
if ($severity_counts{$severity} > $severity_limits->{$severity}) {
print "[+] More than $severity_limits->{$severity} $severity code scanning alerts found.\n";
$threshold_exceeded = 1;
}
}

if ($threshold_exceeded) {
return 1;
}
}
}

else {
print "Error: Unable to fetch code scanning alerts. HTTP status code: " . $alerts_request -> code() . "\n";

return 1;
}
else {
print "Error: Unable to fetch code scanning alerts. HTTP status code: " . $alerts_request->code() . "\n";
return 1;
}

return 0;
return 0;
}
}

1;
1;
26 changes: 13 additions & 13 deletions lib/SecurityGate/Engine/Dependencies.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ package SecurityGate::Engine::Dependencies {
my ($class, $token, $repository, $severity_limits) = @_;

my %severity_counts = map { $_ => 0 } @SEVERITIES;

my $endpoint = "https://api.github.com/repos/$repository/dependabot/alerts";
my $userAgent = Mojo::UserAgent -> new();
my $request = $userAgent -> get($endpoint, {Authorization => "Bearer $token"}) -> result();
my $userAgent = Mojo::UserAgent->new();
my $request = $userAgent->get($endpoint, {Authorization => "Bearer $token"})->result();

if ($request->code() == 200) {
my $data = $request->json();

if ($request -> code() == 200) {
my $data = $request -> json();

foreach my $alert (@$data) {
if ($alert -> {state} eq "open") {
my $severity = $alert -> {security_vulnerability} -> {severity};
if ($alert->{state} eq "open") {
my $severity = $alert->{security_vulnerability}->{severity};
$severity_counts{$severity}++;
}
}

print "[!] Total of security alerts:\n\n";
print "\n[!] Total of dependency alerts:\n\n";

foreach my $severity (@SEVERITIES) {
print "[-] $severity: $severity_counts{$severity}\n";
Expand All @@ -38,20 +38,20 @@ package SecurityGate::Engine::Dependencies {
my $threshold_exceeded = 0;

foreach my $severity (@SEVERITIES) {
if ($severity_counts{$severity} > $severity_limits -> {$severity}) {
if ($severity_counts{$severity} > $severity_limits->{$severity}) {
print "[+] More than $severity_limits->{$severity} $severity security alerts found.\n";
$threshold_exceeded = 1;
}
}

return $threshold_exceeded;
}

else {
print "Error: Unable to fetch alerts. HTTP status code: " . $request -> code() . "\n";
print "Error: Unable to fetch alerts. HTTP status code: " . $request->code() . "\n";
return 1;
}
}
}

1;
1;
37 changes: 21 additions & 16 deletions lib/SecurityGate/Engine/Secrets.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,48 @@ package SecurityGate::Engine::Secrets {
my ($class, $token, $repository, $severity_limits) = @_;

my $endpoint = "https://api.github.com/repos/$repository/secret-scanning/alerts";
my $userAgent = Mojo::UserAgent -> new();
my $request = $userAgent -> get($endpoint, {Authorization => "Bearer $token"}) -> result();
my $userAgent = Mojo::UserAgent->new();
my $request = $userAgent->get($endpoint, {Authorization => "Bearer $token"})->result();

if ($request -> code() == 200) {
my $data = $request -> json();
if ($request->code() == 200) {
my $data = $request->json();
my $open_alerts = 0;
my @alert_details;

foreach my $alert (@$data) {
if ($alert -> {state} eq "open") {
if ($alert->{state} eq "open") {
$open_alerts++;

my $locations_endpoint = "https://api.github.com/repos/$repository/secret-scanning/alerts/$alert -> {number}/locations";
my $locations_request = $userAgent -> get($locations_endpoint, {Authorization => "Bearer $token"}) -> result();
my $locations_endpoint = "https://api.github.com/repos/$repository/secret-scanning/alerts/" . $alert->{number} . "/locations";
my $locations_request = $userAgent->get($locations_endpoint, {Authorization => "Bearer $token"})->result();

if ($locations_request -> code() == 200) {
my $locations = $locations_request -> json();
if ($locations_request->code() == 200) {
my $locations = $locations_request->json();

push @alert_details, {
alert_number => $alert -> {number},
alert_number => $alert->{number},
locations => $locations,
};
}
}
}

print "[!] Total of open secret scanning alerts: $open_alerts\n";
print "\n[!] Total of open secret scanning alerts: $open_alerts\n\n";

foreach my $detail (@alert_details) {
print "[-] Alert " . $detail -> {alert_number} . " found in the following locations:\n";
print "[-] Alert " . $detail->{alert_number} . " found in the following locations:\n";

foreach my $location (@{$detail -> {locations}}) {
print " File: " . $location -> {path} . ", Start line: " . $location -> {start_line} . "\n";
foreach my $location (@{$detail->{locations}}) {
my $file_path = $location->{details}->{path} // 'Unknown file';
my $start_line = $location->{details}->{start_line} // 'Unknown line';

print " File: $file_path, Start line: $start_line\n";
}
}

my $threshold = $severity_limits -> {high};
print "\n";

my $threshold = $severity_limits->{high};
if ($open_alerts > $threshold) {
print "[+] More than $threshold secret scanning alerts found. Blocking pipeline.\n";
return 1;
Expand All @@ -57,7 +62,7 @@ package SecurityGate::Engine::Secrets {
}

else {
print "Error: Unable to fetch secret scanning alerts. HTTP status code: " . $request -> code() . "\n";
print "Error: Unable to fetch secret scanning alerts. HTTP status code: " . $request->code() . "\n";
return 1;
}
}
Expand Down
20 changes: 5 additions & 15 deletions security-gate.pl
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,13 @@ sub main {
my $result = 0;

my %alert_checks = (
'dependency-alerts' => sub { SecurityGate::Engine::Dependencies -> new($token, $repository, \%severity_limits) },
'secret-alerts' => sub { SecurityGate::Engine::Secrets -> new($token, $repository, \%severity_limits) },
'code-alerts' => sub { SecurityGate::Engine::Code -> new($token, $repository, \%severity_limits) }
'dependency-alerts' => $dependency_alerts ? sub { SecurityGate::Engine::Dependencies->new($token, $repository, \%severity_limits) } : undef,
'secret-alerts' => $secret_alerts ? sub { SecurityGate::Engine::Secrets->new($token, $repository, \%severity_limits) } : undef,
'code-alerts' => $code_alerts ? sub { SecurityGate::Engine::Code->new($token, $repository, \%severity_limits) } : undef
);

for my $alert_type (keys %alert_checks) {
if ($alert_type eq 'dependency-alerts' && $dependency_alerts) {
$result += $alert_checks{$alert_type}->();
}

elsif ($alert_type eq 'secret-alerts' && $secret_alerts) {
$result += $alert_checks{$alert_type}->();
}

elsif ($alert_type eq 'code-alerts' && $code_alerts) {
$result += $alert_checks{$alert_type}->();
}
for my $check (grep { defined } values %alert_checks) {
$result += $check->();
}

return $result;
Expand Down
Loading