-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Salim Afiune Maya <[email protected]>
- Loading branch information
Showing
1 changed file
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
// Copyright (c) Mondoo, Inc. | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
|
||
package cmd | ||
|
||
import ( | ||
"dario.cat/mergo" | ||
"github.com/AlecAivazis/survey/v2" | ||
Check failure on line 8 in apps/cnspec/cmd/integrate.go GitHub Actions / go-test
Check failure on line 8 in apps/cnspec/cmd/integrate.go GitHub Actions / go-test
|
||
"github.com/cockroachdb/errors" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
// cnspec integrate | ||
rootCmd.AddCommand(integrateCmd) | ||
// cnspec integrate azure | ||
integrateCmd.AddCommand(integrateAzureCmd) | ||
} | ||
|
||
var ( | ||
integrateCmd = &cobra.Command{ | ||
Use: "integrate", | ||
Aliases: []string{"onboard"}, | ||
Hidden: true, | ||
Short: "Onboard integrations for continuous scanning into the Mondoo platform", | ||
Long: "Run automation code to onboard your account and deploy Mondoo into various environments.", | ||
} | ||
integrateAzureCmd = &cobra.Command{ | ||
Use: "azure", | ||
Aliases: []string{"az"}, | ||
Short: "Onboard Microsoft Azure", | ||
Long: `Use this command to connect your Azure environment into the Mondoo platform.`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
// Generate TF Code | ||
cli.StartProgress("Generating Azure Terraform Code...") | ||
|
||
if cli.Profile != "default" { | ||
GenerateAzureCommandState.LaceworkProfile = cli.Profile | ||
} | ||
|
||
// Setup modifiers for NewTerraform constructor | ||
mods := []azure.AzureTerraformModifier{ | ||
azure.WithLaceworkProfile(GenerateAzureCommandState.LaceworkProfile), | ||
azure.WithSubscriptionID(GenerateAzureCommandState.SubscriptionID), | ||
azure.WithAllSubscriptions(GenerateAzureCommandState.AllSubscriptions), | ||
azure.WithManagementGroup(GenerateAzureCommandState.ManagementGroup), | ||
azure.WithExistingStorageAccount(GenerateAzureCommandState.ExistingStorageAccount), | ||
azure.WithStorageAccountName(GenerateAzureCommandState.StorageAccountName), | ||
azure.WithStorageLocation(GenerateAzureCommandState.StorageLocation), | ||
azure.WithActivityLogIntegrationName(GenerateAzureCommandState.ActivityLogIntegrationName), | ||
azure.WithConfigIntegrationName(GenerateAzureCommandState.ConfigIntegrationName), | ||
azure.WithEntraIdActivityLogIntegrationName(GenerateAzureCommandState.EntraIdIntegrationName), | ||
azure.WithEventHubLocation(GenerateAzureCommandState.EventHubLocation), | ||
azure.WithEventHubPartitionCount(GenerateAzureCommandState.EventHubPartitionCount), | ||
} | ||
|
||
// Check if AD Creation is required, need to set values for current integration | ||
if !GenerateAzureCommandState.CreateAdIntegration { | ||
mods = append(mods, azure.WithAdApplicationId(GenerateAzureCommandState.AdApplicationId)) | ||
mods = append(mods, azure.WithAdApplicationPassword(GenerateAzureCommandState.AdApplicationPassword)) | ||
mods = append(mods, azure.WithAdServicePrincipalId(GenerateAzureCommandState.AdServicePrincipalId)) | ||
} | ||
|
||
// Check subscriptions | ||
if !GenerateAzureCommandState.AllSubscriptions { | ||
if len(GenerateAzureCommandState.SubscriptionIds) > 0 { | ||
mods = append(mods, azure.WithSubscriptionIds(GenerateAzureCommandState.SubscriptionIds)) | ||
} | ||
} | ||
|
||
// Check management groups | ||
if GenerateAzureCommandState.ManagementGroup { | ||
mods = append(mods, azure.WithManagementGroupId(GenerateAzureCommandState.ManagementGroupId)) | ||
} | ||
|
||
// Check storage account | ||
if GenerateAzureCommandState.ExistingStorageAccount { | ||
mods = append(mods, | ||
azure.WithStorageAccountResourceGroup(GenerateAzureCommandState.StorageAccountResourceGroup)) | ||
} | ||
|
||
// Create new struct | ||
data := azure.NewTerraform( | ||
GenerateAzureCommandState.Config, | ||
GenerateAzureCommandState.ActivityLog, | ||
GenerateAzureCommandState.EntraIdActivityLog, | ||
GenerateAzureCommandState.CreateAdIntegration, | ||
mods...) | ||
|
||
// Generate HCL for azure deployment | ||
hcl, err := data.Generate() | ||
cli.StopProgress() | ||
|
||
if err != nil { | ||
return errors.Wrap(err, "failed to generate terraform code") | ||
} | ||
|
||
// Write-out generated code to location specified | ||
dirname, _, err := writeGeneratedCodeToLocation(cmd, hcl, "azure") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Prompt to execute, if the command line flag has not been set | ||
if !GenerateAzureCommandExtraState.TerraformApply { | ||
err = SurveyQuestionInteractiveOnly(SurveyQuestionWithValidationArgs{ | ||
Prompt: &survey.Confirm{Default: GenerateAzureCommandExtraState.TerraformApply, Message: QuestionRunTfPlan}, | ||
Response: &GenerateAzureCommandExtraState.TerraformApply, | ||
}) | ||
|
||
if err != nil { | ||
return errors.Wrap(err, "failed to prompt for terraform execution") | ||
} | ||
} | ||
|
||
locationDir, _ := determineOutputDirPath(dirname, "azure") | ||
if GenerateAzureCommandExtraState.TerraformApply { | ||
// Execution pre-run check | ||
err := executionPreRunChecks(dirname, locationDir, "azure") | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// Output where code was generated | ||
if !GenerateAzureCommandExtraState.TerraformApply { | ||
cli.OutputHuman(provideGuidanceAfterExit(false, false, locationDir, "terraform")) | ||
} | ||
|
||
return nil | ||
}, | ||
PreRunE: func(cmd *cobra.Command, _ []string) error { | ||
|
||
// Validate output location is OK if supplied | ||
dirname, err := cmd.Flags().GetString("output") | ||
if err != nil { | ||
return errors.Wrap(err, "failed to load command flags") | ||
} | ||
if err := validateOutputLocation(dirname); err != nil { | ||
return err | ||
} | ||
|
||
// Validate Storage Location | ||
storageLocation, err := cmd.Flags().GetString("location") | ||
if err != nil { | ||
return errors.Wrap(err, "failed to load command flags") | ||
} | ||
if err := validateAzureLocation(storageLocation); storageLocation != "" && err != nil { | ||
return err | ||
} | ||
|
||
// Load any cached inputs if interactive | ||
if cli.InteractiveMode() { | ||
cachedOptions := &azure.GenerateAzureTfConfigurationArgs{} | ||
iacParamsExpired := cli.ReadCachedAsset(CachedAzureAssetIacParams, &cachedOptions) | ||
if iacParamsExpired { | ||
cli.Log.Debug("loaded previously set values for Azure iac generation") | ||
} | ||
|
||
extraState := &AzureGenerateCommandExtraState{} | ||
extraStateParamsExpired := cli.ReadCachedAsset(CachedAzureAssetExtraState, &extraState) | ||
if extraStateParamsExpired { | ||
cli.Log.Debug("loaded previously set values for Azure iac generation (extra state)") | ||
} | ||
|
||
// Determine if previously cached options exists; prompt user if they'd like to continue | ||
answer := false | ||
if !iacParamsExpired || !extraStateParamsExpired { | ||
if err := SurveyQuestionInteractiveOnly(SurveyQuestionWithValidationArgs{ | ||
Prompt: &survey.Confirm{Message: QuestionUsePreviousCache, Default: false}, | ||
Response: &answer, | ||
}); err != nil { | ||
return errors.Wrap(err, "failed to load saved options") | ||
} | ||
} | ||
|
||
// If the user decides NOT to use the previous values; we won't load them. However, every time the command runs | ||
// we are going to write out new cached values, so if they run it - bail out - and run it again they'll get | ||
// re-prompted. | ||
if answer { | ||
// Merge cached inputs to current options (current options win) | ||
if err := mergo.Merge(GenerateAzureCommandState, cachedOptions); err != nil { | ||
return errors.Wrap(err, "failed to load saved options") | ||
} | ||
if err := mergo.Merge(GenerateAzureCommandExtraState, extraState); err != nil { | ||
return errors.Wrap(err, "failed to load saved options") | ||
} | ||
} | ||
} | ||
|
||
// Collect and/or confirm parameters | ||
err = promptAzureGenerate(GenerateAzureCommandState, GenerateAzureCommandExtraState) | ||
if err != nil { | ||
return errors.Wrap(err, "collecting/confirming parameters") | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
) |