From 5b6db21f3cc6266dda37069ff948f85060a423c9 Mon Sep 17 00:00:00 2001 From: magodo Date: Fri, 27 Sep 2024 10:50:57 +0800 Subject: [PATCH] Query mode: Supports `--arg-table` and `--arg-authorization-scope-filter` --- command_before_func.go | 8 +++++++ flag.go | 22 +++++++++++++----- go.mod | 2 +- go.sum | 2 ++ internal/meta/meta_query.go | 45 +++++++++++++++++++++---------------- main.go | 26 ++++++++++++++++----- pkg/config/config.go | 31 ++++++++++++++++++------- 7 files changed, 96 insertions(+), 40 deletions(-) diff --git a/command_before_func.go b/command_before_func.go index 1f0a323..aeeae41 100644 --- a/command_before_func.go +++ b/command_before_func.go @@ -3,9 +3,11 @@ package main import ( "fmt" "os" + "slices" "strings" "github.com/Azure/aztfexport/internal/utils" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph" "github.com/hashicorp/terraform-config-inspect/tfconfig" "github.com/urfave/cli/v2" ) @@ -113,6 +115,12 @@ func commandBeforeFunc(fset *FlagSet, mode Mode) func(ctx *cli.Context) error { return fmt.Errorf("`--name` can't be specified for multi-resource mode") } } + case ModeQuery: + if fset.flagARGAuthorizationScopeFilter != "" { + if !slices.Contains(armresourcegraph.PossibleAuthorizationScopeFilterValues(), armresourcegraph.AuthorizationScopeFilter(fset.flagARGAuthorizationScopeFilter)) { + return fmt.Errorf("invalid value of `--arg-authorization-scope-filter`") + } + } } // Initialize output directory diff --git a/flag.go b/flag.go index dc40eca..2ed64d5 100644 --- a/flag.go +++ b/flag.go @@ -87,12 +87,16 @@ type FlagSet struct { // flagRecursive // flagIncludeRoleAssignment // flagIncludeResourceGroup - flagPattern string - flagRecursive bool - flagResName string - flagResType string - flagIncludeRoleAssignment bool - flagIncludeResourceGroup bool + // flagARGTable + // flagARGAuthorizationScopeFilter + flagPattern string + flagRecursive bool + flagResName string + flagResType string + flagIncludeRoleAssignment bool + flagIncludeResourceGroup bool + flagARGTable string + flagARGAuthorizationScopeFilter string } type Mode string @@ -251,6 +255,12 @@ func (flag FlagSet) DescribeCLI(mode Mode) string { if flag.flagIncludeResourceGroup { args = append(args, "--include-resource-group=true") } + if flag.flagARGTable != "" { + args = append(args, "--arg-table="+flag.flagARGTable) + } + if flag.flagARGAuthorizationScopeFilter != "" { + args = append(args, "--arg-authorization-scope-filter="+flag.flagARGAuthorizationScopeFilter) + } } return "aztfexport " + strings.Join(args, " ") } diff --git a/go.mod b/go.mod index 107ef7c..10f6064 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/hashicorp/terraform-json v0.22.1 github.com/hexops/gotextdiff v1.0.3 github.com/magodo/armid v0.0.0-20240524082432-7ce06ae46c33 - github.com/magodo/azlist v0.0.0-20240903084323-b329fe33ce23 + github.com/magodo/azlist v0.0.0-20240926110356-8798310310af github.com/magodo/aztft v0.3.1-0.20240823092950-b8a7f3cdf3ae github.com/magodo/slog2hclog v0.0.0-20240614031327-090ebd72a033 github.com/magodo/spinner v0.0.0-20240524082745-3a2305db1bdc diff --git a/go.sum b/go.sum index 572068f..e5cfa59 100644 --- a/go.sum +++ b/go.sum @@ -233,6 +233,8 @@ github.com/magodo/armid v0.0.0-20240524082432-7ce06ae46c33 h1:KmQ16pNsI7DaELU+Cb github.com/magodo/armid v0.0.0-20240524082432-7ce06ae46c33/go.mod h1:rR8E7zfGMbmfnSQvrkFiWYdhrfTqsVSltelnZB09BwA= github.com/magodo/azlist v0.0.0-20240903084323-b329fe33ce23 h1:99U0TtE+gi7EjXi3Lo6sKFReU2ID2f2wK2gCJSz8/Ow= github.com/magodo/azlist v0.0.0-20240903084323-b329fe33ce23/go.mod h1:xefFDOxzRssOEjGoxvrO8jeTWlzHXbY6sCJYOt+Jh5k= +github.com/magodo/azlist v0.0.0-20240926110356-8798310310af h1:r55nPAyFztYNdXNVmZgNtDU6AbKbfdy/Cbg6xnOnidM= +github.com/magodo/azlist v0.0.0-20240926110356-8798310310af/go.mod h1:xefFDOxzRssOEjGoxvrO8jeTWlzHXbY6sCJYOt+Jh5k= github.com/magodo/aztft v0.3.1-0.20240823092950-b8a7f3cdf3ae h1:+2PWj5sHws1EsOmStkdiMA5vjgchGGyasSfcNZ6Cbj4= github.com/magodo/aztft v0.3.1-0.20240823092950-b8a7f3cdf3ae/go.mod h1:swhCPmbwehJXrVgu8SCr/XFb2e9tkgEp+Wnnv3K0ZsQ= github.com/magodo/slog2hclog v0.0.0-20240614031327-090ebd72a033 h1:K2seYsMAzoICCLdDe7uU2WyaACLW+tvdTWG3QB+pyec= diff --git a/internal/meta/meta_query.go b/internal/meta/meta_query.go index 3df0783..6875477 100644 --- a/internal/meta/meta_query.go +++ b/internal/meta/meta_query.go @@ -7,17 +7,20 @@ import ( "github.com/Azure/aztfexport/internal/resourceset" "github.com/Azure/aztfexport/internal/tfaddr" "github.com/Azure/aztfexport/pkg/config" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph" "github.com/magodo/azlist/azlist" ) type MetaQuery struct { baseMeta - argPredicate string - recursiveQuery bool - resourceNamePrefix string - resourceNameSuffix string - includeRoleAssignment bool - includeResourceGroup bool + argPredicate string + recursiveQuery bool + resourceNamePrefix string + resourceNameSuffix string + includeRoleAssignment bool + includeResourceGroup bool + argTable string + argAuthenticationScopeFilter armresourcegraph.AuthorizationScopeFilter } func NewMetaQuery(cfg config.Config) (*MetaQuery, error) { @@ -28,11 +31,13 @@ func NewMetaQuery(cfg config.Config) (*MetaQuery, error) { } meta := &MetaQuery{ - baseMeta: *baseMeta, - argPredicate: cfg.ARGPredicate, - recursiveQuery: cfg.RecursiveQuery, - includeRoleAssignment: cfg.IncludeRoleAssignment, - includeResourceGroup: cfg.IncludeResourceGroup, + baseMeta: *baseMeta, + argPredicate: cfg.ARGPredicate, + recursiveQuery: cfg.RecursiveQuery, + includeRoleAssignment: cfg.IncludeRoleAssignment, + includeResourceGroup: cfg.IncludeResourceGroup, + argTable: cfg.ARGTable, + argAuthenticationScopeFilter: armresourcegraph.AuthorizationScopeFilter(cfg.ARGAuthorizationScopeFilter), } meta.resourceNamePrefix, meta.resourceNameSuffix = resourceNamePattern(cfg.ResourceNamePattern) @@ -99,14 +104,16 @@ func (meta *MetaQuery) ListResource(ctx context.Context) (ImportList, error) { func (meta MetaQuery) queryResourceSet(ctx context.Context, predicate string, recursive bool) (*resourceset.AzureResourceSet, error) { opt := azlist.Option{ - Logger: meta.logger.WithGroup("azlist"), - SubscriptionId: meta.subscriptionId, - Cred: meta.azureSDKCred, - ClientOpt: meta.azureSDKClientOpt, - Parallelism: meta.parallelism, - Recursive: recursive, - ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), - IncludeResourceGroup: meta.includeResourceGroup, + Logger: meta.logger.WithGroup("azlist"), + SubscriptionId: meta.subscriptionId, + Cred: meta.azureSDKCred, + ClientOpt: meta.azureSDKClientOpt, + Parallelism: meta.parallelism, + Recursive: recursive, + IncludeResourceGroup: meta.includeResourceGroup, + ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), + ARGTable: meta.argTable, + ARGAuthorizationScopeFilter: meta.argAuthenticationScopeFilter, } lister, err := azlist.NewLister(opt) if err != nil { diff --git a/main.go b/main.go index 41881b7..7d329ce 100644 --- a/main.go +++ b/main.go @@ -421,6 +421,18 @@ func main() { Usage: "Include the resource groups that the exported resources belong to", Destination: &flagset.flagIncludeResourceGroup, }, + &cli.StringFlag{ + Name: "arg-table", + EnvVars: []string{"AZTFEXPORT_ARG_TABLE"}, + Usage: `The Azure Resource Graph table name. Defaults to "Resources".`, + Destination: &flagset.flagARGTable, + }, + &cli.StringFlag{ + Name: "arg-authorization-scope-filter", + EnvVars: []string{"AZTFEXPORT_ARG_AUTHORIZATION_SCOPE_FILTER"}, + Usage: `The Azure Resource Graph Authorization Scope Filter parameter. Possible values are: "AtScopeAndBelow", "AtScopeAndAbove", "AtScopeAboveAndBelow" and "AtScopeExact"`, + Destination: &flagset.flagARGAuthorizationScopeFilter, + }, }, resourceGroupFlags...) mappingFileFlags := append([]cli.Flag{}, commonFlags...) @@ -608,12 +620,14 @@ func main() { // Initialize the config cfg := config.Config{ - CommonConfig: commonConfig, - ARGPredicate: predicate, - ResourceNamePattern: flagset.flagPattern, - RecursiveQuery: flagset.flagRecursive, - IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, - IncludeResourceGroup: flagset.flagIncludeResourceGroup, + CommonConfig: commonConfig, + ARGPredicate: predicate, + ResourceNamePattern: flagset.flagPattern, + RecursiveQuery: flagset.flagRecursive, + IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + IncludeResourceGroup: flagset.flagIncludeResourceGroup, + ARGTable: flagset.flagARGTable, + ARGAuthorizationScopeFilter: flagset.flagARGAuthorizationScopeFilter, } return realMain(c.Context, cfg, flagset.flagNonInteractive, flagset.hflagMockClient, flagset.flagPlainUI, flagset.flagGenerateMappingFile, flagset.hflagProfile, flagset.DescribeCLI(ModeQuery), flagset.hflagTFClientPluginPath) diff --git a/pkg/config/config.go b/pkg/config/config.go index 49c6023..b725045 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -112,20 +112,35 @@ type Config struct { // MappingFile specifies the path of mapping file, this indicates the map file mode. MappingFile string - // ResourceNamePattern specifies the resource name pattern, this only applies to resource group mode, query mode and multi-resource mode. + ///////////////////////// + // Scope: rg, res (multi), query + + // ResourceNamePattern specifies the resource name pattern ResourceNamePattern string - // RecursiveQuery specifies whether to recursively list the child/proxy resources of the ARG resulted resource list, this only applies to query mode. - RecursiveQuery bool + ///////////////////////// + // Scope: rg, query + + // IncludeRoleAssignment specifies whether to include the role assginments assigned to the exported resources + IncludeRoleAssignment bool - // TFResourceName specifies the TF resource name, this only applies to resource mode. + ///////////////////////// + // Scope: res (single) + + // TFResourceName specifies the TF resource name TFResourceName string - // TFResourceName specifies the TF resource type (if empty, will try to deduce the type), this only applies to resource mode. + // TFResourceName specifies the TF resource type (if empty, will try to deduce the type) TFResourceType string - // IncludeRoleAssignment specifies whether to include the role assginments assigned to the exported resources, this only applies to rg and query mode - IncludeRoleAssignment bool + ///////////////////////// + // Scope: query - // IncludeResourceGroup specifies whether to include the resource groups that the exported resources belong to, this only applies to query mode + // RecursiveQuery specifies whether to recursively list the child/proxy resources of the ARG resulted resource list + RecursiveQuery bool + // IncludeResourceGroup specifies whether to include the resource groups that the exported resources belong to IncludeResourceGroup bool + // ARGTable specifies the ARG table name, which defaults to the "Resources" table + ARGTable string + // ARGAuthorizationScopeFilter specifies the AuthorizationScopeFilter parameter. Possible values are: "AtScopeAndBelow", "AtScopeAndAbove", "AtScopeAboveAndBelow" and "AtScopeExact" + ARGAuthorizationScopeFilter string }