├── GitHub-Enterprise-App ├── Readme.md └── prisma-cloud-github-webhook.zip ├── README.md └── aws-codepipeline ├── PrismaCloudCompute └── buildspec.yml ├── PrismaCloudIacScan ├── Bash │ ├── PrismaCloudIaCAction.json │ └── poll.sh └── Lambda │ └── PrismaCloudIaCScan.zip └── README.md /GitHub-Enterprise-App/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /GitHub-Enterprise-App/prisma-cloud-github-webhook.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaloAltoNetworks/Prisma-Cloud-DevOps-Security/f36756e3fc0fb2a76ffe3daf139291276e35e80c/GitHub-Enterprise-App/prisma-cloud-github-webhook.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Prisma Cloud DevOps Security

2 | 3 | The Prisma Cloud devOps security capabilities are geared to meet the common goal of delivering releases faster and preventing security lapses by applying a consistent set of checks through the build-to-release process that keep your applications and infrastructure secure. 4 | 5 | Prisma Cloud devOps security enables devOps and security teams to identify insecure configurations in Infrastructure-as-Code (IaC) templates and vulnerabilities in container images so that security issues are identified before actual resources are deployed in runtime environments. 6 | To identify potential issues you can scan the content in your templates and files in AWS CloudFormation Templates (JSON or YAML format), HashiCorp Terraform templates (HCL format), and Kubernetes App manifests (JSON or YAML format) against a list of IaC policies policies. Currently, these policies provide good coverage of AWS and GCP CIS standards. 7 | 8 | ![alt text](https://docs.paloaltonetworks.com/content/dam/techdocs/en_US/dita/_graphics/uv/prisma/prisma-cloud/prisma-cloud-admin-guide/IaC_concept.png) 9 | -------------------------------------------------------------------------------- /aws-codepipeline/PrismaCloudCompute/buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | # In this example, we're using environment variables 4 | # to store the username & password of our Prisma Cloud Compute CI user account 5 | # and the URL to our console 6 | 7 | # Username: The Prisma Cloud Compute user with the CI User role 8 | # Password: The password for this user account 9 | # Prisma_Cloud_Compute_Console_URL: The base URL for the console -- http://console..com:8083 -- without a trailing / 10 | 11 | phases: 12 | install: 13 | runtime-versions: 14 | docker: 18 15 | build: 16 | commands: 17 | - echo Build started on `date` 18 | - echo Building the Docker image... 19 | - docker build -t $IMAGE_NAME:$IMAGE_TAG . 20 | post_build: 21 | commands: 22 | - echo Build completed on `date` 23 | - echo Downloading twistcli 24 | - curl -k -u $Username:$Password --output ./twistcli $Prisma_Cloud_Compute_Console_URL/api/v1/util/twistcli 25 | - chmod +x ./twistcli 26 | - echo Scanning with twistcli 27 | 28 | # Run the scan with twistcli, providing detailed results in CodeBuild and 29 | # pushing the results to the Twistlock console. 30 | # --details returns all vulnerabilities & compliance issues rather than just summaries. 31 | # -address points to our Twistlock console 32 | # -u and -p provide credentials for the console. These creds only need the CI User role. 33 | # Finally, we provide the name of the image we built with 'docker build', above. 34 | 35 | - ./twistcli images scan --details -address $Prisma_Cloud_Compute_Console_URL -u $Username -p $Password $IMAGE_NAME:$IMAGE_TAG 36 | 37 | # Add --vulnerability-threshold and/or --compliance-threshold to this command to 38 | # fail builds based on the thresholds. 39 | # See twistcli documentation for more details. 40 | 41 | -------------------------------------------------------------------------------- /aws-codepipeline/PrismaCloudIacScan/Bash/PrismaCloudIaCAction.json: -------------------------------------------------------------------------------- 1 | { 2 | "category": "Test", 3 | "provider": "Prisma-Cloud-IaC-Scan", 4 | "version": "1", 5 | "settings": { 6 | "entityUrlTemplate": "https://s3.console.aws.amazon.com/s3/buckets/{Config:S3BucketName}/?region={Config:S3BucketRegion}&tab=overview", 7 | "executionUrlTemplate": "https://s3.console.aws.amazon.com/s3/buckets/{Config:S3BucketName}/?region={Config:S3BucketRegion}&tab=overview" 8 | }, 9 | 10 | "configurationProperties": [ 11 | { 12 | "name": "S3BucketName", 13 | "required": true, 14 | "key": true, 15 | "secret": false, 16 | "queryable": false, 17 | "description": "The S3 bucket name.", 18 | "type": "String" 19 | }, 20 | { 21 | "name": "S3BucketRegion", 22 | "required": true, 23 | "key": true, 24 | "secret": false, 25 | "queryable": false, 26 | "description": "The region where the S3 bucket specified", 27 | "type": "String" 28 | }, 29 | { 30 | "name": "Prisma_Cloud_API_URL", 31 | "required": true, 32 | "key": true, 33 | "secret": false, 34 | "queryable": false, 35 | "description": "Prisma Cloud server URL", 36 | "type": "String" 37 | 38 | }, 39 | { 40 | "name": "Access_Key", 41 | "required": true, 42 | "key": true, 43 | "secret": false, 44 | "queryable": false, 45 | "description": "Prisma Cloud access key", 46 | "type": "String" 47 | 48 | }, 49 | { 50 | "name": "Secret_Key", 51 | "required": true, 52 | "key": true, 53 | "secret": true, 54 | "queryable": false, 55 | "description": "Prisma Cloud secret key", 56 | "type": "String" 57 | 58 | }, 59 | { 60 | "name": "Failure_Criteria_High_Severity", 61 | "required": true, 62 | "key": true, 63 | "secret": false, 64 | "queryable": false, 65 | "description": "Provide failure threshold for high severity security issues", 66 | "type": "Number" 67 | }, 68 | { 69 | "name": "Failure_Criteria_Medium_Severity", 70 | "required": true, 71 | "key": true, 72 | "secret": false, 73 | "queryable": false, 74 | "description": "Provide failure threshold for medium severity security issues.", 75 | "type": "Number" 76 | }, 77 | { 78 | "name": "Failure_Criteria_Low_Severity", 79 | "required": true, 80 | "key": true, 81 | "secret": false, 82 | "queryable": false, 83 | "description": "Provide failure threshold for low severity security issues.", 84 | "type": "Number" 85 | }, 86 | { 87 | "name": "Failure_Criteria_Operator", 88 | "required": true, 89 | "key": true, 90 | "secret": false, 91 | "queryable": false, 92 | "description": "Provide operator for high, medium, low severity failure thresholds.", 93 | "type": "String" 94 | } 95 | ], 96 | "inputArtifactDetails": { 97 | "maximumCount": 1, 98 | "minimumCount": 0 99 | }, 100 | "outputArtifactDetails": { 101 | "maximumCount": 1, 102 | "minimumCount": 0 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /aws-codepipeline/PrismaCloudIacScan/Bash/poll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -u 4 | set -e 5 | trap "echo ERR; exit" ERR 6 | 7 | # exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> cmds.log; done;) 8 | 9 | #set -x 10 | 11 | if [[ -z "${1:-}" ]]; then 12 | echo "Usage: ./poll.sh " >&2 13 | echo -e "Example:\n ./poll.sh \"category=Test,owner=Custom,version=1,provider=Prisma-Cloud-IaC-Scan\"" >&2 14 | exit 1 15 | fi 16 | 17 | echo_ts() { 18 | 19 | echo -e "\n" >> Prisma_Cloud_IaC_Scan.log 20 | echo "$1" >> Prisma_Cloud_IaC_Scan.log 21 | 22 | } 23 | 24 | run() { 25 | 26 | local action_type_id="$1" 27 | echo_ts "actiontypeid: $action_type_id" 28 | 29 | #while : 30 | #do 31 | local job_json="$(fetch_job "$action_type_id")" 32 | 33 | if [[ "$job_json" != "null" && "$job_json" != "None" && "$job_json" != "" ]]; then 34 | 35 | local job_id="$(echo "$job_json" | jq -r '.id')" 36 | echo "job_id: $job_id" 37 | mkdir $job_id 38 | chmod +x $job_id 39 | cd $job_id || update_job_status "$job_json" "job id not found" 40 | 41 | acknowledge_job "$job_json" 42 | local build_json=$(create_build "$job_json") 43 | else 44 | sleep 10 45 | fi 46 | #done 47 | } 48 | acknowledge_job() { 49 | 50 | local job_json="$1" 51 | local job_id="$(echo "$job_json" | jq -r '.id')" 52 | local nonce="$(echo "$job_json" | jq -r '.nonce')" 53 | 54 | echo_ts "Acknowledging CodePipeline job (id: $job_id nonce: $nonce)" >&2 55 | 56 | aws codepipeline acknowledge-job --job-id "$job_id" --nonce "$nonce" > /dev/null 2>&1 57 | } 58 | 59 | fetch_job() { 60 | 61 | local action_type_id="$1" 62 | 63 | aws codepipeline poll-for-jobs --max-batch-size 1 \ 64 | --action-type-id "$action_type_id" \ 65 | --query 'jobs[0]' 66 | } 67 | 68 | action_configuration_value() { 69 | 70 | local job_json="$1" 71 | local configuration_key="$2" 72 | 73 | echo "$job_json" | jq -r ".data.actionConfiguration.configuration | .[\"$configuration_key\"]" 74 | 75 | } 76 | 77 | update_job_status() { 78 | local job_json="$1" 79 | local build_state="$2" 80 | 81 | local job_id="$(echo "$job_json" | jq -r '.id')" 82 | 83 | echo_ts "Updating CodePipeline job with '$build_state' and job_id '$job_id'result" >&2 84 | 85 | if [[ "$build_state" == "success" ]]; then 86 | aws codepipeline put-job-success-result \ 87 | --job-id "$job_id" \ 88 | --execution-details "summary=Build succeeded,externalExecutionId=$job_id,percentComplete=100" 89 | else 90 | aws codepipeline put-job-failure-result \ 91 | --job-id "$job_id" \ 92 | --failure-details "type=JobFailed,message=Build $build_state,externalExecutionId=$job_id" 93 | fi 94 | } 95 | 96 | 97 | decide_job_status(){ 98 | local job_json="$1" 99 | local stats="$2" 100 | local in_high="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Failure_Criteria_High_Severity")" 101 | local in_med="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Failure_Criteria_Medium_Severity")" 102 | local in_low="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Failure_Criteria_Low_Severity")" 103 | local in_oper="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Failure_Criteria_Operator")" 104 | 105 | local resp_high="$(echo "$stats" | jq -r '.high')" 106 | local resp_med="$(echo "$stats" | jq -r '.medium')" 107 | local resp_low="$(echo "$stats" | jq -r '.low')" 108 | 109 | 110 | if [[ $in_oper == null ]];then 111 | in_oper="or" 112 | fi 113 | if [[ $in_high == null ]];then 114 | in_high=0 115 | fi 116 | if [[ $in_med == null ]];then 117 | in_med=0 118 | fi 119 | if [[ $in_low == null ]];then 120 | in_low=0 121 | fi 122 | 123 | if [[ $stats != null ]] ;then 124 | if [[ "$in_oper" == "or" && ( "$resp_high" -ge "$in_high" || "$resp_med" -ge "$in_med" || "$resp_low" -ge "$in_low" ) ]] ;then 125 | echo_ts "Prisma Cloud IaC scan failed with issues as security issues count (High: $resp_high, Medium: $resp_med, Low: $resp_low) meets or exceeds failure criteria (High: $in_high, Medium: $in_med, Low: $in_low)" 126 | update_job_status "$job_json" "failure" 127 | 128 | elif [[ "$in_oper" == "and" && ( "$resp_high" -ge "$in_high" && "$resp_med" -ge "$in_med" && "$resp_low" -ge "$in_low" ) ]]; then 129 | echo_ts "Prisma Cloud IaC scan failed with issues as security issues count (High: $resp_high, Medium: $resp_med, Low: $resp_low) meets or exceeds failure criteria (High: $in_high, Medium: $in_med, Low: $in_low)" 130 | update_job_status "$job_json" "failure" 131 | 132 | else 133 | echo_ts "Prisma Cloud IaC scan succeeded with issues as security issues count (High: $resp_high, Medium: $resp_med, Low: $resp_low) does not exceed failure criteria (High: $in_high, Medium: $in_med, Low: $in_low)" 134 | update_job_status "$job_json" "success" 135 | fi 136 | 137 | else 138 | update_job_status "$job_json" "success" 139 | fi 140 | 141 | } 142 | 143 | create_build() { 144 | 145 | local job_json="$1" 146 | local job_id="$(echo "$job_json" | jq -r '.id')" 147 | local s3_bucket=$(action_configuration_value "$job_json" "S3BucketName") 148 | local bucketName="$(echo "$job_json" | jq -r ".data.inputArtifacts[0].location.s3Location | .[\"bucketName\"]")" 149 | local object_key="$(echo "$job_json" | jq -r ".data.inputArtifacts[0].location.s3Location | .[\"objectKey\"]")" 150 | local output_object="$(echo "$job_json" | jq -r ".data.outputArtifacts[0].location.s3Location | .[\"objectKey\"]")" 151 | 152 | local console_url="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Prisma_Cloud_API_URL")" 153 | local access_key="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Access_Key")" 154 | local secret_key="$(echo "$job_json" | jq -r ".data.actionConfiguration.configuration.Secret_Key")" 155 | 156 | 157 | if [ -z "$console_url" ]; then 158 | echo_ts "Please enter valid Prisma Cloud API URL in plugin in Input param. For details refer to :plugin link" 159 | update_job_status "$job_json" "Please enter valid Prisma Cloud API URL in plugin in Input param. For details refer to plugin link" 160 | exit 1; 161 | fi 162 | 163 | local login_url="${console_url}/login" 164 | 165 | local req_cmd=$(curl -k -i -o -X POST $login_url -H "Content-Type:application/json" -d "{\"username\":\"${access_key}\",\"password\":\"${secret_key}\"}" ) || update_job_status "$job_json" "$err_500" 166 | 167 | local err_400="Invalid credentials please verify that API URL, Access Key and Secret Key in Prisma Cloud plugin settings are valid For details refer to Extension link https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/prisma-cloud-devops-security/use-the-prisma-cloud-extension-for-aws-codepipeline.html" 168 | local err_500="Oops! Something went wrong, please try again or refer to documentation on https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/prisma-cloud-devops-security/use-the-prisma-cloud-extension-for-aws-codepipeline.html" 169 | 170 | http_status=$(echo "$req_cmd" | grep HTTP | awk '{print $2}') 171 | 172 | if [ -z "$http_status" ]; then 173 | echo_ts '$err_500' >&2 174 | update_job_status "$job_json" "error" 175 | exit 1; 176 | fi 177 | 178 | if [[ "$http_status" == 400 || "$http_status" == 401 ]] ; then 179 | echo_ts '$err_400' >&2 180 | update_job_status "$job_json" "error" 181 | exit 1 182 | 183 | fi 184 | 185 | if [[ $http_status -ge 500 ]] ; then 186 | echo_ts '$err_500' >&2 187 | update_job_status "$job_json" "error" 188 | exit 1 189 | fi 190 | 191 | output_response=$(echo "$req_cmd" | grep token) 192 | 193 | local token="$(echo "$output_response" | jq .token | tr -d '"')" 194 | 195 | 196 | local scan_location="$(echo $bucketName/$object_key)" 197 | 198 | aws s3 cp s3://$scan_location . || update_job_status "$job_json" "Copy Object from S3 bucket failed" 199 | 200 | 201 | local file=( *.zip ) 202 | 203 | mv $file artifact.zip 204 | 205 | iacAPI=${console_url}/iac_scan 206 | 207 | while : 208 | do 209 | 210 | local response="$(curl -k -X POST $iacAPI -H "x-redlock-auth:${token}" -F templateFile=@artifact.zip)" || update_job_status "$job_json" "Call from API failed" 211 | 212 | local result="$(echo "$response" | jq -r '.result.is_successful')" 213 | 214 | if [[ $result ]] 215 | then 216 | local matched="$(echo "$response" | jq -r '.result.rules_matched')" 217 | 218 | if [[ $matched != null ]] ;then 219 | 220 | local stats="$(echo "$response" | jq -r '.result.severity_stats')" 221 | 222 | display="$(echo "$matched" | jq -r 'sort_by(.severity) | (["SEVERITY" ,"NAME" ,"FILES"] | (., map(length*"-")) ), (.[] | [.severity , .name, .files[0] ]) | join(",")' | column -t -s ",")" || update_job_status "$job_json" "Unknown Error " 223 | 224 | else 225 | echo_ts "Good job! Prisma Cloud did not detect any issues." 226 | 227 | fi 228 | fi 229 | 230 | if [[ "$result" != "null" ]]; then 231 | 232 | if [[ $result == "true" ]] ;then 233 | decide_job_status "$job_json" "$stats" 234 | 235 | fi 236 | break 237 | else 238 | echo_ts "Build is running" 239 | sleep 3 240 | fi 241 | done 242 | 243 | echo_ts "$display" >&2 244 | 245 | aws s3 cp Prisma_Cloud_IaC_Scan.log s3://$s3_bucket/Prisma_Cloud_IaC_Scan_$job_id.log || update_job_status "$job_json" "upload results to S3 bucket failed" 246 | 247 | cd .. 248 | rm -fr $job_id 249 | 250 | } 251 | 252 | run "$1" 253 | -------------------------------------------------------------------------------- /aws-codepipeline/PrismaCloudIacScan/Lambda/PrismaCloudIaCScan.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaloAltoNetworks/Prisma-Cloud-DevOps-Security/f36756e3fc0fb2a76ffe3daf139291276e35e80c/aws-codepipeline/PrismaCloudIacScan/Lambda/PrismaCloudIaCScan.zip -------------------------------------------------------------------------------- /aws-codepipeline/README.md: -------------------------------------------------------------------------------- 1 |

Overview

2 | 3 | 4 | This extension enables Prisma Cloud Infrastructure-as-Code (IaC) scan and container image / serverless zip scan functionality from Palo Alto Networks Inc. in AWS Code Pipelines. Prisma Cloud IaC Scan identifies insecure configurations in common Infrastructure-as-Code (IaC) templates - for example, AWS Cloud Formation Templates, HashiCorp Terraform templates, Kubernetes App Deployment YAML files. More details about the functionality can be found here: https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/prisma-cloud-devops-security.html 5 | 6 | 7 |

Prisma Cloud IaC Scan

8 | 9 | User can us this feature in 2 ways : 10 | 1. Using AWS Lambda 11 | OR 12 | 2. Creating Custom action to run poll jobs (bash script) either in local enviornment or EC2 instance with AWS account. 13 | 14 | More Details on how to use it can be found in the documentation link: 15 | https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/prisma-cloud-devops-security/use-the-prisma-cloud-extension-for-aws-codepipeline.html 16 | 17 | 18 |

Prisma Cloud Compute Image Scanning

19 | /buildspec.yml includes details on how to use twistcli when using AWS CodeBuild 20 | --------------------------------------------------------------------------------