paint-brush
Azure DevOps में अधिकारों, अनुमतियों और पहुंच स्तरों का स्वचालनद्वारा@socialdiscoverygroup
12,833 रीडिंग
12,833 रीडिंग

Azure DevOps में अधिकारों, अनुमतियों और पहुंच स्तरों का स्वचालन

द्वारा Social Discovery Group6m2023/11/29
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

जब व्यवसाय तेजी से बढ़ रहा है, तो एक DevOps इंजीनियर को मैन्युअल एक्सेस प्रबंधन सहित CI/CD के लिए उपयोग की जाने वाली सभी प्रणालियों में प्रक्रियाओं को स्वचालित करने की चुनौती का सामना करना पड़ता है। ऐसे नियमित कार्य ग्राहकों के अनुरोधों के समाधान को नाटकीय रूप से धीमा कर देते हैं। लेख में, सोशल डिस्कवरी ग्रुप टीम Azure DevOps में अधिकारों, अनुमतियों और पहुंच स्तरों को स्वचालित करने के लिए अनुकूलित समाधान साझा करती है।
featured image - Azure DevOps में अधिकारों, अनुमतियों और पहुंच स्तरों का स्वचालन
Social Discovery Group HackerNoon profile picture
0-item

जब व्यवसाय तेजी से बढ़ रहा है, तो एक DevOps इंजीनियर को मैन्युअल एक्सेस प्रबंधन सहित CI/CD के लिए उपयोग की जाने वाली सभी प्रणालियों में प्रक्रियाओं को स्वचालित करने की चुनौती का सामना करना पड़ता है। ऐसे नियमित कार्य तब स्वीकार्य हो सकते हैं जब आपके पास एक छोटी टीम हो, प्रत्येक 3 चरणों के साथ 10 रिलीज़ तक, और 10 परिवर्तनीय समूह हों।


हालाँकि, कल्पना करें कि यदि आपकी टीम सैकड़ों लोगों तक बढ़ती है, जिन्हें 500 रिलीज़ तक मैन्युअल रूप से संचालित करने की आवश्यकता होती है, प्रत्येक 10 चरणों और 200 परिवर्तनीय समूहों के साथ। इस मामले में, मैन्युअल एक्सेस प्रबंधन ग्राहक अनुरोधों के समाधान को नाटकीय रूप से धीमा कर देता है।


इस स्तर पर, प्रत्येक व्यवसाय को कुशल स्वचालितीकरण की आवश्यकता का सामना करना पड़ता है।


सोशल डिस्कवरी ग्रुप में, हम प्राथमिक क्लाउड तकनीक के रूप में Azure DevOps पर भरोसा करते हैं। हालाँकि, वर्तमान में, इसमें अधिकारों, अनुमतियों और पहुंच स्तरों को स्वचालित करने की कार्यक्षमता का अभाव है। उपयोगकर्ता की ज़रूरतों को तुरंत पूरा करने के लिए, हमने कुछ कस्टम समाधान ढूंढने और अनुमतियाँ निर्दिष्ट करने को स्वचालित करने का निर्णय लिया।

Azure DevOps में स्वचालित कैसे करें

इस लेख में, हम Azure DevOps में कुछ नियमित कार्यों को स्वचालित करने के बारे में कुछ अच्छी बातें साझा करेंगे, जिन पर ध्यान केंद्रित किया जाएगा:


  • Azure पाइपलाइन का उपयोग करके मास्क के आधार पर परिवर्तनीय समूहों के लिए किसी समूह या उपयोगकर्ता को अनुमतियाँ निर्दिष्ट करना।


  • Azure पाइपलाइन का उपयोग करके कैटलॉग समूहों में वर्गीकृत संपूर्ण रिलीज़ समूहों के लिए विशिष्ट चरणों के लिए समूह या उपयोगकर्ता अनुमतियाँ निर्दिष्ट करना।

प्रयुक्त प्रौद्योगिकी स्टैक: Azure सेवाएँ, Azure DevOps, बैश, Azure CLI

