diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d14948 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +System.Net.Http.Formatting.dll +AADClient.exe +ARMClient.exe +ARMClient.Authentication.dll +ArmClient.zip +Microsoft.IdentityModel.Clients.ActiveDirectory.dll +Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll +Newtonsoft.Json.dll +System.IdentityModel.Tokens.Jwt.dll diff --git a/GraphToPolicy.ps1 b/GraphToPolicy.ps1 new file mode 100644 index 0000000..e2e38ae --- /dev/null +++ b/GraphToPolicy.ps1 @@ -0,0 +1,90 @@ +<# +.SYNOPSIS +Converts an Azure Resource Graph query into a policy rule. + +.PARAMETER Query +Azure Resource Graph Query which needs to be converted to the policy rule + +.PARAMETER Effect +Optional parameter for setting the policy effect. Default value is "audit" + +.PARAMETER CreatePolicy +Optional parameter to create the policy and use the value as the policy name. + +.EXAMPLE +./GraphToPolicy -Query "where type =~ 'microsoft.compute/virtualmachines' and isempty(aliases['Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk.id'])|summarize count()" -Effect "audit" -CreatePolicy "AuditNonManagedDiskPolicy" +#> + +Param( + [Parameter(Mandatory=$True)] + [string]$Query, + [Parameter(Mandatory=$False)] + [string]$Effect = "audit", + [Parameter(Mandatory=$False)] + [string]$CreatePolicy = "" +) + +function CreateNewPolicy +{ + echo "Creating policy '$CreatePolicy' ..." + $resp = $resp -join "" + $policyRule = $resp[17..($resp.Length-2)] + $policyRule = $policyRule -join "" + $policyRule = $policyRule -replace " ","" -replace """","'" + #echo $policyRule + az policy definition create --rules ""$policyRule"" --name ""$CreatePolicy"" --display-name ""$CreatePolicy"" +} + +function CallAzureResourceGraph +{ + & $ArmClientPath token *>$null + if (-not ($?)) + { + & $ArmClientPath login *>$null + } + $response = & $ArmClientPath post "/providers/Microsoft.ResourceGraph/resources/policy?api-version=2018-09-01-preview&effect=$Effect" $Query + if($response[0] -eq "{") { + return $response + } + return $response[1..$response.Length] +} + +function DownloadArmClient +{ + if([environment]::OSVersion.Platform -eq "Win32NT"){ + $global:ArmClientPath = ".\armclient.exe" + $check = Test-Path($global:ArmClientPath) + if( $check-eq $false){ + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest "http://github.com/projectkudu/ARMClient/releases/download/v1.3/ARMClient.zip" -OutFile ArmClient.zip + Expand-Archive .\ArmClient.zip -DestinationPath . + } + } + else{ + $global:ArmClientPath = "./armclient" + $path = "./DownloadArmClient.sh" + $check = Test-Path($global:ArmClientPath) + if( $check-eq $false){ + # file with path $path doesn't exist + # let's download and run it + echo 'curl -sL https://github.com/yangl900/armclient-go/releases/download/v0.2.3/armclient-go_linux_64-bit.tar.gz | tar -xz' > $path + bash $path + } + } + # Find a way to avoid this warning + if(-not (Test-Path $ArmClientPath)){ + Write-Error "Unable to find ArmClient, the script would not work" + throw [System.IO.FileNotFoundException] "armclient does not exists." + } +} + +DownloadArmClient +#echo $ArmClientPath +$resp = CallAzureResourceGraph + +if($CreatePolicy -ne ""){ + CreateNewPolicy +} else { + echo $resp +} + \ No newline at end of file diff --git a/GraphToPolicy.sh b/GraphToPolicy.sh deleted file mode 100644 index 91cb024..0000000 --- a/GraphToPolicy.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -POSITIONAL=() -while [[ $# -gt 0 ]] -do -key="$1" - -case $key in - -q|--q|--query) - QUERY="$2" - shift # past argument - shift # past value - ;; - -e|--e|--effect) - EFFECT="$2" - shift # past argument - shift # past value - ;; - -c|--c|--create) - POLICY="$2" - shift # past argument - shift # past value - ;; - *) # unknown option - POSITIONAL+=("$1") # save it in an array for later - shift # past argument - ;; -esac -done -set -- "${POSITIONAL[@]}" # restore positional parameters - -if [ -z $POLICY ] -then -eval ./armclient post '"/providers/Microsoft.ResourceGraph.PPE/resources/policy?api-version=2017-10-05-preview&effect='${EFFECT:-audit}'"' '"'${QUERY}'"'| sed '1 d' -else -p=$(eval ./armclient post '"/providers/Microsoft.ResourceGraph.PPE/resources/policy?api-version=2017-10-05-preview&effect='${EFFECT:-audit}'"' '"'${QUERY}'"'| sed '1 d') -az policy definition create --rules "${p: 18:-1}" -n $POLICY -fi diff --git a/README.md b/README.md index a2213dc..a9001e5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,24 @@ -"# ConvertToPolicy" -Download setupCloudShellEnvironment.sh into cloud shell environment or your shell environement -run "source ./setupCloudShellEnvironment.sh" -This will set up an alias and get armclient for you. +# ConvertToPolicy +This tool converts a Azure Resource Graph query into a policy rule. -You can also get armclient on your own here "https://github.com/yangl900/armclient-go/releases/download/v0.2.3/armclient-go_linux_64-bit.tar.gz" +You can do the following : -Run commands using graph2policy or ./GraphToPolicy script. +- Pass what action to take in the policy +- Create a policy by passing a policy name to the script. -Run the query you want to convert. -Example: -graph2policy -q "where type contains 'compute'" -e "deny" +To run this tool, you'll need to setup the environment +1. Download setupCloudShellEnvironment.sh into cloud shell environment or your shell environement. +2. run "source ./setupCloudShellEnvironment.sh" +3. This will set up an alias and also install armclient in your shell. + +## Usage +You can run commands using *graph2policy* or *./GraphToPolicy* script. + +## Examples +1. Generate the policy rule from Graph query with a "deny" action. + +*graph2policy -q "where type contains 'compute'" -e "deny"* + +2. Create a policy for a given graph query + +*graph2policy -q "where type =~ 'microsoft.compute/virtualmachines' and isempty(aliases['Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk.id'])|summarize count()" --effect "audit" --creat "AuditNonManagedDiskPolicy"* diff --git a/setupCloudShellEnvironment.sh b/setupCloudShellEnvironment.sh index 316f0fe..3f8a6f9 100644 --- a/setupCloudShellEnvironment.sh +++ b/setupCloudShellEnvironment.sh @@ -38,7 +38,7 @@ then eval ./armclient post '"'"'"/providers/Microsoft.ResourceGraph.PPE/resources/policy?api-version=2017-10-05-preview&effect='"'\${EFFECT:-audit}'"'"'"'" "'"'"'"'\${QUERY}'"'"'"'| sed '1 d'"' else p=$(eval ./armclient post '"'"'"/providers/Microsoft.ResourceGraph.PPE/resources/policy?api-version=2017-10-05-preview&effect='"'\${EFFECT:-audit}'"'"'"'" "'"'"'"'\${QUERY}'"'"'"'| sed '1 d'"') -az policy definition create --rules "${p: 18:-1}" -n $POLICY +az policy definition create --rules "${p: 18:-1}" -n $POLICY --display-name $POLICY fi ' > GraphToPolicy