diff --git a/client/workflows.go b/client/workflows.go
deleted file mode 100644
index faad86b..0000000
--- a/client/workflows.go
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package client
-
-import (
- "context"
- "fmt"
- "net/url"
-
- "github.com/bloodhoundad/azurehound/client/query"
- "github.com/bloodhoundad/azurehound/client/rest"
- "github.com/bloodhoundad/azurehound/models/azure"
-)
-
-func (s *azureClient) GetAzureWorkflow(ctx context.Context, subscriptionId, groupName, workflowName, expand string) (*azure.Workflow, error) {
- var (
- path = fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Logic/workflows/%s", subscriptionId, groupName, workflowName)
- params = query.Params{ApiVersion: "2016-06-01", Expand: expand}.AsMap()
- headers map[string]string
- response azure.Workflow
- )
- if res, err := s.resourceManager.Get(ctx, path, params, headers); err != nil {
- return nil, err
- } else if err := rest.Decode(res.Body, &response); err != nil {
- return nil, err
- } else {
- return &response, nil
- }
-}
-
-func (s *azureClient) GetAzureWorkflows(ctx context.Context, subscriptionId string, filter string, top int32) (azure.WorkflowList, error) {
- var (
- path = fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Logic/workflows", subscriptionId)
- params = query.Params{ApiVersion: "2016-06-01", Filter: filter, Top: top}.AsMap()
- headers map[string]string
- response azure.WorkflowList
- )
-
- if res, err := s.resourceManager.Get(ctx, path, params, headers); err != nil {
- return response, err
- } else if err := rest.Decode(res.Body, &response); err != nil {
- return response, err
- } else {
- return response, nil
- }
-}
-
-func (s *azureClient) ListAzureWorkflows(ctx context.Context, subscriptionId string, filter string, top int32) <-chan azure.WorkflowResult {
- out := make(chan azure.WorkflowResult)
-
- go func() {
- defer close(out)
-
- var (
- errResult = azure.WorkflowResult{
- SubscriptionId: subscriptionId,
- }
- nextLink string
- )
-
- if result, err := s.GetAzureWorkflows(ctx, subscriptionId, filter, top); err != nil {
- errResult.Error = err
- out <- errResult
- } else {
- for _, u := range result.Value {
- out <- azure.WorkflowResult{SubscriptionId: subscriptionId, Ok: u}
- }
-
- nextLink = result.NextLink
- for nextLink != "" {
- var list azure.WorkflowList
- if url, err := url.Parse(nextLink); err != nil {
- errResult.Error = err
- out <- errResult
- nextLink = ""
- } else if req, err := rest.NewRequest(ctx, "GET", url, nil, nil, nil); err != nil {
- errResult.Error = err
- out <- errResult
- nextLink = ""
- } else if res, err := s.resourceManager.Send(req); err != nil {
- errResult.Error = err
- out <- errResult
- nextLink = ""
- } else if err := rest.Decode(res.Body, &list); err != nil {
- errResult.Error = err
- out <- errResult
- nextLink = ""
- } else {
- for _, u := range list.Value {
- out <- azure.WorkflowResult{
- SubscriptionId: "/subscriptions/" + subscriptionId,
- Ok: u,
- }
- }
- nextLink = list.NextLink
- }
- }
- }
- }()
- return out
-}
diff --git a/cmd/list-workflow-role-assignments.go b/cmd/list-workflow-role-assignments.go
deleted file mode 100644
index 7d4709b..0000000
--- a/cmd/list-workflow-role-assignments.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package cmd
-
-import (
- "context"
- "fmt"
- "os"
- "os/signal"
- "path"
- "sync"
- "time"
-
- "github.com/bloodhoundad/azurehound/client"
- "github.com/bloodhoundad/azurehound/enums"
- "github.com/bloodhoundad/azurehound/models"
- "github.com/bloodhoundad/azurehound/pipeline"
- "github.com/spf13/cobra"
-)
-
-func init() {
- listRootCmd.AddCommand(listWorkflowRoleAssignment)
-}
-
-var listWorkflowRoleAssignment = &cobra.Command{
- Use: "workflow-role-assignments",
- Long: "Lists Azure Workflow (Logic apps) Owners and Contributors",
- Run: listWorkflowRoleAssignmentImpl,
- SilenceUsage: true,
-}
-
-func listWorkflowRoleAssignmentImpl(cmd *cobra.Command, args []string) {
- ctx, stop := signal.NotifyContext(cmd.Context(), os.Interrupt, os.Kill)
- defer gracefulShutdown(stop)
-
- log.V(1).Info("testing connections")
- azClient := connectAndCreateClient()
- log.Info("collecting azure workflow role assignments...")
- start := time.Now()
- subscriptions := listSubscriptions(ctx, azClient)
- stream := listWorkflowRoleAsignments(ctx, azClient, listWorkflows(ctx, azClient, subscriptions))
- outputStream(ctx, stream)
- duration := time.Since(start)
- log.Info("collection completed", "duration", duration.String())
-}
-
-func listWorkflowRoleAsignments(ctx context.Context, client client.AzureClient, workflows <-chan interface{}) <-chan interface{} {
- var (
- out = make(chan interface{})
- ids = make(chan string)
- streams = pipeline.Demux(ctx.Done(), ids, 25)
- wg sync.WaitGroup
- )
-
- go func() {
- defer close(ids)
-
- for result := range pipeline.OrDone(ctx.Done(), workflows) {
- if workflow, ok := result.(AzureWrapper).Data.(models.Workflow); !ok {
- log.Error(fmt.Errorf("failed type assertion"), "unable to continue enumerating workflow role assignments", "result", result)
- return
- } else {
- ids <- workflow.Id
- }
- }
- }()
-
- wg.Add(len(streams))
- for i := range streams {
- stream := streams[i]
- go func() {
- defer wg.Done()
- for id := range stream {
- var (
- workflowRoleAssignments = models.AzureRoleAssignments{
- ObjectId: id,
- }
- count = 0
- )
- for item := range client.ListRoleAssignmentsForResource(ctx, id, "") {
- if item.Error != nil {
- log.Error(item.Error, "unable to continue processing role assignments for this workflow", "workflowId", id)
- } else {
- roleDefinitionId := path.Base(item.Ok.Properties.RoleDefinitionId)
-
- workflowRoleAssignment := models.AzureRoleAssignment{
- Assignee: item.Ok,
- ObjectId: item.ParentId,
- RoleDefinitionId: roleDefinitionId,
- }
- log.V(2).Info("found workflow role assignment", "workflowRoleAssignment", workflowRoleAssignment)
- count++
- workflowRoleAssignments.RoleAssignments = append(workflowRoleAssignments.RoleAssignments, workflowRoleAssignment)
- }
- }
- out <- AzureWrapper{
- Kind: enums.KindAZWorkflowRoleAssignment,
- Data: workflowRoleAssignments,
- }
- log.V(1).Info("finished listing workflow role assignments", "workflowId", id, "count", count)
- }
- }()
- }
-
- go func() {
- wg.Wait()
- close(out)
- log.Info("finished listing all workflow role assignments")
- }()
-
- return out
-}
diff --git a/cmd/list-workflows.go b/cmd/list-workflows.go
deleted file mode 100644
index 6207f5e..0000000
--- a/cmd/list-workflows.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package cmd
-
-import (
- "context"
- "fmt"
- "os"
- "os/signal"
- "sync"
- "time"
-
- "github.com/bloodhoundad/azurehound/client"
- "github.com/bloodhoundad/azurehound/enums"
- "github.com/bloodhoundad/azurehound/models"
- "github.com/bloodhoundad/azurehound/pipeline"
- "github.com/spf13/cobra"
-)
-
-func init() {
- listRootCmd.AddCommand(listWorkflowsCmd)
-}
-
-var listWorkflowsCmd = &cobra.Command{
- Use: "workflows",
- Long: "Lists Azure Workflows (Logic Apps)",
- Run: listWorkflowsCmdImpl,
- SilenceUsage: true,
-}
-
-func listWorkflowsCmdImpl(cmd *cobra.Command, args []string) {
- ctx, stop := signal.NotifyContext(cmd.Context(), os.Interrupt, os.Kill)
- defer gracefulShutdown(stop)
-
- azClient := connectAndCreateClient()
- log.Info("collecting azure workflows...")
- start := time.Now()
- stream := listWorkflows(ctx, azClient, listSubscriptions(ctx, azClient))
- outputStream(ctx, stream)
- duration := time.Since(start)
- log.Info("collection completed", "duration", duration.String())
-}
-
-func listWorkflows(ctx context.Context, client client.AzureClient, subscriptions <-chan interface{}) <-chan interface{} {
- var (
- out = make(chan interface{})
- ids = make(chan string)
- streams = pipeline.Demux(ctx.Done(), ids, 25)
- wg sync.WaitGroup
- )
-
- go func() {
- defer close(ids)
- for result := range pipeline.OrDone(ctx.Done(), subscriptions) {
- if subscription, ok := result.(AzureWrapper).Data.(models.Subscription); !ok {
- log.Error(fmt.Errorf("failed type assertion"), "unable to continue enumerating workflows", "result", result)
- return
- } else {
- ids <- subscription.SubscriptionId
- }
- }
- }()
-
- wg.Add(len(streams))
- for i := range streams {
- stream := streams[i]
- go func() {
- defer wg.Done()
- for id := range stream {
- count := 0
- // Azure only allows requesting 100 workflows at a time. The previous
- // value of math.MaxInt32 was causing issues and not collecting
- // workflows at all. This is not a great fix, since it requires proper
- // pagination in case there are more than 100 workflows, but it's better
- // as an interim solution than it was before.
- for item := range client.ListAzureWorkflows(ctx, id, "", 100) {
- if item.Error != nil {
- log.Error(item.Error, "unable to continue processing workflows for this subscription", "subscriptionId", id)
- } else {
- resourceGroupId := item.Ok.ResourceGroupId()
- workflow := models.Workflow{
- Workflow: item.Ok,
- SubscriptionId: item.SubscriptionId,
- ResourceGroupId: resourceGroupId,
- TenantId: client.TenantInfo().TenantId,
- }
- log.V(2).Info("found workflow", "workflow", workflow)
- count++
- out <- AzureWrapper{
- Kind: enums.KindAZWorkflow,
- Data: workflow,
- }
- }
- }
- log.V(1).Info("finished listing workflows", "subscriptionId", id, "count", count)
- }
- }()
- }
-
- go func() {
- wg.Wait()
- close(out)
- log.Info("finished listing all workflows")
- }()
-
- return out
-}
diff --git a/enums/workflow_provisioning_state.go b/enums/workflow_provisioning_state.go
deleted file mode 100644
index 42a2864..0000000
--- a/enums/workflow_provisioning_state.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package enums
-
-type WorkflowProvisioningState string
-
-const (
- AcceptedProvisioningState WorkflowProvisioningState = "Accepted"
- CanceledProvisioningState WorkflowProvisioningState = "Canceled"
- CompletedProvisioningState WorkflowProvisioningState = "Completed"
- CreatedProvisioningState WorkflowProvisioningState = "Created"
- CreatingProvisioningState WorkflowProvisioningState = "Creating"
- DeletedProvisioningState WorkflowProvisioningState = "Deleted"
- DeletingProvisioningState WorkflowProvisioningState = "Deleting"
- FailedProvisioningState WorkflowProvisioningState = "Failed"
- MovingProvisioningState WorkflowProvisioningState = "Moving"
- NotSpecifiedProvisioningState WorkflowProvisioningState = "NotSpecified"
- ReadyProvisioningState WorkflowProvisioningState = "Ready"
- RegisteredProvisioningState WorkflowProvisioningState = "Registered"
- RegisteringProvisioningState WorkflowProvisioningState = "Registering"
- RunningProvisioningState WorkflowProvisioningState = "Running"
- SucceededProvisioningState WorkflowProvisioningState = "Succeeded"
- UnregisteredProvisioningState WorkflowProvisioningState = "Unregistered"
- UnregisteringProvisioningState WorkflowProvisioningState = "Unregistering"
- UpdatingProvisioningState WorkflowProvisioningState = "Updating"
-)
diff --git a/enums/workflow_state.go b/enums/workflow_state.go
deleted file mode 100644
index abb7b6d..0000000
--- a/enums/workflow_state.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package enums
-
-type WorkflowState string
-
-const (
- CompletedWorkflowState WorkflowState = "Completed"
- DeletedWorkflowState WorkflowState = "Deleted"
- DisabledWorkflowState WorkflowState = "Disabled"
- EnabledWorkflowState WorkflowState = "Enabled"
- NotSpecifiedWorkflowState WorkflowState = "NotSpecified"
- SuspendedWorkflowState WorkflowState = "Suspended"
-)
diff --git a/go.mod b/go.mod
index 3147865..33a3d76 100644
--- a/go.mod
+++ b/go.mod
@@ -31,10 +31,7 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
- golang.org/x/mod v0.5.0 // indirect
golang.org/x/text v0.3.7 // indirect
- golang.org/x/tools v0.1.7 // indirect
- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
diff --git a/go.sum b/go.sum
index 160bec4..9f9a43d 100644
--- a/go.sum
+++ b/go.sum
@@ -422,7 +422,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -634,12 +633,10 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
diff --git a/models/workflow.go b/models/workflow.go
deleted file mode 100644
index d51093b..0000000
--- a/models/workflow.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2022 Specter Ops, Inc.
-//
-// This file is part of AzureHound.
-//
-// AzureHound is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// AzureHound is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package models
-
-import "github.com/bloodhoundad/azurehound/models/azure"
-
-type Workflow struct {
- azure.Workflow
- SubscriptionId string `json:"subscriptionId"`
- ResourceGroupId string `json:"resourceGroupId"`
- ResourceGroupName string `json:"resourceGroupName"`
- TenantId string `json:"tenantId"`
-}