You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2021/09/20 16:34:51 UTC

[GitHub] [cloudstack] aleskxyz commented on a change in pull request #4890: Universal sshkey and password manager script

aleskxyz commented on a change in pull request #4890:
URL: https://github.com/apache/cloudstack/pull/4890#discussion_r712333915



##########
File path: setup/bindir/cloud-set-guest-sshkey-password-userdata-configdrive.in
##########
@@ -0,0 +1,507 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+username=root
+userDataServerPort=8080
+configDriveLabel=config-2
+
+function findPrimaryNetwork(){
+    outputLog "Detecting primary network"
+    if command -v ip &> /dev/null
+    then
+        primaryNet=$(ip -o -4 route show to default | awk '{print $5}')
+    elif command -v netstat &> /dev/null
+    then
+        primaryNet=$(netstat -r4 | grep default | awk '{print $(NF)}')
+    elif command -v route &> /dev/null
+    then
+        primaryNet=$(route -4 2> /dev/null | grep default | awk '{print $(NF)}')
+        if [ -z "$primaryNet" ]
+        then
+            primaryNet=$(route get default 2> /dev/null | grep interface | tr -d ' ' | awk '{split($0,a,":"); print a[2]}')
+        fi
+    fi
+    if [ -z "$primaryNet" ]
+    then
+        outputLog "Could not find primary network"
+        return 1
+    fi
+    echo "$primaryNet"
+    return 0
+}
+
+function findUserDataServer(){
+    primaryNet=$1
+    outputLog "Trying to find userdata server"
+    if [ -z "$primaryNet" ]
+    then
+        outputLog "Unable to determine the userdata server, falling back to data-server"
+        echo "data-server"
+        return 0
+    fi
+
+    if command -v netplan &> /dev/null
+    then
+        outputLog "Operating System is using netplan"
+
+        userDataServer=$(netplan ip leases "$primaryNet" | grep SERVER_ADDRESS | awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in netplan config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v nmcli &> /dev/null
+    then
+        outputLog "Operating System is using NetworkManager"
+
+        userDataServer=$(nmcli -t connection show "$(nmcli -t -f UUID,DEVICE connection | grep "$primaryNet" | awk '{split($0,a,":"); print a[1]}')" | grep next_server | tr -d ' ' |awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in NetworkManager config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v wicked &> /dev/null
+    then
+        outputLog "Operating System is using wicked"
+
+        userDataServer=$(grep SERVERID /run/wicked/leaseinfo."$primaryNet"* | tr -d "'" | awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in wicked config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v udhcpc &> /dev/null
+    then
+        outputLog "Operating System is using udhcpc"
+
+        userDataServer=$(< /run/dhcp-server-ip."$primaryNet")
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in udhcpc"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    outputLog "Searching for DHCP server in lease files"
+
+    primaryLease=$(
+        dhcpFolders="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* /var/lib/NetworkManager/* /var/db/dhclient*"
+        for files in $dhcpFolders
+        do
+            if [ -e "$files" ]
+            then
+                < "$files" tr -d '\n' | sed 's/  //g ; s/lease {//g ; s/}/\n/g' | grep 'option routers'
+            fi
+        done
+    )
+
+    serverList=$(
+        IFS=$'\n'
+        for line in $(echo -e "$primaryLease")
+        do
+            splitLine=$(echo "$line" | sed -e 's/;/\n/g')
+            if date -j &> /dev/null
+            then
+                timestamp=$(date -j -f "%Y/%m/%d %H:%M:%S" "$(echo "$splitLine" | grep 'expire' | sed -r 's/.*expire [0-9]+ (.*)/\1/')" +"%s")
+            else
+                timestamp=$(date -d "$(echo "$splitLine" | grep 'expire' | sed -e 's/.*expire [0-9]\+ \(.*\)/\1/')" +"%s")
+            fi
+            interface=$(echo "$splitLine" | grep 'interface' | sed -e 's/.*interface "\(.*\)"/\1/')
+            server=$(echo "$splitLine" | grep 'dhcp-server-identifier' | sed -e 's/.*dhcp-server-identifier \(.*\)/\1/')
+            echo "$timestamp","$interface","$server"
+        done
+    )
+
+    userDataServer=$(echo "$serverList" | grep "$primaryNet" | sort -n | tail -1 | awk '{split($0,a,","); print a[3]}')
+
+    if [ -n "$userDataServer" ]
+    then
+        outputLog "Userdata server found: $userDataServer"
+        echo "$userDataServer"
+        return 0
+    fi
+
+    outputLog "Unable to determine the userdata server, falling back to data-server"
+    echo "data-server"
+    return 0
+}
+
+function getPasswordFromUserDataServer(){
+    userDataServer=$1
+    userDataServerPort=$2
+    outputLog "Sending request to userdata server at $userDataServer to get the password"
+    if ! response=$(curl --silent --connect-timeout 20 --retry 3 --header "DomU_Request: send_my_password" http://"$userDataServer":"$userDataServerPort")
+    then
+        outputLog "Failed to send request to userdata server at $userDataServer"
+        return 4
+    fi
+    outputLog "Got response from userdata server at $userDataServer"
+    response=$(echo "$response" | tr -d '\r')
+    case $response in
+        "")
+            outputLog "Userdata server at $userDataServer did not have any password for the VM"
+            return 2
+        ;;
+        "bad_request")
+            outputLog "VM sent an invalid request to userdata server at $userDataServer"
+            return 3
+        ;;
+        "saved_password")
+            outputLog "VM has already saved a password from the userdata server at $userDataServer"
+            return 1
+        ;;
+        *)
+            outputLog "VM got a valid password from server at $userDataServer"
+            echo "$response"
+            return 0
+    esac
+}
+
+function findHomeDirectory(){
+    username=$1
+    getent passwd "$username"|awk -F ":" '{print $6}'
+}
+
+function setPassword(){
+    username=$1
+    homeDir=$2
+    password=$3
+    if command -v md5sum &> /dev/null
+    then
+        newMd5=$(echo "$password" | md5sum | awk '{print $1}')
+    elif command -v md5 &> /dev/null
+    then
+        newMd5=$(echo "$password" | md5)
+    else
+        newMd5='N/A'
+    fi
+    if [ $newMd5 != 'N/A' ]
+    then
+        if [ -f "$homeDir"/.password.md5 ]
+        then
+            oldMd5=$(cat "$homeDir"/.password.md5)
+        fi
+        if [ "$newMd5" ==  "$oldMd5" ]
+        then
+            outputLog  "There is no update of VM password"
+            return 0
+        fi
+    else
+        outputLog "Cannot determine change of password"
+    fi
+    outputLog "Changing password for user $username"
+    if command -v chpasswd &> /dev/null
+    then
+        echo "$username":"$password" | chpasswd
+    elif command -v usermod &> /dev/null && command -v mkpasswd &> /dev/null
+    then
+        usermod -p "$(mkpasswd -m SHA-512 "$password")" "$username"
+    elif command -v pw &> /dev/null
+    then
+        echo "$password" | pw mod user "$username" -h 0
+    else
+        outputLog "Failed to change password for user $username"
+        return 1
+    fi
+    outputLog "Successfully changed password for user $username"
+    if [ $newMd5 != 'N/A' ]
+    then
+        echo "$newMd5" > "$homeDir"/.password.md5
+        chmod 600 "$homeDir"/.password.md5
+        chown "$username": "$homeDir"/.password.md5
+    fi
+    return 0
+}
+
+function sendAckToUserDataServer(){
+    userDataServer=$1
+    userDataServerPort=$2
+    outputLog "Sending acknowledgment to userdata server at $userDataServer"
+    if ! curl --silent --connect-timeout 20 --retry 3 --header "DomU_Request: saved_password" "$userDataServer":"$userDataServerPort" &> /dev/null
+    then
+        outputLog "Failed to sent acknowledgment to userdata server at $userDataServer"
+        return 1
+    fi
+    outputLog "Successfully sent acknowledgment to userdata server at $userDataServer"
+    return 0
+}
+
+function getPublicKeyFromUserDataServer(){
+    userDataServer=$1
+    outputLog "Sending request to userdata server at $userDataServer to get public key"
+    if ! reponse=$(curl --silent --connect-timeout 20 --retry 3 http://"$userDataServer"/latest/public-keys)

Review comment:
       Thank you for comment. It seems curl always return 0 in case of server error. I add --fail option to handle server errors.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org