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

Azure: Dynamically get subscription ID(s) #1366

Merged
merged 4 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
cloud.google.com/go/iam v1.1.2
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.8.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.2.0
github.com/aquasecurity/go-dep-parser v0.0.0-20230605080024-b71d9356a6c6
github.com/aquasecurity/trivy v0.42.1
github.com/aquasecurity/trivy-db v0.0.0-20230515061101-378ab9ed302c
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,12 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1 h1:LNHhpdK7hzUcx/k1LIcuh
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1/go.mod h1:uE9zaUfEQT/nbQjVi2IblCG9iaLtZsuYZ8ne+PuQ02M=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.8.1 h1:nGiU2ovpbtkcC3x+g/wNHV4S9TOIYe2/yOVAj3wiGHI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.8.1/go.mod h1:T3ZgvD1aRKu12mEA0fU3PPvI7V0Nh0wzIdK0QMBhf0Y=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.2.0 h1:Pmy0+3ox1IC3sp6musv87BFPIdQbqyPFjn7I8I0o2Js=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.2.0/go.mod h1:ThfyMjs6auYrWPnYJjI3H4H++oVPrz01pizpu8lfl3A=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
Expand Down
2 changes: 1 addition & 1 deletion magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,6 @@ func BuildOpaBundle() (err error) {
return err
}

fmt.Printf("Generated OPA bundle from %s branch at %s", branch, cspPoliciesPkgDir)
fmt.Printf("Generated OPA bundle from %s branch at %s\n", branch, cspPoliciesPkgDir)
return nil
}
65 changes: 52 additions & 13 deletions resources/providers/azurelib/inventory/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,24 @@ package inventory
import (
"bytes"
"context"
"os"
"fmt"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
"github.com/elastic/elastic-agent-libs/logp"
"github.com/samber/lo"

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

type Provider struct {
log *logp.Logger
client *AzureClientWrapper
ctx context.Context
Config auth.AzureFactoryConfig
log *logp.Logger
client *AzureClientWrapper
subscriptions []*string
ctx context.Context
Config auth.AzureFactoryConfig
}

type ProviderInitializer struct{}
Expand Down Expand Up @@ -64,28 +68,65 @@ type ProviderInitializerAPI interface {
}

func (p *ProviderInitializer) Init(ctx context.Context, log *logp.Logger, azureConfig auth.AzureFactoryConfig) (ServiceAPI, error) {
log = log.Named("azure")

clientFactory, err := armresourcegraph.NewClientFactory(azureConfig.Credentials, nil)
if err != nil {
return nil, err
}

client := clientFactory.NewClient()

// We wrap the client so we can mock it in tests
// We wrap the client, so we can mock it in tests
wrapper := &AzureClientWrapper{
AssetQuery: func(ctx context.Context, query armresourcegraph.QueryRequest, options *armresourcegraph.ClientResourcesOptions) (armresourcegraph.ClientResourcesResponse, error) {
return client.Resources(ctx, query, options)
},
}

subscriptions, err := p.getSubscriptionIds(ctx, azureConfig)
if err != nil {
return nil, fmt.Errorf("failed to get subscription ids: %w", err)
}
log.Info(
lo.Reduce(subscriptions, func(agg string, item *string, _ int) string {
return fmt.Sprintf("%s %s", agg, strings.Dereference(item))
}, "subscriptions:"),
)

return &Provider{
Config: azureConfig,
client: wrapper,
log: log,
ctx: ctx,
log: log,
client: wrapper,
subscriptions: subscriptions,
ctx: ctx,
Config: azureConfig,
}, nil
}

func (p *ProviderInitializer) getSubscriptionIds(ctx context.Context, azureConfig auth.AzureFactoryConfig) ([]*string, error) {
// TODO: mockable
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Init() is not tested so I consider it out of scope to test this function for now, we should handle this technical debt after the feature freeze though


var result []*string

clientFactory, err := armsubscriptions.NewClientFactory(azureConfig.Credentials, nil)
if err != nil {
return nil, err
}
pager := clientFactory.NewClient().NewListPager(nil)
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
return nil, err
}
for _, subscription := range page.Value {
if subscription != nil {
result = append(result, subscription.SubscriptionID)
}
}
}
return result, nil
}

func (p *Provider) ListAllAssetTypesByName(assets []string) ([]AzureAsset, error) {
p.log.Infof("Listing Azure assets: %v", assets)
var resourceAssets []AzureAsset
Expand All @@ -95,9 +136,7 @@ func (p *Provider) ListAllAssetTypesByName(assets []string) ([]AzureAsset, error
Options: &armresourcegraph.QueryRequestOptions{
ResultFormat: to.Ptr(armresourcegraph.ResultFormatObjectArray),
},
Subscriptions: []*string{
// TODO: Populate from config or query (not sensitive but still don't want to commit)
to.Ptr(os.Getenv("AZURE_SUBSCRIPTION_ID"))},
Subscriptions: p.subscriptions,
}

resourceAssets, err := p.runPaginatedQuery(query)
Expand Down