forked from KelvinTegelaar/AzGlue
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit df112de
Showing
2 changed files
with
81 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,69 @@ | ||
using namespace System.Net | ||
param($Request, $TriggerMetadata) | ||
#Check if AZapiKey is correct | ||
if ($request.Headers.'x-api-key' -eq $ENV:AzAPIKey) { | ||
#Comparing the client IP to the Organization list, and checking if it exists. | ||
$ClientIP = ($request.headers.'X-Forwarded-For' -split ':')[0] | ||
$CompareList = import-csv "AzGlueForwarder\OrgList.csv" -delimiter "," | ||
$AllowedOrgs = $comparelist | where-object { $_.ip -eq $ClientIP } | ||
if (!$AllowedOrgs) { | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
headers = @{'content-type' = 'application\json' } | ||
StatusCode = [httpstatuscode]::OK | ||
Body = @{"Error" = "401 - No match found in allowed list" } | convertto-json | ||
}) | ||
exit 1 | ||
} | ||
|
||
#Sending request to ITGlue | ||
#$resource = $request.params.path -replace "AzGlueForwarder/", "" | ||
$resource = $request.url -replace "https://$($ENV:WEBSITE_HOSTNAME)/API", "" | ||
#Replace x-api-key with actual key | ||
$ITGHeaders = @{ | ||
"x-api-key" = $ENV:ITGlueAPIKey | ||
} | ||
$Method = $($Request.method) | ||
$ITGBody = $($Request.body) | ||
#write-host ($AllowedOrgs | out-string) | ||
$SuccessfullQuery = $false | ||
$attempt = 3 | ||
while ($attempt -gt 0 -and -not $SuccessfullQuery) { | ||
try { | ||
$ITGlueRequest = Invoke-RestMethod -Method $Method -ContentType "application/vnd.api+json" -Uri "$($ENV:ITGlueURI)/$resource" -Body $ITGBody -Headers $ITGHeaders | ||
$SuccessfullQuery = $true | ||
} | ||
catch { | ||
$ITGlueRequest = @{'Errorcode' = $_.Exception.Response.StatusCode.value__ } | ||
$rand = get-random -Minimum 0 -Maximum 10 | ||
start-sleep $rand | ||
$attempt-- | ||
if ($attempt -eq 0) { $ITGlueRequest = @{'Errorcode' = "Error code $($_.Exception.Response.StatusCode.value__) - Made 3 attempts and upload failed. $($_.Exception.Message) " } } | ||
} | ||
} | ||
|
||
#Checking if we can strip the data that does not belong to this client. | ||
#Important so passwords/items can only be retrieved belonging to this organisation. | ||
#Can't do it for all requests, such as get-organisation, but for senstive data it works perfectly. :) | ||
|
||
if ($($ITGlueRequest.data.attributes.'organization-id')) { | ||
write-host ($AllowedOrgs.ITGlueOrgID) | ||
$ITGlueRequest.data = $ITGlueRequest.data | where-object { $_.attributes.'organization-id' -in $($AllowedOrgs.ITGlueOrgID) } | ||
} | ||
|
||
#Sending the final object back to the client. | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
headers = @{'content-type' = 'application\json' } | ||
StatusCode = [httpstatuscode]::OK | ||
Body = $ITGlueRequest | ||
}) | ||
|
||
|
||
} | ||
else { | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
headers = @{'content-type' = 'application\json' } | ||
StatusCode = [httpstatuscode]::OK | ||
Body = @{"Error" = "401 - No API Key entered or API key incorrect." } | convertto-json | ||
}) | ||
|
||
} |
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,12 @@ | ||
# Azglue - A forwarder hosted in Azure to Secure the IT-Glue API. | ||
See https://www.cyberdrain.com/documenting-with-powershell-handling-it-glue-api-security-and-rate-limiting/ for more information. | ||
|
||
After my previous blogs the comment I’ve received most was worries about the API key. If they key gets stolen you’re giving away the keys to the castle. The API has no limitations and with a leaked key all your documentation could be download. I’ve been discussing this issue with IT-Glue for some time but haven’t gotten a real solution yet. This has forced me to look for a solution myself. I gave myself some requirements for the solution. | ||
|
||
- The solution needed to be simple and accessible for everyone. | ||
- The solution needed to have multiple levels of authentication; an API key, IP whitelisting, and organization whitelisting. | ||
- The solution needed to block requests for all passwords/files/etc for all organisations. | ||
- The solution needed to allow some form of handling of the API rate limiting, e.g. repeating a request if it was rate limited. | ||
- The solution needed to be able to used, without adapting any scripts (except URLs and API codes.) | ||
- So after some research I decided to use an Azure Function for this. I’ve blogged about Azure Functions before, but the main reason is that running this function in the consumption model will cost us nothing (or next to nothing if you are an extremely heavy user.) | ||
|