cmd/terraformCmd.go (115 lines of code) (raw):

// MIT License // // Copyright (c) Microsoft Corporation. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE package main import ( "context" "fmt" "os" "github.com/Azure/mpf/pkg/infrastructure/authorizationCheckers/terraform" resourceGroupManager "github.com/Azure/mpf/pkg/infrastructure/resourceGroupManager" sproleassignmentmanager "github.com/Azure/mpf/pkg/infrastructure/spRoleAssignmentManager" "github.com/Azure/mpf/pkg/usecase" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var ( flgTFPath string flgWorkingDir string flgVarFilePath string flgImportExistingResourcesToState bool flgTargetModule string ) const FoundPermissionsFromFailedRunFilename = ".permissionsFromFailedRun.json" // terraformCmd represents the terraform command // var func NewTerraformCommand() *cobra.Command { terraformCmd := &cobra.Command{ Use: "terraform", Short: "A brief description of your command", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, Run: getMPFTerraform, } terraformCmd.Flags().StringVarP(&flgTFPath, "tfPath", "", "", "Path to Terraform Executable") err := terraformCmd.MarkFlagRequired("tfPath") if err != nil { log.Errorf("Error marking flag required for Terraform executable path: %v\n", err) } terraformCmd.Flags().StringVarP(&flgWorkingDir, "workingDir", "", "", "Path to Terraform Working Directory") err = terraformCmd.MarkFlagRequired("workingDir") if err != nil { log.Errorf("Error marking flag required for Terraform working directory: %v\n", err) } terraformCmd.Flags().StringVarP(&flgVarFilePath, "varFilePath", "", "", "Path to Terraform Variable File") terraformCmd.Flags().BoolVarP(&flgImportExistingResourcesToState, "importExistingResourcesToState", "", true, "On existing resource error, import existing resources into to Terraform State. This will also destroy the imported resources before MPF execution completes.") terraformCmd.Flags().StringVarP(&flgTargetModule, "targetModule", "", "", "The Terraform module to Target Module to run MPF on") return terraformCmd } func getMPFTerraform(cmd *cobra.Command, args []string) { setLogLevel() log.Info("Executin MPF for Terraform") log.Infof("TFPath: %s\n", flgTFPath) log.Infof("WorkingDir: %s\n", flgWorkingDir) log.Infof("VarFilePath: %s\n", flgVarFilePath) log.Infof("ImportExistingResourcesToState: %t\n", flgImportExistingResourcesToState) // validate if working directory exists if _, err := os.Stat(flgWorkingDir); os.IsNotExist(err) { log.Fatalf("Working Directory does not exist: %s\n", flgWorkingDir) } flgWorkingDir, err := getAbsolutePath(flgWorkingDir) if err != nil { log.Errorf("Error getting absolute path for terraform working directory: %v\n", err) } // validate if tfPath exists if _, err := os.Stat(flgTFPath); os.IsNotExist(err) { log.Fatalf("Terraform Executable does not exist: %s\n", flgTFPath) } flgTFPath, err := getAbsolutePath(flgTFPath) if err != nil { log.Errorf("Error getting absolute path for terraform executable: %v\n", err) } if flgVarFilePath != "" { if _, err := os.Stat(flgVarFilePath); os.IsNotExist(err) { log.Fatalf("Terraform Variable File does not exist: %s\n", flgVarFilePath) } flgVarFilePath, err = getAbsolutePath(flgVarFilePath) if err != nil { log.Errorf("Error getting absolute path for terraform variable file: %v\n", err) } } ctx := context.Background() mpfConfig := getRootMPFConfig() var rgManager usecase.ResourceGroupManager var spRoleAssignmentManager usecase.ServicePrincipalRolemAssignmentManager rgManager = resourceGroupManager.NewResourceGroupManager(flgSubscriptionID) spRoleAssignmentManager = sproleassignmentmanager.NewSPRoleAssignmentManager(flgSubscriptionID) var deploymentAuthorizationCheckerCleaner usecase.DeploymentAuthorizationCheckerCleaner var mpfService *usecase.MPFService initialPermissionsToAdd := []string{"Microsoft.Resources/deployments/read", "Microsoft.Resources/deployments/write"} permissionsToAddToResult := []string{"Microsoft.Resources/deployments/read", "Microsoft.Resources/deployments/write"} // Check if permissions file from previous failed run exists if terraform.DoesTFFileExist(flgWorkingDir, FoundPermissionsFromFailedRunFilename) { prevResult, err := terraform.LoadMPFResultFromFile(flgWorkingDir, FoundPermissionsFromFailedRunFilename) if err != nil { log.Warnf("Error loading permissions from previous failed run: %v\n, continuing....", err) } prevRunFoundPermissions := prevResult.RequiredPermissions[""] if len(prevRunFoundPermissions) > 0 { log.Warnf("Found permissions from previous failed run: %v\n Adding the Permissions....", prevRunFoundPermissions) initialPermissionsToAdd = append(initialPermissionsToAdd, prevRunFoundPermissions...) permissionsToAddToResult = append(permissionsToAddToResult, prevRunFoundPermissions...) } } deploymentAuthorizationCheckerCleaner = terraform.NewTerraformAuthorizationChecker(flgWorkingDir, flgTFPath, flgVarFilePath, flgImportExistingResourcesToState, flgTargetModule) mpfService = usecase.NewMPFService(ctx, rgManager, spRoleAssignmentManager, deploymentAuthorizationCheckerCleaner, mpfConfig, initialPermissionsToAdd, permissionsToAddToResult, false, true, false) displayOptions := getDislayOptions(flgShowDetailedOutput, flgJSONOutput, mpfConfig.SubscriptionID) mpfResult, err := mpfService.GetMinimumPermissionsRequired() if err != nil { if len(mpfResult.RequiredPermissions) > 0 { fmt.Println("Error occurred while getting minimum permissions required. However, some permissions were identified prior to the error.") _ = terraform.SaveMPFResultsToFile(flgWorkingDir, FoundPermissionsFromFailedRunFilename, mpfResult) displayResult(mpfResult, displayOptions) } log.Fatal(err) } if terraform.DoesTFFileExist(flgWorkingDir, FoundPermissionsFromFailedRunFilename) { _ = terraform.DeleteTFFile(flgWorkingDir, FoundPermissionsFromFailedRunFilename) } displayResult(mpfResult, displayOptions) }