Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Asset Inventory][Azure] Add storage assets #2576

Merged
merged 38 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
fb7ca77
add support for Azure Queues and Queue Services
kubasobon Sep 30, 2024
16698e8
add Azure Storage fetcher
kubasobon Oct 1, 2024
e831714
enable new fetcher
kubasobon Oct 1, 2024
7d10bdd
fix Subscription ID issue by using name
kubasobon Oct 1, 2024
6d542b8
fill TenantID and ResourceGroup for Storage Accounts
kubasobon Oct 1, 2024
7de6458
update ASSETS.md
kubasobon Oct 1, 2024
74252e7
update mocks
kubasobon Oct 1, 2024
d49c408
build(deps): Bump google.golang.org/api from 0.198.0 to 0.199.0 in th…
dependabot[bot] Oct 1, 2024
f74b40d
add integration test cases for new resources
kubasobon Oct 1, 2024
6ad9836
fix linter issues
kubasobon Oct 1, 2024
83fb7ab
remove renamed mock files
kubasobon Oct 1, 2024
2a583f0
fix provider references
kubasobon Oct 1, 2024
03d206f
add new function tests
kubasobon Oct 2, 2024
9fd79d9
add new function tests (2nd time)
kubasobon Oct 2, 2024
875937f
change error handilng for Storage assets
kubasobon Oct 17, 2024
5bfa461
build(deps): Bump the aws group with 23 updates (#2569)
dependabot[bot] Oct 7, 2024
d51b6a0
build(deps): Bump go.elastic.co/go-licence-detector from 0.6.1 to 0.7…
dependabot[bot] Oct 7, 2024
0c6698d
build(deps): Bump google.golang.org/grpc from 1.67.0 to 1.67.1 (#2572)
dependabot[bot] Oct 7, 2024
1526643
build(deps): Bump updatecli/updatecli-action from 2.67.0 to 2.68.0 in…
dependabot[bot] Oct 7, 2024
ad9c61b
[updatecli] Update to elastic/beats@775d26d94a5a (#2564)
cloudsecmachine Oct 7, 2024
8027f2c
build(deps): Bump github.com/dgraph-io/ristretto from 0.1.1 to 1.0.0 …
dependabot[bot] Oct 7, 2024
6b74b8d
[updatecli] Update hermit and pre-commit dependencies (#2565)
cloudsecmachine Oct 7, 2024
ae63924
[updatecli] Update Golang version to 1.23.2 (#2581)
cloudsecmachine Oct 7, 2024
1329bb1
Fix Create Environment agent version for Serverless (#2547)
opauloh Oct 10, 2024
43f2696
feat: replace x/exp with stdlib functions (#2580)
kruskall Oct 10, 2024
da28121
Increase LeaseDuration to create stickiness (#2588)
amirbenun Oct 10, 2024
7bd3b07
mergify: replace queue action for queue_rules (#2500)
v1v Oct 13, 2024
dcd0e58
Update version compatibility handling (#2594)
gurevichdmitry Oct 14, 2024
4600259
Skip Azure PostgreSQL tests (#2600)
gurevichdmitry Oct 14, 2024
9be79d6
Update k8s integration tests timeout (#2601)
gurevichdmitry Oct 14, 2024
bcf707c
fix gh artifacts upload for docker images (#2562)
moukoublen Oct 14, 2024
cae0f26
Revert "fix gh artifacts upload for docker images" (#2606)
moukoublen Oct 15, 2024
3ff0902
change formatting
kubasobon Oct 17, 2024
545e93c
[updatecli] Update hermit and pre-commit dependencies (#2598)
cloudsecmachine Oct 21, 2024
8af7996
Merge branch 'main' into ast-inv-azure-storage
kubasobon Oct 29, 2024
6ab1d91
Merge branch 'main' into ast-inv-azure-storage
kubasobon Oct 30, 2024
8598936
Merge branch 'main' into ast-inv-azure-storage
kubasobon Oct 31, 2024
5e53c9d
Merge branch 'main' into ast-inv-azure-storage
kubasobon Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions internal/inventory/ASSETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ Infrastructure: 24% (18/73)

## AZURE Resources

**Progress: 23% (12/51)**
**Progress: 29% (15/51)**
Identity: 0% (0/8)
Infrastructure: 27% (12/43)
Infrastructure: 34% (15/43)

<details> <summary>Full table</summary>

Expand All @@ -114,8 +114,8 @@ Infrastructure: 27% (12/43)
| Identity | Directory | Group | Azure AD Group | No ❌ |
| Identity | Directory | User | Azure AD User | No ❌ |
| Identity | Service Identity | Service Principal | Azure AD Service Principal | No ❌ |
| Infrastructure | Application Integration | Message Queue | Azure Storage Queue | No ❌ |
| Infrastructure | Application Integration | Message Queue | Azure Storage Queue Service | No ❌ |
| Infrastructure | Application Integration | Message Queue | Azure Storage Queue | Yes ✅ |
| Infrastructure | Application Integration | Message Queue | Azure Storage Queue Service | Yes ✅ |
| Infrastructure | Application | Web Application | Azure App Service | Yes ✅ |
| Infrastructure | Compute | Virtual Machine | Azure Virtual Machine | Yes ✅ |
| Infrastructure | Container | Registry | Azure Container Registry | Yes ✅ |
Expand Down Expand Up @@ -154,7 +154,7 @@ Infrastructure: 27% (12/43)
| Infrastructure | Storage | File Storage | Azure Storage File Service | No ❌ |
| Infrastructure | Storage | File Storage | Azure Storage File Share | No ❌ |
| Infrastructure | Storage | Object Storage | Azure Storage Blob Container | No ❌ |
| Infrastructure | Storage | Object Storage | Azure Storage Blob Service | No ❌ |
| Infrastructure | Storage | Object Storage | Azure Storage Blob Service | Yes ✅ |
| Infrastructure | Storage | Snapshot | Azure Snapshot | Yes ✅ |
| Infrastructure | Storage | Storage | Azure Storage Account | Yes ✅ |

Expand Down
40 changes: 24 additions & 16 deletions internal/inventory/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@ const (
type AssetSubCategory string

const (
SubCategoryApplication AssetSubCategory = "application"
SubCategoryAuthorization AssetSubCategory = "authorization"
SubCategoryCompute AssetSubCategory = "compute"
SubCategoryContainer AssetSubCategory = "container"
SubCategoryDatabase AssetSubCategory = "database"
SubCategoryDigitalIdentity AssetSubCategory = "digital-identity"
SubCategoryIntegration AssetSubCategory = "integration"
SubCategoryManagement AssetSubCategory = "management"
SubCategoryMessaging AssetSubCategory = "messaging"
SubCategoryNetwork AssetSubCategory = "network"
SubCategoryStorage AssetSubCategory = "storage"
SubCategoryServiceIdentity AssetSubCategory = "service-identity"
SubCategoryAccessManagement AssetSubCategory = "access-management"
SubCategoryServerless AssetSubCategory = "serverless"
SubCategoryAccessManagement AssetSubCategory = "access-management"
SubCategoryApplication AssetSubCategory = "application"
SubCategoryApplicationIntegration AssetSubCategory = "application-integration"
SubCategoryAuthorization AssetSubCategory = "authorization"
SubCategoryCompute AssetSubCategory = "compute"
SubCategoryContainer AssetSubCategory = "container"
SubCategoryDatabase AssetSubCategory = "database"
SubCategoryDigitalIdentity AssetSubCategory = "digital-identity"
SubCategoryIntegration AssetSubCategory = "integration"
SubCategoryManagement AssetSubCategory = "management"
SubCategoryMessaging AssetSubCategory = "messaging"
SubCategoryNetwork AssetSubCategory = "network"
SubCategoryServerless AssetSubCategory = "serverless"
SubCategoryServiceIdentity AssetSubCategory = "service-identity"
SubCategoryStorage AssetSubCategory = "storage"
)

// AssetType is used to build the document index. Use only numbers, letters and dashes (-)
Expand All @@ -57,6 +58,7 @@ const (
TypeGateway AssetType = "gateway"
TypeInterface AssetType = "interface"
TypeLoadBalancer AssetType = "load-balancer"
TypeMessageQueue AssetType = "message-queue"
TypeNoSQLDatabase AssetType = "nosql-database"
TypeNotificationService AssetType = "notification-service"
TypeObjectStorage AssetType = "object-storage"
Expand All @@ -68,15 +70,15 @@ const (
TypeRole AssetType = "role"
TypeScalability AssetType = "scalability"
TypeServerless AssetType = "serverless"
TypeServiceAccount AssetType = "service-account"
TypeServiceAccountKey AssetType = "service-account-key"
TypeSnapshot AssetType = "snapshot"
TypeStorage AssetType = "storage"
TypeSubnet AssetType = "subnet"
TypeUser AssetType = "user"
TypeVirtualMachine AssetType = "virtual-machine"
TypeVirtualNetwork AssetType = "virtual-network"
TypeWebApplication AssetType = "web-application"
TypeServiceAccount AssetType = "service-account"
TypeServiceAccountKey AssetType = "service-account-key"
TypeResourceHierarchy AssetType = "resource-hierarchy"
TypeOrchestration AssetType = "orchestration"
TypeFunction AssetType = "function"
Expand All @@ -99,6 +101,9 @@ const (
SubTypeAzureSQLServer AssetSubType = "azure-sql-server"
SubTypeAzureSnapshot AssetSubType = "azure-snapshot"
SubTypeAzureStorageAccount AssetSubType = "azure-storage-account"
SubTypeAzureStorageBlobService AssetSubType = "azure-storage-blob-service"
SubTypeAzureStorageQueue AssetSubType = "azure-storage-queue"
SubTypeAzureStorageQueueService AssetSubType = "azure-storage-queue-service"
romulets marked this conversation as resolved.
Show resolved Hide resolved
SubTypeAzureSubscription AssetSubType = "azure-subscription"
SubTypeAzureTenant AssetSubType = "azure-tenant"
SubTypeAzureVirtualMachine AssetSubType = "azure-virtual-machine"
Expand Down Expand Up @@ -193,6 +198,9 @@ var (
AssetClassificationAzureSQLServer = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryDatabase, Type: TypeRelationalDatabase, SubType: SubTypeAzureSQLServer}
AssetClassificationAzureSnapshot = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryStorage, Type: TypeSnapshot, SubType: SubTypeAzureSnapshot}
AssetClassificationAzureStorageAccount = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryStorage, Type: TypeStorage, SubType: SubTypeAzureStorageAccount}
AssetClassificationAzureStorageBlobService = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryStorage, Type: TypeObjectStorage, SubType: SubTypeAzureStorageBlobService}
AssetClassificationAzureStorageQueue = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryApplicationIntegration, Type: TypeMessageQueue, SubType: SubTypeAzureStorageQueue}
AssetClassificationAzureStorageQueueService = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryApplicationIntegration, Type: TypeMessageQueue, SubType: SubTypeAzureStorageQueueService}
AssetClassificationAzureSubscription = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryManagement, Type: TypeCloudAccount, SubType: SubTypeAzureSubscription}
AssetClassificationAzureTenant = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryManagement, Type: TypeCloudAccount, SubType: SubTypeAzureTenant}
AssetClassificationAzureVirtualMachine = AssetClassification{Category: CategoryInfrastructure, SubCategory: SubCategoryCompute, Type: TypeVirtualMachine, SubType: SubTypeAzureVirtualMachine}
Expand Down
1 change: 1 addition & 0 deletions internal/inventory/azurefetcher/azurefetchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ func New(logger *logp.Logger, provider azurelib.ProviderAPI, _ *azure_auth.Azure
return []inventory.AssetFetcher{
newAccountFetcher(logger, provider),
newResourceGraphFetcher(logger, provider),
newStorageFetcher(logger, provider),
}
}
12 changes: 6 additions & 6 deletions internal/inventory/azurefetcher/fetcher_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ import (

type accountFetcher struct {
logger *logp.Logger
provider subscriptionProvider
provider accountProvider
}

type (
subscriptionProviderFunc func(context.Context) ([]azurelib.AzureAsset, error)
subscriptionProvider interface {
accountProviderFunc func(context.Context) ([]azurelib.AzureAsset, error)
accountProvider interface {
ListTenants(ctx context.Context) ([]azurelib.AzureAsset, error)
ListSubscriptions(ctx context.Context) ([]azurelib.AzureAsset, error)
}
)

func newAccountFetcher(logger *logp.Logger, provider subscriptionProvider) inventory.AssetFetcher {
func newAccountFetcher(logger *logp.Logger, provider accountProvider) inventory.AssetFetcher {
return &accountFetcher{
logger: logger,
provider: provider,
Expand All @@ -49,7 +49,7 @@ func newAccountFetcher(logger *logp.Logger, provider subscriptionProvider) inven
func (f *accountFetcher) Fetch(ctx context.Context, assetChan chan<- inventory.AssetEvent) {
resourcesToFetch := []struct {
name string
function subscriptionProviderFunc
function accountProviderFunc
classification inventory.AssetClassification
}{
{"Tenants", f.provider.ListTenants, inventory.AssetClassificationAzureTenant},
Expand All @@ -60,7 +60,7 @@ func (f *accountFetcher) Fetch(ctx context.Context, assetChan chan<- inventory.A
}
}

func (f *accountFetcher) fetch(ctx context.Context, resourceName string, function subscriptionProviderFunc, classification inventory.AssetClassification, assetChan chan<- inventory.AssetEvent) {
func (f *accountFetcher) fetch(ctx context.Context, resourceName string, function accountProviderFunc, classification inventory.AssetClassification, assetChan chan<- inventory.AssetEvent) {
f.logger.Infof("Fetching %s", resourceName)
defer f.logger.Infof("Fetching %s - Finished", resourceName)

Expand Down
4 changes: 2 additions & 2 deletions internal/inventory/azurefetcher/fetcher_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestAccountFetcher_Fetch_Tenants(t *testing.T) {

// setup
logger := logp.NewLogger("azurefetcher_test")
provider := newMockSubscriptionProvider(t)
provider := newMockAccountProvider(t)
provider.EXPECT().ListTenants(mock.Anything).Return(azureAssets, nil)
provider.EXPECT().ListSubscriptions(mock.Anything).Return(nil, nil)
fetcher := newAccountFetcher(logger, provider)
Expand Down Expand Up @@ -94,7 +94,7 @@ func TestAccountFetcher_Fetch_Subscriptions(t *testing.T) {

// setup
logger := logp.NewLogger("azurefetcher_test")
provider := newMockSubscriptionProvider(t)
provider := newMockAccountProvider(t)
provider.EXPECT().ListTenants(mock.Anything).Return(nil, nil)
provider.EXPECT().ListSubscriptions(mock.Anything).Return(azureAssets, nil)
fetcher := newAccountFetcher(logger, provider)
Expand Down
121 changes: 121 additions & 0 deletions internal/inventory/azurefetcher/fetcher_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// 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"
"fmt"

"github.com/elastic/elastic-agent-libs/logp"

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

type storageFetcher struct {
logger *logp.Logger
provider storageProvider
}

type (
storageProviderFunc func(context.Context, []azurelib.AzureAsset) ([]azurelib.AzureAsset, error)
storageProvider interface {
ListSubscriptions(ctx context.Context) ([]azurelib.AzureAsset, error)
ListStorageAccountBlobServices(ctx context.Context, storageAccounts []azurelib.AzureAsset) ([]azurelib.AzureAsset, error)
ListStorageAccountQueues(ctx context.Context, storageAccounts []azurelib.AzureAsset) ([]azurelib.AzureAsset, error)
ListStorageAccountQueueServices(ctx context.Context, storageAccounts []azurelib.AzureAsset) ([]azurelib.AzureAsset, error)
ListStorageAccounts(ctx context.Context, storageAccountsSubscriptionsIds []string) ([]azurelib.AzureAsset, error)
}
)

func newStorageFetcher(logger *logp.Logger, provider storageProvider) inventory.AssetFetcher {
return &storageFetcher{
logger: logger,
provider: provider,
}
}

func (f *storageFetcher) Fetch(ctx context.Context, assetChan chan<- inventory.AssetEvent) {
resourcesToFetch := []struct {
name string
function storageProviderFunc
classification inventory.AssetClassification
}{
{"Storage Blob Services", f.provider.ListStorageAccountBlobServices, inventory.AssetClassificationAzureStorageBlobService},
{"Storage Queue Services", f.provider.ListStorageAccountQueueServices, inventory.AssetClassificationAzureStorageQueueService},
{"Storage Queues", f.provider.ListStorageAccountQueues, inventory.AssetClassificationAzureStorageQueue},
}

storageAccounts, err := f.listStorageAccounts(ctx)
if err != nil {
f.logger.Errorf("Could not fetch anything: %v", err)
return
}

for _, r := range resourcesToFetch {
f.fetch(ctx, storageAccounts, r.name, r.function, r.classification, assetChan)
}
}

func (f *storageFetcher) listStorageAccounts(ctx context.Context) ([]azurelib.AzureAsset, error) {
subscriptions, err := f.provider.ListSubscriptions(ctx)
if err != nil {
return nil, fmt.Errorf("error listing subscriptions: %v", err)
}

subscriptionIds := make([]string, len(subscriptions))
for _, subscription := range subscriptions {
subscriptionIds = append(subscriptionIds, subscription.Name)
}

storageAccounts, err := f.provider.ListStorageAccounts(ctx, subscriptionIds)
if err != nil {
return nil, fmt.Errorf("error listing storage accounts: %v", err)
}

return storageAccounts, nil
}

func (f *storageFetcher) fetch(ctx context.Context, storageAccounts []azurelib.AzureAsset, resourceName string, function storageProviderFunc, classification inventory.AssetClassification, assetChan chan<- inventory.AssetEvent) {
f.logger.Infof("Fetching %s", resourceName)
romulets marked this conversation as resolved.
Show resolved Hide resolved
defer f.logger.Infof("Fetching %s - Finished", resourceName)

azureAssets, err := function(ctx, storageAccounts)
if err != nil {
f.logger.Errorf("Could not fetch %s: %v", resourceName, err)
return
}

for _, item := range azureAssets {
assetChan <- inventory.NewAssetEvent(
classification,
[]string{item.Id},
item.DisplayName,
inventory.WithRawAsset(item),
inventory.WithCloud(inventory.AssetCloud{
Provider: inventory.AzureCloudProvider,
Account: inventory.AssetCloudAccount{
Id: item.TenantId,
},
Service: &inventory.AssetCloudService{
Name: "Azure",
},
}),
)
}
}
Loading
Loading