Have global data in dom's graph format now. just need to write the table creation code

This commit is contained in:
sethsec-bf committed 2024-01-25 15:24:49 -05:00
1 parent 4d3c6a4c67
commit aeccb6db6d
5 files changed
+600 -52

No files matched your search

+197 -8
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
ingestor "github.com/BishopFox/cloudfox/aws/graph/ingester"
@@ -12,8 +13,10 @@ import (
"github.com/BishopFox/cloudfox/internal"
"github.com/BishopFox/cloudfox/internal/aws/policy"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/iam/types"
"github.com/aws/aws-sdk-go-v2/service/sts"
"github.com/bishopfox/knownawsaccountslookup"
"github.com/dominikbraun/graph"
"github.com/sirupsen/logrus"
)
@@ -45,6 +48,28 @@ type GraphCommand struct {
modLog *logrus.Entry
}
type GraphCommand2 struct {
// General configuration data
Caller sts.GetCallerIdentityOutput
AWSRegions []string
Goroutines int
AWSProfile string
WrapTable bool
AWSOutputType string
AWSTableCols string
Verbosity int
AWSOutputDirectory string
AWSConfig aws.Config
Version string
SkipAdminCheck bool
GlobalGraph graph.Graph[string, string]
output internal.OutputData2
modLog *logrus.Entry
}
func (m *GraphCommand) RunGraphCommand() {
// These struct values are used by the output module
@@ -167,6 +192,57 @@ func (m *GraphCommand) RunGraphCommand() {
}
func (m *GraphCommand2) RunGraphCommand2() {
// These struct values are used by the output module
m.output.Verbosity = m.Verbosity
m.output.Directory = m.AWSOutputDirectory
m.output.CallingModule = "graph"
m.modLog = internal.TxtLog.WithFields(logrus.Fields{
"module": m.output.CallingModule,
})
if m.AWSProfile == "" {
m.AWSProfile = internal.BuildAWSPath(m.Caller)
}
m.output.FilePath = filepath.Join(m.AWSOutputDirectory, "cloudfox-output", "aws", fmt.Sprintf("%s-%s", m.AWSProfile, aws.ToString(m.Caller.Account)))
m.output.Headers = []string{
"Account",
"Principal Arn",
"IsAdmin?",
"CanPrivEscToAdmin?",
}
// If the user specified table columns, use those.
// If the user specified -o wide, use the wide default cols for this module.
// Otherwise, use the hardcoded default cols for this module.
var tableCols []string
// If the user specified table columns, use those.
if m.AWSTableCols != "" {
// If the user specified wide as the output format, use these columns.
// remove any spaces between any commas and the first letter after the commas
m.AWSTableCols = strings.ReplaceAll(m.AWSTableCols, ", ", ",")
m.AWSTableCols = strings.ReplaceAll(m.AWSTableCols, ", ", ",")
tableCols = strings.Split(m.AWSTableCols, ",")
} else if m.AWSOutputType == "wide" {
tableCols = []string{
"Account",
"Principal Arn",
"IsAdmin?",
"CanPrivEscToAdmin?",
}
// Otherwise, use the default columns.
} else {
tableCols = []string{
"Principal Arn",
"IsAdmin?",
"CanPrivEscToAdmin?",
}
}
internal.TxtLog.Debug("tableCols: ", tableCols)
}
func (m *GraphCommand) collectAccountDataForGraph() []models.Account {
//OrganizationsCommandClient := InitOrgClient(m.AWSConfig)
var accounts []models.Account
@@ -257,9 +333,9 @@ func (m *GraphCommand) collectAccountDataForGraph() []models.Account {
func (m *GraphCommand) collectRoleDataForGraph() []models.Role {
var isAdmin, canPrivEscToAdmin string
iamClient := InitIAMClient(m.AWSConfig)
iamSimClient := InitIamCommandClient(iamClient, m.Caller, m.AWSProfile, m.Goroutines)
localAdminMap := make(map[string]bool)
// iamClient := InitIAMClient(m.AWSConfig)
// iamSimClient := InitIamCommandClient(iamClient, m.Caller, m.AWSProfile, m.Goroutines)
// localAdminMap := make(map[string]bool)
var roles []models.Role
IAMCommandClient := InitIAMClient(m.AWSConfig)
@@ -276,11 +352,11 @@ func (m *GraphCommand) collectRoleDataForGraph() []models.Role {
break
}
if m.pmapperError == nil {
isAdmin, canPrivEscToAdmin = GetPmapperResults(m.SkipAdminCheck, m.pmapperMod, role.Arn)
} else {
isAdmin, canPrivEscToAdmin = GetIamSimResult(m.SkipAdminCheck, role.Arn, iamSimClient, localAdminMap)
}
// if m.pmapperError == nil {
// isAdmin, canPrivEscToAdmin = GetPmapperResults(m.SkipAdminCheck, m.pmapperMod, role.Arn)
// } else {
// isAdmin, canPrivEscToAdmin = GetIamSimResult(m.SkipAdminCheck, role.Arn, iamSimClient, localAdminMap)
// }
// for _, row := range m.PermissionRowsFromAllProfiles {
// if row.Arn == aws.ToString(role.Arn) {
@@ -414,3 +490,116 @@ func (m *GraphCommand) collectRoleDataForGraph() []models.Role {
}
return roles
}
func ConvertIAMRoleToModelRole(role types.Role, vendors *knownawsaccountslookup.Vendors) models.Role {
var isAdmin, canPrivEscToAdmin string
accountId := strings.Split(aws.ToString(role.Arn), ":")[4]
trustsdoc, err := policy.ParseRoleTrustPolicyDocument(role)
if err != nil {
internal.TxtLog.Error(err.Error())
return models.Role{}
}
var TrustedPrincipals []models.TrustedPrincipal
var TrustedServices []models.TrustedService
var TrustedFederatedProviders []models.TrustedFederatedProvider
//var TrustedFederatedSubjects string
var trustedProvider string
var trustedSubjects string
var vendorName string
for _, statement := range trustsdoc.Statement {
for _, principal := range statement.Principal.AWS {
if strings.Contains(principal, ":root") {
//check to see if the accountID is known
accountID := strings.Split(principal, ":")[4]
vendorName = vendors.GetVendorNameFromAccountID(accountID)
}
TrustedPrincipals = append(TrustedPrincipals, models.TrustedPrincipal{
TrustedPrincipal: principal,
ExternalID: statement.Condition.StringEquals.StsExternalID,
VendorName: vendorName,
//IsAdmin: false,
//CanPrivEscToAdmin: false,
})
}
for _, service := range statement.Principal.Service {
TrustedServices = append(TrustedServices, models.TrustedService{
TrustedService: service,
AccountID: accountId,
//IsAdmin: false,
//CanPrivEscToAdmin: false,
})
}
for _, federated := range statement.Principal.Federated {
if statement.Condition.StringLike.TokenActionsGithubusercontentComAud != "" || len(statement.Condition.StringLike.TokenActionsGithubusercontentComSub) > 0 {
trustedProvider = "GitHub"
trustedSubjects := strings.Join(statement.Condition.StringLike.TokenActionsGithubusercontentComSub, ",")
if trustedSubjects == "" {
trustedSubjects = "ALL REPOS!!!"
} else {
trustedSubjects = "Repos: " + trustedSubjects
}
} else if statement.Condition.StringEquals.SAMLAud == "https://signin.aws.amazon.com/saml" {
if strings.Contains(statement.Principal.Federated[0], "AWSSSO") {
trustedProvider = "AWS SSO" // (" + statement.Principal.Federated[0] + ")"
} else if strings.Contains(statement.Principal.Federated[0], "Okta") {
trustedProvider = "Okta" // (" + statement.Principal.Federated[0] + ")"
}
trustedSubjects = "Not applicable"
} else if statement.Condition.StringEquals.OidcEksAud != "" || statement.Condition.StringEquals.OidcEksSub != "" || statement.Condition.StringLike.OidcEksAud != "" || statement.Condition.StringLike.OidcEksSub != "" {
trustedProvider = "EKS" // (" + statement.Principal.Federated[0] + ")"
if statement.Condition.StringEquals.OidcEksSub != "" {
trustedSubjects = statement.Condition.StringEquals.OidcEksSub
} else if statement.Condition.StringLike.OidcEksSub != "" {
trustedSubjects = statement.Condition.StringLike.OidcEksSub
} else {
trustedSubjects = "ALL SERVICE ACCOUNTS!"
}
} else if statement.Principal.Federated[0] == "cognito-identity.amazonaws.com" {
trustedProvider = "Cognito" // (" + statement.Principal.Federated[0] + ")"
if statement.Condition.ForAnyValueStringLike.CognitoAMR != "" {
trustedSubjects = statement.Condition.ForAnyValueStringLike.CognitoAMR
}
} else {
if trustedProvider == "" && strings.Contains(statement.Principal.Federated[0], "oidc.eks") {
trustedProvider = "EKS" // (" + statement.Principal.Federated[0] + ")"
trustedSubjects = "ALL SERVICE ACCOUNTS!"
} else if trustedProvider == "" && strings.Contains(statement.Principal.Federated[0], "AWSSSO") {
trustedProvider = "AWS SSO" // (" + statement.Principal.Federated[0] + ")"
}
trustedSubjects = "Not applicable"
}
TrustedFederatedProviders = append(TrustedFederatedProviders, models.TrustedFederatedProvider{
TrustedFederatedProvider: federated,
ProviderShortName: trustedProvider,
TrustedSubjects: trustedSubjects,
//IsAdmin: false,
//CanPrivEscToAdmin: false,
})
}
}
//create new object of type models.Role
cfRole := models.Role{
Id: aws.ToString(role.Arn),
AccountID: accountId,
ARN: aws.ToString(role.Arn),
Name: aws.ToString(role.RoleName),
TrustsDoc: trustsdoc,
TrustedPrincipals: TrustedPrincipals,
TrustedServices: TrustedServices,
TrustedFederatedProviders: TrustedFederatedProviders,
CanPrivEscToAdmin: canPrivEscToAdmin,
IsAdmin: isAdmin,
}
//roles = append(roles, role)
return cfRole
}
+247 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/BishopFox/cloudfox/aws/graph/ingester/schema"
"github.com/BishopFox/cloudfox/internal/aws/policy"
"github.com/BishopFox/cloudfox/internal/common"
"github.com/dominikbraun/graph"
)
type Role struct {
@@ -22,7 +23,8 @@ type Role struct {
IsAdmin string
IdValue string
IsAdminP bool
PathToAdmin bool
PathToAdminSameAccount bool
PathToAdminCrossAccount bool
}
type TrustedPrincipal struct {
@@ -113,6 +115,7 @@ func (a *Role) MakeRelationships() []schema.Relationship {
TargetLabel: schema.Role,
RelationshipType: schema.CanAssume,
})
// make a CAN_BE_ASSUMED_BY relationship between this role and the trusted principal
// relationships = append(relationships, schema.Relationship{
// SourceNodeID: a.Id,
@@ -326,3 +329,246 @@ func (a *Role) MakeRelationships() []schema.Relationship {
return relationships
}
// func (a *Role) MakeVertex() {
// // make a vertex for this role as populate all of the data in the Role struct as attributes
// err := GlobalGraph.AddVertex(
// a.Id,
// graph.VertexAttribute("Name", a.Name),
// graph.VertexAttribute("Type", "Role"),
// graph.VertexAttribute("AccountID", a.AccountID),
// graph.VertexAttribute("ARN", a.ARN),
// graph.VertexAttribute("CanPrivEscToAdmin", a.CanPrivEscToAdmin),
// graph.VertexAttribute("IsAdmin", a.IsAdmin),
// graph.VertexAttribute("IdValue", a.IdValue),
// graph.VertexAttribute("IsAdminP", a.IsAdminP),
// graph.VertexAttribute("PathToAdminSameAccount", a.PathToAdminSameAccount),
// graph.VertexAttribute("PathToAdminCrossAccount", a.PathToAdminCrossAccount),
// )
// }
func (a *Role) MakeEdges(GlobalGraph graph.Graph[string, string]) []schema.Relationship {
var relationships []schema.Relationship
// get thisAccount id from role arn
var thisAccount string
if len(a.ARN) >= 25 {
thisAccount = a.ARN[13:25]
} else {
fmt.Sprintf("Could not get account number from this role arn%s", a.ARN)
}
for _, TrustedPrincipal := range a.TrustedPrincipals {
//get account id from the trusted principal arn
var trustedPrincipalAccount string
if len(TrustedPrincipal.TrustedPrincipal) >= 25 {
trustedPrincipalAccount = TrustedPrincipal.TrustedPrincipal[13:25]
} else {
fmt.Sprintf("Could not get account number from this TrustedPrincipal%s", TrustedPrincipal.TrustedPrincipal)
}
var PermissionsRowAccount string
// if the role trusts a principal in this same account explicitly, then the principal can assume the role
if thisAccount == trustedPrincipalAccount {
// make a CAN_ASSUME relationship between the trusted principal and this role
err := GlobalGraph.AddEdge(
TrustedPrincipal.TrustedPrincipal,
a.Id,
graph.EdgeAttribute("AssumeRole", "Same account explicit trust"),
)
if err != nil {
fmt.Println(err)
fmt.Println(TrustedPrincipal.TrustedPrincipal + a.Id + "Same account explicit trust")
}
}
// If the role trusts a principal in this account or another account using the :root notation, then we need to iterate over all of the rows in AllPermissionsRows to find the principals that have sts:AssumeRole permissions on this role
// if the role we are looking at trusts root in it's own account
if strings.Contains(TrustedPrincipal.TrustedPrincipal, fmt.Sprintf("%s:root", thisAccount)) {
err := GlobalGraph.AddVertex(
a.Id,
graph.VertexAttribute("Name", a.Name),
graph.VertexAttribute("Type", "Account"),
graph.VertexAttribute("AccountID", a.AccountID),
)
if err != nil {
if err == graph.ErrVertexAlreadyExists {
fmt.Println(a.Id + " already exists")
}
}
// iterate over all rows in AllPermissionsRows
for _, PermissionsRow := range common.PermissionRowsFromAllProfiles {
// but we only care about the rows that have arns that are in this account
if len(PermissionsRow.Arn) >= 25 {
PermissionsRowAccount = PermissionsRow.Arn[13:25]
} else {
fmt.Sprintf("Could not get account number from this PermissionsRow%s", PermissionsRow.Arn)
}
if PermissionsRowAccount == thisAccount {
// lets only look for rows that have sts:AssumeRole permissions
if strings.EqualFold(PermissionsRow.Action, "sts:AssumeRole") ||
strings.EqualFold(PermissionsRow.Action, "*") ||
strings.EqualFold(PermissionsRow.Action, "sts:Assume*") ||
strings.EqualFold(PermissionsRow.Action, "sts:*") {
// lets only focus on rows that have an effect of Allow
if strings.EqualFold(PermissionsRow.Effect, "Allow") {
// if the resource is * or the resource is this role arn, then this principal can assume this role
if PermissionsRow.Resource == "*" || strings.Contains(PermissionsRow.Resource, a.ARN) {
// make a CAN_ASSUME relationship between the trusted principal and this role
//evalutate if the princiapl is a user or a role and set a variable accordingly
//var principalType schema.NodeLabel
if strings.EqualFold(PermissionsRow.Type, "User") {
err := GlobalGraph.AddEdge(
PermissionsRow.Arn,
a.Id,
graph.EdgeAttribute("AssumeRole", "Same account root trust and trusted principal has permission to assume role"),
)
if err != nil {
fmt.Println(err)
fmt.Println(PermissionsRow.Arn + a.Id + "Same account root trust and trusted principal has permission to assume role")
}
} else if strings.EqualFold(PermissionsRow.Type, "Role") {
err := GlobalGraph.AddEdge(
PermissionsRow.Arn,
a.Id,
graph.EdgeAttribute("AssumeRole", "Same account root trust and trusted principal has permission to assume role"),
)
if err != nil {
fmt.Println(err)
fmt.Println(PermissionsRow.Arn + a.Id + "Same account root trust and trusted principal has permission to assume role")
}
}
}
}
}
}
}
} else if strings.Contains(TrustedPrincipal.TrustedPrincipal, ":root") && TrustedPrincipal.VendorName != "" {
err := GlobalGraph.AddVertex(
a.Id,
graph.VertexAttribute("Name", a.Name),
graph.VertexAttribute("Type", "Account"),
graph.VertexAttribute("AccountID", a.AccountID),
graph.VertexAttribute("VendorName", TrustedPrincipal.VendorName),
)
if err != nil {
if err == graph.ErrVertexAlreadyExists {
fmt.Println(a.Id + " already exists")
}
}
// If the role trusts :root in another account and the trusted principal is a vendor, we will make a relationship between our role and a vendor node instead of a principal node
relationships = append(relationships, schema.Relationship{
SourceNodeID: TrustedPrincipal.TrustedPrincipal,
TargetNodeID: a.Id,
SourceLabel: schema.Vendor,
TargetLabel: schema.Role,
RelationshipType: schema.CanAssume,
})
err = GlobalGraph.AddEdge(
//TrustedPrincipal.TrustedPrincipal,
TrustedPrincipal.VendorName,
a.Id,
graph.EdgeAttribute("VendorAssumeRole", "Cross account root trust and trusted principal is a vendor"),
)
if err != nil {
fmt.Println(err)
fmt.Println(TrustedPrincipal.VendorName + a.Id + "Cross account root trust and trusted principal is a vendor")
}
} else if strings.Contains(TrustedPrincipal.TrustedPrincipal, fmt.Sprintf("%s:root", trustedPrincipalAccount)) {
err := GlobalGraph.AddVertex(
a.Id,
graph.VertexAttribute("Name", a.Name),
graph.VertexAttribute("Type", "Account"),
graph.VertexAttribute("AccountID", a.AccountID),
)
if err != nil {
if err == graph.ErrVertexAlreadyExists {
fmt.Println(a.Id + " already exists")
}
}
// iterate over all rows in AllPermissionsRows
for _, PermissionsRow := range common.PermissionRowsFromAllProfiles {
// but we only care about the rows that have arns that are in this other account
if len(PermissionsRow.Arn) >= 25 {
PermissionsRowAccount = PermissionsRow.Arn[13:25]
} else {
fmt.Sprintf("Could not get account number from this PermissionsRow%s", PermissionsRow.Arn)
}
if PermissionsRowAccount == trustedPrincipalAccount {
// lets only look for rows that have sts:AssumeRole permissions
if strings.EqualFold(PermissionsRow.Action, "sts:AssumeRole") ||
strings.EqualFold(PermissionsRow.Action, "*") ||
strings.EqualFold(PermissionsRow.Action, "sts:Assume*") ||
strings.EqualFold(PermissionsRow.Action, "sts:*") {
// lets only focus on rows that have an effect of Allow
if strings.EqualFold(PermissionsRow.Effect, "Allow") {
// if the resource is * or the resource is this role arn, then this principal can assume this role
if PermissionsRow.Resource == "*" || strings.Contains(PermissionsRow.Resource, a.ARN) {
// make a CAN_ASSUME relationship between the trusted principal and this role
if strings.EqualFold(PermissionsRow.Type, "User") {
err := GlobalGraph.AddEdge(
PermissionsRow.Arn,
a.Id,
graph.EdgeAttribute("CrossAccountAssumeRole", "Cross account root trust and trusted principal has permission to assume role"),
)
if err != nil {
fmt.Println(err)
fmt.Println(PermissionsRow.Arn + a.Id + "Cross account root trust and trusted principal has permission to assume role")
}
} else if strings.EqualFold(PermissionsRow.Type, "Role") {
err := GlobalGraph.AddEdge(
PermissionsRow.Arn,
a.Id,
graph.EdgeAttribute("CrossAccountAssumeRole", "Cross account root trust and trusted principal has permission to assume role"),
)
if err != nil {
fmt.Println(err)
fmt.Println(PermissionsRow.Arn + a.Id + "Cross account root trust and trusted principal has permission to assume role")
}
}
}
}
}
}
}
}
}
// pmapper takes care of this part so commenting out for now - but leaving as a placeholder
// for _, TrustedService := range a.TrustedServices {
// // make relationship from trusted service to this role of type can assume
// // make relationship from this role to trusted service of type can be assumed by
// }
for _, TrustedFederatedProvider := range a.TrustedFederatedProviders {
// make relationship from trusted federated provider to this role of type can assume
GlobalGraph.AddVertex(
TrustedFederatedProvider.TrustedFederatedProvider,
graph.VertexAttribute("Type", "FederatedIdentity"),
)
err := GlobalGraph.AddEdge(
TrustedFederatedProvider.TrustedFederatedProvider,
a.Id,
graph.EdgeAttribute("FederatedAssumeRole", "Trusted federated provider"),
)
if err != nil {
fmt.Println(err)
fmt.Println(TrustedFederatedProvider.TrustedFederatedProvider + a.Id + "Trusted federated provider")
}
}
return relationships
}
+33 -1
View File
@@ -115,7 +115,39 @@ func (m *PmapperModule) createAndPopulateGraph() graph.Graph[string, string] {
}
for _, edge := range m.Edges {
_ = pmapperGraph.AddEdge(edge.Source, edge.Destination)
err := pmapperGraph.AddEdge(
edge.Source,
edge.Destination,
graph.EdgeAttribute(edge.ShortReason, edge.Reason),
)
if err != nil {
if err == graph.ErrEdgeAlreadyExists {
// update the ege by copying the existing graph.Edge with attributes and add the new attributes
//fmt.Println("Edge already exists, but adding a new one!")
// get the existing edge
existingEdge, _ := pmapperGraph.Edge(edge.Source, edge.Destination)
// get the map of attributes
existingProperties := existingEdge.Properties
// add the new attributes to attributes map within the properties struct
// Check if the Attributes map is initialized, if not, initialize it
if existingProperties.Attributes == nil {
existingProperties.Attributes = make(map[string]string)
}
// Add or update the attribute
existingProperties.Attributes[edge.ShortReason] = edge.Reason
//Update the edge
pmapperGraph.UpdateEdge(
edge.Source,
edge.Destination,
graph.EdgeAttributes(existingProperties.Attributes),
)
}
//fmt.Println(edge.Reason)
}
}
//internal.Cache.Set(cacheKey, pmapperGraph, cache.DefaultExpiration)
+123 -38
View File
@@ -8,6 +8,7 @@ import (
"path/filepath"
"github.com/BishopFox/cloudfox/aws"
"github.com/BishopFox/cloudfox/aws/graph/ingester/schema/models"
"github.com/BishopFox/cloudfox/aws/sdk"
"github.com/BishopFox/cloudfox/internal"
"github.com/BishopFox/cloudfox/internal/common"
@@ -60,6 +61,8 @@ import (
"github.com/aws/aws-sdk-go-v2/service/sqs"
"github.com/aws/aws-sdk-go-v2/service/ssm"
"github.com/aws/smithy-go/ptr"
"github.com/bishopfox/knownawsaccountslookup"
"github.com/dominikbraun/graph"
"github.com/fatih/color"
"github.com/kyokomi/emoji"
"github.com/spf13/cobra"
@@ -932,31 +935,12 @@ func runFilesystemsCommand(cmd *cobra.Command, args []string) {
}
func runGraphCommand(cmd *cobra.Command, args []string) {
for _, profile := range AWSProfiles {
//var AWSConfig = internal.AWSConfigFileLoader(profile, cmd.Root().Version)
caller, err := internal.AWSWhoami(profile, cmd.Root().Version, AWSMFAToken)
if err != nil {
continue
}
//instantiate a permissions client and populate the permissions data
fmt.Println("Getting GAAD for " + profile)
PermissionsCommandClient := aws.InitPermissionsClient(*caller, profile, cmd.Root().Version, Goroutines, AWSMFAToken)
PermissionsCommandClient.GetGAAD()
PermissionsCommandClient.ParsePermissions("")
common.PermissionRowsFromAllProfiles = append(common.PermissionRowsFromAllProfiles, PermissionsCommandClient.Rows...)
}
// for _, profile := range AWSProfiles {
// caller, err := internal.AWSWhoami(profile, cmd.Root().Version, AWSMFAToken)
// if err != nil {
// continue
// }
// fmt.PrintLn("Importing Pmapper for " + profile)
// }
GlobalGraph := graph.New(graph.StringHash, graph.Directed())
//var PermissionRowsFromAllProfiles []common.PermissionsRow
var GlobalRoles []models.Role
vendors := knownawsaccountslookup.NewVendorMap()
vendors.PopulateKnownAWSAccounts()
for _, profile := range AWSProfiles {
var AWSConfig = internal.AWSConfigFileLoader(profile, cmd.Root().Version, AWSMFAToken)
caller, err := internal.AWSWhoami(profile, cmd.Root().Version, AWSMFAToken)
@@ -964,22 +948,123 @@ func runGraphCommand(cmd *cobra.Command, args []string) {
continue
}
graphCommandClient := aws.GraphCommand{
Caller: *caller,
AWSProfile: profile,
Goroutines: Goroutines,
AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken),
WrapTable: AWSWrapTable,
AWSOutputType: AWSOutputType,
AWSTableCols: AWSTableCols,
AWSOutputDirectory: AWSOutputDirectory,
Verbosity: Verbosity,
AWSConfig: AWSConfig,
Version: cmd.Root().Version,
SkipAdminCheck: AWSSkipAdminCheck,
//Gather all Permissions data
fmt.Println("Getting GAAD for " + profile)
PermissionsCommandClient := aws.InitPermissionsClient(*caller, profile, cmd.Root().Version, Goroutines, AWSMFAToken)
PermissionsCommandClient.GetGAAD()
PermissionsCommandClient.ParsePermissions("")
common.PermissionRowsFromAllProfiles = append(common.PermissionRowsFromAllProfiles, PermissionsCommandClient.Rows...)
// Gather all Pmapper data
fmt.Println("Importing Pmapper for " + profile)
pmapperMod, pmapperError := aws.InitPmapperGraph(*caller, AWSProfile, Goroutines)
if pmapperError != nil {
fmt.Println("Error importing pmapper data: " + pmapperError.Error())
}
graphCommandClient.RunGraphCommand()
for _, node := range pmapperMod.Nodes {
GlobalGraph.AddVertex(node.Arn)
}
for _, edge := range pmapperMod.Edges {
err := GlobalGraph.AddEdge(
edge.Source,
edge.Destination,
graph.EdgeAttribute(edge.ShortReason, edge.Reason),
)
if err != nil {
if err == graph.ErrEdgeAlreadyExists {
// update the ege by copying the existing graph.Edge with attributes and add the new attributes
//fmt.Println("Edge already exists")
// get the existing edge
existingEdge, _ := GlobalGraph.Edge(edge.Source, edge.Destination)
// get the map of attributes
existingProperties := existingEdge.Properties
// add the new attributes to attributes map within the properties struct
// Check if the Attributes map is initialized, if not, initialize it
if existingProperties.Attributes == nil {
existingProperties.Attributes = make(map[string]string)
}
// Add or update the attribute
existingProperties.Attributes[edge.ShortReason] = edge.Reason
GlobalGraph.UpdateEdge(
edge.Source,
edge.Destination,
graph.EdgeAttributes(existingProperties.Attributes),
)
}
}
}
//Gather all role data
fmt.Println("Getting Roles for " + profile)
IAMCommandClient := aws.InitIAMClient(AWSConfig)
ListRolesOutput, err := sdk.CachedIamListRoles(IAMCommandClient, ptr.ToString(caller.Account))
if err != nil {
internal.TxtLog.Error(err)
}
for _, role := range ListRolesOutput {
modelRole := aws.ConvertIAMRoleToModelRole(role, vendors)
GlobalRoles = append(GlobalRoles, modelRole)
}
//making edges
fmt.Println("Making edges for " + profile)
for _, role := range GlobalRoles {
role.MakeEdges(GlobalGraph)
}
// print how many nodes and edges are in the graph to the screen and exit
for _, profile := range AWSProfiles {
var AWSConfig = internal.AWSConfigFileLoader(profile, cmd.Root().Version, AWSMFAToken)
caller, err := internal.AWSWhoami(profile, cmd.Root().Version, AWSMFAToken)
if err != nil {
continue
}
// graphCommandClient := aws.GraphCommand{
// Caller: *caller,
// AWSProfile: profile,
// Goroutines: Goroutines,
// AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken),
// WrapTable: AWSWrapTable,
// AWSOutputType: AWSOutputType,
// AWSTableCols: AWSTableCols,
// AWSOutputDirectory: AWSOutputDirectory,
// Verbosity: Verbosity,
// AWSConfig: AWSConfig,
// Version: cmd.Root().Version,
// SkipAdminCheck: AWSSkipAdminCheck,
// }
// graphCommandClient.RunGraphCommand()
graphCommandClient := aws.GraphCommand2{
Caller: *caller,
AWSProfile: profile,
Goroutines: Goroutines,
AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken),
WrapTable: AWSWrapTable,
AWSOutputType: AWSOutputType,
AWSTableCols: AWSTableCols,
AWSOutputDirectory: AWSOutputDirectory,
Verbosity: Verbosity,
AWSConfig: AWSConfig,
Version: cmd.Root().Version,
SkipAdminCheck: AWSSkipAdminCheck,
GlobalGraph: GlobalGraph,
}
graphCommandClient.RunGraphCommand2()
}
}
// // print the edges to the screen
// edges, _ := GlobalGraph.Edges()
// for _, edge := range edges {
// fmt.Println(edge)
// }
}
func runIamSimulatorCommand(cmd *cobra.Command, args []string) {
-4
View File
@@ -1,7 +1,5 @@
package common
import "github.com/dominikbraun/graph"
type PermissionsRow struct {
AWSService string
Type string
@@ -17,5 +15,3 @@ type PermissionsRow struct {
}
var PermissionRowsFromAllProfiles []PermissionsRow
var GlobalGraph graph.Graph[string, string]