From 5d8146be9e448606980cfa614cf689d9e7015ebd Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 6 Jun 2024 19:07:27 +0530 Subject: [PATCH] feat: add aws client Signed-off-by: Vishal Choudhary --- pkg/clients/aws/events.go | 70 +++++++++++++++++++++++++++++++++++++ pkg/clients/aws/main.go | 61 ++++++++++++++++++++++++++++++++ pkg/clients/aws/policies.go | 22 ++++++++++++ pkg/clients/aws/task.go | 27 ++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 pkg/clients/aws/events.go create mode 100644 pkg/clients/aws/main.go create mode 100644 pkg/clients/aws/policies.go create mode 100644 pkg/clients/aws/task.go diff --git a/pkg/clients/aws/events.go b/pkg/clients/aws/events.go new file mode 100644 index 0000000..9e0be79 --- /dev/null +++ b/pkg/clients/aws/events.go @@ -0,0 +1,70 @@ +package aws + +import "time" + +type LambdaEvent struct { + Version string `json:"version"` + ID string `json:"id"` + DetailType string `json:"detail-type"` + Source string `json:"source"` + Account string `json:"account"` + Time time.Time `json:"time"` + Region string `json:"region"` + Resources []string `json:"resources"` + Detail Detail `json:"detail"` +} +type Details struct { + Name string `json:"name"` + Value string `json:"value"` +} +type Attachments struct { + ID string `json:"id"` + Type string `json:"type"` + Status string `json:"status"` + Details []Details `json:"details"` +} +type Attributes struct { + Name string `json:"name"` + Value string `json:"value"` +} +type Containers struct { + ContainerArn string `json:"containerArn"` + LastStatus string `json:"lastStatus"` + Name string `json:"name"` + Image string `json:"image"` + TaskArn string `json:"taskArn"` + NetworkInterfaces []interface{} `json:"networkInterfaces"` + CPU string `json:"cpu"` + Memory string `json:"memory"` +} +type EphemeralStorage struct { + SizeInGiB int `json:"sizeInGiB"` +} +type ContainerOverrides struct { + Name string `json:"name"` +} +type Overrides struct { + ContainerOverrides []ContainerOverrides `json:"containerOverrides"` +} +type Detail struct { + Attachments []Attachments `json:"attachments"` + Attributes []Attributes `json:"attributes"` + AvailabilityZone string `json:"availabilityZone"` + ClusterArn string `json:"clusterArn"` + Containers []Containers `json:"containers"` + CPU string `json:"cpu"` + CreatedAt time.Time `json:"createdAt"` + DesiredStatus string `json:"desiredStatus"` + EnableExecuteCommand bool `json:"enableExecuteCommand"` + EphemeralStorage EphemeralStorage `json:"ephemeralStorage"` + Group string `json:"group"` + LaunchType string `json:"launchType"` + LastStatus string `json:"lastStatus"` + Memory string `json:"memory"` + Overrides Overrides `json:"overrides"` + PlatformVersion string `json:"platformVersion"` + TaskArn string `json:"taskArn"` + TaskDefinitionArn string `json:"taskDefinitionArn"` + UpdatedAt time.Time `json:"updatedAt"` + Version int `json:"version"` +} diff --git a/pkg/clients/aws/main.go b/pkg/clients/aws/main.go new file mode 100644 index 0000000..0960d70 --- /dev/null +++ b/pkg/clients/aws/main.go @@ -0,0 +1,61 @@ +package aws + +import ( + "encoding/json" + "log" + + "github.com/aws/aws-lambda-go/events" + "github.com/aws/aws-lambda-go/lambda" + "github.com/vishal-chdhry/cloud-image-verification/pkg/imageverifier" +) + +func handler(event events.CloudWatchEvent) { + var eventDetail Detail + err := json.Unmarshal(event.Detail, &eventDetail) + if err != nil { + log.Fatalf("[ERROR] %v error during event unmarshalling: %v", event.ID, err) + } + + lambdaEvent := LambdaEvent{ + Version: event.Version, + ID: event.ID, + DetailType: event.DetailType, + Source: event.Source, + Account: event.AccountID, + Time: event.Time, + Region: event.Region, + Resources: event.Resources, + Detail: eventDetail, + } + + log.Printf("Cluster: %v\n", lambdaEvent.Detail.ClusterArn) + log.Printf("taskArn: %v\n", lambdaEvent.Detail.TaskArn) + log.Printf("taskDefinitionArn: %v\n", lambdaEvent.Detail.TaskDefinitionArn) + log.Printf("accountId: %v\n", lambdaEvent.Account) + + policies, err := getPolicies() + if err != nil { + log.Printf("Failed to fetch policies: %v", err) + } + iv := imageverifier.NewVerifier(*policies) + for i := 0; i < len(lambdaEvent.Detail.Containers); i++ { + log.Printf("Container Image %v : %v", i, lambdaEvent.Detail.Containers[i].Image) + err := iv.Verify(lambdaEvent.Detail.Containers[i].Image) + if err != nil { + log.Printf("Error while verifing image: %v", err) + log.Printf("%v NOT VERIFIED", lambdaEvent.Detail.Containers[i].Image) + log.Printf("Stopping Task %v", lambdaEvent.Detail.TaskArn) + err := stopTask(lambdaEvent.Detail.ClusterArn, lambdaEvent.Detail.TaskArn) + if err != nil { + log.Printf("Stopping Task %v : %v", lambdaEvent.Detail.TaskArn, err) + } + + } else { + log.Println("VERIFIED") + } + } +} + +func main() { + lambda.Start(handler) +} diff --git a/pkg/clients/aws/policies.go b/pkg/clients/aws/policies.go new file mode 100644 index 0000000..ddee99a --- /dev/null +++ b/pkg/clients/aws/policies.go @@ -0,0 +1,22 @@ +package aws + +import ( + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/vishal-chdhry/cloud-image-verification/pkg/policy" +) + +func getPolicies() (*policy.VerificationPolicies, error) { + pol := os.Getenv("VERIFICATION_POLICIES") + if len(pol) != 0 { + return nil, errors.New("must provide VERIFICATION_POLICIES") + } + var validationPolicies policy.VerificationPolicies + if err := json.Unmarshal([]byte(pol), &validationPolicies); err != nil { + return nil, fmt.Errorf("invalid validation policy provided: %w", err) + } + return &validationPolicies, nil +} diff --git a/pkg/clients/aws/task.go b/pkg/clients/aws/task.go new file mode 100644 index 0000000..93b9d30 --- /dev/null +++ b/pkg/clients/aws/task.go @@ -0,0 +1,27 @@ +package aws + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ecs" +) + +type NotificationMessage struct { + Message string + ClusterArn string + TaskDefinitionArn string + TaskArn string +} + +func stopTask(clusterArn string, taskArn string) error { + stopTaskInput := ecs.StopTaskInput{Cluster: aws.String(clusterArn), + Reason: aws.String("lambda error: image not verified"), Task: aws.String(taskArn)} + + var svc = ecs.New(session.Must(session.NewSession())) + + _, err := svc.StopTask(&stopTaskInput) + if err != nil { + return err + } + return nil +}