diff --git a/cloudtrail-api/go.mod b/cloudtrail-api/go.mod index d7881b8..fb948b9 100644 --- a/cloudtrail-api/go.mod +++ b/cloudtrail-api/go.mod @@ -6,7 +6,6 @@ require ( github.com/aws/aws-sdk-go-v2 v1.38.3 github.com/aws/aws-sdk-go-v2/config v1.30.3 github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.51.0 - github.com/aws/aws-sdk-go-v2/service/costexplorer v1.54.0 github.com/aws/aws-sdk-go-v2/service/ec2 v1.251.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.86.0 github.com/aws/aws-sdk-go-v2/service/sts v1.36.0 diff --git a/cloudtrail-api/go.sum b/cloudtrail-api/go.sum index 861b074..8b1ff25 100644 --- a/cloudtrail-api/go.sum +++ b/cloudtrail-api/go.sum @@ -18,8 +18,6 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.2 h1:sBpc8Ph6CpfZsEdkz/8bfg8WhKlW github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.2/go.mod h1:Z2lDojZB+92Wo6EKiZZmJid9pPrDJW2NNIXSlaEfVlU= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.51.0 h1:mEDXhybFN7q39EBrN3SiZt0sebBU18ZNUuvOPftYI84= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.51.0/go.mod h1:bAz9Mfw6YqILCw087zDfCyDuZNs4wK4S+G+JSHBSyW0= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.54.0 h1:5e/C1PaQywGtklpMotdHKon/8MfsDyzJ9WFh0ge8G38= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.54.0/go.mod h1:tR04F/rUvoQ/5YFp3XS+SDB6pWc/Ls0f19WKA8PauDI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.251.0 h1:hGHSNZDTFnhLGUpRkQORM8uBY9R/FOkxCkuUUJBEOQ4= github.com/aws/aws-sdk-go-v2/service/ec2 v1.251.0/go.mod h1:SmMqzfS4HVsOD58lwLZ79oxF58f8zVe5YdK3o+/o1Ck= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= diff --git a/cloudtrail-api/main.go b/cloudtrail-api/main.go index 4a8e0ab..8b9973a 100644 --- a/cloudtrail-api/main.go +++ b/cloudtrail-api/main.go @@ -70,23 +70,6 @@ func main() { } _ = utils.StoreCreateEventSqlite(db, event) } - - // Aggregate costs per user and resource - userResources, err := utils.GetUserResourcesSqlite(db) - utils.Err("error getting user resources: %v", err) - - result := make(map[string]map[string]float64) - for user, resources := range userResources { - costs, err := utils.GetResourceCosts(cfg, resources) - if err != nil { - continue - } - result[user] = costs - } - - out, err := json.MarshalIndent(result, "", " ") - utils.Err("error marshalling result: %s", err) - fmt.Println(string(out)) } var events = []string{ diff --git a/cloudtrail-api/utils/aws_utils.go b/cloudtrail-api/utils/aws_utils.go index f779ca3..c4e58c4 100644 --- a/cloudtrail-api/utils/aws_utils.go +++ b/cloudtrail-api/utils/aws_utils.go @@ -2,17 +2,14 @@ package utils import ( "context" - "database/sql" - _ "github.com/mattn/go-sqlite3" "log" - "strconv" "strings" "time" + _ "github.com/mattn/go-sqlite3" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/service/costexplorer" - costexplorerTypes "github.com/aws/aws-sdk-go-v2/service/costexplorer/types" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/sts" ) @@ -55,91 +52,3 @@ type CreateEvent struct { ResourceId string Timestamp time.Time } - -const SqliteDBPath = "finleap_events.db" - -// Initialize SQLite DB and create table if not exists -func InitSqliteDB() (*sql.DB, error) { - db, err := sql.Open("sqlite3", SqliteDBPath) - if err != nil { - return nil, err - } - createTable := `CREATE TABLE IF NOT EXISTS events ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT, - resource_id TEXT, - timestamp TEXT - );` - _, err = db.Exec(createTable) - if err != nil { - return nil, err - } - return db, nil -} - -// Store a create event in SQLite -func StoreCreateEventSqlite(db *sql.DB, event CreateEvent) error { - stmt := `INSERT INTO events (username, resource_id, timestamp) VALUES (?, ?, ?)` - _, err := db.Exec(stmt, event.Username, event.ResourceId, event.Timestamp.Format(time.RFC3339)) - return err -} - -// Get all resources created by each user from SQLite -func GetUserResourcesSqlite(db *sql.DB) (map[string][]string, error) { - result := make(map[string][]string) - rows, err := db.Query(`SELECT username, resource_id FROM events`) - if err != nil { - return nil, err - } - defer rows.Close() - for rows.Next() { - var username, resourceId string - if err := rows.Scan(&username, &resourceId); err != nil { - continue - } - result[username] = append(result[username], resourceId) - } - return result, nil -} - -// Get cost for a list of resources using Cost Explorer -func GetResourceCosts(cfg aws.Config, resources []string) (map[string]float64, error) { - ce := costexplorer.NewFromConfig(cfg) - costs := make(map[string]float64) - end := time.Now().Format("2006-01-02") - start := "2023-01-01" // Change as needed - for _, resource := range resources { - input := &costexplorer.GetCostAndUsageInput{ - TimePeriod: &costexplorerTypes.DateInterval{ - Start: &start, - End: &end, - }, - Granularity: costexplorerTypes.GranularityMonthly, - Metrics: []string{"UnblendedCost"}, - Filter: &costexplorerTypes.Expression{ - Dimensions: &costexplorerTypes.DimensionValues{ - Key: costexplorerTypes.DimensionResourceId, - Values: []string{resource}, - }, - }, - } - resp, err := ce.GetCostAndUsage(context.TODO(), input) - if err != nil { - costs[resource] = 0.0 - continue - } - var total float64 - for _, res := range resp.ResultsByTime { - for _, grp := range res.Groups { - for _, met := range grp.Metrics { - amt, err := strconv.ParseFloat(*met.Amount, 64) - if err == nil { - total += amt - } - } - } - } - costs[resource] = total - } - return costs, nil -} diff --git a/cloudtrail-api/utils/database.go b/cloudtrail-api/utils/database.go new file mode 100644 index 0000000..9441c5c --- /dev/null +++ b/cloudtrail-api/utils/database.go @@ -0,0 +1,58 @@ +package utils + +import ( + "database/sql" + "time" +) + +const SqliteDBPath = "finleap_events.db" + +// Initialize SQLite DB and create table if not exists +func InitSqliteDB() (*sql.DB, error) { + // TODO: remove this after using actual data from ../../cloudtrail-dynamodb instead of SQLite + + db, err := sql.Open("sqlite3", SqliteDBPath) + if err != nil { + return nil, err + } + createTable := `CREATE TABLE IF NOT EXISTS events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT, + resource_id TEXT, + timestamp TEXT + );` + _, err = db.Exec(createTable) + if err != nil { + return nil, err + } + return db, nil +} + +// Store a create event in SQLite +func StoreCreateEventSqlite(db *sql.DB, event CreateEvent) error { + // TODO: remove this after using actual data from ../../cloudtrail-dynamodb instead of SQLite + + stmt := `INSERT INTO events (username, resource_id, timestamp) VALUES (?, ?, ?)` + _, err := db.Exec(stmt, event.Username, event.ResourceId, event.Timestamp.Format(time.RFC3339)) + return err +} + +// Get all resources created by each user from SQLite +func GetUserResourcesSqlite(db *sql.DB) (map[string][]string, error) { + // TODO: use actual data from ../../cloudtrail-dynamodb instead of SQLite + + result := make(map[string][]string) + rows, err := db.Query(`SELECT username, resource_id FROM events`) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var username, resourceId string + if err := rows.Scan(&username, &resourceId); err != nil { + continue + } + result[username] = append(result[username], resourceId) + } + return result, nil +}