Skip to content

Commit 20083ac

Browse files
fix: add missing subscription_id from azurerm block (#1177)
* fix: add missing subscription_id from azurerm block Signed-off-by: Darren Murray <[email protected]> * test: update azure generation tests Signed-off-by: Darren Murray <[email protected]> * refactor: address code review comments Signed-off-by: Darren Murray <[email protected]> * test: update azure generation tests Signed-off-by: Darren Murray <[email protected]> --------- Signed-off-by: Darren Murray <[email protected]>
1 parent aec4fe2 commit 20083ac

File tree

6 files changed

+167
-7
lines changed

6 files changed

+167
-7
lines changed

cli/cmd/generate_azure.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ import (
1414

1515
var (
1616
// Define question text here so they can be reused in testing
17-
QuestionAzureEnableConfig = "Enable Azure configuration integration?"
18-
QuestionAzureConfigName = "Specify custom configuration integration name: (optional)"
19-
QuestionEnableActivityLog = "Enable Azure Activity Log Integration?"
20-
QuestionActivityLogName = "Specify custom Activity Log integration name: (optional)"
17+
QuestionAzureEnableConfig = "Enable Azure configuration integration?"
18+
QuestionAzureConfigName = "Specify custom configuration integration name: (optional)"
19+
QuestionEnableActivityLog = "Enable Azure Activity Log Integration?"
20+
QuestionActivityLogName = "Specify custom Activity Log integration name: (optional)"
21+
QuestionAddAzureSubscriptionID = "Set Azure Subscription ID?"
22+
QuestionAzureSubscriptionID = "Specify the Azure Subscription ID to be used to provision Lacework resources: (optional)"
2123

2224
QuestionAzureAnotherAdvancedOpt = "Configure another advanced integration option"
2325
QuestionAzureConfigAdvanced = "Configure advanced integration options?"
@@ -169,6 +171,7 @@ By default, this command will function interactively, prompting for the required
169171
// Setup modifiers for NewTerraform constructor
170172
mods := []azure.AzureTerraformModifier{
171173
azure.WithLaceworkProfile(GenerateAzureCommandState.LaceworkProfile),
174+
azure.WithSubscriptionID(GenerateAzureCommandState.SubscriptionID),
172175
azure.WithAllSubscriptions(GenerateAzureCommandState.AllSubscriptions),
173176
azure.WithManagementGroup(GenerateAzureCommandState.ManagementGroup),
174177
azure.WithExistingStorageAccount(GenerateAzureCommandState.ExistingStorageAccount),
@@ -371,6 +374,12 @@ func initGenerateAzureTfCommandFlags() {
371374
"",
372375
"specify a custom configuration integration name")
373376

377+
generateAzureTfCommand.PersistentFlags().StringVar(
378+
&GenerateAzureCommandState.SubscriptionID,
379+
"subscription_id",
380+
"",
381+
"specify the Azure Subscription ID to be used to provision Lacework resources")
382+
374383
generateAzureTfCommand.PersistentFlags().BoolVar(
375384
&GenerateAzureCommandState.CreateAdIntegration,
376385
"ad_create",
@@ -601,6 +610,32 @@ func promptCustomizeAzureLoggingRegion(config *azure.GenerateAzureTfConfiguratio
601610
return nil
602611
}
603612

613+
func askAzureSubscriptionID(config *azure.GenerateAzureTfConfigurationArgs) error {
614+
var addSubscription bool
615+
616+
// if subscription has been set by --subscription_id flag do not prompt
617+
if config.SubscriptionID != "" {
618+
return nil
619+
}
620+
621+
if err := SurveyQuestionInteractiveOnly(SurveyQuestionWithValidationArgs{
622+
Prompt: &survey.Confirm{Message: QuestionAddAzureSubscriptionID, Default: false},
623+
Response: &addSubscription,
624+
}); err != nil {
625+
return err
626+
}
627+
628+
if addSubscription {
629+
if err := survey.AskOne(&survey.Input{
630+
Message: QuestionAzureSubscriptionID,
631+
}, &config.SubscriptionID); err != nil {
632+
return err
633+
}
634+
}
635+
636+
return nil
637+
}
638+
604639
func askAdvancedAzureOptions(config *azure.GenerateAzureTfConfigurationArgs, extraState *AzureGenerateCommandExtraState) error {
605640
answer := ""
606641

@@ -738,6 +773,10 @@ func promptAzureGenerate(config *azure.GenerateAzureTfConfigurationArgs, extraSt
738773
return errors.New("must enable activity log or config")
739774
}
740775

776+
if err := askAzureSubscriptionID(config); err != nil {
777+
return err
778+
}
779+
741780
// Find out if the customer wants to specify more advanced features
742781
if err := SurveyQuestionInteractiveOnly(SurveyQuestionWithValidationArgs{
743782
Prompt: &survey.Confirm{Message: QuestionAzureConfigAdvanced, Default: extraState.AskAdvanced},

integration/azure_generation_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func TestGenerationAzureSimple(t *testing.T) {
6868
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
6969
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
7070
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
71+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
7172
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
7273
MsgRsp{cmd.QuestionRunTfPlan, "n"},
7374
})
@@ -108,6 +109,7 @@ func TestGenerationAzureCustomizedOutputLocation(t *testing.T) {
108109
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
109110
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
110111
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
112+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
111113
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
112114
MsgMenu{cmd.AzureAdvancedOptDone, 5},
113115
MsgRsp{cmd.QuestionAzureCustomizeOutputLocation, dir},
@@ -146,6 +148,7 @@ func TestGenerationAzureConfigOnly(t *testing.T) {
146148
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
147149
MsgRsp{cmd.QuestionEnableActivityLog, "n"},
148150
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
151+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
149152
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
150153
MsgRsp{cmd.QuestionRunTfPlan, "n"},
151154
})
@@ -179,6 +182,7 @@ func TestGenerationAzureActivityLogOnly(t *testing.T) {
179182
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
180183
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
181184
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
185+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
182186
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
183187
MsgRsp{cmd.QuestionRunTfPlan, "n"},
184188
})
@@ -215,6 +219,7 @@ func TestGenerationAzureNoADEnabled(t *testing.T) {
215219
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
216220
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
217221
MsgRsp{cmd.QuestionEnableAdIntegration, "n"},
222+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
218223
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
219224
MsgMenu{cmd.AzureAdvancedOptLocation, 2},
220225
MsgRsp{cmd.QuestionADApplicationPass, pass},
@@ -258,6 +263,7 @@ func TestGenerationAzureNamedConfig(t *testing.T) {
258263
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
259264
MsgRsp{cmd.QuestionEnableActivityLog, "n"},
260265
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
266+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
261267
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
262268

263269
MsgMenu{cmd.AzureAdvancedOptDone, 0},
@@ -300,6 +306,7 @@ func TestGenerationAzureNamedActivityLog(t *testing.T) {
300306
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
301307
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
302308
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
309+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
303310
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
304311

305312
MsgMenu{cmd.AzureAdvancedOptDone, 0},
@@ -340,6 +347,7 @@ func TestGenerationAzureAdvancedOptsDone(t *testing.T) {
340347
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
341348
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
342349
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
350+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
343351
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
344352

345353
MsgMenu{cmd.AzureAdvancedOptDone, 6},
@@ -387,6 +395,7 @@ func TestGenerationAzureWithExistingTerraform(t *testing.T) {
387395
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
388396
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
389397
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
398+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
390399
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
391400
MsgMenu{cmd.AzureAdvancedOptDone, 5},
392401
MsgRsp{cmd.QuestionAzureCustomizeOutputLocation, dir},
@@ -425,6 +434,7 @@ func TestGenerationAzureConfigAllSubs(t *testing.T) {
425434
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
426435
MsgRsp{cmd.QuestionEnableActivityLog, "n"},
427436
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
437+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
428438
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
429439
MsgMenu{cmd.AzureAdvancedOptDone, 1},
430440
MsgRsp{cmd.QuestionEnableAllSubscriptions, "y"},
@@ -465,6 +475,7 @@ func TestGenerationAzureConfigMgmntGroup(t *testing.T) {
465475
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
466476
MsgRsp{cmd.QuestionEnableActivityLog, "n"},
467477
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
478+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
468479
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
469480

470481
MsgMenu{cmd.AzureAdvancedOptDone, 2},
@@ -508,6 +519,7 @@ func TestGenerationAzureConfigSubs(t *testing.T) {
508519
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
509520
MsgRsp{cmd.QuestionEnableActivityLog, "n"},
510521
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
522+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
511523
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
512524

513525
MsgMenu{cmd.AzureAdvancedOptDone, 1},
@@ -551,6 +563,7 @@ func TestGenerationAzureActivityLogSubs(t *testing.T) {
551563
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
552564
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
553565
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
566+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
554567
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
555568

556569
MsgMenu{cmd.AzureAdvancedOptDone, 1},
@@ -595,6 +608,7 @@ func TestGenerationAzureActivityLogStorageAccount(t *testing.T) {
595608
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
596609
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
597610
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
611+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
598612
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
599613

600614
MsgMenu{cmd.AzureAdvancedOptDone, 3},
@@ -641,6 +655,7 @@ func TestGenerationAzureActivityLogAllSubs(t *testing.T) {
641655
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
642656
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
643657
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
658+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
644659
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
645660

646661
MsgMenu{cmd.AzureAdvancedOptDone, 1},
@@ -683,6 +698,7 @@ func TestGenerationAzureActivityLogLocation(t *testing.T) {
683698
MsgRsp{cmd.QuestionAzureEnableConfig, "n"},
684699
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
685700
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
701+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
686702
MsgRsp{cmd.QuestionAzureConfigAdvanced, "y"},
687703

688704
MsgMenu{cmd.AzureAdvancedOptDone, 2},
@@ -728,6 +744,7 @@ func TestGenerationAzureOverwrite(t *testing.T) {
728744
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
729745
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
730746
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
747+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
731748
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
732749
MsgRsp{cmd.QuestionRunTfPlan, "n"},
733750
})
@@ -746,6 +763,7 @@ func TestGenerationAzureOverwrite(t *testing.T) {
746763
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
747764
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
748765
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
766+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
749767
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
750768
MsgRsp{"already exists, overwrite?", "n"},
751769
MsgRsp{cmd.QuestionRunTfPlan, "n"},
@@ -781,6 +799,7 @@ func TestGenerationAzureOverwriteOutput(t *testing.T) {
781799
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
782800
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
783801
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
802+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
784803
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
785804
MsgRsp{cmd.QuestionRunTfPlan, "n"},
786805
})
@@ -801,6 +820,7 @@ func TestGenerationAzureOverwriteOutput(t *testing.T) {
801820
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
802821
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
803822
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
823+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
804824
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
805825
MsgRsp{"already exists, overwrite?", "n"},
806826
MsgRsp{cmd.QuestionRunTfPlan, "n"},
@@ -830,6 +850,7 @@ func TestGenerationAzureLaceworkProfile(t *testing.T) {
830850
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
831851
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
832852
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
853+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "n"},
833854
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
834855
MsgRsp{cmd.QuestionRunTfPlan, "n"},
835856
})
@@ -851,6 +872,41 @@ func TestGenerationAzureLaceworkProfile(t *testing.T) {
851872
assert.Equal(t, buildTf, tfResult)
852873
}
853874

875+
func TestGenerationAzureWithSubscriptionID(t *testing.T) {
876+
os.Setenv("LW_NOCACHE", "true")
877+
defer os.Setenv("LW_NOCACHE", "")
878+
var final string
879+
var runError error
880+
mockSubscriptionID := "111aaa1a-a1a1-11aa-a111-1aaaa1a11a11"
881+
882+
// Run CLI
883+
tfResult := runGenerateAzureTest(t,
884+
func(c *expect.Console) {
885+
expectsCliOutput(t, c, []MsgRspHandler{
886+
MsgRsp{cmd.QuestionAzureEnableConfig, "y"},
887+
MsgRsp{cmd.QuestionEnableActivityLog, "y"},
888+
MsgRsp{cmd.QuestionEnableAdIntegration, "y"},
889+
MsgRsp{cmd.QuestionAddAzureSubscriptionID, "y"},
890+
MsgRsp{cmd.QuestionAzureSubscriptionID, mockSubscriptionID},
891+
MsgRsp{cmd.QuestionAzureConfigAdvanced, "n"},
892+
MsgRsp{cmd.QuestionRunTfPlan, "n"},
893+
})
894+
final, _ = c.ExpectEOF()
895+
},
896+
"generate",
897+
"cloud-account",
898+
"az",
899+
)
900+
901+
// Ensure CLI ran correctly
902+
assert.Nil(t, runError)
903+
assert.Contains(t, final, "Terraform code saved in")
904+
905+
// Create the TF directly with lwgenerate and validate same result via CLI
906+
buildTf, _ := azure.NewTerraform(true, true, true, azure.WithSubscriptionID(mockSubscriptionID)).Generate()
907+
assert.Equal(t, buildTf, tfResult)
908+
}
909+
854910
func runGenerateAzureTest(t *testing.T, conditions func(*expect.Console), args ...string) string {
855911
os.Setenv("HOME", tfPath)
856912

integration/test_resources/help/generate_cloud-account_azure

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Flags:
3535
--output string location to write generated content (default is ~/lacework/azure)
3636
--storage_account_name string specify storage account name
3737
--storage_resource_group string specify storage resource group
38+
--subscription_id string specify the Azure Subscription ID to be used to provision Lacework resources
3839
--subscription_ids strings list of subscriptions to grant read access; format is id1,id2,id3
3940
--terraform-apply run terraform apply for the generated hcl
4041

lwgenerate/azure/azure.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ type GenerateAzureTfConfigurationArgs struct {
4040
// List of subscription Ids
4141
SubscriptionIds []string
4242

43+
// Subscription ID configured in azurerm provider block
44+
SubscriptionID string
45+
4346
// Grant read access to ALL subscriptions
4447
AllSubscriptions bool
4548

@@ -197,6 +200,12 @@ func WithLaceworkProfile(name string) AzureTerraformModifier {
197200
}
198201
}
199202

203+
func WithSubscriptionID(subcriptionID string) AzureTerraformModifier {
204+
return func(c *GenerateAzureTfConfigurationArgs) {
205+
c.SubscriptionID = subcriptionID
206+
}
207+
}
208+
200209
// Generate new Terraform code based on the supplied args.
201210
func (args *GenerateAzureTfConfigurationArgs) Generate() (string, error) {
202211
// Validate inputs
@@ -220,7 +229,7 @@ func (args *GenerateAzureTfConfigurationArgs) Generate() (string, error) {
220229
return "", errors.Wrap(err, "failed to generate AD provider")
221230
}
222231

223-
azureRMProvider, err := createAzureRMProvider()
232+
azureRMProvider, err := createAzureRMProvider(args.SubscriptionID)
224233
if err != nil {
225234
return "", errors.Wrap(err, "failed to generate AM provider")
226235
}
@@ -307,19 +316,25 @@ func createAzureADProvider() ([]*hclwrite.Block, error) {
307316
// features = {}
308317
// }
309318
//
310-
func createAzureRMProvider() ([]*hclwrite.Block, error) {
319+
func createAzureRMProvider(subscriptionID string) ([]*hclwrite.Block, error) {
311320
blocks := []*hclwrite.Block{}
312321
attrs := map[string]interface{}{}
322+
featureAttrs := map[string]interface{}{}
323+
324+
if subscriptionID != "" {
325+
attrs["subscription_id"] = subscriptionID
326+
}
313327

314328
provider, err := lwgenerate.NewProvider(
315329
"azurerm",
330+
lwgenerate.HclProviderWithAttributes(attrs),
316331
).ToBlock()
317332

318333
if err != nil {
319334
return nil, err
320335
}
321336
// Create the features block
322-
featuresBlock, err := lwgenerate.HclCreateGenericBlock("features", []string{}, attrs)
337+
featuresBlock, err := lwgenerate.HclCreateGenericBlock("features", []string{}, featureAttrs)
323338
provider.Body().AppendBlock(featuresBlock)
324339

325340
if err != nil {

lwgenerate/azure/azure_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,13 @@ func TestGenerationWithLaceworkProvider(t *testing.T) {
231231
assert.NotNil(t, hcl)
232232
assert.Equal(t, laceworkProfile, hcl)
233233
}
234+
235+
func TestGenerationAzureRmProviderWithSubscriptionID(t *testing.T) {
236+
configWithSubscription, fileErr := getFileContent("test-data/config-with-azurerm-subscription.tf")
237+
assert.Nil(t, fileErr)
238+
239+
hcl, err := azure.NewTerraform(true, false, true, azure.WithSubscriptionID("test-subscription")).Generate()
240+
assert.Nil(t, err)
241+
assert.NotNil(t, hcl)
242+
assert.Equal(t, configWithSubscription, hcl)
243+
}

0 commit comments

Comments
 (0)