Skip to content

Commit

Permalink
add Active Directory fetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
kubasobon committed Oct 18, 2024
1 parent 69bd009 commit 4ad3558
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 9 deletions.
10 changes: 8 additions & 2 deletions internal/flavors/assetinventory/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
azure_auth "github.com/elastic/cloudbeat/internal/resources/providers/azurelib/auth"
gcp_auth "github.com/elastic/cloudbeat/internal/resources/providers/gcplib/auth"
gcp_inventory "github.com/elastic/cloudbeat/internal/resources/providers/gcplib/inventory"
"github.com/elastic/cloudbeat/internal/resources/providers/msgraph"
)

type Strategy interface {
Expand Down Expand Up @@ -96,10 +97,15 @@ func (s *strategy) initAzureFetchers(_ context.Context) ([]inventory.AssetFetche
initializer := &azurelib.ProviderInitializer{}
provider, err := initializer.Init(s.logger, *azureConfig)
if err != nil {
return nil, fmt.Errorf("failed to initialize azure config: %w", err)
return nil, fmt.Errorf("failed to initialize azure provider: %w", err)
}

msgraphProvider, err := msgraph.NewProvider(s.logger, *azureConfig)
if err != nil {
return nil, fmt.Errorf("failed to initialize azure msgraph provider: %w", err)
}

return azurefetcher.New(s.logger, provider, azureConfig), nil
return azurefetcher.New(s.logger, provider, msgraphProvider), nil
}

func (s *strategy) initGcpFetchers(ctx context.Context) ([]inventory.AssetFetcher, error) {
Expand Down
6 changes: 3 additions & 3 deletions internal/inventory/ASSETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ Infrastructure: 24% (18/73)

## AZURE Resources

**Progress: 23% (12/51)**
Identity: 0% (0/8)
**Progress: 25% (13/51)**
Identity: 12% (1/8)
Infrastructure: 27% (12/43)

<details> <summary>Full table</summary>
Expand All @@ -110,7 +110,7 @@ Infrastructure: 27% (12/43)
| Identity | Access Management | Role | Azure Role | No ❌ |
| Identity | Application | Application | Azure AD Application | No ❌ |
| Identity | Digital Identity | Administrator | Azure Server AD Administrator | No ❌ |
| Identity | Digital Identity | Principal | Azure Principal | No ❌ |
| Identity | Digital Identity | Principal | Azure Principal | Yes ✅ |
| Identity | Directory | Group | Azure AD Group | No ❌ |
| Identity | Directory | User | Azure AD User | No ❌ |
| Identity | Service Identity | Service Principal | Azure AD Service Principal | No ❌ |
Expand Down
3 changes: 3 additions & 0 deletions internal/inventory/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const (
TypeObjectStorage AssetType = "object-storage"
TypePeering AssetType = "peering"
TypePolicy AssetType = "policy"
TypePrincipal AssetType = "principal"
TypeRegistry AssetType = "registry"
TypeRelationalDatabase AssetType = "relational"
TypeResourceGroup AssetType = "resource-group"
Expand Down Expand Up @@ -94,6 +95,7 @@ const (
SubTypeAzureCosmosDBSQLDatabase AssetSubType = "azure-cosmos-db-sql-database"
SubTypeAzureDisk AssetSubType = "azure-disk"
SubTypeAzureElasticPool AssetSubType = "azure-elastic-pool"
SubTypeAzurePrincipal AssetSubType = "azure-principal"
SubTypeAzureResourceGroup AssetSubType = "azure-resource-group"
SubTypeAzureSQLDatabase AssetSubType = "azure-sql-database"
SubTypeAzureSQLServer AssetSubType = "azure-sql-server"
Expand Down Expand Up @@ -191,6 +193,7 @@ var (
AssetClassificationAzureResourceGroup = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryManagement, Type: TypeResourceGroup, SubType: SubTypeAzureResourceGroup}
AssetClassificationAzureSQLDatabase = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryDatabase, Type: TypeRelationalDatabase, SubType: SubTypeAzureSQLDatabase}
AssetClassificationAzureSQLServer = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryDatabase, Type: TypeRelationalDatabase, SubType: SubTypeAzureSQLServer}
AssetClassificationAzureServicePrincipal = AssetClassification{Category: CategoryIdentity, SubCategory: SubCategoryDigitalIdentity, Type: TypePrincipal, SubType: SubTypeAzurePrincipal}
AssetClassificationAzureSnapshot = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryStorage, Type: TypeSnapshot, SubType: SubTypeAzureSnapshot}
AssetClassificationAzureStorageAccount = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryStorage, Type: TypeStorage, SubType: SubTypeAzureStorageAccount}
AssetClassificationAzureSubscription = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryManagement, Type: TypeCloudAccount, SubType: SubTypeAzureSubscription}
Expand Down
5 changes: 3 additions & 2 deletions internal/inventory/azurefetcher/azurefetchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import (

"github.com/elastic/cloudbeat/internal/inventory"
"github.com/elastic/cloudbeat/internal/resources/providers/azurelib"
azure_auth "github.com/elastic/cloudbeat/internal/resources/providers/azurelib/auth"
"github.com/elastic/cloudbeat/internal/resources/providers/msgraph"
)

