[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
orCSP
(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 ASFFAwsAccountId
field and digging for theResources.[*].Details.Other
to remember what every single Provider unique / top level GUID is called - it should be obvious thatProviderAccountId
would be a GCP Project whenProviderType
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 asProviderAccountId
, avoids needing to dig for the non-AWS information. Regions seem to be at least uniform instead of using a "Zone" conceptAssetCategory
: A high-level descriptor of the category the service maps into - using a modified version of how AWS presents its service offerings. Should NOT includeServerless
orFront-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 schemafleet
,image
, anduser
- an AppStream 2.0 User would fit in theIdentity & Access Management
category whereas an AppStream 2.0 Image would fit intoStorage
and the AppStream 2.0 Fleet itself would actually beEnd User Computing
AssetComponent
: Currently exists asAssetType
which needs to be re-written. This is the actual resource the Check within the Auditor is written against. Such asInstance
for EC2/GCE/Azure VM orTask Definition
within ECS orVolume
with Amazon EC2 (EBS?). There SHOULD NOT be repetition here. For instance, instead of sayingAmazon EBS Volume
just call itVolume
. 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 ofSystem 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
andassets_csv
as valid ouput types
- Requires de-duplication by Resource ID - in AWS this would be an ARN, for everything else use the
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")