diff --git a/terragrunt-multi-envs/azure-pipelines.yaml b/terragrunt-multi-envs/azure-pipelines.yaml index 57411e3..b49a26e 100644 --- a/terragrunt-multi-envs/azure-pipelines.yaml +++ b/terragrunt-multi-envs/azure-pipelines.yaml @@ -11,18 +11,21 @@ resources: - repository: templates type: github name: ssc-spc-cloud-nuage/azure-pipelines - ref: refs/tags/v1.0.1 + ref: refs/tags/v1.1.0 endpoint: 'gh-ssc-spc-cloud-nuage-sc' stages: - template: pipelines/stage-elszenvs-template.yaml parameters: - checkovSkipChecks: 'CKV_SECRET_3,CKV2_AZURE_1,CKV2_AZURE_33,CKV_AZURE_33,CKV2_AZURE_38,CKV_AZURE_50,CKV_AZURE_93,CKV2_AZURE_11,CKV2_AZURE_16,\ - CKV2_AZURE_17,CKV2_AZURE_22,CKV2_AZURE_48,CKV2_AZURE_31,CKV_AZURE_41,CKV_AZURE_114,CKV_AZURE_20,CKV_AZURE_183,CKV_AZURE_151,\ - CKV2_AZURE_35,CKV2_AZURE_36,CKV2_AZURE_32,CKV2_AZURE_24,CKV_AZURE_35,CKV_SECRET_6,CKV_AZURE_235,CKV_AZURE_164,CKV_AZURE_167,CKV_AZURE_166 \ - CKV_AZURE_233,CKV_AZURE_149,CKV_AZURE_178,CKV_AZURE_49,CKV_AZURE_17,CKV_AZURE_66,CKV_AZURE_71,CKV_AZURE_63,CKV_AZURE_65,CKV_AZURE_88,CKV_AZURE_16' + checkovArgs: '--quiet --skip-check CKV_SECRET_3,CKV2_AZURE_1,CKV2_AZURE_33,CKV_AZURE_33,CKV2_AZURE_38,CKV_AZURE_50,CKV_AZURE_93,CKV2_AZURE_11,CKV2_AZURE_16,\ + CKV2_AZURE_17,CKV2_AZURE_22,CKV2_AZURE_48,CKV2_AZURE_31,CKV_AZURE_41,CKV_AZURE_114,CKV_AZURE_20,CKV_AZURE_183,CKV_AZURE_151,\ + CKV2_AZURE_35,CKV2_AZURE_36,CKV2_AZURE_32,CKV2_AZURE_24,CKV_AZURE_35,CKV_SECRET_6,CKV_AZURE_235,CKV_AZURE_164,CKV_AZURE_167,CKV_AZURE_166,\ + CKV_AZURE_233,CKV_AZURE_149,CKV_AZURE_178,CKV_AZURE_49,CKV_AZURE_17,CKV_AZURE_66,CKV_AZURE_71,CKV_AZURE_63,CKV_AZURE_65,CKV_AZURE_88,CKV_AZURE_16,\ + CKV_AZURE_109,CKV_AZURE_59,CKV_AZURE_244,CKV_AZURE_212,CKV_AZURE_231,CKV_AZURE_225,CKV_AZURE_97,CKV_AZURE_160,CKV_AZURE_9,CKV_AZURE_10,CKV_AZURE_109,CKV2_AZURE_41,CKV2_AZURE_40' eslzEnvs: - envName: 'dev' # Required. Name of the folder of the environment serviceConnection: # Required. Name of the service connection to the subscription pool: 'Devops' # Required. Name of the self-hosted agent pool layers: ['L2_blueprint_project'] # Required. name of the folders of the layers tracked for changes multiRunID: "" # Optional. Id of the run if the same env is defined multiple times + terraformVersion: '1.9.8' # Required. Terraform version to use + terragruntVersion: '0.68.4' # Required. Terragrunt version to use diff --git a/terragrunt-multi-envs/templates/job-terragruntapply-template.yaml b/terragrunt-multi-envs/templates/job-terragruntapply-template.yaml index 132d5e1..bc96ab7 100644 --- a/terragrunt-multi-envs/templates/job-terragruntapply-template.yaml +++ b/terragrunt-multi-envs/templates/job-terragruntapply-template.yaml @@ -9,7 +9,10 @@ parameters: type: string - name: multiRunID type: string - + - name: terraformVersion + type: string + - name: terragruntVersion + type: string jobs: - ${{ each layer in parameters.layers }}: @@ -27,27 +30,20 @@ jobs: if [ ! -d "$(Agent.ToolsDirectory)/.tfenv" ]; then git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tfenv.git $(Agent.ToolsDirectory)/.tfenv echo 'export PATH=$(Agent.ToolsDirectory)/.tfenv/bin:$PATH' >> ~/.profile - $(Agent.ToolsDirectory)/.tfenv/bin/tfenv install 1.9.1 - $(Agent.ToolsDirectory)/.tfenv/bin/tfenv use 1.9.1 + $(Agent.ToolsDirectory)/.tfenv/bin/tfenv install ${{ parameters.terraformVersion }} + $(Agent.ToolsDirectory)/.tfenv/bin/tfenv use ${{ parameters.terraformVersion }} fi if [ ! -d "$(Agent.ToolsDirectory)/.tgenv" ]; then git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tgenv.git $(Agent.ToolsDirectory)/.tgenv echo 'export PATH=$(Agent.ToolsDirectory)/.tgenv/bin:$PATH' >> ~/.profile - $(Agent.ToolsDirectory)/.tgenv/bin/tgenv install 0.66.9 - $(Agent.ToolsDirectory)/.tgenv/bin/tgenv use 0.66.9 + $(Agent.ToolsDirectory)/.tgenv/bin/tgenv install ${{ parameters.terragruntVersion }} + $(Agent.ToolsDirectory)/.tgenv/bin/tgenv use ${{ parameters.terragruntVersion }} fi source ~/.profile displayName: 'install terraform/terragrunt' - - task: DownloadBuildArtifacts@1 - name: DownloadTF - inputs: - buildType: current - downloadType: single - artifactName: tf_${{ parameters.eslzEnvFolder}}_${{ layer }} - downloadPath: '$(Build.SourcesDirectory)' - task: DownloadBuildArtifacts@1 name: DownloadPlan inputs: @@ -57,21 +53,34 @@ jobs: downloadPath: '$(Agent.TempDirectory)' - task: AzureCLI@2 displayName: 'terragrunt apply' + timeoutInMinutes: 240 inputs: azureSubscription: ${{ parameters.serviceConnection }} scriptType: bash scriptLocation: inlineScript addSpnToEnvironment: true - failOnStandardError : true - visibleAzLogin: false + failOnStandardError : false inlineScript: | + set -e export ARM_CLIENT_ID=$servicePrincipalId export ARM_OIDC_TOKEN=$idToken export ARM_TENANT_ID=$tenantId export ARM_SUBSCRIPTION_ID=$(az account show --query id -o tsv) export ARM_USE_OIDC=true export PIPELINE_TOKEN=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv) + export TERRAGRUNT_PIPELINE_RUN=true + # export instrumentationKey=$(az keyvault secret show --id https://g3scckv-cpms-mma-f07c-kv.vault.azure.net/secrets/instkey/a68523ce6abf4d77addf4cfbc247fbd1 --query value -o tsv) + # export apiKey=$(az keyvault secret show --id https://g3scckv-cpms-mma-f07c-kv.vault.azure.net/secrets/G3Sc-CPMS-MMahdavian-app-insights-appi-api-key/59750d02a3bc498abcf7e30d4d01e936 --query value -o tsv) + + # echo "##vso[task.setvariable variable=instrumentationKey;issecret=true]$instrumentationKey" + # echo "##vso[task.setvariable variable=apiKey;issecret=true]$apiKey" cd $(Build.SourcesDirectory)/landing_zones_*/${{ parameters.eslzEnvFolder}}/${{ layer }}/ terragrunt apply -auto-approve $(Agent.TempDirectory)/plan_${{ parameters.eslzEnvFolder}}_${{ layer }}/plan.tfplan + # applyExitCode=$? + + # echo "##vso[task.setvariable variable=applyExitCode;issecret=true]$applyExitCode" + visibleAzLogin: false + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) \ No newline at end of file diff --git a/terragrunt-multi-envs/templates/job-terragruntplan-template.yaml b/terragrunt-multi-envs/templates/job-terragruntplan-template.yaml index bb2e807..278c21b 100644 --- a/terragrunt-multi-envs/templates/job-terragruntplan-template.yaml +++ b/terragrunt-multi-envs/templates/job-terragruntplan-template.yaml @@ -5,7 +5,7 @@ parameters: type: string - name: eslzEnvFolder type: string - - name: checkovSkipChecks + - name: checkovArgs type: string - name: eslzEnvPool type: string @@ -17,7 +17,7 @@ jobs: dependsOn: InitJob condition: and(succeeded(), eq(dependencies.InitJob.outputs['GitDiffTask.RepoChange${{ layer }}'], 'true')) variables: - AgentName: $[ dependencies.InitJob.outputs['TFTGInstall.JobAgentName'] ] + AgentName: $[ dependencies.InitJob.outputs['InstallTools.JobAgentName'] ] pool: name: ${{ parameters.eslzEnvPool }} demands: Agent.Name -equals $(AgentName) @@ -29,7 +29,6 @@ jobs: scriptType: bash scriptLocation: inlineScript addSpnToEnvironment: true - visibleAzLogin: false inlineScript: | export ARM_CLIENT_ID=$servicePrincipalId export ARM_OIDC_TOKEN=$idToken @@ -38,21 +37,27 @@ jobs: export ARM_USE_OIDC=true export PIPELINE_TOKEN=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv) + # instrumentation_key=$(az keyvault secret show --id https://g3scckv-cpms-mma-f07c-kv.vault.azure.net/secrets/instkey/a68523ce6abf4d77addf4cfbc247fbd1 --query value -o tsv) + # api_key=$(az keyvault secret show --id https://g3scckv-cpms-mma-f07c-kv.vault.azure.net/secrets/G3Sc-CPMS-MMahdavian-app-insights-appi-api-key/59750d02a3bc498abcf7e30d4d01e936 --query value -o tsv) + echo "##vso[task.setvariable variable=ARMClient;issecret=true]$ARM_CLIENT_ID" echo "##vso[task.setvariable variable=OIDCToken;issecret=true]$ARM_OIDC_TOKEN" echo "##vso[task.setvariable variable=SubID;issecret=true]$ARM_SUBSCRIPTION_ID" echo "##vso[task.setvariable variable=TenantID;issecret=true]$ARM_TENANT_ID" echo "##vso[task.setvariable variable=pipelineToken;issecret=true]$PIPELINE_TOKEN" + # echo "##vso[task.setvariable variable=instrumentationKey;issecret=true]$instrumentation_key" + # echo "##vso[task.setvariable variable=apiKey;issecret=true]$api_key" cd $(Build.SourcesDirectory)/landing_zones_*/${{ parameters.eslzEnvFolder}}/${{ layer }}/ terragrunt init - + visibleAzLogin: false - task: bash@3 name: TerragruntValidate inputs: targetType: inline - failOnStderr: true + #failOnStderr: true script: | + set -e cd $(Build.SourcesDirectory)/landing_zones_*/${{ parameters.eslzEnvFolder}}/${{ layer }}/ terragrunt validate env: @@ -67,11 +72,12 @@ jobs: name: TerragruntPlan inputs: targetType: inline - failOnStderr: true - script: | + failOnStderr: false + script: | + set -e cd $(Build.SourcesDirectory)/landing_zones_*/${{ parameters.eslzEnvFolder}}/${{ layer }}/ terragrunt plan --out=$(Build.ArtifactStagingDirectory)/plan.tfplan - terragrunt show -no-color $(Build.ArtifactStagingDirectory)/plan.tfplan > $(Build.ArtifactStagingDirectory)/plan_${{ layer }}.txt + terragrunt show -no-color --terragrunt-forward-tf-stdout $(Build.ArtifactStagingDirectory)/plan.tfplan > $(Build.ArtifactStagingDirectory)/plan_${{ layer }}.txt env: ARM_CLIENT_ID: $(ARMClient) ARM_TENANT_ID: $(TenantID) @@ -79,6 +85,7 @@ jobs: ARM_OIDC_TOKEN: $(OIDCToken) ARM_USE_OIDC: true PIPELINE_TOKEN: $(pipelineToken) + SYSTEM_ACCESSTOKEN: $(System.AccessToken) - task: bash@3 name: Checkov @@ -87,7 +94,7 @@ jobs: script: | cd $(Build.SourcesDirectory)/landing_zones_*/${{ parameters.eslzEnvFolder}}/${{ layer }}/ terragrunt show -json $(Build.ArtifactStagingDirectory)/plan.tfplan > plan.json - checkov -f plan.json --skip-check ${{ parameters.checkovSkipChecks }} --quiet + checkov -f plan.json ${{ parameters.checkovArgs }} env: ARM_CLIENT_ID: $(ARMClient) ARM_TENANT_ID: $(TenantID) @@ -96,7 +103,6 @@ jobs: ARM_USE_OIDC: true PIPELINE_TOKEN: $(pipelineToken) - - task: bash@3 name: CommentPlanOnPR inputs: @@ -132,10 +138,4 @@ jobs: inputs: PathtoPublish: $(Build.ArtifactStagingDirectory) ArtifactName: plan_${{ parameters.eslzEnvFolder}}_${{ layer }} - - - task: PublishBuildArtifacts@1 - name: PublishTF - inputs: - PathtoPublish: $(Build.SourcesDirectory) - ArtifactName: tf_${{ parameters.eslzEnvFolder }}_${{ layer }} \ No newline at end of file diff --git a/terragrunt-multi-envs/templates/stage-elszenvs-template.yaml b/terragrunt-multi-envs/templates/stage-elszenvs-template.yaml index 91da02b..14d608f 100644 --- a/terragrunt-multi-envs/templates/stage-elszenvs-template.yaml +++ b/terragrunt-multi-envs/templates/stage-elszenvs-template.yaml @@ -1,8 +1,13 @@ parameters: - name: eslzEnvs type: object - - name: checkovSkipChecks + - name: checkovArgs type: string + - name: terraformVersion + type: string + - name: terragruntVersion + type: string + stages: - ${{ each eslzEnv in parameters.eslzEnvs }}: - stage: ${{ eslzEnv.envName }}_Plan_${{ eslzEnv.multiRunID }} @@ -14,10 +19,46 @@ stages: steps: - checkout: none - bash: | - sudo apt-get install jq -y - sudo apt-get install unzip -y - curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash - name: InstallPackages + if ! command -v jq &> /dev/null; then + sudo apt-get update + sudo apt-get install -y jq + fi + + if ! command -v unzip &> /dev/null; then + sudo apt-get update + sudo apt-get install -y unzip + fi + + if ! command -v az &> /dev/null; then + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + fi + + if [ ! -d "$(Agent.ToolsDirectory)/.tfenv" ]; then + git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tfenv.git $(Agent.ToolsDirectory)/.tfenv + echo 'export PATH=$(Agent.ToolsDirectory)/.tfenv/bin:$PATH' >> ~/.profile + fi + $(Agent.ToolsDirectory)/.tfenv/bin/tfenv install ${{ parameters.terraformVersion }} + $(Agent.ToolsDirectory)/.tfenv/bin/tfenv use ${{ parameters.terraformVersion }} + + if [ ! -d "$(Agent.ToolsDirectory)/.tgenv" ]; then + git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tgenv.git $(Agent.ToolsDirectory)/.tgenv + echo 'export PATH=$(Agent.ToolsDirectory)/.tgenv/bin:$PATH' >> ~/.profile + fi + $(Agent.ToolsDirectory)/.tgenv/bin/tgenv install ${{ parameters.terragruntVersion }} + $(Agent.ToolsDirectory)/.tgenv/bin/tgenv use ${{ parameters.terragruntVersion }} + + if ! command -v checkov &> /dev/null; then + sudo apt-get update + sudo apt install python3-pip -y + pip3 install checkov + echo 'export PATH=$HOME/.local/bin:$PATH' >> ~/.profile + fi + + source ~/.profile + + echo "##vso[task.setvariable variable=JobAgentName;isOutput=true]$(Agent.Name)" + name: InstallTools + - bash: | if [[ $(Build.Reason) == "PullRequest" ]]; then sourceBranch=$(echo $(System.PullRequest.SourceBranch) | sed 's|refs/heads/||') @@ -27,7 +68,10 @@ stages: echo "Manual build triggered from $sourceBranch" fi defaultBranch=$(curl -s -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" -H "Content-Type: application/json" "$(System.CollectionUri)$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)?api-version=7.1-preview.1" | jq -r .defaultBranch | sed 's|refs/heads/||') - changedFiles=$(curl -s -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" -H "Content-Type: application/json" "$(System.CollectionUri)$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/diffs/commits?baseVersion=$defaultBranch&targetVersion=$sourceBranch&api-version=7.1-preview.1" | jq '.changes[].item.path') + changedFiles=$(curl -s -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" -H "Content-Type: application/json" "$(System.CollectionUri)$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/diffs/commits?baseVersion=$defaultBranch&targetVersion=$sourceBranch&api-version=7.1" | jq '.changes[].item.path') + echo $defaultBranch + echo "--------" + echo $changedFiles echo "$LAYERS_JSON" | jq -r '.[]' | while read -r layername; do foldertocheck="${{ eslzEnv.envName }}/$layername/" if [[ "$changedFiles" =~ $foldertocheck ]]; then @@ -43,34 +87,7 @@ stages: env: LAYERS_JSON: ${{ convertToJson(eslzEnv.layers) }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - bash: | - if [ ! -d "$(Agent.ToolsDirectory)/.tfenv" ]; then - git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tfenv.git $(Agent.ToolsDirectory)/.tfenv - echo 'export PATH=$(Agent.ToolsDirectory)/.tfenv/bin:$PATH' >> ~/.profile - $(Agent.ToolsDirectory)/.tfenv/bin/tfenv install 1.9.1 - $(Agent.ToolsDirectory)/.tfenv/bin/tfenv use 1.9.1 - fi - - if [ ! -d "$(Agent.ToolsDirectory)/.tgenv" ]; then - git clone --depth=1 https://github.com/ssc-spc-cloud-nuage/tgenv.git $(Agent.ToolsDirectory)/.tgenv - echo 'export PATH=$(Agent.ToolsDirectory)/.tgenv/bin:$PATH' >> ~/.profile - $(Agent.ToolsDirectory)/.tgenv/bin/tgenv install 0.66.9 - $(Agent.ToolsDirectory)/.tgenv/bin/tgenv use 0.66.9 - fi - echo "##vso[task.setvariable variable=JobAgentName;isOutput=true]$(Agent.Name)" - - displayName: 'install terraform/terragrunt' - name: TFTGInstall - - - bash: | - if [ ! -f $HOME/.local/bin/checkov ]; then - sudo apt install python3-pip -y - pip3 install checkov - echo 'export PATH=$HOME/.local/bin:$PATH' >> ~/.profile - fi - - displayName: 'Install Checkov' - template: /terragrunt-multi-envs/templates/job-terragruntplan-template.yaml@templates @@ -78,7 +95,7 @@ stages: serviceConnection: ${{ eslzEnv.serviceConnection }} eslzEnvFolder: ${{ eslzEnv.envName }} layers: ${{ eslzEnv.layers }} - checkovSkipChecks: ${{ parameters.checkovSkipChecks }} + checkovArgs: ${{ parameters.checkovArgs }} eslzEnvPool: ${{ eslzEnv.pool }} - job: PostPlanJob @@ -88,7 +105,7 @@ stages: - TerragruntPlan_${{ eslzEnv.envName }}_${{ layer }} condition: always() variables: - AgentName: $[ dependencies.InitJob.outputs['TFTGInstall.JobAgentName'] ] + AgentName: $[ dependencies.InitJob.outputs['InstallTools.JobAgentName'] ] pool: name: ${{ eslzEnv.pool }} demands: Agent.Name -equals $(AgentName) @@ -114,6 +131,22 @@ stages: echo "Changes in plan detected in $layername)." echo "##vso[task.setvariable variable=PlanChange;isOutput=true]true" fi + + # if echo "$planvar" | grep -q "Plan:.*to add"; then + # echo "Changes in plan detected in $layername)." + # changes_detected=true + # elif echo "$planvar" | grep -q "Plan:.*to change"; then + # echo "Changes in plan detected in $layername)." + # changes_detected=true + # elif echo "$planvar" | grep -q "Plan:.*to destroy"; then + # echo "Changes in plan detected in $layername)." + # changes_detected=true + # else + # echo "No Changes in plan detected in $layername)." + # changes_detected=false + # fi + + # echo "##vso[task.setvariable variable=PlanChange;isOutput=true]$changes_detected" fi done name: CheckPlanChangeTask @@ -135,3 +168,5 @@ stages: layers: ${{ eslzEnv.layers }} eslzEnvPool: ${{ eslzEnv.pool }} multiRunID: ${{ eslzEnv.multiRunID }} + terraformVersion: ${{ parameters.terraformVersion }} + terragruntVersion: ${{ parameters.terragruntVersion }} \ No newline at end of file