Created
April 15, 2023 06:58
-
-
Save GTRekter/890746911dfd87d0719abce9f6175761 to your computer and use it in GitHub Desktop.
This is a bash script that configures several organization policies for a specified Azure DevOps organization. The script makes use of the Azure DevOps REST API to perform PATCH requests on the different policies. The policies that are being configured include disallowing third-party application access via OAuth, disallowing SSH authentication, …
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
PAT="" | |
ORG_NAME="" | |
DEFAULT_JSON={ | |
"organization": { | |
"policies": { | |
"disallow_third_party_application_access_via_oauth": false, | |
"disallow_ssh_authentication": false, | |
"log_audit_events": true, | |
"allow_public_projects": true, | |
"additional_protections_public_package_registries": true, | |
"enable_azure_active_directory_conditional_access_policy_validation": true, | |
"disallow_external_guest_access": false, | |
"allow_team_and_project_administrators_to_invite_new_users": true, | |
"request_access": { | |
"enable": false, | |
"url": "https://dev.azure.com/GTRekter" | |
} | |
} | |
} | |
} | |
echo "Configure $ORG_NAME organization policies" | |
THIRD_PARTY_ACCESS_VIA_OAUTH=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.disallow_third_party_application_access_via_oauth') | |
echo "Setting Third-party application access via OAuth to $THIRD_PARTY_ACCESS_VIA_OAUTH" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$THIRD_PARTY_ACCESS_VIA_OAUTH'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.DisallowOAuthAuthentication?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Third-party application access via OAuth policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Third-party application access via OAuth policy was successful" | |
fi | |
SSH_AUTHENTICATION=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.disallow_ssh_authentication') | |
echo "Setting SSH authentication to $SSH_AUTHENTICATION" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$SSH_AUTHENTICATION'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.DisallowSecureShell?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the SSH authentication policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the SSH authentication policy was successful" | |
fi | |
LOG_AUDIT_EVENTS=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.log_audit_events') | |
echo "Setting Log audit events to $LOG_AUDIT_EVENTS" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$LOG_AUDIT_EVENTS'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.LogAuditEvents?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Log audit events policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Log audit events policy was successful" | |
fi | |
ALLOW_PUBLIC_PROJECTS=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.allow_public_projects') | |
echo "Setting Allow public projects to $ALLOW_PUBLIC_PROJECTS" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ALLOW_PUBLIC_PROJECTS'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.AllowAnonymousAccess?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Allow public projects policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Allow public projects policy was successful" | |
fi | |
ARTIFACTS_EXTERNAL_PACKAGE_PROTECTION_TOKEN=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.additional_protections_public_package_registries') | |
echo "Setting Additional protections for public package registries to $ARTIFACTS_EXTERNAL_PACKAGE_PROTECTION_TOKEN" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ARTIFACTS_EXTERNAL_PACKAGE_PROTECTION_TOKEN'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.ArtifactsExternalPackageProtectionToken?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Additional protections for public package registries policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Additional protections for public package registries policy was successful" | |
fi | |
ENFORCE_AZURE_ACTIVE_DIRECTORY_CONDITIONAL_ACCESS=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.enable_azure_active_directory_conditional_access_policy_validation') | |
echo "Setting Additional protections for public package registries to $ENFORCE_AZURE_ACTIVE_DIRECTORY_CONDITIONAL_ACCESS" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ENFORCE_AZURE_ACTIVE_DIRECTORY_CONDITIONAL_ACCESS'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.EnforceAADConditionalAccess?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Additional protections for public package registries policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Additional protections for public package registries policy was successful" | |
fi | |
ALLOW_TEAM_ADMINS_INVITATIONS_ACCESS_TOKEN=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.allow_team_and_project_administrators_to_invite_new_users') | |
echo "Setting Additional protections for public package registries to $ALLOW_TEAM_ADMINS_INVITATIONS_ACCESS_TOKEN" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ALLOW_TEAM_ADMINS_INVITATIONS_ACCESS_TOKEN'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.AllowTeamAdminsInvitationsAccessToken?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Additional protections for public package registries policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Additional protections for public package registries policy was successful" | |
fi | |
ALLOW_GUEST_USERS=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.disallow_external_guest_access') | |
echo "Setting Allow guest users to $ALLOW_GUEST_USERS" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ALLOW_GUEST_USERS'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Allow guest users policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Allow guest users policy was successful" | |
fi | |
REQUEST_ACCESS=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.request_access.enable') | |
REQUEST_ACCESS_URL=$(echo "$DEFAULT_JSON" | jq -r '.organization.policies.request_access.url') | |
if [ ! $REQUEST_ACCESS ]; then | |
echo "Read organization ID. This property is needed to get a list of service endpoints" | |
RESPONSE=$(curl --silent \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json" \ | |
--data-raw '{"contributionIds": ["ms.vss-features.my-organizations-data-provider"],"dataProviderContext":{"properties":{}}}' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/Contribution/HierarchyQuery?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
RESPONSE_BODY=$(sed '$ d' <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 200 ]; then | |
echo "Failed to get the list of existing service endpoints. $RESPONSE" | |
exit 1; | |
else | |
echo "The list of existing service endpoints was succesfully retrieved" | |
fi | |
ORG_ID=$(echo "$RESPONSE_BODY" | jq '.dataProviders."ms.vss-features.my-organizations-data-provider".organizations[] | select(.name == "'"$ORG_NAME"'") | .id' | tr -d '"') | |
echo "Setting $ORG_NAME organization url to $REQUEST_ACCESS_URL" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$ALLOW_GUEST_USERS'"}]' \ | |
"https://vssps.dev.azure.com/$ORG_NAME/_apis/Organization/Collections/$ORG_ID/Properties?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 200 ]; then | |
echo "Error during the configuration of the organization url. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the organization url was successful" | |
fi | |
fi | |
echo "Setting Request access to $REQUEST_ACCESS" | |
RESPONSE=$(curl --silent \ | |
--request PATCH \ | |
--write-echo "\n%{http_code}" \ | |
--header "Authorization: Basic $(echo -n :$PAT | base64)" \ | |
--header "Content-Type: application/json-patch+json" \ | |
--data-raw '[{"from":"","op":2,"path":"/Value","value":"'$REQUEST_ACCESS'"}]' \ | |
"https://dev.azure.com/$ORG_NAME/_apis/OrganizationPolicy/Policies/Policy.AllowRequestAccessToken?api-version=5.0-preview.1") | |
HTTP_STATUS=$(tail -n1 <<< "$RESPONSE") | |
if [ $HTTP_STATUS != 204 ]; then | |
echo "Error during the configuration of the Request access policy. $RESPONSE_BODY" | |
exit 1; | |
else | |
echo "Configuration of the Request access policy was successful" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment