#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=dbsettings.ico #AutoIt3Wrapper_Res_Comment=Learning Tree RDS Sign In #AutoIt3Wrapper_Res_Description=Sign in to Amazon RDS #AutoIt3Wrapper_Res_Fileversion=1.0.0.0 #AutoIt3Wrapper_Res_LegalCopyright=Learning Tree International #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include #include #include #include #include #include ;NOTES ;Aquire Oracle RDS DB name and machine number from metadata ;Edit into connection files ;Developed on a 493 load that only has a single connection so check this when adding to new load ;Developed by Robin Johnston 2026 ;V1.0 - Conversion to Cloudshare from previous Java version Global $version = StringLeft(FileGetVersion(@ScriptFullPath),3) FileChangeDir(@ScriptDir) ;Make sure we have correct file path Global $sTnsnamesFile = "C:\software\oracle\network\tnsnames.ora" Global $sConnectionsFile = "C:\Users\Administrator\AppData\Roaming\SQL Developer\system3.2.20.09.87\o.jdeveloper.db.connection.11.1.1.4.37.59.48\connections.xml" Global $sBackupDir = "C:\software\rdssync\rdsbak" Global $force = False Global $LogFile = "RDSSignIn.log" If StringInStr($cmdlineraw, "/f") Or StringInStr($cmdlineraw, ".au3") Then ;allow a forced update FileDelete(@ScriptDir & '\' & $LogFile) RegDelete("HKCU\Software\RDSSignIn","ClassId") $force = True WriteLog("Forced restart, log cleared, registry emptied") EndIf If (@YEAR & @MON & @MDAY) - StringTrimRight(FileGetTime($LogFile,0,1),6) > 0 Then FileDelete($LogFile) EndIf Global $hLogFile = FileOpen(@ScriptDir & '\' & $LogFile, 1) WriteLog("", 1) Global $classId, $seqnum, $hostname, $vmNum Global $Instructor = False ;Only run once If Not _Singleton(@ScriptName) Then If $cmdline[0] > 0 Then If $cmdline[1] = "stop" or StringRight($cmdline[1],1) = "s" Then ;DO nothing.... Else WriteLog("Already running.") Exit EndIf EndIf EndIf $backoff=1000+Random(1,1000,1) Do local $metadata=InetRead("https://metadata.cloudshare.com/api/v3/unauthenticated/metadata") ;If @error set here, then metadata is bad - backoff, retry a few times, then reboot to see if that fixes it If @error Then Sleep($backoff) $backoff = $backoff * 2 EndIf If $backoff > 16000 Then ;Have we been here before? If RegRead("HKCU\Software\RDSSignIn","Backoff") == "ONCE" Then ;Already done this once - so throw up error and quit RegDelete("HKCU\Software\RDSSignIn","Backoff") WriteLog("Quitting because no VM metadata discovered") MsgBox(0,"RDSSignIn Error V" & $version,"Unable to pull the Cloudshare metadata" & @CR & @CR & "Check the Network Config and if this error persists, fully powercycle the whole environment") Exit Else RegWrite("HKCU\Software\RDSSignIn","Backoff", "REG_SZ", "ONCE") WriteLog("Rebooting to see if we can pickup metadata on second boot") Shutdown(6) ;Reboot if taking too long EndIf EndIf Until Not @error ;get some metadata $metadata = BinaryToString($metadata) WriteLog("Cloudshare Metadata: " & $metadata) Local $jsonObj = Json_Decode($metadata) WriteLog("Cloudshare Metadata: " & @CRLF & Json_Encode($jsonObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) ConsoleWrite("Full Metadata: " & @CRLF & Json_Encode($jsonObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) If Json_ObjExists($jsonObj, "custom-properties") Then Local $custObj = Json_ObjGet($jsonObj, "custom-properties") ConsoleWrite("Custom Properties: " & @CRLF & Json_Encode($custObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) Else ;Bail because no custom properties ProgressOff() WriteLog("No Custom Properties found in the metadata, Exiting") MsgBox(0,"RDSSignIn Info V" & $version,"This course requires the RDS custom property to be defined" & @CR & @CR & "You will need to redeploy the course and set it up as you do so, or sign in to AWS manually!") Exit EndIf Local $classId = Json_ObjGet($jsonObj,"class-id") WriteLog("Cloudshare ClassId is " & $classId) ConsoleWrite("Cloudshare ClassId is " & $classId & @CRLF) If $classId="" Then ProgressOff() WriteLog("No ClassId discovered, Exiting") MsgBox(0,"RDSSignIn Info V" & $version,"This course requires a valid ClassId" & @CR & @CR & "You will need to redeploy correctly before you can proceed with the course exercises") Exit EndIf If $classId=RegRead("HKCU\Software\RDSSignIn","ClassId") Then ;This system has already been processed so just quit WriteLog("ClassId " & $classId & " has already been processed, Exiting...") Exit EndIf ;Need to decide if Instructor (2 options) or Student VM If StringInStr(Json_ObjGet($jsonObj, "env-name"),"instructor") Then $instructor = True WriteLog("Found Instructor VM") ConsoleWrite("Found Instructor VM" & @CRLF) ;look for instructor params in metadata, if missing get them from API If Json_ObjGet($custObj, "studNum")=Null Then ;Have the class_id, use real api to pull the trainingName from v3 api $trainingName = _CS_V3_Get("/class/" & $classId) $userdata = _CS_V4_Get("/trainings?name=contains(" & $trainingName & ")") ;V3 & V4 Get just returns required fields here, namely training name and training description WriteLog("Cloudshare Training name from V3 API is " & $trainingName) ConsoleWrite("Cloudshare Training name from V3 API is " & $trainingName & @CRLF) WriteLog("Cloudshare userdata from V4 API is " & $userdata) ConsoleWrite("Cloudshare userdata from V4 API is " & $userdata & @CRLF) $RDS = GetCSParam($userdata,"AWS_RDS_NAME=") $PORT = 1500 If StringInStr($RDS, ":") Then ;Has a port number $PORT = StringSplit($RDS,":")[2] $RDS = StringSplit($RDS,":")[1] EndIf $STUDENT = "ora1_student1" ; Legacy setting because cannot change account layout on RDS at the moment, so instructor first ConsoleWrite("AWS RDS name from V4 API on Instructor VM is " & $RDS & @CRLF) WriteLog("AWS RDS name from V4 API on Instructor VM is " & $RDS ) ConsoleWrite("AWS RDS port from V4 API on Instructor VM is " & $PORT & @CRLF) WriteLog("AWS RDS port from V4 API on Instructor VM is " & $PORT) ConsoleWrite("AWS STUDENT/INSTRUCTOR user on Instructor VM is " & $STUDENT & @CRLF) WriteLog("AWS STUDENT/INSTRUCTOR user on Instructor VM is " & $STUDENT) Else ;look for instructor params in metadata since it is available $RDS = Json_ObjGet($custObj, "awsRdsName") If Not IsKeyword($RDS) Then $PORT = 1500 If StringInStr($RDS, ":") Then ;Has a port number $PORT = StringSplit($RDS,":")[2] $RDS = StringSplit($RDS,":")[1] EndIf $STUDENT = "ora1_student1" ConsoleWrite("AWS RDS name from metadata on Instructor VM is " & $RDS & @CRLF) WriteLog("AWS RDS name from metadata on Instructor VM is " & $RDS ) ConsoleWrite("AWS RDS port from metadata on Instructor VM is " & $PORT & @CRLF) WriteLog("AWS RDS port from metadata on Instructor VM is " & $PORT) ConsoleWrite("AWS INSTRUCTOR user on Instructor VM is " & $STUDENT & @CRLF) WriteLog("AWS INSTRUCTOR user on Instructor VM is " & $STUDENT) Else ConsoleWrite("Unable to extract RDS metadata from the Cloudshare metadata" & @CRLF) WriteLog("Unable to extract RDS metadata from the Cloudshare metadata") MsgBox(0,"RDSSignIn Info V" & $version, "Unable to extract RDS metadata from the Cloudshare metadata" & @CR & @CR & "You will need to redeploy the course using latest deployment tool, or sign in to AWS manually!") Exit EndIf EndIf Else ;look for student params in metadata since it is available $RDS = Json_ObjGet($custObj, "awsRdsName") If Not IsKeyword($RDS) Then $PORT = 1500 If StringInStr($RDS, ":") Then ;Has a port number $PORT = StringSplit($RDS,":")[2] $RDS = StringSplit($RDS,":")[1] EndIf $STUDENT = Json_ObjGet($custObj, "studNum") $STUDENT += 1 $STUDENT = "ora1_student" & $STUDENT ConsoleWrite("AWS RDS name from metadata is " & $RDS & @CRLF) WriteLog("AWS RDS name from metadata is " & $RDS) ConsoleWrite("AWS RDS port from metadata is " & $PORT & @CRLF) WriteLog("AWS RDS port from metadata is " & $PORT) ConsoleWrite("AWS STUDENT user is " & $STUDENT & @CRLF) WriteLog("AWS STUDENT user is " & $STUDENT) Else ConsoleWrite("Unable to extract RDS metadata from the Cloudshare metadata" & @CRLF) WriteLog("Unable to extract RDS metadata from the Cloudshare metadata") MsgBox(0,"RDSSignIn Info V" & $version, "Unable to extract RDS metadata from the Cloudshare metadata" & @CR & @CR & "You will need to redeploy the course using latest deployment tool, or sign in to AWS manually!") Exit EndIf EndIf ProgressOn("RDSSignIn Info V" & $version,"RDSSignIn progress","Aquired Cloudshare metadata",Default,@DesktopHeight/4) Sleep(4000) ProgressSet(25,"Extracted the RDS name and port info") Sleep(2000) ;OK, got all info, lets do the config WriteRdsConfigFile($sTnsnamesFile, $RDS, $PORT) ConsoleWrite("Updated " & $sTnsnamesFile & @CRLF) WriteLog("Updated " & $sTnsnamesFile) WriteOraReferenceXml($sConnectionsFile, $STUDENT) ConsoleWrite("Updated " & $sConnectionsFile & @CRLF) WriteLog("Updated " & $sConnectionsFile) ProgressSet(100,"RDS Sign In should now be complete. Exiting...") Sleep(5000) ;Job done so update registry to prevent rerun RegWrite("HKCU\Software\RDSSignIn","classId", "REG_SZ", $classId) ConsoleWrite("Registry updated to prevent rerun, Exiting..." & @CRLF) WriteLog("Registry updated to prevent rerun, Exiting...") Exit ; ====================================================================================== ; FUNCTIONS USED ; ====================================================================================== Func GetCSParam($sData,$sKey) ;ConsoleWrite("Looking for " & $sKey & " in " & $sData & @CRLF) If StringInStr($sData,$sKey) Then ; Trim leading/trailing whitespace around the whole string $sData = StringStripWS($sData, 3) ; Regex tolerant of spaces around colon/value/comma ;Local $sPattern = $sKey & "\s*([^,\s]+)" Local $sPattern = $sKey & "\s*([^,]+)" ; Run regex search Local $aMatch = StringRegExp($sData, $sPattern, 1) ; If found, return the captured value, else return empty If @error Or UBound($aMatch) = 0 Then Return SetError(1,0,"") ; nothing found Else ;MsgBox(0,"Initial Result for " & $sKey,'"'&$aMatch[0]&'"') $data=StringStripWS($aMatch[0],1) If Not @Compiled Then ProgressOff() ;MsgBox(0,"Initial Result for " & $param,'"'&$data&'"') If StringInStr($data,',') Then $data=StringLeft($data,StringInStr($data,',')-1) ;MsgBox(0,"Cut Result for " & $param,$data) If StringInStr($data,@LF) Then ;trim to right from space ;MsgBox(0,"",StringInStr($data,@LF)) $data=StringLeft($data,StringInStr($data,@LF)-1) EndIf ;MsgBox(0,"Final Result for " & $param,$data) Return($data) EndIf Else Return SetError(1,0,"") EndIf EndFunc ;==>GetCSParam ; Writes a fresh RDS-style entry file, optionally backing up existing file first. ; Returns True on success, False on failure. ; ; @error codes: ; 1 = Backup failed ; 2 = Could not open target file for writing ; 3 = Write failed ; Func WriteRdsConfigFile($sFilePath, $sHost, $iPort, $sAlias = "RDS", $sSid = "ORAC", $bBackup = True) ; Backup existing file (only if it exists and backup requested) If $bBackup And FileExists($sFilePath) Then Local $sStamp = @YEAR & "." & @MON & "." & @MDAY & "." & @HOUR & "." & @MIN & "." & @SEC ; Extract just the filename from the full path (tnsnames.ora) Local $sFileName = StringTrimLeft($sFilePath, StringInStr($sFilePath, "\", 0, -1)) ; Compose backup destination: \tnsnames.ora.2023.11.07.18.39.20.bak Local $sBak = $sBackupDir & "\" & $sFileName & "." & $sStamp & ".bak" If Not FileCopy($sFilePath, $sBak, $FC_OVERWRITE) Then Return SetError(1, 0, False) Else ConsoleWrite("File " & $sFileName & " was backed up to " & $sBak & @CRLF) WriteLog("File" & $sFileName & " was backed up to " & $sBak) EndIf EndIf ; Build the file content using a format template ; StringFormat is similar to sprintf and is ideal for templating. [1](https://www.libvirt.org/manpages/virsh.html) Local $sContent = StringFormat( _ "%s =" & @CRLF & _ " (DESCRIPTION =" & @CRLF & _ " (ADDRESS =" & @CRLF & _ " (PROTOCOL = TCP)" & @CRLF & _ " (HOST = %s)" & @CRLF & _ " (PORT = %d)" & @CRLF & _ " )" & @CRLF & _ " (CONNECT_DATA = " & @CRLF & _ " (SERVER = DEDICATED)" & @CRLF & _ " (SID = %s)" & @CRLF & _ " )" & @CRLF & _ " )" & @CRLF, _ $sAlias, $sHost, $iPort, $sSid) ; Write fresh file (overwrite) Local $hFile = FileOpen($sFilePath, $FO_OVERWRITE) If $hFile = -1 Then Return SetError(2, 0, False) EndIf Local $iOk = FileWrite($hFile, $sContent) FileClose($hFile) If $iOk = 0 Then Return SetError(3, 0, False) EndIf Return True EndFunc Func WriteOraReferenceXml($sFilePath, $sUser, $bBackup = True) ; Backup existing file (only if it exists and backup requested) If $bBackup And FileExists($sFilePath) Then Local $sStamp = @YEAR & "." & @MON & "." & @MDAY & "." & @HOUR & "." & @MIN & "." & @SEC ; Extract just the filename from the full path (connections.xml) Local $sFileName = StringTrimLeft($sFilePath, StringInStr($sFilePath, "\", 0, -1)) ; Compose backup destination: \connections.xml.2023.11.07.18.39.20.bak Local $sBak = $sBackupDir & "\" & $sFileName & "." & $sStamp & ".bak" If Not FileCopy($sFilePath, $sBak, $FC_OVERWRITE) Then Return SetError(1, 0, False) Else ConsoleWrite("File" & $sFileName & " was backed up to " & $sBak & @CRLF) WriteLog("File" & $sFileName & " was backed up to " & $sBak) EndIf EndIf Local $sXml = StringFormat( _ "" & @CRLF & _ "" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " false" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " TNS" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " Oracle" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " RDS" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " thin" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " TRUE" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " oracle.jdbc.OracleDriver" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " oraJDBC" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " false" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " %s" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " false" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " ORA1" & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ " " & @CRLF & _ "" & @CRLF, _ $sUser) Local $hFile = FileOpen($sFilePath, $FO_OVERWRITE) If $hFile = -1 Then Return SetError(2, 0, False) If FileWrite($hFile, $sXml) = 0 Then FileClose($hFile) Return SetError(3, 0, False) EndIf FileClose($hFile) Return True EndFunc