jonrau1 / ElectricEye

ElectricEye is a multi-cloud, multi-SaaS Python CLI tool for Asset Management, Security Posture Management & Attack Surface Monitoring supporting 100s of services and evaluations to harden your CSP & SaaS environments with controls mapped to over 20 industry, regulatory, and best practice controls frameworks

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[PFR] Asset Management

jonrau1 opened this issue · comments

Story

As the maintainer of ElectricEye I want to add Asset information into every Auditor so that I can enrich current findings and create an Asset Management output module.

Definition of Done

Quite awhile ago on UpWork someone had inquired about adapting ElectricEye to being a "Cloud Asset Manager" tool of sorts, as it already supported ~100 or so components within. While there was certainly room to do so, it did not make a lot of sense, until now.

Since ElectricEye is stuck with ASFF, the ProductFields or UserDefinedFields objects (dict type in Python) can be used which support 47 and 50 key:value pairs, respectively. This can be extracted using custom Outputs and eventually built into the ee-api, ee-frontend, and similar projects / upgrades for ElectricEye 3.0 without breaking any ASFF findings being written to Security Hub directly.

The first pass of sorts needs to have the taxonomy for asset manager written out. The second pass needs to include the actual full context of the Asset itself. Likely taking any response object from the various APIs and writing it into a base64 encoded string which can be decoded when re-writing into an Asset Report or used for API / Front-ends.

The taxonomy should include the Provider (maybe Provider Type?), Category (e.g., Database, Machine Learning, Containers), Asset Service (the actual cloud service name, if available, e.g., AWS IAM, GCP Compute Engine, Azure Front Door), and the Asset Type / Asset Component which is the specific resource/sub-type that the Check is written against such as a User or Instance or Cluster. Ideally without repetition and in as few words as possible.

The outputs should include the resource ID (De-duped), the new Taxonomy and blob, as well as provider-specific information such as Account (or Tenancy, Project, etc.), Region, Partition / special info (differentiating between AWS and AWS GovCloud for instance), and maybe even a Provider Type (SaaS vs CSP?)

Requirements

  • Into every single Auditor insert the following information
    • Provider: Defines the upstream vendor, e.g., Servicenow, AWS, GCP, etc.
    • ProviderType: Defines the kind of provider - SaaS or CSP (can be expanded later)
    • ProviderAccountId: Area for a Project ID, AWS Account ID, OCI Tenancy ID etc to be included - this is to avoid having to differentiate between using the ASFF AwsAccountId field and digging for the Resources.[*].Details.Other to remember what every single Provider unique / top level GUID is called - it should be obvious that ProviderAccountId would be a GCP Project when ProviderType is GCP and respectively goes for Azure Subscription IDs, ServiceNow Instance Names, OCI Tenancies, etc.
    • AssetRegion: Area to define the exact Region an asset exists. Same rational as ProviderAccountId, avoids needing to dig for the non-AWS information. Regions seem to be at least uniform instead of using a "Zone" concept
    • AssetCategory: A high-level descriptor of the category the service maps into - using a modified version of how AWS presents its service offerings. Should NOT include Serverless or Front-End and instead opt-for the "highest level". This can also help capture different components in an offering and how they map. For instance, AWS AppStream 2.0 has in its API schema fleet, image, and user - an AppStream 2.0 User would fit in the Identity & Access Management category whereas an AppStream 2.0 Image would fit into Storage and the AppStream 2.0 Fleet itself would actually be End User Computing
    • AssetComponent: Currently exists as AssetType which needs to be re-written. This is the actual resource the Check within the Auditor is written against. Such as Instance for EC2/GCE/Azure VM or Task Definition within ECS or Volume with Amazon EC2 (EBS?). There SHOULD NOT be repetition here. For instance, instead of saying Amazon EBS Volume just call it Volume. There will be overlaps across CSPs (and some SaaS for things like "User") which is fine. For SaaS providers, this will need to be whatever their respective API or UI defines the "thing" as - in ServiceNow there are a lot of System Property components as that is what the evaluation is against.
    • AssetDetails: Contains a B64 encoded string of whatever the API object is for the asset being assessed
  • New Ouputs for the asset management
    • Requires de-duplication by Resource ID - in AWS this would be an ARN, for everything else use the Resources.[*].Id field
    • Contains the entire asset/provider-specific info from ProductFields
    • Total findings (pass, fail, total) for the Asset
    • Support assets_json and assets_csv as valid ouput types

These new Outputs will need to be overhauled with #110 either way so doesn't need too much craziness. Re-use the "ouput name" from Click

Nice to Have

Really stupid idea for an asset score...

  • Round-up of security findings for an "Asset Security Score" (AssetSecurityScore) which would be Total, Info, Low, Med, High, Critical and then have different weights for each and divide out of 1000 for a "FICO score for assets". This may be a stupid idea...
  • Research any "Cloud BOM" to see if that can be used

Additional Information

Stupid idea for the scoring. Doesn't work

import json

lowFactor = 1.05
mediumFactor = 1.15
highFactor = 1.25
criticalFactor = 1.50

assetScore = {
    "AssetName": "Database_main",
    "InformationalFindings": 20,
    "LowFindings": 5,
    "MediumFindings": 2,
    "HighFindings": 5,
    "CriticalFindings": 1
}

totalFindings = assetScore["InformationalFindings"] + \
                assetScore["LowFindings"] + \
                assetScore["MediumFindings"] + \
                assetScore["HighFindings"] + \
                assetScore["CriticalFindings"]

assetName = assetScore["AssetName"]
print(f"Asset {assetName} has a {totalFindings} total findings")

#     ((assetScore["InformationalFindings"]) * 1000) + \
securityScore = \
    ((assetScore["LowFindings"] * lowFactor) * 1000) + \
    ((assetScore["MediumFindings"] * mediumFactor) * 1000) + \
    ((assetScore["HighFindings"] * highFactor) * 1000) + \
    ((assetScore["CriticalFindings"] * criticalFactor) * 1000)

finalScore = ((assetScore["InformationalFindings"] * 1000) - (securityScore // 4)) / 1000

print(f"Asset {assetName} has a {finalScore} score")