वर्तमान में, Azure अनुमतियाँ निर्दिष्ट करने के लिए 3 विकल्प प्रदान करता है: साइट के ग्राफ़िकल इंटरफ़ेस का उपयोग करना, az DevOps CLI और API अनुरोधों का उपयोग करना। पहला विकल्प सबसे सीधा और तेज़ है; हालाँकि, जैसे-जैसे कंपनी बढ़ती है और सीआई/सीडी पाइपलाइनों और चरों की संख्या बढ़ती है, मैन्युअल रूप से अनुमतियाँ निर्दिष्ट करना समय लेने वाला हो जाता है।


अनुमतियाँ देने का दूसरा विकल्प कार्यक्षमता में सीमित है; दूसरे शब्दों में, उपयोगकर्ता किसी विशिष्ट टीम की पेशकश से आगे नहीं जा सकता। REST API के माध्यम से तीसरा विकल्प इस समय सबसे बहुमुखी है। आइए एक विशिष्ट उदाहरण पर विचार करें जहां हमारे पास कई चरणों वाली कई रिलीज़ पाइपलाइन हैं:


कई चरणों वाली पाइपलाइनें जारी करें


कई चरणों वाली पाइपलाइनें जारी करें


प्रत्येक परिनियोजन चरण के लिए एक विशिष्ट उपयोगकर्ता/समूह (तथाकथित पूर्व-तैनाती अनुमोदन फ़ंक्शन) से अनुमति की आवश्यकता होती है। यहां एक समस्या तब प्रकट होती है जब किसी विशिष्ट उपयोगकर्ता या समूह को अनुमोदकों की दी गई सूची से जोड़ने या हटाने की आवश्यकता होती है।


जैसे-जैसे कंपनी का विस्तार होता है, जब पाइपलाइनों और चरणों की संख्या एन गुना बढ़ जाती है, तो नियमित मामला एक समस्या बन जाता है, और इस समस्या का समाधान केवल एपीआई अनुरोधों के माध्यम से संभव है। हमारी ओर से कार्यान्वयन इस प्रकार दिखता है:


 " pool: vmImage: ubuntu-latest parameters: - name: folder_names type: string default: '\' - name: stage_names type: string default: 'Dev' - name: group_names type: string default: 'Devops' variables: - name: organization value: ORGANIZATION - name: project value: PROJECT - name: pat Value: PAT steps: - bash: | export organization="$(organization)" export project="$(project)" export pat="$(pat)" export folder_names='${{ parameters.folder_names }}' export stage_names='${{ parameters.stage_names }}' export group_names='${{ parameters.group_names }}' export pipeline_name_array=() export stage_name_array=() export group_name_array=() IFS=',' read -ra folder_name_array <<< "$folder_names" IFS=',' read -ra stage_name_array <<< "$stage_names" IFS=',' read -ra group_name_array <<< "$group_names" # Make a GET request to retrieve the release pipelines within the specified project pipeline_url="https://vsrm.dev.azure.com/$organization/$project/_apis/release/definitions?api-version=7.0" pipeline_response=$(curl -s -u ":$pat" "$pipeline_url") # Check for errors in the response if [[ "$pipeline_response" == *"error"* ]]; then echo "Error fetching release pipeline data." exit 1 fi pipeline_names=($(echo "$pipeline_response" | jq -r '.value[].name')) pipeline_ids=($(echo "$pipeline_response" | jq -r '.value[].id')) for ((i=0; i<${#pipeline_names[@]}; i++)); do pipeline_name="${pipeline_names[i]}" pipeline_id="${pipeline_ids[i]}" # Make a GET request to retrieve the release pipeline details pipeline_detail_url="https://vsrm.dev.azure.com/$organization/$project/_apis/release/definitions/$pipeline_id?api-version=7.0" pipeline_detail_response=$(curl -s -u ":$pat" "$pipeline_detail_url") # Extract the releaseDefinition.path from the pipeline details pipeline_path=$(echo "$pipeline_detail_response" | jq -r '.path') # Check if the pipeline_path matches any of the specified folder_names for folder_name in "${folder_name_array[@]}"; do if [[ "$pipeline_path" == *"$folder_name"* ]]; then # Make a GET request to retrieve all releases for the specified pipeline releases_url="https://vsrm.dev.azure.com/$organization/$project/_apis/release/releases?api-version=7.0&definitionId=$pipeline_id" releases_response=$(curl -s -u ":$pat" "$releases_url") # Extract the release names release_names=$(echo "$releases_response" | jq -r '.value[].id') release_definition_url="https://vsrm.dev.azure.com/$organization/$project/_apis/release/definitions/$pipeline_id?api-version=7.0" release_definition_response=$(curl -s -u ":$pat" "$release_definition_url") # Iterate through each group name for group_name in "${group_name_array[@]}"; do # Make a GET request to retrieve the list of groups groups_response=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/graph/groups?api-version=7.1-preview.1") # Find the origin_id for the specified group name origin_id=$(echo "$groups_response" | jq -r ".value[] | select(.displayName == \"$group_name\") | .originId") if [ -z "$origin_id" ]; then echo "Group '$group_name' not found or origin_id not available for release '$release_name'." else # Iterate through each stage name for stage_name in "${stage_name_array[@]}"; do # Construct the JSON structure for the new approval new_approval='{ "rank": 1, "isAutomated": false, "isNotificationOn": false, "approver": { "id": "'"$origin_id"'" } }' # Use jq to update the JSON structure for the specified stage updated_definition=$(echo "$release_definition_response" | jq --argjson new_approval "$new_approval" '.environments |= map(if .name == "'"$stage_name"'" then .preDeployApprovals.approvals += [$new_approval] else . end)') # Make a PUT request to update the release definition for the specified stage put_response=$(curl -s -u ":$pat" -X PUT -H "Content-Type: application/json" -d "$updated_definition" "$release_definition_url") release_definition_response=$(curl -s -u ":$pat" "$release_definition_url") # Check if the update was successful if [[ "$put_response" == *"The resource could not be found."* ]]; then echo "Error updating release definition for stage '$stage_name' and group '$group_name'." else echo "Pre-deployment approval added successfully to stage '$stage_name' for group '$group_name' in '$pipeline_id'." fi done fi done fi done done displayName: 'PreDeployApprovals' "