func New(logger *logp.Logger, provider azurelib.ProviderAPI, _ *azure_auth.AzureFactoryConfig) []inventory.AssetFetcher {
func New(logger *logp.Logger, provider azurelib.ProviderAPI, msgraphProvider msgraph.ProviderAPI) []inventory.AssetFetcher {
return []inventory.AssetFetcher{
newAccountFetcher(logger, provider),
newActiveDirectoryFetcher(logger, msgraphProvider),
newResourceGraphFetcher(logger, provider),
}
}
86 changes: 86 additions & 0 deletions internal/inventory/azurefetcher/fetcher_activedirectory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package azurefetcher

import (
"context"

"github.com/elastic/elastic-agent-libs/logp"
"github.com/microsoftgraph/msgraph-sdk-go/models"

"github.com/elastic/cloudbeat/internal/inventory"
azurelib "github.com/elastic/cloudbeat/internal/resources/providers/azurelib/inventory"
"github.com/elastic/cloudbeat/internal/resources/utils/pointers"
)

type activedirectoryFetcher struct {
logger *logp.Logger
provider activedirectoryProvider
}

type (
activedirectoryProviderFunc func(context.Context) ([]azurelib.AzureAsset, error)
activedirectoryProvider interface {
ListServicePrincipals(ctx context.Context) ([]*models.ServicePrincipal, error)
}
)

func newActiveDirectoryFetcher(logger *logp.Logger, provider activedirectoryProvider) inventory.AssetFetcher {
return &activedirectoryFetcher{
logger: logger,
provider: provider,
}
}

func (f *activedirectoryFetcher) Fetch(ctx context.Context, assetChan chan<- inventory.AssetEvent) {
f.fetchServicePrincipals(ctx, assetChan)
}

func (f *activedirectoryFetcher) fetchServicePrincipals(ctx context.Context, assetChan chan<- inventory.AssetEvent) {
f.logger.Info("Fetching Service Principals")
defer f.logger.Info("Fetching Service Principals - Finished")

items, err := f.provider.ListServicePrincipals(ctx)
if err != nil {
f.logger.Errorf("Could not fetch Service Principals: %v", err)
}

for _, item := range items {
var tenantId string
if uuid := item.GetAppOwnerOrganizationId(); uuid != nil {
tenantId = uuid.String()
}
assetChan <- inventory.NewAssetEvent(
inventory.AssetClassificationAzureServicePrincipal,
[]string{pointers.Deref(item.GetId())},
pointers.Deref(item.GetDisplayName()),
inventory.WithRawAsset(
item.GetBackingStore().Enumerate(),
),
inventory.WithCloud(inventory.AssetCloud{
Provider: inventory.AwsCloudProvider,
Account: inventory.AssetCloudAccount{
Id: tenantId,
},
Service: &inventory.AssetCloudService{
Name: "Azure",
},
}),
)
}
}
21 changes: 19 additions & 2 deletions internal/resources/providers/msgraph/provider.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package msgraph

import (
"context"
"fmt"

"github.com/elastic/cloudbeat/internal/resources/providers/azurelib/auth"

"github.com/elastic/elastic-agent-libs/logp"
graph "github.com/microsoftgraph/msgraph-sdk-go"
graphcore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"

"github.com/elastic/cloudbeat/internal/resources/providers/azurelib/auth"
)

type ProviderAPI interface {
Expand Down

0 comments on commit 4ad3558

Please sign in to comment.