Skip to content

Commit

Permalink
Merge pull request #25 from softonic/refactor-to-clean-code
Browse files Browse the repository at this point in the history
Refactor to clean code
  • Loading branch information
santinoncs authored Jun 6, 2023
2 parents 800178b + d45415b commit 6383089
Show file tree
Hide file tree
Showing 20 changed files with 916 additions and 595 deletions.
463 changes: 84 additions & 379 deletions app/actor/armor_actor.go

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions app/actor/armor_actor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package actor
import (
"reflect"
"testing"

"github.com/softonic/ip-blocker/app/utils"
)

func TestDetectWhichOfTheseIPsAreNotBlocked(t *testing.T) {
Expand Down Expand Up @@ -33,9 +35,9 @@ func TestDetectWhichOfTheseIPsAreNotBlocked(t *testing.T) {
"2.2.2.2",
}

result := uniqueItems(elasticIPs, armorIPs)
result := utils.UniqueItems(elasticIPs, armorIPs)

result = removeDuplicateStr(result)
result = utils.RemoveDuplicateStr(result)

if !reflect.DeepEqual(expected, result) {
t.Errorf("Error actual = %v, and Expected = %v.", result, expected)
Expand Down Expand Up @@ -71,9 +73,9 @@ func TestDetectWhichOfTheseIPsAreNotExcluded(t *testing.T) {
"2.2.2.2",
}

result := uniqueItems(elasticIPs, exceptionsIPs)
result := utils.UniqueItems(elasticIPs, exceptionsIPs)

result = removeDuplicateStr(result)
result = utils.RemoveDuplicateStr(result)

if !reflect.DeepEqual(expected, result) {
t.Errorf("Error actual = %v, and Expected = %v.", result, expected)
Expand Down
38 changes: 38 additions & 0 deletions app/actor/gcpArmorConfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package actor

import (
"os"

"github.com/softonic/ip-blocker/app/utils"
"gopkg.in/yaml.v2"
)

// ActorConfig is the configuration for the actor
type ActorConfig struct {
Project string
Policy string
TTLRules int
ExcludeIPs string
}

// GCPArmorRulesConf is the configuration for the Armor rules
type GCPArmorRulesConf struct {
preview bool `yaml:"preview"`
action string `yaml:"action"`
}

func (c *GCPArmorRulesConf) Parse(data []byte) error {
return yaml.Unmarshal(data, c)
}

var conf utils.MapConf

func (c *GCPArmorRulesConf) LoadConfig() error {
configPath := os.Getenv("CONFIG_PATH")
if configPath == "" {
configPath = "/etc/config/gcp-armor-config.yaml" // valor por defecto
}

return utils.GetConf(configPath, &conf)

}
28 changes: 28 additions & 0 deletions app/actor/gcpArmorConnection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package actor

import (
"context"

compute "cloud.google.com/go/compute/apiv1"
"k8s.io/klog"
)

// GCPArmorConnection is a struct to connect to GCP Armor
type GCPArmorConnection struct {
Client *compute.SecurityPoliciesClient
Ctx context.Context
}

func NewGCPArmorConnection() (*GCPArmorConnection, error) {
ctx := context.Background()
client, err := compute.NewSecurityPoliciesRESTClient(ctx)
if err != nil {
klog.Error("\nError: ", err)
return nil, err
}

return &GCPArmorConnection{
Client: client,
Ctx: ctx,
}, nil
}
90 changes: 90 additions & 0 deletions app/actor/gcpArmorQueries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package actor

import (
"fmt"
"strings"

computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
"k8s.io/klog"
)

// Build the query to Add a Rule to the Security Policy
func buildArmorQueryAddRule(blockStringArray []string, project string, policy string, action string, description string, priority int32, preview bool) *computepb.AddRuleSecurityPolicyRequest {

versioned := computepb.SecurityPolicyRuleMatcher_SRC_IPS_V1.Enum()

match := &computepb.SecurityPolicyRuleMatcher{
Config: &computepb.SecurityPolicyRuleMatcherConfig{
SrcIpRanges: blockStringArray,
},
VersionedExpr: versioned,
}

req := &computepb.AddRuleSecurityPolicyRequest{

Project: project,
SecurityPolicy: policy,
SecurityPolicyRuleResource: &computepb.SecurityPolicyRule{
Action: &(action),
Description: &description,
Priority: &priority,
Preview: &(preview),
Match: match,
},
}

return req

}

// Execute the query to add a rule to the armor policy
func (g *GCPArmorActor) executeArmorQueryAddRule(ips []string, priority int32, action, description string, preview bool) error {

client := g.Connection.Client
ctx := g.Connection.Ctx

req := buildArmorQueryAddRule(ips, g.ActorConfig.Project, g.ActorConfig.Policy, action, description, priority, preview)

_, err := client.AddRule(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "Cannot have rules with the same priorities") {
// reexecute the query with prio + 1 if the prio is already used
priority++
req := buildArmorQueryAddRule(ips, g.ActorConfig.Project, g.ActorConfig.Policy, action, description, priority, preview)
_, err := client.AddRule(ctx, req)
if err != nil {
klog.Error("\nError: ", err)
return err
}
} else {
klog.Error("\nError: ", err)
return err
}
}

if err != nil {
return fmt.Errorf("error executing add armor query: %v", err)
}

return nil
}

// Execute the query to remove a rule from the armor policy
func (g *GCPArmorActor) executeArmorQueryRemoveRule(priority int32) error {
client := g.Connection.Client
ctx := g.Connection.Ctx

req := &computepb.RemoveRuleSecurityPolicyRequest{
Project: g.ActorConfig.Project,
SecurityPolicy: g.ActorConfig.Policy,
Priority: &priority,
}

_, err := client.RemoveRule(ctx, req)

if err != nil {
return fmt.Errorf("error executing remove armor query: %v", err)
}

return nil
}
73 changes: 73 additions & 0 deletions app/actor/ipGetter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package actor

import (
"github.com/softonic/ip-blocker/app/actor/utils"
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

type IPGetter struct {
actor *GCPArmorActor
}

func NewIPGetter(actor *GCPArmorActor) *IPGetter {
return &IPGetter{actor: actor}
}

// GetIPsToBlock: this function will get the IPs already blocked
func (g *IPGetter) GetBlockedIPs(rules []*computepb.SecurityPolicyRule) ([]string, error) {

var sourceIps computepb.SecurityPolicyRuleMatcherConfig

var ips []string

for _, singleRule := range rules {

sourceIps = computepb.SecurityPolicyRuleMatcherConfig{
SrcIpRanges: singleRule.Match.Config.SrcIpRanges,
}

ips = append(ips, sourceIps.SrcIpRanges...)

}

return ips, nil

}

// getLastPriority: this function will get the last priority of the rules
func getLastPriority(rules []*computepb.SecurityPolicyRule) int32 {

var lastPriority int32

for _, singleRule := range rules {

if *singleRule.Priority > lastPriority {
lastPriority = *singleRule.Priority
}

}

if lastPriority == 0 {
lastPriority = 1000
}

return lastPriority

}

func getCandidateIPsToBlock(handler utils.IPListHandler, candidateIPs, alreadyBlockedIPs, excludedIPs []string) []string {
candidateIPs = handler.UniqueItems(candidateIPs, alreadyBlockedIPs)
candidateAfterExcluded := handler.UniqueItems(candidateIPs, excludedIPs)
candidateAfterExcluded = handler.RemoveDuplicateStr(candidateAfterExcluded)

return addCidrMaskToIPs(candidateAfterExcluded)
}

// This function add the cidr mask to the IPs
func addCidrMaskToIPs(ips []string) []string {
var ipsWithCidr []string
for _, k := range ips {
ipsWithCidr = append(ipsWithCidr, k+"/32")
}
return ipsWithCidr
}
118 changes: 118 additions & 0 deletions app/actor/rulesGetter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package actor

import (
"strconv"
"time"

actorUtils "github.com/softonic/ip-blocker/app/actor/utils"
globalUtils "github.com/softonic/ip-blocker/app/utils"

"k8s.io/klog"

"regexp"

computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

type RulesGetter struct {
actor *GCPArmorActor
}

func NewRulesGetter(actor *GCPArmorActor) *RulesGetter {
return &RulesGetter{actor: actor}
}

// GetSecurityRules: get Rules that were created by IPBlocker
func (g *RulesGetter) GetSecurityRules() ([]*computepb.SecurityPolicyRule, error) {
req := &computepb.GetSecurityPolicyRequest{
Project: g.actor.ActorConfig.Project,
SecurityPolicy: g.actor.ActorConfig.Policy,
}

resp, err := g.actor.Connection.Client.Get(g.actor.Connection.Ctx, req)
if err != nil {
klog.Error("\nError: ", err)
return nil, err
}

var ipBlockerRules []*computepb.SecurityPolicyRule

for _, singleRule := range resp.Rules {

match := false
match, _ = regexp.MatchString("ipblocker:[0-9]{10}", *singleRule.Description)

if !match {
continue
}

// && singleRule.Match.VersionedExpr == computepb.SecurityPolicyRuleMatcher_SRC_IPS_V1.Enum()

if *singleRule.Action != "allow" && *singleRule.Match.VersionedExpr == 70925961 {

ipBlockerRules = append(ipBlockerRules, singleRule)

}

}

return ipBlockerRules, nil
}

// GetBlockedIPsFromActorThatCanBeUnblocked: return IPs that has been blocked for more than ttlRules min
func getBlockedIPsFromActorThatCanBeUnblocked(rules []*computepb.SecurityPolicyRule, ttlRules int) []string {

now := time.Now()
secs := now.Unix()

var ips, restIps []string

for _, singleRule := range rules {

// && singleRule.Match.VersionedExpr == computepb.SecurityPolicyRuleMatcher_SRC_IPS_V1.Enum()

unixTimeStampFromDescString := actorUtils.ExtractFromDescription(*singleRule.Description)
n, err := strconv.ParseInt(unixTimeStampFromDescString, 10, 64)
if err != nil {
continue
}
if (secs - n) > int64(ttlRules*60) {

restIps = singleRule.Match.Config.SrcIpRanges

ips = append(ips, restIps...)
} else {
klog.Infof("This rule with priority %d is still valid", *singleRule.Priority)
}

}

return ips

}

func GetRuleFromIP(rules []*computepb.SecurityPolicyRule, ips []string) ([]int32, error) {

var prios []int32

for _, singleRule := range rules {

for _, k := range singleRule.Match.Config.SrcIpRanges {
for _, m := range ips {
if k == m {
found := globalUtils.Find(prios, *singleRule.Priority)
// check if prio already exists in array []prio
// so the ip is in the rule, you can get the prio of this rule
if !found {
prios = append(prios, *singleRule.Priority)
}

}
}
}

}

return prios, nil

}
Loading

0 comments on commit 6383089

Please sign in to comment.