लाइब्रेरी अनुभाग के साथ भी ऐसा ही मुद्दा उठता है जब कई परिवर्तनीय समूह बनाए जाते हैं, जहां किसी चीज़ के साथ संबद्धता को इंगित करने के लिए एक विशिष्ट शब्द का उपयोग किया जाता है। आइए एक उदाहरण देखें जहां सेवा-संबंधित चर के साथ उनकी संबद्धता को दर्शाने के लिए "सेवाएं" शब्द वाले कई चर समूह बनाए जाते हैं।


और ऐसे परिदृश्य की भी जांच करें जहां एक विशिष्ट समूह को कुछ अनुमतियों के साथ सभी चर तक पहुंच की आवश्यकता होती है।


पुस्तकालय अनुभाग जब अनेक परिवर्तनशील समूह


इस सामान्य मामले का समाधान भी केवल REST API के माध्यम से ही संभव है:


 " variables: - name: organization value: ORGANIZATION - name: project value: PROJECT - name: pat value: PAT parameters: - name: searchWord type: string default: 'SERVICES' - name: UserOrGroupName type: string default: 'Devops' - name: UserRights type: string default: 'Administrator' steps: - bash: | export organization="$(organization)" export project="$(project)" export pat="$(pat)" export userOrGroupName='${{ parameters.UserOrGroupName }}' export UserRights='${{ parameters.UserRights }}' export searchWord='${{ parameters.searchWord }}' # Perform the API request and store the JSON response in a variable response=$(curl -s -u ":$pat" "https://dev.azure.com/$organization/$project/_apis/distributedtask/variablegroups?api-version=6.0") # Initialize an empty array to store matching JSON objects matching_json=() # Loop through the JSON objects and append matching objects to the array while read -r json; do if [[ $(echo "$json" | jq -r '.name' | grep "$searchWord") ]]; then matching_json+=("$json") fi done < <(echo "$response" | jq -c '.value[]') # Iterate through the matching variable groups and assign permissions for group in "${matching_json[@]}"; do # Extract the variable group ID and name variableGroupId=$(echo "$group" | jq -r '.id') variableGroupName=$(echo "$group" | jq -r '.name') # Determine the type of userOrGroupName (username or group name) if [[ $myString != *'@'* ]]; then # If userOrGroupName matches the username format, it's treated as a username roleName=$UserRights assignType="group" groupsResponse=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/graph/groups?api-version=6.0-preview.1") #groupOriginId=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/identities?searchFilter=$userOrGroupName&api-version=6.0" | jq -r '.value[0].originId') groupOriginId=$(echo "$groupsResponse" | jq -r ".value[] | select(.displayName == \"$userOrGroupName\") | .originId") # Get the user's originId using Azure DevOps REST API #userOriginId=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/identities?searchFilter=$userOrGroupName&api-version=6.0" | jq -r '.value[0].principalName') else # Otherwise, it's treated as a group name roleName=$UserRights assignType="user" userOriginId=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/identities?searchFilter=$userOrGroupName&api-version=6.0" | jq -r '.value[0].principalName') # Get the group's originId using Azure DevOps REST API #groupOriginId=$(curl -s -u ":$pat" "https://vssps.dev.azure.com/$organization/_apis/identities?searchFilter=$userOrGroupName&api-version=6.0" | jq -r '.value[0].originId') fi # Construct the API URL for assigning permissions apiUrl="https://dev.azure.com/$organization/_apis/securityroles/scopes/distributedtask.variablegroup/roleassignments/resources/19802563-1b7b-43d6-81e0-16cf29d68c0d$"$variableGroupId"?api-version=5.1-preview" # Assign permissions based on the userOrGroupName type if [ "$assignType" == "group" ]; then # Assign permissions to a group # Construct the request body with group's originId requestBody="[{ \"roleName\": \"$roleName\", \"userId\": \"$groupOriginId\" }]" else # Assign permissions to a user # Construct the request body with the user's uniqueName requestBody="[{ \"roleName\": \"$roleName\", \"uniqueName\": \"$userOrGroupName\" }]" fi # Execute the REST API call to assign permissions response=$(curl -s -u ":$pat" -X PUT -H "Content-Type: application/json" -d "$requestBody" "$apiUrl") # Check if the permissions were successfully assigned if [[ "$response" == *"error"* ]]; then echo "Error assigning permissions to $assignType '$userOrGroupName' in variable group '$variableGroupName'." else echo "Permissions assigned successfully to $assignType '$userOrGroupName' in variable group '$variableGroupName'." fi done displayName: 'variable-groups' "


इन प्रक्रियाओं को स्वचालित करके, हमने प्रोजेक्ट की सुरक्षा को बढ़ाते हुए, Azure DevOps में अधिकारों और अनुमति संरचनाओं की अधिक विस्तृत समझ प्राप्त की।


अब हमारे पास कार्यों की एक विस्तृत श्रृंखला के लिए स्थिर और बहुमुखी पाइपलाइन हैं, जो उपयोगकर्ता के अनुरोधों के लिए प्रसंस्करण समय को तेज करती हैं और उनकी निष्पादन गुणवत्ता में सुधार करती हैं।


इसके अतिरिक्त, हमारे समग्र सिस्टम विकास की गति और गुणवत्ता में सुधार हुआ है क्योंकि हम नियमित कार्यों से हटकर अन्य सीआई/सीडी कार्यों के लिए अधिक समय आवंटित करते हैं।


हमने दैनिक कार्यों को स्वचालित करने, विभिन्न कार्यान्वयन विकल्पों का पता लगाने और उनका विश्लेषण करने, डीबग करने और परिष्कृत करने के लिए महत्वपूर्ण प्रयास किए हैं। तैयार पाइपलाइन और स्क्रिप्ट का होना एक जबरदस्त सुविधा है, क्योंकि वे कुछ ही सेकंड में कार्य पूरा कर सकते हैं।