diff --git a/src/utils/cracker/.editorconfig b/src/utils/cracker/.editorconfig deleted file mode 100644 index 66154009..00000000 --- a/src/utils/cracker/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -; Top-most EditorConfig file -root = true - -; Windows-style newlines -[*] -end_of_line = CRLF - -; Tab indentation -[*.{cpp,h}] -indent_style = tab -tab_width = 4 \ No newline at end of file diff --git a/src/utils/cracker/.gitattributes b/src/utils/cracker/.gitattributes deleted file mode 100644 index a0784126..00000000 --- a/src/utils/cracker/.gitattributes +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### -* text=auto - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just comment the entries below and -# uncomment the group further below -############################################################################### - -*.sln text eol=crlf -*.csproj text eol=crlf -*.vbproj text eol=crlf -*.vcxproj text eol=crlf -*.vcproj text eol=crlf -*.dbproj text eol=crlf -*.fsproj text eol=crlf -*.lsproj text eol=crlf -*.wixproj text eol=crlf -*.modelproj text eol=crlf -*.sqlproj text eol=crlf -*.wmaproj text eol=crlf - -*.xproj text eol=crlf -*.props text eol=crlf -*.filters text eol=crlf -*.vcxitems text eol=crlf - - -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -#*.xproj merge=binary -#*.props merge=binary -#*.filters merge=binary -#*.vcxitems merge=binary diff --git a/src/utils/cracker/.gitignore b/src/utils/cracker/.gitignore deleted file mode 100644 index 69a917ba..00000000 --- a/src/utils/cracker/.gitignore +++ /dev/null @@ -1,72 +0,0 @@ -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.out -*.app - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ -*.VC.opendb - -# Visual C++ Solution -*.VC.db - -# NuGet packages -packages/ - -# Alkhaser log file -log.txt - -# Packages -packages/ diff --git a/src/utils/dxs/ConsoleApplication.tpl b/src/utils/dxs/ConsoleApplication.tpl deleted file mode 100644 index 132a1737..00000000 --- a/src/utils/dxs/ConsoleApplication.tpl +++ /dev/null @@ -1,1162 +0,0 @@ -Console App -ConsoleTemplate -Console Application -[*BEGINPRO*] -[*BEGINDEF*] -[MakeDef] -Menu=1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 -1=4,O,$B\RC.EXE /v,1 -2=3,O,$B\ML.EXE /c /coff /Cp /nologo /I"$I",2 -3=5,O,$B\LINK.EXE /SUBSYSTEM:CONSOLE /RELEASE /VERSION:4.0 /LIBPATH:"$L" /OUT:"$5",3,4 -4=0,0,,5 -5=rsrc.obj,O,$B\CVTRES.EXE,rsrc.res -6=*.obj,O,$B\ML.EXE /c /coff /Cp /nologo /I"$I",*.asm -7=0,0,"$E\x32dbg.exe",5 -11=4,O,$B\RC.EXE /v,1 -12=3,O,$B\ML.EXE /c /coff /Cp /Zi /Zd /nologo /I"$I",2 -13=5,O,$B\LINK.EXE /SUBSYSTEM:CONSOLE /DEBUG /DEBUGTYPE:CV /PDB:"$18" /VERSION:4.0 /LIBPATH:"$L" /OUT:"$5",3,4 -14=0,0,,5 -15=rsrc.obj,O,$B\CVTRES.EXE,rsrc.res -16=*.obj,O,$B\ML.EXE /c /coff /Cp /Zi /Zd /nologo /I"$I",*.asm -17=0,0,"$E\x32dbg.exe",5 -[MakeFiles] -0=ConsoleTemplate.rap -1=ConsoleTemplate.rc -2=ConsoleTemplate.asm -3=ConsoleTemplate.obj -4=ConsoleTemplate.res -5=ConsoleTemplate.exe -6=ConsoleTemplate.def -7=ConsoleTemplate.dll -8=ConsoleTemplate.txt -9=ConsoleTemplate.lib -10=ConsoleTemplate.mak -11=ConsoleTemplate.hla -12=ConsoleTemplate.com -13=ConsoleTemplate.ocx -14=ConsoleTemplate.idl -15=ConsoleTemplate.tlb -16=ConsoleTemplate.sys -17=ConsoleTemplate.dp32 -18=ConsoleTemplate.pdb -19=ConsoleTemplate.dp64 -[Resource] -1=,1,8,ConsoleTemplate.xml -2=,100,2,ConsoleTemplate.ico -[StringTable] -[Accel] -[VerInf] -Nme=VERINF1 -ID=1 -FV=1.0.0.0 -PV=1.0.0.0 -VerOS=0x00000004 -VerFT=0x00000001 -VerLNG=0x00000409 -VerCHS=0x000004B0 -ProductVersion=1.0.0.0 -ProductName=ConsoleTemplate -OriginalFilename=ConsoleTemplate -LegalTrademarks=(C) 2017 fearless - www.LetTheLightIn.in -LegalCopyright=(C) 2017 fearless - www.LetTheLightIn.in -InternalName=ConsoleTemplate -FileDescription=ConsoleTemplate -FileVersion=1.0.0.0 -CompanyName=fearless -[Group] -Group=Assembly,Resources,Misc -1=1 -2=1 -3=2 -[*ENDDEF*] -[*BEGINTXT*] -ConsoleTemplate.asm -.686 -.MMX -.XMM -.model flat,stdcall -option casemap:none -include \masm32\macros\macros.asm - -;DEBUG32 EQU 1 - -IFDEF DEBUG32 - PRESERVEXMMREGS equ 1 - Includelib M:\Masm32\lib\Debug32.lib - DBG32LIB equ 1 - DEBUGEXE textequ <'M:\Masm32\DbgWin.exe'> - Include M:\Masm32\include\debug32.inc -ENDIF - - -Include [*PROJECTNAME*].inc - - -.CODE - -Main PROC - - Invoke ConsoleStarted - .IF eax == TRUE ; Started From Console - - Invoke ConsoleAttach - Invoke ConsoleSetIcon, ICO_MAIN - Invoke ConsoleGetTitle, Addr szConTitle, SIZEOF szConTitle - Invoke ConsoleSetTitle, Addr TitleName - Invoke [*PROJECTNAME*]ConInfo, CON_OUT_INFO - - ; Start main console processing - Invoke [*PROJECTNAME*]Main - ; Exit main console processing - - ;Invoke ConsolePause, CON_PAUSE_ANY_KEY_CONTINUE - Invoke ConsoleSetTitle, Addr szConTitle - Invoke ConsoleSetIcon, ICO_CMD - Invoke ConsoleShowCursor - Invoke ConsoleFree - - .ELSE ; Started From Explorer - - Invoke ConsoleAttach - Invoke ConsoleSetIcon, ICO_MAIN - Invoke ConsoleSetTitle, Addr TitleName - Invoke [*PROJECTNAME*]ConInfo, CON_OUT_INFO - Invoke [*PROJECTNAME*]ConInfo, CON_OUT_ABOUT - ;Invoke [*PROJECTNAME*]ConInfo, CON_OUT_USAGE - Invoke ConsolePause, CON_PAUSE_ANY_KEY_EXIT - Invoke ConsoleSetIcon, ICO_CMD - Invoke ConsoleFree - - .ENDIF - - Invoke ExitProcess,0 - ret -Main ENDP - - -;------------------------------------------------------------------------------------- -; [*PROJECTNAME*]Main -;------------------------------------------------------------------------------------- -[*PROJECTNAME*]Main PROC - - Invoke [*PROJECTNAME*]RegisterSwitches - Invoke [*PROJECTNAME*]RegisterCommands - Invoke [*PROJECTNAME*]ProcessCmdLine - - ;--------------------------------------------------------------------------------- - ; HELP: /? help switch or no switch - ;--------------------------------------------------------------------------------- - .IF eax == CMDLINE_NOTHING || eax == CMDLINE_HELP ; no switch provided or /? - - Invoke [*PROJECTNAME*]ConInfo, CON_OUT_HELP - - ;--------------------------------------------------------------------------------- - ; CMDLINE_FILEIN - ;--------------------------------------------------------------------------------- - .ELSEIF eax == CMDLINE_FILEIN - - - ;--------------------------------------------------------------------------------- - ; CMDLINE_FILEIN_FILEOUT - ;--------------------------------------------------------------------------------- - .ELSEIF eax == CMDLINE_FILEIN_FILEOUT - - - ;--------------------------------------------------------------------------------- - ; CMDLINE_FOLDER_FILESPEC - ;--------------------------------------------------------------------------------- - .ELSEIF eax == CMDLINE_FOLDER_FILESPEC - - - ;--------------------------------------------------------------------------------- - ; CMDLINE_FILEIN_FILESPEC - ;--------------------------------------------------------------------------------- - .ELSEIF eax == CMDLINE_FILEIN_FILESPEC - - - ;--------------------------------------------------------------------------------- - ; ERROR - ;--------------------------------------------------------------------------------- - .ELSE - - Invoke [*PROJECTNAME*]ConErr, eax - - .ENDIF - - ret -[*PROJECTNAME*]Main ENDP - - -;----------------------------------------------------------------------------------------- -; Process command line information -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]ProcessCmdLine PROC - LOCAL dwLenCmdLineParameter:DWORD - LOCAL bFileIn:DWORD - LOCAL bCommand:DWORD - - Invoke GetCommandLine - Invoke ConsoleParseCmdLine, Addr CmdLineParameters - mov TotalCmdLineParameters, eax ; will be at least 1 as param 0 is name of exe - - .IF TotalCmdLineParameters == 1 ; nothing extra specified - mov eax, CMDLINE_NOTHING - ret - .ENDIF - - Invoke ConsoleCmdLineParam, Addr CmdLineParameters, 1, TotalCmdLineParameters, Addr CmdLineParameter - .IF sdword ptr eax > 0 - mov dwLenCmdLineParameter, eax - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - - .IF TotalCmdLineParameters == 2 - - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 1, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_ERROR' - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_UNKNOWN - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_UNKNOWN' - - .ELSEIF eax == CMDLINE_PARAM_TYPE_SWITCH - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_SWITCH' - Invoke ConsoleSwitchID, Addr CmdLineParameter, FALSE - .IF eax == SWITCH_HELP || eax == SWITCH_HELP_UNIX || eax == SWITCH_HELP_UNIX2 - mov eax, CMDLINE_HELP - ret - .ELSE - mov eax, CMDLINE_UNKNOWN_SWITCH - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_COMMAND - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_COMMAND' - Invoke ConsoleCommandID, Addr CmdLineParameter, FALSE - ;PrintDec eax - .IF eax == -1 - mov eax, CMDLINE_UNKNOWN_COMMAND - ret - .ELSE - mov eax, CMDLINE_COMMAND_WITHOUT_FILEIN - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_FILESPEC' - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - mov eax, CMDLINE_FILEIN_FILESPEC - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILENAME - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_FILENAME' - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - mov eax, CMDLINE_FILEIN - ret - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - ;PrintText 'ConsoleCmdLineParamType CMDLINE_PARAM_TYPE_FOLDER' - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - ; assume filespec of *.* in folder provided - Invoke lstrcat, Addr sz[*PROJECTNAME*]InFilename, Addr szFolderAllFiles - mov eax, CMDLINE_FOLDER_FILESPEC - ret - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - .ENDIF - .ENDIF - - ;------------------------------------------------------------------------------------- - ; FILENAMEIN FILENAMEOUT or OPTION FILENAMEIN/FILESPECIN - ;------------------------------------------------------------------------------------- - mov bFileIn, FALSE - mov bCommand, FALSE - .IF TotalCmdLineParameters == 3 - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 1, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_UNKNOWN - - .ELSEIF eax == CMDLINE_PARAM_TYPE_SWITCH - Invoke ConsoleSwitchID, Addr CmdLineParameter, FALSE - .IF eax == SWITCH_HELP || eax == SWITCH_HELP_UNIX || eax == SWITCH_HELP_UNIX2 - mov eax, CMDLINE_HELP - ret - .ELSE - mov eax, CMDLINE_UNKNOWN_SWITCH - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_COMMAND - Invoke ConsoleCommandID, Addr CmdLineParameter, FALSE - .IF eax == -1 - mov eax, CMDLINE_UNKNOWN_COMMAND - ret - .ELSE - ; check commands - .ENDIF - mov bCommand, TRUE - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILENAME - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - ;mov bFileIn, TRUE - ;mov eax, CMDLINE_FILEIN - ;ret - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - ; assume filespec of *.* in folder provided - Invoke lstrcat, Addr sz[*PROJECTNAME*]InFilename, Addr szFolderAllFiles - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - - .ENDIF - - ; Get 2nd param - Invoke ConsoleCmdLineParam, Addr CmdLineParameters, 2, TotalCmdLineParameters, Addr CmdLineParameter - .IF sdword ptr eax > 0 - mov dwLenCmdLineParameter, eax - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 2, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_UNKNOWN - - .ELSEIF eax == CMDLINE_PARAM_TYPE_SWITCH - Invoke ConsoleSwitchID, Addr CmdLineParameter, FALSE - .IF eax == SWITCH_HELP || eax == SWITCH_HELP_UNIX || eax == SWITCH_HELP_UNIX2 - mov eax, CMDLINE_HELP - ret - .ELSE - mov eax, CMDLINE_UNKNOWN_SWITCH - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_COMMAND ; user specified filename/filespec/folder first then command? - Invoke ConsoleCommandID, Addr CmdLineParameter, FALSE - .IF eax == -1 - mov eax, CMDLINE_UNKNOWN_COMMAND - ret - .ELSE - ; check commands - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - .IF bCommand == TRUE - mov eax, CMDLINE_FILEIN_FILESPEC - ret - .ELSE - mov eax, CMDLINE_FILESPEC_NOT_SUPPORTED - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILENAME - .IF bCommand == TRUE - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - mov eax, CMDLINE_FILEIN - ret - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - .ELSE - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]OutFilename - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 1, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_FILENAME - mov eax, CMDLINE_FILEIN_FILEOUT - ret - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - mov eax, CMDLINE_FILESPEC_NOT_SUPPORTED - ret - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - mov eax, CMDLINE_FOLDER_NOT_SUPPORTED - ret - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - .IF bCommand == TRUE - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - ; assume filespec of *.* in folder provided - Invoke lstrcat, Addr sz[*PROJECTNAME*]InFilename, Addr szFolderAllFiles - mov eax, CMDLINE_FOLDER_FILESPEC - ret - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - .ELSE - mov eax, CMDLINE_FILESPEC_NOT_SUPPORTED - ret - .ENDIF - .ENDIF - .ENDIF - - - ;------------------------------------------------------------------------------------- - ; OPTION FILENAMEIN FILENAMEOUT - ;------------------------------------------------------------------------------------- - - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 1, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_SWITCH - Invoke ConsoleSwitchID, Addr CmdLineParameter, FALSE - .IF eax == SWITCH_HELP || eax == SWITCH_HELP_UNIX || eax == SWITCH_HELP_UNIX2 - mov eax, CMDLINE_HELP - ret - .ELSE - mov eax, CMDLINE_UNKNOWN_SWITCH - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_COMMAND - Invoke ConsoleCommandID, Addr CmdLineParameter, FALSE - .IF eax == -1 - mov eax, CMDLINE_UNKNOWN_COMMAND - ret - .ELSE - ; check commands - .ENDIF - mov bCommand, TRUE - - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - - ; Get 2nd param - Invoke ConsoleCmdLineParam, Addr CmdLineParameters, 2, TotalCmdLineParameters, Addr CmdLineParameter - .IF sdword ptr eax > 0 - mov dwLenCmdLineParameter, eax - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 2, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILENAME - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]InFilename - Invoke exist, Addr sz[*PROJECTNAME*]InFilename - .IF eax == TRUE ; does exist - .ELSE - mov eax, CMDLINE_FILEIN_NOT_EXIST - ret - .ENDIF - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - mov eax, CMDLINE_FILESPEC_NOT_SUPPORTED - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - mov eax, CMDLINE_FOLDER_NOT_SUPPORTED - ret - - .ELSE - mov eax, CMDLINE_ERROR - ret - - .ENDIF - - ; Get 3rd param - Invoke ConsoleCmdLineParam, Addr CmdLineParameters, 3, TotalCmdLineParameters, Addr CmdLineParameter - .IF sdword ptr eax > 0 - mov dwLenCmdLineParameter, eax - .ELSE - mov eax, CMDLINE_ERROR - ret - .ENDIF - - Invoke ConsoleCmdLineParamType, Addr CmdLineParameters, 3, TotalCmdLineParameters - .IF eax == CMDLINE_PARAM_TYPE_ERROR - mov eax, CMDLINE_ERROR - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILENAME - Invoke szCopy, Addr CmdLineParameter, Addr sz[*PROJECTNAME*]OutFilename - mov eax, CMDLINE_FILEIN_FILEOUT - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FILESPEC - mov eax, CMDLINE_FILESPEC_NOT_SUPPORTED - ret - - .ELSEIF eax == CMDLINE_PARAM_TYPE_FOLDER - mov eax, CMDLINE_FOLDER_NOT_SUPPORTED - ret - - .ELSE - mov eax, CMDLINE_ERROR - ret - - .ENDIF - - ret -[*PROJECTNAME*]ProcessCmdLine ENDP - - -;----------------------------------------------------------------------------------------- -; Register switches for use on command line -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]RegisterSwitches PROC - Invoke ConsoleSwitchRegister, CTEXT("/?"), SWITCH_HELP - Invoke ConsoleSwitchRegister, CTEXT("-?"), SWITCH_HELP_UNIX - Invoke ConsoleSwitchRegister, CTEXT("--?"), SWITCH_HELP_UNIX2 - ret -[*PROJECTNAME*]RegisterSwitches ENDP - - -;----------------------------------------------------------------------------------------- -; Register commands for use on command line -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]RegisterCommands PROC - ;Invoke ConsoleCommandRegister, CTEXT("c"), COMMAND_COMPRESS - ;Invoke ConsoleCommandRegister, CTEXT("d"), COMMAND_DECOMPRESS - ret -[*PROJECTNAME*]RegisterCommands ENDP - - -;----------------------------------------------------------------------------------------- -; Prints out console information -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]ConInfo PROC dwMsgType:DWORD - mov eax, dwMsgType - .IF eax == CON_OUT_INFO - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]ConInfo - .ELSEIF eax == CON_OUT_ABOUT - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]ConAbout - .ELSEIF eax == CON_OUT_USAGE - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]ConHelpUsage - .ELSEIF eax == CON_OUT_HELP - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]ConHelp - .ENDIF - ret -[*PROJECTNAME*]ConInfo ENDP - - -;----------------------------------------------------------------------------------------- -; Prints out error information to console -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]ConErr PROC dwErrorType:DWORD - mov eax, dwErrorType - .IF eax == CMDLINE_UNKNOWN_SWITCH || eax == CMDLINE_UNKNOWN_COMMAND || eax == CMDLINE_COMMAND_WITHOUT_FILEIN - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr CmdLineParameter - Invoke ConsoleStdOut, Addr szSingleQuote - mov eax, dwErrorType - .IF eax == CMDLINE_UNKNOWN_SWITCH - Invoke ConsoleStdOut, Addr szErrorUnknownSwitch - .ELSEIF eax == CMDLINE_UNKNOWN_COMMAND - Invoke ConsoleStdOut, Addr szErrorUnknownCommand - .ELSEIF eax == CMDLINE_COMMAND_WITHOUT_FILEIN - Invoke ConsoleStdOut, Addr szErrorCommandWithoutFile - .ENDIF - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - Invoke [*PROJECTNAME*]ConInfo, CON_OUT_USAGE - - .ELSEIF eax == CMDLINE_FILEIN_NOT_EXIST - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]InFilename - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr szErrorFilenameNotExist - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - - .ELSEIF eax == CMDLINE_ERROR - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szErrorOther - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - - .ELSEIF eax == ERROR_FILEIN_IS_EMPTY - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]InFilename - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr szErrorFileZeroBytes - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - - .ELSEIF eax == ERROR_OPENING_FILEIN - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]InFilename - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr szErrorOpeningInFile - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - - .ELSEIF eax == ERROR_CREATING_FILEOUT - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr sz[*PROJECTNAME*]OutFilename - Invoke ConsoleStdOut, Addr szSingleQuote - Invoke ConsoleStdOut, Addr szErrorCreatingOutFile - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - - .ELSEIF eax == ERROR_ALLOC_MEMORY - Invoke ConsoleStdOut, Addr szError - Invoke ConsoleStdOut, Addr szErrorAllocMemory - Invoke ConsoleStdOut, Addr szCRLF - Invoke ConsoleStdOut, Addr szCRLF - .ENDIF - ret -[*PROJECTNAME*]ConErr ENDP - - -;------------------------------------------------------------------------------------- -; [*PROJECTNAME*]FileInOpen - Open file to process -;------------------------------------------------------------------------------------- -[*PROJECTNAME*]FileInOpen PROC lpszFilename:DWORD - - .IF lpszFilename == NULL - mov eax, FALSE - ret - .ENDIF - - ; Tell user we are loading file - mov hFileIn, NULL - mov hMemMapIn, NULL - mov hMemMapInPtr, NULL - mov DWORD ptr qwFileSize+4, 0 - mov DWORD ptr qwFileSize, 0 - mov dwFileSize, 0 - mov dwFileSizeHigh, 0 - - Invoke CreateFile, lpszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL - .IF eax == INVALID_HANDLE_VALUE - ; Tell user that file did not load - mov eax, FALSE - ret - .ENDIF - mov hFileIn, eax - - Invoke CreateFileMapping, hFileIn, NULL, PAGE_READONLY, 0, 0, NULL ; Create memory mapped file - .IF eax == NULL - ; Tell user that file did not map - Invoke CloseHandle, hFileIn - mov eax, FALSE - ret - .ENDIF - mov hMemMapIn, eax - - Invoke MapViewOfFileEx, hMemMapIn, FILE_MAP_READ, 0, 0, 0, NULL - .IF eax == NULL - ; Tell user that file did not mapview - Invoke CloseHandle, hMemMapIn - Invoke CloseHandle, hFileIn - mov eax, FALSE - ret - .ENDIF - mov hMemMapInPtr, eax - - Invoke GetFileSizeEx, hFileIn, Addr qwFileSize - mov eax, DWORD ptr qwFileSize - mov dwFileSize, eax - mov eax, DWORD ptr qwFileSize+4 - mov dwFileSizeHigh, eax - - mov eax, TRUE - - ret - -[*PROJECTNAME*]FileInOpen ENDP - - -;------------------------------------------------------------------------------------- -; [*PROJECTNAME*]FileInClose - Closes currently opened file -;------------------------------------------------------------------------------------- -[*PROJECTNAME*]FileInClose PROC - - .IF hMemMapInPtr != NULL - Invoke UnmapViewOfFile, hMemMapInPtr - mov hMemMapInPtr, NULL - .ENDIF - .IF hMemMapIn != NULL - Invoke CloseHandle, hMemMapIn - mov hMemMapIn, NULL - .ENDIF - .IF hFileIn != NULL - Invoke CloseHandle, hFileIn - mov hFileIn, NULL - .ENDIF - - mov DWORD ptr qwFileSize+4, 0 - mov DWORD ptr qwFileSize, 0 - mov dwFileSize, 0 - mov dwFileSizeHigh, 0 - - ret -[*PROJECTNAME*]FileInClose ENDP - - -;------------------------------------------------------------------------------------- -; [*PROJECTNAME*]FileOutOpen - Create out file -;------------------------------------------------------------------------------------- -[*PROJECTNAME*]FileOutOpen PROC lpszFilename:DWORD - - .IF lpszFilename == NULL - mov eax, FALSE - ret - .ENDIF - - ; Tell user we are loading file - mov hFileOut, NULL - mov hMemMapOut, NULL - mov hMemMapOutPtr, NULL - - Invoke CreateFile, lpszFilename, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE + FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL - .IF eax == INVALID_HANDLE_VALUE - ; Tell user that file did not load - mov eax, FALSE - ret - .ENDIF - mov hFileOut, eax - - mov eax, TRUE - - ret - -[*PROJECTNAME*]FileOutOpen ENDP - - -;------------------------------------------------------------------------------------- -; [*PROJECTNAME*]FileOutClose - Closes output file -;------------------------------------------------------------------------------------- -[*PROJECTNAME*]FileOutClose PROC - .IF hFileOut != NULL - Invoke CloseHandle, hFileOut - mov hFileOut, NULL - .ENDIF - ret -[*PROJECTNAME*]FileOutClose ENDP - - - -;************************************************************************** -; Strip path name to just filename with extention -;************************************************************************** -JustFnameExt PROC USES ESI EDI szFilePathName:DWORD, szFileName:DWORD - LOCAL LenFilePathName:DWORD - LOCAL nPosition:DWORD - - Invoke szLen, szFilePathName - mov LenFilePathName, eax - mov nPosition, eax - - .IF LenFilePathName == 0 - mov edi, szFileName - mov byte ptr [edi], 0 - mov eax, FALSE - ret - .ENDIF - - mov esi, szFilePathName - add esi, eax - - mov eax, nPosition - .WHILE eax != 0 - movzx eax, byte ptr [esi] - .IF al == '\' || al == ':' || al == '/' - inc esi - .BREAK - .ENDIF - dec esi - dec nPosition - mov eax, nPosition - .ENDW - mov edi, szFileName - mov eax, nPosition - .WHILE eax != LenFilePathName - movzx eax, byte ptr [esi] - mov byte ptr [edi], al - inc edi - inc esi - inc nPosition - mov eax, nPosition - .ENDW - mov byte ptr [edi], 0h ; null out filename - mov eax, TRUE - ret - -JustFnameExt ENDP - - - -END Main - - - - - - - -[*ENDTXT*] -[*BEGINTXT*] -ConsoleTemplate.inc -include windows.inc -include user32.inc -include kernel32.inc -include shell32.inc -include masm32.inc -includelib user32.lib -includelib kernel32.lib -includelib shell32.lib -includelib masm32.lib - -include Console.inc -includelib Console.lib - - -;----------------------------------------------------------------------------------------- -; [*PROJECTNAME*] Prototypes -;----------------------------------------------------------------------------------------- -[*PROJECTNAME*]Main PROTO -[*PROJECTNAME*]RegisterSwitches PROTO -[*PROJECTNAME*]RegisterCommands PROTO -[*PROJECTNAME*]ProcessCmdLine PROTO - -[*PROJECTNAME*]ConInfo PROTO :DWORD -[*PROJECTNAME*]ConErr PROTO :DWORD - -[*PROJECTNAME*]FileInOpen PROTO :DWORD -[*PROJECTNAME*]FileInClose PROTO -[*PROJECTNAME*]FileOutOpen PROTO :DWORD -[*PROJECTNAME*]FileOutClose PROTO - - -JustFnameExt PROTO :DWORD, :DWORD -IFNDEF GetCommandLineA -GetCommandLineA PROTO -GetCommandLine EQU -ENDIF - - -.CONST -;----------------------------------------------------------------------------------------- -; [*PROJECTNAME*] Constants -;----------------------------------------------------------------------------------------- -ICO_MAIN EQU 100 -ICO_CMD EQU 101 - -; [*PROJECTNAME*]ConInfo dwMsgType: -CON_OUT_INFO EQU 0 ; Header information -CON_OUT_ABOUT EQU 1 ; About information -CON_OUT_USAGE EQU 2 ; Usage information: switches/commands and params -CON_OUT_HELP EQU 3 ; Help information - -; Constants for [*PROJECTNAME*]ProcessCmdLine -; return values and for [*PROJECTNAME*]ConErr -; dwErrorType: -ERROR_WRITING_DECOMPRESS_DATA EQU -15 ; Writefile failed with writing data out -ERROR_WRITING_COMPRESS_DATA EQU -14 ; Writefile failed with writing data out -ERROR_ALLOC_MEMORY EQU -13 ; GlobalAlloc failed for some reason -ERROR_CREATING_FILEOUT EQU -12 ; Couldnt create temporary output file -ERROR_OPENING_FILEIN EQU -11 ; Couldnt open input filename -ERROR_FILEIN_IS_EMPTY EQU -10 ; 0 byte file -CMDLINE_COMMAND_WITHOUT_FILEIN EQU -8 ; User forgot to supply a filename or filespec or folder with command -CMDLINE_FOLDER_NOT_SUPPORTED EQU -6 ; A folder (assumes \*.* filespec) provided whilst supplying output filename -CMDLINE_FILESPEC_NOT_SUPPORTED EQU -5 ; Using *.* etc wildcards whilst supplying output filename -CMDLINE_FILEIN_NOT_EXIST EQU -4 ; Filename or filepath provided does not exist -CMDLINE_ERROR EQU -3 ; General error reading parameters -CMDLINE_UNKNOWN_COMMAND EQU -2 ; User provided a command that wasnt recognised -CMDLINE_UNKNOWN_SWITCH EQU -1 ; User provided a / or - switch that wasnt recognised -CMDLINE_NOTHING EQU 0 ; -CMDLINE_HELP EQU 1 ; User specified /? -? --? as a parameter -CMDLINE_FILEIN EQU 2 ; A single filename was specified -CMDLINE_FILEIN_FILESPEC EQU 3 ; A filespec (*.*, *.txt) was specified -CMDLINE_FILEIN_FILEOUT EQU 4 ; A filename for input and a filename for output was specified -CMDLINE_FOLDER_FILESPEC EQU 5 ; A folder was specified (assumes \*.* filespec) - -; [*PROJECTNAME*] Switch IDs: /? -? --? -SWITCH_HELP EQU 0 ; /? help switch -SWITCH_HELP_UNIX EQU 1 ; -? help switch -SWITCH_HELP_UNIX2 EQU 2 ; --? help switch - -; [*PROJECTNAME*] Command IDs: c d -;COMMAND_COMPRESS EQU 0 ; c - set [*PROJECTNAME*] mode to compress -;COMMAND_DECOMPRESS EQU 1 ; d - set [*PROJECTNAME*] mode to decompress - - -.DATA -;----------------------------------------------------------------------------------------- -; [*PROJECTNAME*] Initialized Data -;----------------------------------------------------------------------------------------- -AppName DB '[*PROJECTNAME*]',0 -TitleName DB '[*PROJECTNAME*] Tool v1.0.0.0',0 -szConTitle DB MAX_PATH DUP (0) -CmdLineParameters DB 512 DUP (0) -CmdLineParameter DB 256 DUP (0) -ErrParameter DB 256 DUP (0) -TotalCmdLineParameters DD 0 - -; Help -sz[*PROJECTNAME*]ConInfo DB 13,10,"[[*PROJECTNAME*]] v1.00 - [*PROJECTNAME*] Tool - Copyright (C) 2017 fearless",13,10,13,10,0 - -sz[*PROJECTNAME*]ConAbout DB "About:",13,10 - DB "========",13,10 - DB "[*PROJECTNAME*] is a console program which needs to be ran from a command prompt.",13,10 - DB "For detailed help on the [*PROJECTNAME*] options, specify [*PROJECTNAME*] /? at the prompt.",13,10 - DB 13,10,13,10 - DB "Credits:",13,10 - DB "========",13,10 - DB "[*PROJECTNAME*] is designed and programmed by fearless (C) Copyright 2017",13,10 - DB "Written using Microsoft Macro Assembler, Steve Hutch MASM32 libraries and",13,10 - DB "Zlib library Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler. ",13,10 - DB 13,10,0 - -sz[*PROJECTNAME*]ConHelp DB "Usage: [*PROJECTNAME*] [/?]",13,10 - DB " [path]infilename",13,10 - DB " [path]infilename [[path]outfilename]",13,10 - DB 13,10 - DB 13,10 - DB " /? Displays this help",13,10 - DB 13,10 - DB " [path]infilename is name of a valid file to uncompress",13,10 - DB " to a standard bif file. Supports the use of wildcards * and ? ",13,10 - DB " for batch operations. See note below for details on how files",13,10 - DB " are saved if you use this feature",13,10 - DB 13,10 - DB " [path]outfilename (optional) is name of the file to save the",13,10 - DB " uncompressed file to. Cannot use wildcards if this is used.",13,10 - DB 13,10 - DB 13,10 - DB "Note: If outfilename is not specified, the output is to the original",13,10 - DB " infilename provided, overwritting the original file data.",13,10 - DB 13,10 - DB " If you wish to prevent accidentally overwritting files, specify",13,10 - DB " both infilename and outfilename.",13,10 - DB 13,10 - DB 13,10 - DB 13,10,0 - -sz[*PROJECTNAME*]ConHelpUsage DB "Usage: [*PROJECTNAME*] [/?]",13,10 - DB " [path]infilename",13,10 - DB " [path]infilename [[path]outfilename]",13,10 - DB 13,10,0 - - -; Error message -szError DB "[!] Error: ",0 -szErrorUnknownSwitch DB " invalid switch specified.",0 -szErrorUnknownCommand DB " invalid command specified.",0 -szErrorCommandWithoutFile DB " command specified but no filename or filespec provided.",0 -szErrorFileSpecNotSupported DB " wildcard filespec not supported for input file(s) when also specifying output filename as well.",0 -szErrorFilenameNotExist DB " filename/filepath does not exist.",0 -szErrorOther DB "unknown error occured whilst parsing parameters and switches.",0 -szErrorFolderNotSupported DB " folder (assumes *.*) not supported for input file(s) when also specifying output filename as well.",0 -szErrorFileZeroBytes DB " file 0 bytes, skipping.",0 -szErrorOpeningInFile DB " failed to open input file.",0 -szErrorCreatingOutFile DB " failed to create output file.",0 -szErrorAllocMemory DB "failed to allocate memory for operation.",0 - - -; Punctuation -szComma DB ',',0 -szSpace DB ' ',0 -szColon DB ':',0 -szLeftBracket DB '{',0 -szRightBracket DB '}',0 -szBackslash DB '\',0 -szLeftSquareBracket DB '[',0 -szRightSquareBracket DB ']',0 -szQuote DB '"',0 -szSingleQuote DB "'",0 -szDash DB '-',0 -szForwardslash DB '/',0 -szWildCardStar DB '*',0 -szWildCardQuestion DB '?',0 -szLF DB 10,0 -szCRLF DB 13,10,0 -szFolderAllFiles DB '\*.*',0 - -SwitchHelp DB '/?',0 -SwitchHelpAlt DB '-?',0 -SwitchHelpAlt2 DB '--?',0 - -; Filename Buffers -sz[*PROJECTNAME*]SelfFilename DB MAX_PATH DUP (0) -sz[*PROJECTNAME*]SelfFilepath DB MAX_PATH DUP (0) -sz[*PROJECTNAME*]InFilename DB MAX_PATH DUP (0) -sz[*PROJECTNAME*]OutFilename DB MAX_PATH DUP (0) - - -.DATA? -;----------------------------------------------------------------------------------------- -; [*PROJECTNAME*] Uninitialized Data -;----------------------------------------------------------------------------------------- -hFileIn DD ? -hMemMapIn DD ? -hMemMapInPtr DD ? -hFileOut DD ? -hMemMapOut DD ? -hMemMapOutPtr DD ? -qwFileSize DQ ? -dwFileSize DD ? -dwFileSizeHigh DD ? - - - - - - - - - - - - - - - - - - - -[*ENDTXT*] -[*BEGINTXT*] -ConsoleTemplate.rc -#include "Res/ConsoleTemplateVer.rc" -#include "Res/ConsoleTemplateRes.rc" -[*ENDTXT*] -[*ENDPRO*] -[*BEGINTXT*] -Res\[*PROJECTNAME*]Res.Rc -#define MANIFEST 24 -1 MANIFEST DISCARDABLE "[*PROJECTNAME*].xml" -100 ICON DISCARDABLE "[*PROJECTNAME*].ico" -[*ENDTXT*] -[*BEGINBIN*] -[*PROJECTNAME*].ico -0000010001002020040000000000E80200001600000028000000200000004000 -0000010004000000000000020000000000000000000000000000000000000000 -000000008000008000000080800080000000800080008080000080808000C0C0 -C0000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF000000 -0000000000000000000000000000000000000000000000000000000700000000 -0000000000000000000000111100000000000000000000000000011111100000 -0000000000000000000011911117000000000000000000000001199991110000 -0000000000000000001199999911000000000000000000000119999999100000 -0000000000000000119999999100000000000000000000011999999910000000 -0000000000000011999999910000000000000000000001199999991000000000 -0000000000001199999991000000000000000000000119999999100000000000 -0000000000119999999100000000000867000000011999999910000000000088 -707000001199999991000000000008FF8770000719999999100000000000778F -F8780001999999910000000000007778FF877771999999100000000000000777 -8FF8777719999100000000000000007778FF8887119910000000000000000000 -778FFF887777000000000000000000007788FFF8877700000000000000000000 -07788FFF887777000000000000000000087788FFF87777777000000000000000 -0077788FFF8778877000000000000000000877888FFF87777000000000000000 -000087778888FF88700000000000000000000087778888880000000000000000 -000000000777700000000000000000000000000000000000000000000000FFFF -FFFFFFFFFFEFFFFFFFC3FFFFFF81FFFFFF00FFFFFE00FFFFFC00FFFFF801FFFF -F003FFFFE007FFFFC00FFFFF801FFFFF003FFFFE007FFFFC00FFE3F801FFC1F0 -03FF81E007FF00E00FFF00001FFF80003FFFC0007FFFF000FFFFF000FFFFF800 -3FFFF80007FFFC0007FFFE0007FFFF0007FFFFC00FFFFFF87FFFFFFFFFFF -[*ENDBIN*] -[*BEGINTXT*] -[*PROJECTNAME*].xml - - - - [*PROJECTNAME*] - - - - - - -[*ENDTXT*] -[*BEGINTXT*] -Res\[*PROJECTNAME*]Ver.rc -#define VERINF1 1 -VERINF1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -FILEOS 0x00000004 -FILETYPE 0x00000001 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "FileVersion", "1.0.0.0\0" - VALUE "FileDescription", "[*PROJECTNAME*]\0" - VALUE "InternalName", "[*PROJECTNAME*]\0" - VALUE "OriginalFilename", "[*PROJECTNAME*]\0" - VALUE "ProductName", "[*PROJECTNAME*]\0" - VALUE "ProductVersion", "1.0.0.0\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 0x04B0 - END -END -[*ENDTXT*] diff --git a/src/utils/kernelos/harvard/seh-based-exploits/Millenium MP3 Studio.exe b/src/utils/kernelos/harvard/seh-based-exploits/Millenium MP3 Studio.exe deleted file mode 100644 index 243c8776..00000000 Binary files a/src/utils/kernelos/harvard/seh-based-exploits/Millenium MP3 Studio.exe and /dev/null differ diff --git a/src/utils/kernelos/harvard/seh-based-exploits/README.md b/src/utils/kernelos/harvard/seh-based-exploits/README.md deleted file mode 100644 index 0a417e37..00000000 --- a/src/utils/kernelos/harvard/seh-based-exploits/README.md +++ /dev/null @@ -1,27 +0,0 @@ -* An __exception handler__ is a piece of code that is written inside an application, with the purpose of dealing with the fact that the application throws an execption. A typical exception handler looks like this : -``` -try { - //run stuff. If an exception occurs, go to code -} -catch{ - // run stuff when exception occurs -} -``` -* A quick look on the stack on how the try & catch blocks are related to each other and placed on the stack

-* Windows has a default __SEH (Structured Exception Handler)__ which will catch exceptions. If Windows catches an exception, you’ll see a “xxx has encountered a problem and needs to close” popup. This is often the result of the __default__ handler kicking in (UnhandledExceptionFilter) -* Check is an exception handler is registered: ```s 00400000 l 0040c000 64 A1```. __64 A1__ is the opcode for fs[0] -* This is proof that an exception handler is registered. Dump the TEB -> ```d fs:[0]``` should be != 0xffffffff. - -### Changes in Windows XP SP1 with regards to SEH, and the impact of GS/DEP/SafeSEH and other protection mechanisms on exploit writing: -* XOR: In order to be able to build an exploit based on SEH overwrite, we will need to make a distinction between __Windows XP pre-SP1__ and __SP and up__. Since Windows XP SP1, before the exception handler is called, all registers are __XORed__ with each other, making them all contain 0x00000000, which means you won’t be able to find a reference to your payload in one of the registers. -* SafeSEH: Some additional protection was added to compilers, helping to stop the abuse of SEH overwrites. This protection mechanism is active for all modules that are compiled with __/safeSEH__. - -### How to exploit: -* The theory behind this technique is: If we can overwrite the pointer to the SE handler that will be used to deal with a given exception, and we can cause the application to throw another exception (a forced exception), we should be able to get control by forcing the application to jump to your shellcode (instead of to the real exception handler function). - -* A typical payload will look like this: [Junk][nSEH][SEH][Nop-Shellcode] - * Where nSEH = the jump to the shellcode, and SEH is a reference to a pop pop ret -* Further down the stack, we see FFFFFFFF, which looks likeindicates the end of the SEH chain. -* In a typical RET overflow, you overwrite EIP and make it jump to your shellcode. - - it may also suffer from buffer size problems, limiting the amount of space available to host your shellcode. -* When an exception occurs, the exception dispatcher creates its own stack frame. It will push elements from the EH Handler on to the newly created stack (as part of a function prologue).� One of the fields in the EH Structure is the EstablisherFrame.� This field points to the address of the exception registration record (the next SEH) that was pushed onto the program stack. This same address is also located at ESP+8 when the handler is called. \ No newline at end of file diff --git a/src/utils/kernelos/harvard/seh-based-exploits/soritong10.exe b/src/utils/kernelos/harvard/seh-based-exploits/soritong10.exe deleted file mode 100644 index ec537326..00000000 Binary files a/src/utils/kernelos/harvard/seh-based-exploits/soritong10.exe and /dev/null differ diff --git a/src/utils/kernelos/harvard/stack-based-overflows/EasyRMtoMP3Converter.exe b/src/utils/kernelos/harvard/stack-based-overflows/EasyRMtoMP3Converter.exe deleted file mode 100644 index ee1b9dba..00000000 Binary files a/src/utils/kernelos/harvard/stack-based-overflows/EasyRMtoMP3Converter.exe and /dev/null differ diff --git a/src/utils/kernelos/harvard/stack-based-overflows/README.md b/src/utils/kernelos/harvard/stack-based-overflows/README.md deleted file mode 100644 index 821f0a92..00000000 --- a/src/utils/kernelos/harvard/stack-based-overflows/README.md +++ /dev/null @@ -1,81 +0,0 @@ -* Let’s use a few lines of simple code to demonstrate the behaviour : - ``` - #include - - void do_something(char *Buffer) - { - char MyVar[128]; - strcpy(MyVar,Buffer); - } - - int main (int argc, char **argv) - { - do_something(argv[1]); - } - ``` -* The disassembly of the function looks like this : - ``` - 00401290 /$ 55 PUSH EBP - 00401291 |. 89E5 MOV EBP,ESP - 00401293 |. 81EC 98000000 SUB ESP,98 - 00401299 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; | - 0040129C |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; | - 004012A0 |. 8D85 78FFFFFF LEA EAX,DWORD PTR SS:[EBP-88] ; | - 004012A6 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; | - 004012A9 |. E8 72050000 CALL ; \strcpy - 004012AE |. C9 LEAVE - 004012AF \. C3 RETN - ``` -

-* The epilog instruction is executed by a __LEAVE__ instruction (which will restore both the frame pointer and EIP). -* So… Suppose you can overwrite the buffer in MyVar, EBP, EIP and you have A’s (your own code) in the area before and after saved EIP… think about it. After sending the buffer __([MyVar][EBP][EIP][your code])__, ESP will/should point at the beginning of [your code]. So if you can make EIP go to your code, you’re in control. -* When a buffer on the stack overflows, the term _stack based overflow_ or _stack buffer overflow_ is used. When you are trying to write past the end of the stack frame, the term _stack overflow_ is used. Don’t mix those two up, as they are entirely different. -* The next step is to determining the buffer size to write exactly into EIP. Metasploit has a nice tool to assist us with calculating the offset. - - ./pattern_create.rb -l 5000 - - ./pattern_offset.rb -q 0x356b4234 -l 5000 -* We control EIP. So we can point EIP to somewhere else, to a place that contains our own code (shellcode). But where is this space, how can we put our shellcode in that location and how can we make EIP jump to that location ? -* When the application crashes, take a look at the registers and dump all of them (d esp, d eax, d ebx, d ebp, …). If you can see your buffer (either the A’s or the C’s) in one of the registers, then you may be able to replace those with shellcode and jump to that location. -* Jumping directly to a memory address may not be a good solution after all. (0x000ff730 contains a __null byte__, which is a string terminator… so the A’s you are seeing are coming from the first part of the buffer… We never reached the point where we started writing our data after overwrite EIP. -* Besides, using a memory address to jump to in an exploit would make the exploit very unreliable. After all, this memory address could be different in other OS versions, languages, etc…) -* Search for `jmp esp` VA in loaded DLLs": s l (`s 70000000 l fffffff ff e4`) -* If we can find the opcode in one of Easy RM to MP3 dll’s, then we have a good chance of making the exploit work reliably across windows platforms. If we need to use a dll that belongs to the OS, then we might find that the exploit does not work for other versions of the OS. -* If the address starts with a null byte, because of little endian, the null byte would be the last byte in the EIP register. And if you are not sending any payload after overwrite EIP (so if the shellcode is fed before overwriting EIP, and it is still reachable via a register), then this will work. -* If you have a size limitation in terms of buffer space, then you might even want to look at __multi-staged shellcode__, or using specifically handcrafted shellcodes such as this one [32byte cmd.exe shellcode for xp sp2 en](https://packetstormsecurity.com/shellcode/23bytes-shellcode.txt). -* Alternatively, you can split up your shellcode in smaller ‘eggs’ and use a technique called __egg-hunting__ to reassemble the shellcode before executing it. -* Longer shellcode increases the risk on invalid characters in the shellcode, which need to be filtered out. -* The m3u file probably should contain filenames. So a good start would be to filter out all characters that are not allowed in filenames and filepaths. You could also restrict the character set altogether by using another decoder. We have used __shikata_ga_nai__, but perhaps __alpha_upper__ will work better for filenames. -* There are multiple methods of forcing the execution of shellcode. - - __JMP or CALL reg__: use this technique if you have your shellcode directly pointed by any if the reg. - - __POP + RET__ is only usabled when ESP+offset already contains an address which points to the shellcode. - - __PUSH + RET__: is somewhat similar to call [reg]. If one of the registers is directly pointing at your shellcode, and if for some reason you cannot use a jmp [reg] to jump to the shellcode. - - JMP [reg + offset] : Another technique to overcome the problem that the shellcode begins at an offset of a register (ESP in our example) is by trying to find a jmp [reg + offset] instruction (and overwriting EIP with the address of that instruction) - - __Blind return__: - - Overwrite EIP with an address pointing to a ret instruction - - Hardcode the address of the shellcode at the first 4 bytes of ESP. - - ```[26094 A’s][address of ret][0x000fff730][shellcode]``` - - The problem with this example is that the address used to overwrite EIP contains a null byte. -* Dealing with small buffers: - - Jumping anywhere with custom jumpcode. - - Some other ways to jump: - - __popad__: will thus take 32 bytes from ESP and pops them in the registers in an orderly fashion. - - hardcode address to jump to -* Extra notes: -* Just remember that a typical stack based overflow, where you overwrite EIP, could potentionally be subject to a SEH based exploit technique as well, giving you more stability, a larger buffer size (and overwriting EIP would trigger SEH… so it’s a win win -Once you jump to your shellcode, you often need to know what address EIP actually is. The stack is usually not at the same position. Here’s the easiest way to do it: - ``` - call getip - getip: - pop eax ; eax now contains eip - ``` -* The problem is that the above code compiles to E8 00 00 00 00 58, which is useless if you can’t have null bytes. My solution is the following: - ``` - xor eax, eax - getip: - cmp eax, -1 - je popip - mov eax, -1 - call getip - popip: - pop eax - ``` -* The above compiles to: 33 C0 83 F8 FF 74 0A B8 FF FF FF FF E8 F1 FF FF FF 58. It’s longer, but no nulls! You can then xor any null bytes in your code with FFFFFFFF and use xor dword ptr [eax + ], FFFFFFFF to patch them back at runtime. \ No newline at end of file diff --git a/src/utils/objects/utils/ConfigureMCNP.ps1 b/src/utils/objects/utils/ConfigureMCNP.ps1 deleted file mode 100644 index 3169536b..00000000 --- a/src/utils/objects/utils/ConfigureMCNP.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -# Run this script on the Hyper-V Host which is hosting Container Host (Tenant) VMs - -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ServerAddress" /t REG_SZ /d localhost /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ServiceName" /t REG_SZ /d mds /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ServerPort" /t REG_DWORD /d 6642 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ProxyListeningPort" /t REG_DWORD /d 6642 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ProxyListeningAddress" /t REG_SZ /d 0.0.0.0 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\ProxiedServices\c79d8d8d-bbb4-42ea-8a8f-a492efc40a94" /v "ProxyProtocol" /t REG_SZ /d HttpUriPrefix /f - - -# VFP Policy/NCHostAgent registry -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\MetadataServer" /v "Port" /t REG_DWORD /d 6642 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\MetadataServer" /v "ProxyPort" /t REG_DWORD /d 6642 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\MetadataServer" /v "IP" /t REG_SZ /d 169.254.169.254 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\MetadataServer" /v "MAC" /t REG_SZ /d 22-22-22-22-22-22 /f - - -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\NdResponder" /v "MetadataServer" /t REG_MULTI_SZ /d 169.254.169.254\022-22-22-22-22-22 /f -REG ADD "BLACKMARLINEXEC\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters" /v "MetadataServerPort" /t REG_DWORD /d 6642 /f - -Netsh advfirewall firewall add rule name="Open Port 6642" dir=in action=allow protocol=TCP localport=6642 -Netsh advfirewall firewall add rule name="Open Port 6642" dir=out action=allow protocol=TCP localport=6642 - - - -Restart-service nchostagent diff --git a/src/utils/objects/utils/Get-AllWirelessProfiles.ps1 b/src/utils/objects/utils/Get-AllWirelessProfiles.ps1 deleted file mode 100644 index 2a6c4d4e..00000000 --- a/src/utils/objects/utils/Get-AllWirelessProfiles.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -.Notes - Developed by Steven Holtman and Written in Powershell - Website: https://StevenHoltman.com - Get the latest scripts at https://github.com/stevenholtman - -.Synopsis - Get's the Wireless Networks and Passwords and outputs the information to a log file. - -.DESCRIPTION - Get's the wireless information using the netsh command to get all network info and password in plain text and outputs the data into a log file with just the network name and the wireless passphrase. - -.EXAMPLE - Get-AllWirelessNames -#> -function Get-AllWirelessNames { -# Writting the log file -$LogFile = "$Env:USERPROFILE\Wireless Profiles.log" -$Networks = $(Invoke-Command -ScriptBlock { cmd /c netsh wlan show profiles * | findstr /r /s /i /m /c:"\" }).split(':').Trim("SSID name") -ne "$null" -foreach ($Network in $Networks) { - $NetworkName = (Invoke-Command -ScriptBlock { cmd /c netsh wlan show profile $Network | findstr /r /s /i /m /c:"\" }).split(':')[1].Trim() - $NetworkPassword = (Invoke-Command -ScriptBlock { cmd /c netsh wlan show profile $Network key=clear | findstr /r /s /i /m /c:"\" }).split(':')[1].Trim() - Write-Output "Wireless Network `n SSID: $($Network.Trim('"')) `n Passphrase: $NetworkPassword `n" | Out-File $LogFile -Append -} -Invoke-Item $LogFile -} \ No newline at end of file diff --git a/src/utils/objects/utils/Get-CurrentWirelessProfile.ps1 b/src/utils/objects/utils/Get-CurrentWirelessProfile.ps1 deleted file mode 100644 index 940b0be2..00000000 --- a/src/utils/objects/utils/Get-CurrentWirelessProfile.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -<# -.Notes - Developed by Steven Holtman and Written in Powershell - Website: https://StevenHoltman.com - Get the latest scripts at https://github.com/stevenholtman - -.Synopsis - Get's the Current Wireless Profile and Password and outputs the information to the console. - -.DESCRIPTION - Get's the wireless information using the netsh command to get the currently connected wireless profile info and password in plain text and outputs the data to the console. - -.EXAMPLE - Get-CurrentWirelessProfile -#> -function Get-CurrentWirelessProfile { - try { - $NetworkState = (Invoke-Command -ScriptBlock { cmd /c netsh wlan show interfaces | findstr /r /s /i /m /c:"\" }).split(':')[1].Trim() - if ($NetworkState -eq "connected") { - $NetworkName = (Invoke-Command -ScriptBlock { cmd /c netsh wlan show interfaces | findstr /r /s /i /m /c:"\" }).split(':')[1].Trim() - $NetworkPassword = (Invoke-Command -ScriptBlock { cmd /c netsh wlan show profile "$NetworkName" key=clear | findstr /r /s /i /m /c:"\" }).split(':')[1].Trim() - Write-Output $("Network Name: $NetworkName `n" + "Network Password: $NetworkPassword") - } - } - catch { - Write-Host $($Env:COMPUTERNAME + " does not appear to be connected to wireless.") - } -} \ No newline at end of file diff --git a/src/utils/objects/utils/Get-HashFromFile.ps1 b/src/utils/objects/utils/Get-HashFromFile.ps1 deleted file mode 100644 index 71e23bb0..00000000 --- a/src/utils/objects/utils/Get-HashFromFile.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -<# -.Notes - Developed by Steven Holtman in Powershell - Website: https://StevenHoltman.com - Get the latest scripts at https://github.com/stevenholtman - -.Synopsis - Get's the SHA256 Hash from a file, this is helpful for adding to your AV application or to confirm file hash after download from the developers site. - -.DESCRIPTION - It will prompt for you to enter the Source Directory and Destination Directoy to validate the hashes match in both direcoties for proper data integrity - -.EXAMPLE - Get-FolderComparison -#> -function Get-HashFromFile { - try { - # Adding Form Assembly - Add-Type -AssemblyName System.Windows.Forms - $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ - InitialDirectory = [Environment]::GetFolderPath('Desktop') - Filter = 'Any file type (*.*)|*.*|Executable Files (*.exe)|*.exe|Batch Files (*.bat)|*.bat|Powershell Files (*.ps1)|*.ps1' - Title = 'Select the File you need to retrieve the File Hash for' - } - $DialogforFile = $FileBrowser.ShowDialog() - $GetFileName = Get-FileHash $FileBrowser.FileName - } - catch { - Write-Host $_.Exception.Message - } - finally { - # Defining Variables - $FileName = ($GetFileName.Path).split('\')[-1] - $FileHash = $GetFileName.hash - Write-Output "$FileName's hash: $FileHash" - } -} \ No newline at end of file diff --git a/src/utils/objects/utils/InstallPrivateCloudPlugin.ps1 b/src/utils/objects/utils/InstallPrivateCloudPlugin.ps1 deleted file mode 100644 index 326ee81c..00000000 --- a/src/utils/objects/utils/InstallPrivateCloudPlugin.ps1 +++ /dev/null @@ -1,192 +0,0 @@ -# This script is for testing purposes; The below registration is being added to the manifest. - -param( - [switch]$remove, # remove the plugin - [parameter(Mandatory=$false)] [String]$addr, - [parameter(Mandatory=$false)] [int]$port, - [parameter(Mandatory=$false)] [String]$path, - [parameter(Mandatory=$false)] [String]$format -) - -$agentpath = $path # gets overwritten later, but still keep it user-friendly - -if(!$remove) -{ - function enable-privilege { - param( - ## The privilege to adjust. This set is taken from - ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx - [ValidateSet( - "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", - "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", - "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", - "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", - "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", - "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege", - "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", - "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege", - "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", - "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", - "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")] - $Privilege, - ## The process on which to adjust the privilege. Defaults to the current process. - $ProcessId = $pid, - ## Switch to disable the privilege, rather than enable it. - [Switch] $Disable - ) - - ## Taken from P/Invoke.NET with minor adjustments. - $definition = @' - using System; - using System.Runtime.InteropServices; - - public class AdjPriv - { - [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] - internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, - ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); - - [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] - internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); - [DllImport("advapi32.dll", SetLastError = true)] - internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); - [StructLayout(LayoutKind.Sequential, Pack = 1)] - internal struct TokPriv1Luid - { - public int Count; - public long Luid; - public int Attr; - } - - internal const int SE_PRIVILEGE_ENABLED = 0x00000002; - internal const int SE_PRIVILEGE_DISABLED = 0x00000000; - internal const int TOKEN_QUERY = 0x00000008; - internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; - public static bool EnablePrivilege(long processHandle, string privilege, bool disable) - { - bool retVal; - TokPriv1Luid tp; - IntPtr hproc = new IntPtr(processHandle); - IntPtr htok = IntPtr.Zero; - retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); - tp.Count = 1; - tp.Luid = 0; - if(disable) - { - tp.Attr = SE_PRIVILEGE_DISABLED; - } - else - { - tp.Attr = SE_PRIVILEGE_ENABLED; - } - retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); - retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); - return retVal; - } - } -'@ - - $processHandle = (Get-Process -id $ProcessId).Handle - $type = Add-Type $definition -PassThru - $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable) - } - $RegPath="SYSTEM\CurrentControlSet\Services\hns\Parameters" - enable-privilege SeTakeOwnershipPrivilege - $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($RegPath,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership) - # You must get a blank acl for the key b/c you do not currently have access - $acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None) - $me = [System.Security.Principal.NTAccount]"$env:userdomain\$env:username" - $acl.SetOwner($me) - $key.SetAccessControl($acl) - - # After you have set owner you need to get the acl with the perms so you can modify it. - $acl = $key.GetAccessControl() - $person = [System.Security.Principal.NTAccount]"Administrators" - $access = [System.Security.AccessControl.RegistryRights]"FullControl" - $inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit" - $propagation = [System.Security.AccessControl.PropagationFlags]"None" - $type = [System.Security.AccessControl.AccessControlType]"Allow" - - $rule = New-Object System.Security.AccessControl.RegistryAccessRule( - $person,$access,$inheritance,$propagation,$type - ) - $acl.SetAccessRule($rule) - $key.SetAccessControl($acl) - $key.Close() -} - -$clsid_plugin = "D5AAF7C4-1B3E-4b49-9CF9-9263FAB9DC6D" -$path = "HKLM:\system\CurrentControlSet\services\hns\Parameters" - -$pluginpath = "$path\Plugins\$clsid_plugin" -$node = new-item $pluginpath -force; -$null = new-itemproperty -path $pluginpath -name "Priority" -value 1000; -$null = new-itemproperty -path $pluginpath -name "NetworkRequests" -value 31; -$null = new-itemproperty -path $pluginpath -name "EndpointRequests" -value 31; -$null = new-itemproperty -path $pluginpath -name "ServiceRequests" -value 7; - -# If the user specified a particular set of configuration parameters, install.. -if ($addr -and $port -and $format -and $agentpath) -{ - $VALID_FORMATS = "xml","json" - $format = $format.ToLower(); - $isValidFormat = $false; - - foreach ($fmt in $VALID_FORMATS) - { - if ($format -eq $fmt) - { - $isValidFormat = $true; - break; - } - } - - if (!$isValidFormat) - { - Write-Host -ForegroundColor red -NoNewline "Invalid format! ($format) ... " - Write-Host -ForegroundColor red "Must be one of [ ($VALID_FORMATS -join ', ') ]" - } - else - { - echo "Installing configuration: request=${addr}:${port}/${agentpath}, format=${format}" - $null = New-ItemProperty -Path $pluginpath -name "AgentIPAddress" -value $addr - $null = New-ItemProperty -Path $pluginpath -name "AgentFormat" -value $format - $null = New-ItemProperty -Path $pluginpath -name "AgentPort" -value $port - $null = New-ItemProperty -Path $pluginpath -name "AgentPath" -value $agentpath - } -} - -$data = @( -[psobject]@{ Path="HKLM:Software\Classes\CLSID\{$clsid_plugin}"; - Values = @{ "(default)" = "Private Cloud HNS Plugin"; }; }; -[psobject]@{ Path="HKLM:Software\Classes\CLSID\{$clsid_plugin}\InprocServer32"; - Values = @{"(default)" = "c:\windows\system32\PrivateCloudHNSPlugin.dll"; "ThreadingModel"="Both";}; }; -); - -if($remove) -{ - $keys = @($data.Path); - [array]::Reverse($keys); - foreach($key in $keys) - { - write-host $key - remove-item $key -confirm:$false -erroraction silentlycontinue; - } -} -else -{ - foreach($r in $data) - { - $path = $r.Path; - write-host $path - $node = new-item $path -force; - foreach($name in $r.Values.Keys) - { - $propertyvalue = $r.Values[$name]; - Write-host " $name => $propertyvalue"; - $null = new-itemproperty -path $path -name $name -value $propertyvalue; - } - } -} - -Restart-Service hns diff --git a/src/utils/objects/utils/MultiNodeSampleConfig.psd1 b/src/utils/objects/utils/MultiNodeSampleConfig.psd1 deleted file mode 100644 index 92f8d243..00000000 --- a/src/utils/objects/utils/MultiNodeSampleConfig.psd1 +++ /dev/null @@ -1,130 +0,0 @@ -@{ - ScriptVersion = '3.0' - - #Location from where the VHD will be copied. VHDPath can be a local directory where SDN Express is run or an SMB share. - VHDPath = '\\fileserver\share\Media' - #Name of the VHDX as the golden image to use for VM creation. Use the convert-windowsimage utility to create this from an iso or install.wim. - VHDFile = 'WindowsServer2016Datacenter.vhdx' - - #This is the location on the Hyper-V host where the VM files will be stored, including the VHD. A subdirectory will be created for each VM using the VM name. This location can be a local path on the host, a cluster volume, or an SMB share with appropriate permissions. - VMLocation = 'c:\VMs' - - #Specify the name of the active directory domain where you want the SDN infrastructure VMs to be joined. Domain join takes place offline prior to VM creation. - JoinDomain = 'contoso.com' - - #IMPORTANT: if you deploy multiple network controllers onto the same network segments, you must change the SDNMacPool range to prevent overlap. - SDNMacPoolStart = '02-01-00-00-01-00' - SDNMacPoolEnd = '02-01-00-00-01-FF' - - #ManagmentSubnet, ManagementGateway, and ManagementDNS are not required if DHCP is configured for the management adapters below. - ManagementSubnet = '10.127.132.128/25' - ManagementGateway = '10.127.132.129' - ManagementDNS = @('10.127.130.7', '10.127.130.8') - #Use 0, or comment out ManagementVLANID to configure the management adapter for untagged traffic - ManagementVLANID = 7 - - #Usernames must be in the format Domain\User, Example: Contoso\Greg - #IMPORTANT: DomainJoinUsername is used for admin operations on the Hyper-V host when creating VMs, it is no longer used for domain joining, instead the current user that is running the script requires domain join permission. - DomainJoinUsername = 'Contoso\greg' - LocalAdminDomainUser = 'Contoso\greg' - NCUsername = 'Contoso\greg' - - #RestName must contain the FQDN that will be assigned to the SDN REST floating IP. - RestName = 'sdn.contoso.com' - #When using the Rest IP Address, the RestName must be manually registered to this IP in DNS. This is the preferred way to deploy. - RestIpAddress = '10.127.130.105/31' - - NCs = @( - #Optional parameters for each NC: - # MacAddress - if not specified Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # HostName - if not specified, taken round robin from list of hypervhosts - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - @{ComputerName='Contoso-NC01'; ManagementIP='10.127.132.169'}, - @{ComputerName='Contoso-NC02'; ManagementIP='10.127.132.170'}, - @{ComputerName='Contoso-NC03'; ManagementIP='10.127.132.171'} - ) - Muxes = @( - #Optional parameters for each Mux: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAMacAddress - if not specified PA Adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAIPAddress - if not specified the PA IP Address is taken from the beginning of the HNV PA Pool. The start of the pool is incremented to not include this address. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, PAMacAddress must be outside of the SDN Mac Pool range. PAIPAddress must be outside of the HNV PA IP Pool Start and End range. - @{ComputerName='Contoso-Mux01'; ManagementIP='10.127.132.172'}, - @{ComputerName='Contoso-Mux02'; ManagementIP='10.127.132.173'} - ) - Gateways = @( - #Optional parameters for each Gateway: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # BackEndMac - if not specified Back End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # FrontEndMac - if not specified Front End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, frontendmac, backendmac must be within the SDN Mac Pool range. FrontEndIP must be within the HNV PA IP Pool Start and End range. - @{ComputerName='Contoso-GW01'; ManagementIP='10.127.132.174'}, - @{ComputerName='Contoso-GW02'; ManagementIP='10.127.132.175'} - ) - - # Names of the initial Hyper-V hosts to add to the SDN deployment. If you will be using additional Hyper-V hosts on different HNV PA subnets, you must add those after the initial deployment using the Add-SDNExpressHost function in the SDNExpressModule. - HyperVHosts = @( - 'Host1', - 'Host2', - 'Host3' - ) - - # Intiail HNV PA subnet to add for the network virtualization overlay to use. You can add additional HNV PA subnets after deployment using the Add-SDNExpressVirtualNetworkPASubnet function in the sdnexpressmodule. - PASubnet = '10.10.182.0/25' - PAVLANID = '11' - PAGateway = '10.10.182.1' - PAPoolStart = '10.10.182.6' - PAPoolEnd = '10.10.182.13' - - # Load Balancer and Gateway BGP information - # SDN ASN to be used for load balancing VIPs, public IPs and GRE gateway advertisements. Peering will take place from the HNV PA IP addresses assigned above. It is recommended that your network administrator configure a peer group for the HNV PA subnet. - SDNASN = '64628' - - # Router BGP peering endpoint ASN and IP address that is configured for peering by your network administrator. On some routers it is recommended to peer with the loopback address. - Routers = @( - @{ RouterASN='64623'; RouterIPAddress='10.10.182.1'} - ) - - # Initial set of VIP subnets to use for load balancing and public IPs - PrivateVIPSubnet = '10.10.183.0/29' - PublicVIPSubnet = '10.127.132.0/29' - - # Subnet to use for GRE gateway connection endpoints. This subnet is only used if you configure GRE gateway connections. - GRESubnet = '192.168.0.0/24' - - # Gateway VM network capacity, used by SDN controller for capacity management of gateway connections. - Capacity = 10000000 - - - # Optional fields. Uncomment items if you need to override the defaults. - - # Initial gateway pool name, if not specified will use DefaultAll. Additional pools can be added after the initial deployment using the SDNExpressModule. - # PoolName = 'DefaultAll' - - # Specify ProductKey if you have a product key to use for newly created VMs. If this is not specified you may need - # to connect to the VM console to proceed with eval mode. - # ProductKey = '#####-#####-#####-#####-#####' - - # Switch name is only required if more than one virtual switch exists on the Hyper-V hosts. - # SwitchName='' - - # Amount of Memory and number of Processors to assign to VMs that are created. - # If not specified a default of 8 procs and 8GB RAM are used. - # VMMemory = 4GB - # VMProcessorCount = 4 - - # If Locale and Timezone are not specified the local time zone of the deployment machine is used. - # Locale = '' - # TimeZone = '' - - # Passwords can be optionally included if stored encrypted as text encoded secure strings. Passwords will only be used - # if SDN Express is run on the same machine where they were encrypted, otherwise it will prompt for passwords. - # DomainJoinSecurePassword = '' - # LocalAdminSecurePassword = '' - # NCSecurePassword = '' - -} diff --git a/src/utils/objects/utils/New-PowershellScriptEncoder.ps1 b/src/utils/objects/utils/New-PowershellScriptEncoder.ps1 deleted file mode 100644 index 3eae6e75..00000000 --- a/src/utils/objects/utils/New-PowershellScriptEncoder.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -<# -.Notes - Developed by Steven Holtman and Written in Powershell - Website: https://StevenHoltman.com - Get the latest scripts at https://github.com/stevenholtman - -.Synopsis - Encodes PoweShell script into Base64 and Generates it with the Execution Bypass - -.EXAMPLE - Get-Base64Encoder -#> -function New-PowershellScriptEncoded { - try { - # Adding Form Assembly - Add-Type -AssemblyName System.Windows.Forms - $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ - InitialDirectory = [Environment]::GetFolderPath('Desktop') - Filter = 'Powershell Files (*.ps1)|*.ps1' - Title = 'Select the batch script or powershell script you want to encode' - } - $DialogforFile = $FileBrowser.ShowDialog() - } - catch { - Write-Host $_.Exception.Message - } - finally { - # Defining Variables - $GetScriptName = $FileBrowser.FileName - $ScriptDirectory = Split-Path -Parent $FileBrowser.FileName - $ScriptName = ($GetScriptName).split('\')[-1] - $Base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes([System.IO.File]::ReadAllText("$GetScriptName"))) - Write-Output "powershell.exe -ExecutionPolicy Bypass -EncodedCommand $($($Base64).Trim())" | Out-File "$ScriptDirectory\Encoded-$ScriptName" - Start $ScriptDirectory - } -} \ No newline at end of file diff --git a/src/utils/objects/utils/Powershell_Template.ps1 b/src/utils/objects/utils/Powershell_Template.ps1 deleted file mode 100644 index 6a82750b..00000000 --- a/src/utils/objects/utils/Powershell_Template.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -<# -.Notes - Developed by Steven Holtman in Powershell - Website: https://StevenHoltman.com - Get the latest scripts at https://github.com/stevenholtman - -.Synopsis - Short description - -.DESCRIPTION - Long description - -.EXAMPLE - Example of how to use the PowerShell Script - -#> - -function Get-NameOfScript { - # Script contents within here -} \ No newline at end of file diff --git a/src/utils/objects/utils/SDNExpress.ps1 b/src/utils/objects/utils/SDNExpress.ps1 deleted file mode 100644 index d3d50aad..00000000 --- a/src/utils/objects/utils/SDNExpress.ps1 +++ /dev/null @@ -1,632 +0,0 @@ -# -------------------------------------------------------------- -# Copyright © Microsoft Corporation. All Rights Reserved. -# Microsoft Corporation (or based on where you live, one of its affiliates) licenses this sample code for your internal testing purposes only. -# Microsoft provides the following sample code AS IS without warranty of any kind. The sample code arenot supported under any Microsoft standard support program or services. -# Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. -# The entire risk arising out of the use or performance of the sample code remains with you. -# In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the code be liable for any damages whatsoever -# (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) -# arising out of the use of or inability to use the sample code, even if Microsoft has been advised of the possibility of such damages. -# --------------------------------------------------------------- -<# -.SYNOPSIS - Deploys and configures the Microsoft SDN infrastructure, - including creation of the network controller, Software Load Balancer MUX - and gateway VMs. Then the VMs and Hyper-V hosts are configured to be - used by the Network Controller. When this script completes the SDN - infrastructure is ready to be fully used for workload deployments. -.EXAMPLE - .\SDNExpress.ps1 -ConfigurationDataFile .\MyConfig.psd1 - Reads in the configuration from a PSD1 file that contains a hash table - of settings data. -.EXAMPLE - .\SDNExpress -ConfigurationData $MyConfigurationData - Uses the hash table that is passed in as the configuration data. This - parameter set is useful when programatically generating the - configuration data. -.EXAMPLE - .\SDNExpress - Displays a user interface for interactively defining the configuraiton - data. At the end you have the option to save as a configuration file - before deploying. -.NOTES - Prerequisites: - * All Hyper-V hosts must have Hyper-V enabled and the Virtual Switch - already created. - * All Hyper-V hosts must be joined to Active Directory. - * The physical network must be preconfigured for the necessary subnets and - VLANs as defined in the configuration data. - * The VHD specified in the configuration data must be reachable from the - computer where this script is run. -#> - -[CmdletBinding(DefaultParameterSetName="NoParameters")] -param( - [Parameter(Mandatory=$true,ParameterSetName="ConfigurationFile")] - [String] $ConfigurationDataFile=$null, - [Parameter(Mandatory=$true,ParameterSetName="ConfigurationData")] - [object] $ConfigurationData=$null, - [Switch] $SkipValidation, - [Switch] $SkipDeployment, - [PSCredential] $DomainJoinCredential = $null, - [PSCredential] $NCCredential = $null, - [PSCredential] $LocalAdminCredential = $null - ) - - -# Script version, should be matched with the config files -$ScriptVersion = "3.0" - - -if ((get-wmiobject win32_operatingsystem).caption.Contains("Windows 10")) { - get-windowscapability -name rsat.NetworkController.Tools* -online | Add-WindowsCapability -online -} else { - $feature = get-windowsfeature "RSAT-NetworkController" - if ($null -eq $feature) { - throw "SDN Express requires Windows Server 2016 or later." - } - if (!$feature.Installed) { - add-windowsfeature "RSAT-NetworkController" - } -} - - -import-module .\SDNExpress.psm1 -force - -write-SDNExpressLog "*** Begin SDN Express Deployment ***" -write-SDNExpressLog "ParameterSet: $($psCmdlet.ParameterSetName)" -write-SDNExpressLog " -ConfigurationDataFile: $ConfigurationDataFile" -write-SDNExpressLog " -ConfigurationData: $ConfigurationData" -write-SDNExpressLog " -SkipValidation: $SkipValidation" -write-SDNExpressLog " -SkipDeployment: $SkipValidation" -Write-SDNExpressLog "Version info follows: $($PSVersionTable | out-string)" - -if ($psCmdlet.ParameterSetName -eq "NoParameters") { - write-sdnexpresslog "Begin interactive mode." - - import-module .\SDNExpressUI.psm1 -force - $configData = SDNExpressUI - if ($null -eq $configData) - { - # user cancelled - exit - } - -} elseif ($psCmdlet.ParameterSetName -eq "ConfigurationFile") { - write-sdnexpresslog "Using configuration file passed in by parameter." - $configdata = [hashtable] (Invoke-Expression (Get-Content $ConfigurationDataFile | out-string)) -} elseif ($psCmdlet.ParameterSetName -eq "ConfigurationData") { - write-sdnexpresslog "Using configuration data object passed in by parameter." - $configdata = $configurationData -} - -# if FCNC is enabled, load the modules -if ($configdata.UseFCNC) { - if(-not [string]::IsNullOrEmpty($Global:FCNC_MODULE_PATH_ROOT)) { - ipmo (Join-Path $Global:FCNC_MODULE_PATH_ROOT -ChildPath NetworkControllerFc.psd1) -Force -Scope Global - } else { - import-Module NetworkControllerFc -ErrorAction SilentlyContinue - if ($null -eq (Get-Module NetworkControllerFc)) { - ipmo ..\NetworkControllerFc\NetworkControllerFc.psd1 -Force -Scope Global - } - } - - # rename and copy package - if([string]::IsNullOrEmpty($configdata.FCNCPackage) -eq $false) { - write-sdnexpresslog "looking for FCNC package $($configdata.FCNCPackage)" - # check if the package exists - if (Test-Path $configdata.FCNCPackage) { - write-sdnexpresslog "FCNC package found" - $configdata.FCNCBins = $configdata.FCNCPackage - } else { - write-sdnexpresslog "FCNC package not found" - throw "FCNC package not found" - } - - # copy the nuget to a temp file, rename to zip , decompress it and delete the temp file - write-sdnexpresslog "copying FCNC package to $($configdata.FCNCBins)" - Copy-Item $configdata.FCNCPackage "$($configdata.FCNCPackage).zip" -Verbose - $configdata.FCNCBins = $configdata.FCNCPackage.Replace(".nupkg", ".zip") - - Copy-Item $configdata.FCNCPackage $configdata.FCNCBins -Force - write-sdnexpresslog "unzipping FCNC package" - Expand-Archive -Path $configdata.FCNCBins -DestinationPath $configdata.FCNCBins.Replace(".zip", "") -Force - $configdata.FCNCBins = $configdata.FCNCBins.Replace(".zip", "") - } -} - -if ($Configdata.ScriptVersion -ne $scriptversion) { - write-error "Configuration file version $($ConfigData.ScriptVersion) is not compatible with this version of SDN express. Please update your config file to match the version $scriptversion example." - return -} - -function GetPassword -{ - param( - [String] $SecurePasswordText, - [PSCredential] $Credential, - [String] $Message, - [String] $UserName - ) - if ([String]::IsNullOrEmpty($SecurePasswordText) -and ($null -eq $Credential)) { - write-sdnexpresslog "No credentials found on command line or in config file. Prompting." - $Credential = get-Credential -Message $Message -UserName $UserName - } - - if ($null -ne $Credential) { - write-sdnexpresslog "Using credentials from the command line." - return $Credential.GetNetworkCredential().Password - } - - try { - write-sdnexpresslog "Using credentials from config file." - $securepassword = $SecurePasswordText | convertto-securestring -erroraction Ignore - $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword) - return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) - } catch { - write-sdnexpresslog "Unable to decrpypt credentials in config file. Could be from a different user or generated on different computer. Prompting instead." - $Credential = get-Credential -Message $Message -UserName $UserName - if ($null -eq $credential) { - write-sdnexpresslog "User cancelled credential input. Exiting." - exit - } - return $Credential.GetNetworkCredential().Password - } - -} -function GetNextMacAddress -{ - param( - [String] $MacAddress - ) - - return ("{0:X12}" -f ([convert]::ToInt64($MacAddress.ToUpper().Replace(":", "").Replace("-", ""), 16) + 1)).Insert(2, "-").Insert(5, "-").Insert(8, "-").Insert(11, "-").Insert(14, "-") -} - -try { - $DomainJoinPassword = GetPassword $ConfigData.DomainJoinSecurePassword $DomainJoinCredential "Enter credentials for joining VMs to the AD domain." $configdata.DomainJoinUserName - $NCPassword = GetPassword $ConfigData.NCSecurePassword $NCCredential "Enter credentials for the Network Controller to use." $configdata.NCUserName - $LocalAdminPassword = GetPassword $ConfigData.LocalAdminSecurePassword $LocalAdminCredential "Enter the password for the local administrator of newly created VMs. Username is ignored." "Administrator" - - $NCSecurePassword = $NCPassword | convertto-securestring -AsPlainText -Force - - $credential = New-Object System.Management.Automation.PsCredential($ConfigData.NCUsername, $NCSecurePassword) - - if (![string]::IsNullOrEmpty($ConfigData.ManagementSubnet)) { - $ManagementSubnetBits = $ConfigData.ManagementSubnet.Split("/")[1] - } - - if ([string]::IsNullOrEmpty($ConfigData.PASubnet)) { - if ($ConfigData.Muxes.Count -gt 0) { - throw "Load Balancer Mux configuration requires a PA Subnet." - } - if ($ConfigData.Gateways.Count -gt 0) { - throw "Gateway configuration requires a PA Subnet." - } - } - if (($ConfigData.Muxes.count -gt 0) -or ($ConfigData.Gateways.count -gt 0)) { - $PASubnetBits = $ConfigData.PASubnet.Split("/")[1] - } - - $DomainJoinUserNameDomain = $ConfigData.DomainJoinUserName.Split("\")[0] - $DomainJoinUserNameName = $ConfigData.DomainJoinUserName.Split("\")[1] - $LocalAdminDomainUserDomain = $ConfigData.LocalAdminDomainUser.Split("\")[0] - $LocalAdminDomainUserName = $ConfigData.LocalAdminDomainUser.Split("\")[1] - - if ($null -eq $ConfigData.VMProcessorCount) {$ConfigData.VMProcessorCount = 8} - if ($null -eq $ConfigData.VMMemory) {$ConfigData.VMMemory = 8GB} - if ([string]::IsNullOrEmpty($ConfigData.PoolName)) {$ConfigData.PoolName = "DefaultAll"} - - write-SDNExpressLog "STAGE 1: Create VMs" - - $createparams = @{ - 'ComputerName'=''; - 'VMLocation'=$ConfigData.VMLocation; - 'VMName'=''; - 'VHDSrcPath'=$ConfigData.VHDPath; - 'VHDName'=$ConfigData.VHDFile; - 'VMMemory'=$ConfigData.VMMemory; - 'VMProcessorCount'=$ConfigData.VMProcessorCount; - 'Nics'=@(); - 'CredentialDomain'=$DomainJoinUserNameDomain; - 'CredentialUserName'=$DomainJoinUserNameName; - 'CredentialPassword'=$DomainJoinPassword; - 'JoinDomain'=$ConfigData.JoinDomain; - 'LocalAdminPassword'=$LocalAdminPassword; - 'DomainAdminDomain'=$LocalAdminDomainUserDomain; - 'DomainAdminUserName'=$LocalAdminDomainUserName; - 'SwitchName'=$ConfigData.SwitchName - } - - if (![String]::IsNullOrEmpty($ConfigData.ProductKey)) { - $createparams.ProductKey = $ConfigData.ProductKey - } - if (![String]::IsNullOrEmpty($ConfigData.Locale)) { - $createparams.Locale = $ConfigData.Locale - } - if (![String]::IsNullOrEmpty($ConfigData.TimeZone)) { - $createparams.TimeZone = $ConfigData.TimeZone - } - - write-SDNExpressLog "STAGE 1.0.1: Enable VFP" - foreach ($h in $ConfigData.hypervhosts) { - - write-SDNExpressLog "Adding net virt feature to $($h)" - invoke-command -ComputerName $h -credential $credential { - add-windowsfeature NetworkVirtualization -IncludeAllSubFeature -IncludeManagementTools - } - - write-SDNExpressLog "Enabling VFP on $($h) $($ConfigData.SwitchName)" - invoke-command -ComputerName $h -credential $credential { - param( - [String] $VirtualSwitchName - ) - Enable-VmSwitchExtension -VMSwitchName $VirtualSwitchName -Name "Microsoft Azure VFP Switch Extension" - } -ArgumentList $ConfigData.SwitchName - - invoke-command -ComputerName $h -credential $credential { - Set-Service -Name NCHostAgent -StartupType Automatic; Start-Service -Name NCHostAgent - } - } - - $HostNameIter = 0 - - $useCertBySubject = $false - - if ($ConfigData.UseCertBySubject) { - $useCertBySubject = $true - } - - if (-not $ConfigData.UseFCNC) { - foreach ($NC in $ConfigData.NCs) { - if ([string]::IsNullOrEmpty($nc.macaddress)) { - $nc.macaddress = $ConfigData.SDNMacPoolStart - $configdata.SDNMacPoolStart = GetNextMacAddress($ConfigData.SDNMacPoolStart) - } - - if ([string]::IsNullOrEmpty($nc.HostName)) { - $nc.HostName = $ConfigData.HyperVHosts[$HostNameIter] - $HostNameIter = ($HostNameIter + 1) % $ConfigData.HyperVHosts.Count - } - } - } - - - foreach ($Mux in $ConfigData.Muxes) { - if ([string]::IsNullOrEmpty($Mux.HostName)) { - $Mux.HostName = $ConfigData.HyperVHosts[$HostNameIter] - $HostNameIter = ($HostNameIter + 1) % $ConfigData.HyperVHosts.Count - } - if ([string]::IsNullOrEmpty($Mux.PAIPAddress)) { - $Mux.PAIPAddress = $ConfigData.PAPoolStart - $ConfigData.PAPoolStart = Get-IPAddressInSubnet -Subnet $ConfigData.PAPoolStart -Offset 1 - } - } - #Allocate GW management MACs from outside of SDN pool - foreach ($gateway in $ConfigData.Gateways) { - if ([string]::IsNullOrEmpty($Gateway.macaddress)) { - $gateway.macaddress = $ConfigData.SDNMacPoolStart - $configdata.SDNMacPoolStart = GetNextMacAddress($ConfigData.SDNMacPoolStart) - } - if ([string]::IsNullOrEmpty($Gateway.HostName)) { - $Gateway.HostName = $ConfigData.HyperVHosts[$HostNameIter] - $HostNameIter = ($HostNameIter + 1) % $ConfigData.HyperVHosts.Count - } - } - #Allocate GW FE & BE macs, FE IP from within SDN mac and PA pools - $nextmac = $configdata.SDNMacPoolStart - $PAOffset = 0 - foreach ($gateway in $ConfigData.Gateways) { - if ([string]::IsNullOrEmpty($Gateway.FrontEndMac)) { - $gateway.FrontEndMac = $nextmac - $nextmac = GetNextMacAddress($nextmac) - } - if ([string]::IsNullOrEmpty($Gateway.BackEndMac)) { - $gateway.BackEndMac = $nextmac - $nextmac = GetNextMacAddress($nextmac) - } - if ([string]::IsNullOrEmpty($Gateway.FrontEndIP)) { - $Gateway.FrontEndIP = Get-IPAddressInSubnet -Subnet $ConfigData.PAPoolStart -Offset $PAOffset - $PAOffset += 1 - } - } - - - if (-not $ConfigData.UseFCNC) { - write-SDNExpressLog "STAGE 1.1: Create NC VMs" - foreach ($NC in $ConfigData.NCs) { - $createparams.ComputerName=$NC.HostName; - $createparams.VMName=$NC.ComputerName; - if ([string]::IsNullOrEmpty($NC.ManagementIP)) { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$NC.MacAddress; VLANID=$ConfigData.ManagementVLANID; SwitchName=$NC.ManagementSwitch} - ) - } else { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$NC.MacAddress; IPAddress="$($NC.ManagementIP)/$ManagementSubnetBits"; Gateway=$ConfigData.ManagementGateway; DNS=$ConfigData.ManagementDNS; VLANID=$ConfigData.ManagementVLANID; SwitchName=$NC.ManagementSwitch} - ) - } - $createparams.Roles=@("NetworkController","NetworkControllerTools") - New-SDNExpressVM @createparams - } - } - - - write-SDNExpressLog "STAGE 1.2: Create Mux VMs" - - foreach ($Mux in $ConfigData.Muxes) { - $createparams.ComputerName=$mux.HostName; - $createparams.VMName=$mux.ComputerName; - if ([string]::IsNullOrEmpty($Mux.ManagementIP)) { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$Mux.MacAddress; VLANID=$ConfigData.ManagementVLANID; SwitchName=$Mux.ManagementSwitch}, - @{Name="HNVPA"; MacAddress=$Mux.PAMacAddress; IPAddress="$($Mux.PAIPAddress)/$PASubnetBits"; VLANID=$ConfigData.PAVLANID; IsMuxPA=$true} - ) - } else { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$Mux.MacAddress; IPAddress="$($Mux.ManagementIP)/$ManagementSubnetBits"; Gateway=$ConfigData.ManagementGateway; DNS=$ConfigData.ManagementDNS; VLANID=$ConfigData.ManagementVLANID; SwitchName=$Mux.ManagementSwitch}, - @{Name="HNVPA"; MacAddress=$Mux.PAMacAddress; IPAddress="$($Mux.PAIPAddress)/$PASubnetBits"; VLANID=$ConfigData.PAVLANID; IsMuxPA=$true} - ) - } - $createparams.Roles=@("SoftwareLoadBalancer") - - New-SDNExpressVM @createparams - } - - - if ($ConfigData.NCs.count -gt 0 -or $ConfigData.UseFCNC) { - write-SDNExpressLog "STAGE 2: Network Controller Configuration" - $NCNodes = @() - - - if ($ConfigData.UseFCNC) { - - if ([string]::IsNullOrEmpty($ConfigData.FCNCBins)) - { - $ConfigData.FCNCBins = "C:\Windows\NetworkController" - } - - $NCNodes = $ConfigData.HyperVHosts - - $params = @{ - 'Credential'=$Credential - 'RestName'=$ConfigData.RestName - 'RestIpAddress'=$ConfigData.RestIpAddress - 'ComputerNames'=$NCNodes - 'FCNCBins' = $ConfigData.FCNCBins - 'FCNCDBs' = $ConfigData.FCNCDBs - 'ClusterNetworkName' = $ConfigData.ClusterNetworkName - 'UseCertBySubject' = $useCertBySubject - } - - New-FCNCNetworkController @params - - } else { - foreach ($NC in $ConfigData.NCs) { - $NCNodes += $NC.ComputerName - } - - WaitforComputerToBeReady -ComputerName $NCNodes -Credential $Credential - - $params = @{ - 'Credential'=$Credential - 'RestName'=$ConfigData.RestName - 'RestIpAddress'=$ConfigData.RestIpAddress - 'ComputerNames'=$NCNodes - 'UseCertBySubject' = $useCertBySubject - } - - if (![string]::IsNullOrEmpty($ConfigData.ManagementSecurityGroup)) { - $params.ManagementSecurityGroupName = $ConfigData.ManagementSecurityGroup - $params.ClientSecurityGroupName = $ConfigData.ClientSecurityGroup - } - New-SDNExpressNetworkController @params - } - - - write-SDNExpressLog "STAGE 2.1: Getting REST cert thumbprint in order to find it in local root store." - - # Check through nodes until we find a node that was originally set up with - $NCHostCertThumb = $null - $nodeIdx = 0 - while ($null -eq $NCHostCertThumb -and $nodeIdx -lt $NCNodes.length) { - $NCHostCertThumb = invoke-command -ComputerName $NCNodes[$nodeIdx] -Credential $credential { - param( - $RESTName, - [String] $funcDefGetSdnCert - ) - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - return $cert.Thumbprint - } -ArgumentList $ConfigData.RestName, $Global:fdGetSdnCert - - $nodeIdx++ - } - - $NCHostCert = get-childitem "cert:\localmachine\root\$NCHostCertThumb" - - $params = @{ - 'RestName' = $ConfigData.RestName; - 'MacAddressPoolStart' = $ConfigData.SDNMacPoolStart; - 'MacAddressPoolEnd' = $ConfigData.SDNMacPoolEnd; - 'NCHostCert' = $NCHostCert - 'NCUsername' = $ConfigData.NCUsername; - 'NCPassword' = $NCPassword - 'UseCertBySubject' = $useCertBySubject - } - New-SDNExpressVirtualNetworkManagerConfiguration @Params -Credential $Credential - - if (![string]::IsNullOrEmpty($ConfigData.PASubnet)) { - $params = @{ - 'RestName' = $ConfigData.RestName; - 'AddressPrefix' = $ConfigData.PASubnet; - 'VLANID' = $ConfigData.PAVLANID; - 'DefaultGateways' = $ConfigData.PAGateway; - 'IPPoolStart' = $ConfigData.PAPoolStart; - 'IPPoolEnd' = $ConfigData.PAPoolEnd - } - Add-SDNExpressVirtualNetworkPASubnet @params -Credential $Credential - } else { - write-SDNExpressLog "PA subnets not specified in configuration, skipping Virtual Network PA configuration." - } - } - else - { - $NCHostCert = GetSdnCert -subjectName $configdata.RestName -store "cert:\localmachine\root" - - if ($null -eq $NCHostCert) { - $ErrorText = "Network Controller cert with CN=$($configdata.RestName) not found on $(hostname) in cert:\localmachine\root" - write-SDNExpressLog $ErrorText - throw $ErrorText - } - } - - $useFcNc = $false - if ($ConfigData.UseFCNC) - { - $useFcNc = $true - } - - if ($ConfigData.Muxes.Count -gt 0) { - write-SDNExpressLog "STAGE 3: SLB Configuration" - - if (![string]::IsNullOrEmpty($ConfigData.PrivateVIPSubnet)) { - $params = @{ - 'RestName' = $ConfigData.RestName; - 'PrivateVIPPrefix' = $ConfigData.PrivateVIPSubnet; - 'PublicVIPPrefix' = $ConfigData.PublicVIPSubnet - } - - New-SDNExpressLoadBalancerManagerConfiguration @Params -Credential $Credential - } else { - write-SDNExpressLog "VIP subnets not specified in configuration, skipping load balancer manager configuration." - } - - WaitforComputerToBeReady -ComputerName $ConfigData.Muxes.ComputerName -Credential $Credential - - foreach ($Mux in $ConfigData.muxes) { - Add-SDNExpressMux -ComputerName $Mux.ComputerName -PAMacAddress $Mux.PAMacAddress -PAGateway $ConfigData.PAGateway -LocalPeerIP $Mux.PAIPAddress -MuxASN $ConfigData.SDNASN -Routers $ConfigData.Routers -RestName $ConfigData.RestName -NCHostCert $NCHostCert -Credential $Credential -IsFC $useFcNc - } - } - - - write-SDNExpressLog "STAGE 4: Host Configuration" - $params = @{} - - if (![string]::IsNullOREmpty($ConfigData.PASubnet)) { - $params.HostPASubnetPrefix = $ConfigData.PASubnet; - } - - foreach ($h in $ConfigData.hypervhosts) { - if($ConfigData.Port -ne $null -and $ConfigData.Port -ne 0) { - write-SDNExpressLog "Using port $($ConfigData.Port) for host $h" - $params.Port = $ConfigData.Port - } - - Add-SDNExpressHost @params -ComputerName $h ` - -RestName $ConfigData.RestName ` - -NCHostCert $NCHostCert ` - -Credential $Credential ` - -VirtualSwitchName $ConfigData.SwitchName ` - -IsFC $useFcNc - } - - if ($ConfigData.Gateways.Count -gt 0) { - write-SDNExpressLog "STAGE 5.1: Create Gateway VMs" - - foreach ($Gateway in $ConfigData.Gateways) { - $params = @{ - 'RestName'=$ConfigData.RestName - 'ComputerName'=$gateway.computername - 'HostName'=$gateway.Hostname - 'JoinDomain'=$ConfigData.JoinDomain - 'FrontEndLogicalNetworkName'='HNVPA' - 'FrontEndAddressPrefix'=$ConfigData.PASubnet - } - - $Result = Initialize-SDNExpressGateway @params -Credential $Credential - - $Gateway.FrontEndMac = $Result.FrontEndMac - $Gateway.FrontEndIP = $Result.FrontEndIP - $Gateway.BackEndMac = $Result.BackEndMac - - $createparams.ComputerName=$Gateway.HostName; - $createparams.VMName=$Gateway.ComputerName; - if ([string]::IsNullOrEmpty($Gateway.ManagementIP)) { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$Gateway.MacAddress; VLANID=$ConfigData.ManagementVLANID; SwitchName=$Mux.ManagementSwitch} - @{Name="FrontEnd"; MacAddress=$Gateway.FrontEndMac; IPAddress="$($Gateway.FrontEndIp)/$PASubnetBits"; VLANID=$ConfigData.PAVLANID}, - @{Name="BackEnd"; MacAddress=$Gateway.BackEndMac; VLANID=$ConfigData.PAVLANID} - ); - } else { - $createparams.Nics=@( - @{Name="Management"; MacAddress=$Gateway.MacAddress; IPAddress="$($Gateway.ManagementIP)/$ManagementSubnetBits"; Gateway=$ConfigData.ManagementGateway; DNS=$ConfigData.ManagementDNS; VLANID=$ConfigData.ManagementVLANID; SwitchName=$Mux.ManagementSwitch} - @{Name="FrontEnd"; MacAddress=$Gateway.FrontEndMac; IPAddress="$($Gateway.FrontEndIp)/$PASubnetBits"; VLANID=$ConfigData.PAVLANID}, - @{Name="BackEnd"; MacAddress=$Gateway.BackEndMac; VLANID=$ConfigData.PAVLANID} - ); - } - $createparams.Roles=@("RemoteAccess", "RemoteAccessServer", "RemoteAccessMgmtTools", "RemoteAccessPowerShell", "RasRoutingProtocols", "Web-Application-Proxy") - - New-SDNExpressVM @createparams - } - - write-SDNExpressLog "STAGE 5.3: Configure Gateways" - - if ([String]::IsNullOrEmpty($ConfigData.RedundantCount)) { - $ConfigData.RedundantCount = 1 - } - - if ([string]::IsNullOrEmpty($configdata.GatewayPoolType) -or ($configdata.GatewayPoolType -eq "All")) { - write-SDNExpressLog "Gateway pool type is All." - New-SDNExpressGatewayPool -IsTypeAll -PoolName $ConfigData.PoolName -Capacity $ConfigData.Capacity -GreSubnetAddressPrefix $ConfigData.GreSubnet -RestName $ConfigData.RestName -Credential $Credential -RedundantCount $ConfigData.RedundantCount - } elseif ($configdata.GatewayPoolType -eq "GRE") { - write-SDNExpressLog "Gateway pool type is GRE." - New-SDNExpressGatewayPool -IsTypeGRE -PoolName $ConfigData.PoolName -Capacity $ConfigData.Capacity -GreSubnetAddressPrefix $ConfigData.GreSubnet -RestName $ConfigData.RestName -Credential $Credential -RedundantCount $ConfigData.RedundantCount - } elseif ($configdata.GatewayPoolType -eq "Forwarding") { - write-SDNExpressLog "Gateway pool type is Forwarding." - New-SDNExpressGatewayPool -IsTypeForwarding -PoolName $ConfigData.PoolName -Capacity $ConfigData.Capacity -RestName $ConfigData.RestName -Credential $Credential -RedundantCount $ConfigData.RedundantCount - } elseif ($configdata.GatewayPoolType -eq "IPSec") { - write-SDNExpressLog "Gateway pool type is IPSec." - New-SDNExpressGatewayPool -IsTypeIPSec -PoolName $ConfigData.PoolName -Capacity $ConfigData.Capacity -RestName $ConfigData.RestName -Credential $Credential -RedundantCount $ConfigData.RedundantCount - } else { - write-SDNExpressLog "Gateway pool type is Invalid." - throw "Invalid GatewayPoolType specified in config file." - } - - WaitforComputerToBeReady -ComputerName $ConfigData.Gateways.ComputerName -Credential $Credential - - foreach ($G in $ConfigData.Gateways) { - $params = @{ - 'RestName'=$ConfigData.RestName - 'ComputerName'=$g.computername - 'HostName'=$g.Hostname - 'NCHostCert'= $NCHostCert - 'PoolName'=$ConfigData.PoolName - 'FrontEndIp'=$G.FrontEndIP - 'FrontEndLogicalNetworkName'='HNVPA' - 'FrontEndAddressPrefix'=$ConfigData.PASubnet - 'FrontEndMac'=$G.FrontEndMac - 'BackEndMac'=$G.BackEndMac - 'Routers'=$ConfigData.Routers - 'PAGateway'=$ConfigData.PAGateway - 'ManagementRoutes'=$ConfigData.ManagementRoutes - 'LocalASN'=$ConfigData.SDNASN - } - - if ($ConfigData.UseGatewayFastPath -eq $true) { - New-SDNExpressGateway @params -Credential $Credential -UseFastPath -IsFC $useFcNc - } else { - New-SDNExpressGateway @params -Credential $Credential -IsFC $useFcNc - } - } - - } - - test-sdnexpresshealth -restname $ConfigData.RestName -Credential $Credential -} -catch -{ - $pscmdlet.throwterminatingerror($PSItem) -} - -write-SDNExpressLog "SDN Express deployment complete." diff --git a/src/utils/objects/utils/SDNExpress.psm1 b/src/utils/objects/utils/SDNExpress.psm1 deleted file mode 100644 index dcd131f7..00000000 --- a/src/utils/objects/utils/SDNExpress.psm1 +++ /dev/null @@ -1,4331 +0,0 @@ -# -------------------------------------------------------------- -# Copyright © Microsoft Corporation. All Rights Reserved. -# Microsoft Corporation (or based on where you live, one of its affiliates) licenses this sample code for your internal testing purposes only. -# Microsoft provides the following sample code AS IS without warranty of any kind. The sample code arenot supported under any Microsoft standard support program or services. -# Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. -# The entire risk arising out of the use or performance of the sample code remains with you. -# In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the code be liable for any damages whatsoever -# (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) -# arising out of the use of or inability to use the sample code, even if Microsoft has been advised of the possibility of such damages. -# --------------------------------------------------------------- - -# todo : does it matter to have this enabled ? -#set-strictmode -version 5.0 - -$VerbosePreference = 'Continue' - -$Errors = [ordered] @{ - WINDOWSEDITION = @{Code = 4; Message="Software Defined Networking (SDN) requires an OS containing Windows Server 2016 Datacenter, Windows Server 2019 Datacenter, or Azure Stack HCI."}; - INVALIDKEYUSAGE = @{Code = 11; Message="Certificate in store has invalid key usage."}; - CERTTHUMBPRINT = @{Code = 8; Message="Inconsistent thumbprint for certs with same subject name."}; - NOADAPTERS = @{Code = 6; Message="Network Controller node requires at least one network adapter."}; - INVALIDVSWITCH = @{Code = 9; Message="Invalid virtual switch configuration on host."}; - GENERALEXCEPTION = @{Code = 3; Message="A general exception has occurred. Check ErrorMessage for details."} - COMPUTEREXISTS = @{Code = 1; Message="Unable to register the computer name in Active Directory. This is usually caused by a permission error due to the name already existing, lack of privilege, or inability to delegate credentials."} -} - -#The timestamp for the log is set at the time the module is imported. Re-import the module to reset the log name. -$Logname = "SDNExpress-$(get-date -Format 'yyyyMMdd-HHmmss').log" - -<# - Checks is a certificate in file format is self signed -#> -function IsSelfSignedCert( - [parameter(Mandatory=$true)] [string] $filePath, - [parameter(Mandatory=$false)] [System.Security.SecureString] $secPwd - ) -{ - $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - - if ($secPwd -ne $null) - { - $cert.Import($filePath, $secPwd, 0) - } - else - { - $cert.Import($filePath) - } - - return $cert.Issuer -eq $cert.Subject -} - -<# -.DESCRIPTION -Selects the best certificate for SDN when searching using subject name - -Certs with NC OID have precedence -#> -function GetSdnCert( - [parameter(Mandatory=$true)] [string] $subjectName, - [parameter(Mandatory=$false)][string] $store = "cert:\localmachine\my" - ) -{ - $certs = get-childitem $store ` - | where-object {$_.Subject.ToUpper() -eq "CN=$($subjectName)" } ` - | where-object {$_.NotAfter -ge (get-date) } ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.1"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.2"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.4.1.311.95.1.1.1"}} ` - | Sort-Object -Property NotAfter -Descending - - if ($certs -ne $null) { - return $certs[0] - } - - $certs = get-childitem $store ` - | where-object {$_.Subject.ToUpper() -eq "CN=$($subjectName)" } ` - | where-object {$_.NotAfter -ge (get-date) } ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.1"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.2"}} ` - | Sort-Object -Property NotAfter -Descending - - if ($certs -ne $null) { - return $certs[0] - } - - return $null -} - -$Global:fdGetSdnCert = "function GetSdnCert { ${function:GetSdnCert} }" - -# Get all nodes that are up and included as servers in a given failover cluster and SDN deployment. -function Get-NodesInSDNCluster( - [parameter(Mandatory=$true)] [string] $ComputerName, - [parameter(Mandatory=$true)] [string] $uri, - [parameter(Mandatory=$true)] [object] $CredentialParam - ) -{ - try { - $nodes = Invoke-Command $ComputerName @CredentialParam { get-clusternode | Where-Object { $_.State -eq "Up" } | Select-Object -ExpandProperty Name } - $sdnNodes = (Get-NetworkControllerServer -ConnectionUri $uri).properties.connections.managementaddresses - $domainName = Invoke-Command $ComputerName @CredentialParam { (get-ciminstance win32_computersystem).Domain } - $nodesInSdnCluster = $nodes | Where-Object { ("$($_).$($domainName)" -in $sdnNodes) -or ($_ -in $sdnNodes)} - - return $nodesInSdnCluster - } - catch { - # In case FC is not used with SF based deployment, skip and return an empty list - return @() - } -} - -function Get-RestCertificate( - [parameter(Mandatory=$true)] [string[]] $ComputerNames, - [parameter(Mandatory=$true)] [string] $RestName, - [parameter(Mandatory=$true)] [string] $certPwdString, - [parameter(Mandatory=$true)] [object] $CredentialParam -) -{ - [byte[]] $RestCertPfxData = @() - $nodeIdx = 0 - while ($RestCertPfxData.length -eq 0 -and $nodeIdx -lt $ComputerNames.length) { - $RestCertPfxData = invoke-command -computername $ComputerNames[$nodeIdx] @CredentialParam { - param( - [String] $RestName, - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - - if ($null -ne $Cert) { - write-verbose "Existing certificate meets criteria. Exporting." - } - - if ($null -ne $Cert) { - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - [System.io.file]::WriteAllBytes($TempFile.FullName, $cert.Export("PFX", $certpwdstring)) | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - write-verbose "Returning Cert Data found on $(hostname)" - write-output $CertData - } else { - write-verbose "No certificate found on $(hostname)" - write-output @() - } - } -ArgumentList $RestName, $certpwdstring, $Global:fdGetSdnCert | Parse-RemoteOutput - $nodeIdx += 1 - } - - $RestCertPfxData -} - - # # ##### - ## # ###### ##### # # #### ##### # # # # #### # # ##### ##### #### # # ###### ##### - # # # # # # # # # # # # # # # # ## # # # # # # # # # # # - # # # ##### # # # # # # # #### # # # # # # # # # # # # # ##### # # - # # # # # # ## # # # ##### # # # # # # # # # ##### # # # # # ##### - # ## # # ## ## # # # # # # # # # # # ## # # # # # # # # # # - # # ###### # # # #### # # # # ##### #### # # # # # #### ###### ###### ###### # # - -<# -.SYNOPSIS -Brings up a Network Controller cluster on a set of computers. - -.DESCRIPTION -New-SDNExpressNetworkController takes in a set of computers and configures them as a Network Controller cluster. Computers must be pre-provisioned with network connectivity, Windows Server 2016 Datacenter Edition (or newer) and joined to active directory. New-SDNExpressVM is typically used for create or other compatible method. When complete the Network Controller cluster then needs to be further confgiured for use. - -.PARAMETER ComputerNames -Computers to be configured into the cluster of network controllers. This is an array of computer names, with 1, 3 or 5 members. - -.PARAMETER RESTName -The fully qualified domain name (FQDN) to be used as the Rest endpoint for the newly created cluster. The network controller cluster will automatically register and update this name in DNS pointing to the node which contains the API server for the cluster. - -.PARAMETER RESTIPAddress -Specifies the IP address and subnet bits to follows the active API server node. Must be on the same subnet as the network controller nodes and in the format /. When using RESTIPAddress the RESTName must be manually registered to this IP in DNS. - -.PARAMETER ManagementSecurityGroupName -Management security group for the network controller cluster. When specified the cluster is configured for Kerberos authentication. - -.PARAMETER ClientSecurityGroupName -Client security group for the network controller. When specified the Network Controller is configured for Kerberos authentication. - -.PARAMETER Credential -Credential to use for remoting into the Network Controller computers. - -.PARAMETER Force -Forces the cluster to be recreated even if one already exists. Use with caution. - -.PARAMETER OperationID -Externally supplied Id relayed into progress and error messages. - -.EXAMPLE -New-SDNExpressNetworkController -ComputerNames "Computer1","Computer2","Computer3" -RestName "sdn.contoso.com" -Credential (get-credential) - -This example configures three computers into a network controller cluster and registers the rest interface with sdn.contoso.com. -.EXAMPLE -New-SDNExpressNetworkController -ComputerNames "Computer1","Computer2","Computer3" -RestIPAddress "10.10.10.10/24" -Credential (get-credential) - -This example configures three computers into a network controller cluster and adds the RestIPAddress to the API server. -.EXAMPLE -New-SDNExpressNetworkController -ComputerNames "Computer1","Computer2","Computer3" -RestName "sdn.contoso.com" -ManagementSecurityGroup "NCManagement" -ClientSecurityGroup "NCClients" -Credential (get-credential) - -.NOTES -General notes -#> - function New-SDNExpressNetworkController -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String[]] $ComputerNames, - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String] $RESTName, - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [String] $ManagementSecurityGroupName, - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [String] $ClientSecurityGroupName, - [Parameter(Mandatory=$false,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [ValidateScript({ - if ([string]::isnullorempty($_)) { return $true } - $split = $_.split('/') - if ($split.count -ne 2) { throw "RESTIPAddress parameter must match the syntax /."} - if (!($split[0] -as [ipaddress] -as [bool])) { throw "Invalid IP address specified in RESTIPAddress parameter."} - if (($split[1] -le 0) -or ($split[1] -gt 32)) { throw "Invalid subnet bits specified in RESTIPAddress parameter."} - return $true - })] - [String] $RESTIPAddress = "", - [Parameter(Mandatory=$false,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [PSCredential] $Credential = $null, - [Parameter(Mandatory=$false)] - [Switch] $Force, - [Parameter(Mandatory=$false,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [String] $OperationID = "", - [Parameter(Mandatory=$false)] - [bool] $UseCertBySubject = $false - - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - $certpwdstring = -join ((48..122) | Get-Random -Count 30 | % {[char]$_}) - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $feature = get-windowsfeature "RSAT-NetworkController" - if ($null -eq $feature) { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['WINDOWSEDITION'].Code -LogMessage $Errors['WINDOWSEDITION'].Message #No errormessage because SDN Express generates error - throw $Errors['WINDOWSEDITION'].Message - } - if (!$feature.Installed) { - add-windowsfeature "RSAT-NetworkController" | out-null - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 10 -context $restname - - $RESTName = $RESTName.ToUpper() - - write-sdnexpresslog ("Checking if Controller already deployed by looking for REST response.") - try { - get-networkcontrollerCredential -ConnectionURI "https://$RestName" @CredentialParam | out-null - if (!$force) { - write-sdnexpresslog "Network Controller at $RESTNAME already exists, exiting New-SDNExpressNetworkController." - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - return - } - } - catch { - write-sdnexpresslog "Network Controller does not exist, will continue." - } - - write-sdnexpresslog "Setting properties and adding NetworkController role on all computers in parallel." - invoke-command -ComputerName $ComputerNames { - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Setting registry keys and wsman parameters" - reg add hklm\system\currentcontrolset\services\tcpip6\parameters /v DisabledComponents /t REG_DWORD /d 255 /f | out-null - Set-Item WSMan:\localhost\Shell\MaxConcurrentUsers -Value 100 | out-null - Set-Item WSMan:\localhost\MaxEnvelopeSizekb -Value 7000 | out-null - - write-verbose "Adding NetworkController feature if not already installed offline." - add-windowsfeature NetworkController -IncludeAllSubFeature -IncludeManagementTools -Restart | out-null - } @CredentialParam | Parse-RemoteOutput - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 20 -context $restname - write-sdnexpresslog "Creating local temp directory." - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $TempDir = $TempFile.FullName - New-Item -ItemType Directory -Force -Path $TempDir | out-null - - write-sdnexpresslog "Temp directory is: $($TempFile.FullName)" - write-sdnexpresslog "Creating REST cert on: $($computernames[0])" - - try { - $RestCertPfxData = invoke-command -computername $ComputerNames[0] @CredentialParam { - param( - [String] $RestName, - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - if ($null -eq $Cert) { - write-verbose "Creating new REST certificate." - $Cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$RESTName" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") - } else { - write-verbose "Existing certificate meets criteria. Exporting." - } - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - [System.io.file]::WriteAllBytes($TempFile.FullName, $cert.Export("PFX", $certpwdstring)) | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - write-verbose "Returning Cert Data." - write-output $CertData - } -ArgumentList $RestName, $certpwdstring, $Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['INVALIDKEYUSAGE'].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 30 -context $restname - - write-sdnexpresslog "Temporarily exporting Cert to My store." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $RestCertPfxData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - $RESTCertPFX = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\my" -password $certpwd -exportable - Remove-Item $TempFile.FullName -Force - - $RESTCertThumbprint = $RESTCertPFX.Thumbprint - write-sdnexpresslog "REST cert thumbprint: $RESTCertThumbprint" - write-sdnexpresslog "Exporting REST cert to PFX and CER in temp directory." - - [System.io.file]::WriteAllBytes("$TempDir\$RESTName.pfx", $RestCertPFX.Export("PFX", $certpwdstring)) - Export-Certificate -Type CERT -FilePath "$TempDir\$RESTName" -cert $RestCertPFX | out-null - - # Import only self signed certs in root - if ($RESTCertPFX.Issuer -eq $RESTCertPFX.Subject) - { - write-sdnexpresslog "Importing REST cert (public key only) into Root store." - $RestCert = import-certificate -filepath "$TempDir\$RESTName" -certstorelocation "cert:\localmachine\root" - } - else - { - $RestCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $RestCert.Import("$TempDir\$RESTName") - } - - write-sdnexpresslog "Deleting REST cert from My store." - remove-item -path cert:\localmachine\my\$RESTCertThumbprint - - write-sdnexpresslog "Installing REST cert to my and root store of each NC node." - - foreach ($ncnode in $ComputerNames) { - write-sdnexpresslog "Installing REST cert to my and root store of: $ncnode" - try { - invoke-command -computername $ncnode @CredentialParam { - param( - [String] $RESTName, - [byte[]] $RESTCertPFXData, - [String] $RESTCertThumbprint, - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $RESTCertPFXData | set-content $TempFile.FullName -Encoding Byte - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - - write-verbose "Found $($cert.count) certificate(s) in my store with subject name matching $RestName" - if ($Cert -eq $null) { - write-verbose "Importing new REST cert into My store." - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\my" -password $certpwd -Exportable - } else { - if ($cert.Thumbprint -ne $RestCertThumbprint) { - Remove-Item $TempFile.FullName -Force - throw "REST cert already exists in My store on $(hostname), but thumbprint does not match cert on other nodes." - } - } - - write-verbose "Setting permissions on REST cert." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) - Set-Acl $privKeyCertFile.FullName $privKeyAcl - - $Cert = get-childitem "Cert:\localmachine\root\$RestCertThumbprint" -erroraction Ignore - if ($cert -eq $Null) { - $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $cert.Import($TempFile.FullName, $certpwd, 0) - if ($cert.Issuer -eq $cert.Subject) { - write-verbose "REST cert does not yet exist in Root store, adding." - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - } - } - - Remove-Item $TempFile.FullName -Force - } -Argumentlist $RESTName, $RESTCertPFXData, $RESTCertThumbprint,$certpwdstring,$Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['CERTTHUMBPRINT'].code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 40 -context $restname - # Create Node cert for each NC - - $AllNodeCerts = @() - - foreach ($ncnode in $ComputerNames) { - write-sdnexpresslog "Creating node cert for: $ncnode" - try - { - [byte[]] $CertData = invoke-command -computername $ncnode @CredentialParam { - param( - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $NodeFQDN.ToUpper() - - write-verbose "Found $($cert.count) certificate(s) in my store with subject name matching $NodeFQDN" - - if ($Cert -eq $null) { - write-verbose "Creating new self signed certificate in My store." - $cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$NodeFQDN" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") -DNSNAME $RESTName - } else { - write-verbose "Using existing certificate with thumbprint $($cert.thumbprint)" - } - - write-verbose "Setting permissions on node cert." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) | out-null - Set-Acl $privKeyCertFile.FullName $privKeyAcl | out-null - - write-verbose "Exporting node cert." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - [System.io.file]::WriteAllBytes($TempFile.FullName, $cert.Export("PFX", $certpwdstring)) | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $CertData - } -ArgumentList $CertPwdString, $Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['INVALIDKEYUSAGE'].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - - $certFromFile = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $certFromFile.Import($TempFile.FullName, $certpwd, 0) - - $AllNodeCerts += $certFromFile - - $isCertDataSelfSigned = $certFromFile.Issuer -eq $certFromFile.Subject - # Import only self signed certs - if ($isCertDataSelfSigned ) - { - import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - } - Remove-Item $TempFile.FullName -Force - - if ($isCertDataSelfSigned) { - foreach ($othernode in $ComputerNames) { - write-sdnexpresslog "Installing node cert for $ncnode into root store of $othernode." - - invoke-command -computername $othernode @CredentialParam { - param( - [String] $CertPwdString, - [Byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - Remove-Item $TempFile.FullName -Force - } -ArgumentList $certPwdString,$CertData | Parse-RemoteOutput - } - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 50 -context $restname - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - $HostCert = GetSdnCert -subjectName $NodeFQDN.ToUpper() - if ($HostCert -ne $null -and $HostCert.Issuer -ne $HostCert.Subject -and $HostCert.Issuer -eq "CN=AzureStackCertificationAuthority" ) { - write-sdnexpresslog "Importing AS CA root cert $($HostCert.Issuer) into NC VMs" - $rootCert = get-childitem "cert:\localmachine\root" | where-object {$_.Subject.ToUpper() -eq "$($HostCert.Issuer)" } | Select-Object -First 1 - - if ($rootCert -ne $null) { - [Byte[]] $CertBytes = $rootCert.GetRawCertData() - - foreach ($node in $ComputerNames) { - write-sdnexpresslog "Installing CA root cert into root store of $node." - - invoke-command -computername $node @CredentialParam { - param( - [Byte[]] $CertData - ) - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - Remove-Item $TempFile.FullName -Force - } -ArgumentList @(, $CertBytes ) | Parse-RemoteOutput - } - } - } - - write-sdnexpresslog "Configuring Network Controller role using node: $($ComputerNames[0])" - - $controller = $null - try { $controller = get-networkcontroller -computername $ComputerNames[0] -erroraction Ignore } catch {} - if ($controller -ne $null) { - if ($force) { - write-SDNExpressLog "Controller role found, force option specified, uninstalling." - uninstall-networkcontroller -ComputerName $ComputerNames[0] -force - uninstall-networkcontrollercluster -ComputerName $ComputerNames[0] -force - } else { - write-SDNExpressLog "Controller role found, force option not specified, exiting." - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - return - } - } - - $Nodes = @() - - foreach ($cert in $AllNodeCerts) { - $NodeFQDN = $cert.subject.substring(3) - $server = $NodeFQDN.Split(".")[0] - write-SDNExpressLog "Configuring Node $NodeFQDN with cert thumbprint $($cert.thumbprint)." - - $nic = @() - $nic += invoke-command -computername $server @CredentialParam { get-netadapter } - if ($nic.count -gt 1) { - write-SDNExpressLog ("WARNING: Invalid number of network adapters found in network Controller node.") - write-SDNExpressLog ("WARNING: Using first adapter returned: $($nic[0].name)") - $nic = $nic[0] - } elseif ($nic.count -eq 0) { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["NOADAPTERS"].code -logmessage $Errors["NOADAPTERS"].Message #No errormessage because SDN Express generates error - write-SDNExpressLog ("ERROR: No network adapters found in network Controller node.") - throw $Errors["NOADAPTERS"].Message - } - - if ($UseCertBySubject) - { - $nodes += New-NetworkControllerNodeObject -Name $server -Server $NodeFQDN -FaultDomain ("fd:/"+$server) -RestInterface $nic.Name -NodeCertificateFindBy FindBySubjectName -CertificateSubjectName $NodeFQDN - } - else - { - $nodes += New-NetworkControllerNodeObject -Name $server -Server $NodeFQDN -FaultDomain ("fd:/"+$server) -RestInterface $nic.Name -NodeCertificate $cert -verbose - } - } - - $params = @{ - 'Node'=$nodes; - 'CredentialEncryptionCertificate'=$RESTCert; - 'Credential'=$Credential; - } - - if ([string]::isnullorempty($ManagementSecurityGroupName)) { - $params.add('ClusterAuthentication', 'X509'); - } else { - $params.add('ClusterAuthentication', 'Kerberos'); - $params.add('ManagementSecurityGroup', $ManagementSecurityGroupName) - } - - write-SDNExpressLog "Install-NetworkControllerCluster with parameters:" - foreach ($i in $params.getenumerator()) { write-SDNExpressLog " $($i.key)=$($i.value)"} - Install-NetworkControllerCluster @Params -Force | out-null - write-SDNExpressLog "Finished Install-NetworkControllerCluster." - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 70 -context $restname - - $params = @{ - 'ComputerName'=$ComputerNames[0] - 'Node'=$nodes; - 'ServerCertificate'=$RESTCert; - 'Credential'=$Credential; - } - - if ([string]::isnullorempty($ClientSecurityGroupName)) { - $params.add('ClientAuthentication', 'None'); - } else { - $params.add('ClientAuthentication', 'Kerberos'); - $params.add('ClientSecurityGroup', $ClientSecurityGroupName) - } - - if (![string]::isnullorempty($RestIpAddress)) { - $params.add('RestIPAddress', $RestIpAddress); - } else { - if ($nodes.Length -eq 1 -and $nodes[0].Server -eq $RESTName) { - write-SDNExpressLog "The RestName paramter is not used because it is a single node cluster and the node name is the same as the REST name $($nodes[0].Server)" - } - else { - $params.add('RestName', $RESTName); - } - } - - write-SDNExpressLog "Install-NetworkController with parameters:" - foreach ($i in $params.getenumerator()) { write-SDNExpressLog " $($i.key)=$($i.value)"} - Install-NetworkController @params -force | out-null - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 90 -context $restname - - write-SDNExpressLog "Install-NetworkController complete." - Write-SDNExpressLog "Network Controller cluster creation complete." - - #Verify that SDN REST endpoint is working before returning - Write-SDNExpressLog "Verifying Network Controller is operational." - - if (!($RESTName -as [IPAddress] -as [bool])) - { - $dnsServers = (Get-DnsClientServerAddress -AddressFamily ipv4).ServerAddresses | select -uniq - $dnsWorking = $true - - foreach ($dns in $dnsServers) - { - $dnsResponse = $null - $count = 0 - - while (($dnsResponse -eq $null) -and ($count -lt 90)) { - $dnsResponse = Resolve-DnsName -name $RESTName -Server $dns -ErrorAction Ignore - if ($dnsResponse -eq $null) { - write-sdnexpresslog "No response from the DNS server. Sleeping for 20 seconds" - sleep 20 - } - $count++ - } - - if ($count -eq 90) { - write-sdnexpresslog "REST name not resolving from $dns after 30 minutes." - $dnsWorking = $false - } else { - write-sdnexpresslog "REST name resolved from $dns after $count tries." - } - } - - if (!$dnsWorking) { - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - return - } - } - - write-sdnexpresslog ("Checking for REST response.") - $NotResponding = $true - while ($NotResponding) { - try { - $NotResponding = $false - clear-dnsclientcache - get-networkcontrollerCredential -ConnectionURI "https://$RestName" @CredentialParam | out-null - } - catch { - write-sdnexpresslog "Network Controller is not responding. Will try again in 10 seconds." - sleep 10 - $NotResponding = $true - } - } - - Write-SDNExpressLog "Sleep 60 to allow controller time to settle down." - Start-Sleep -Seconds 60 - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - write-sdnexpresslog ("Network controller setup is complete and ready to use.") - write-sdnexpresslog "New-SDNExpressNetworkController Exit" -} - -function New-FCNCNetworkController -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String[]] $ComputerNames, # may or may not be all the cluster node names because stretch deployments occur on partial clusters - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String] $RESTName, - # [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - # [String] $ManagementSecurityGroupName, - # [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - # [String] $ClientSecurityGroupName, - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [ValidateScript({ - $split = $_.split('/') - if ($split.count -ne 2) { throw "RESTIPAddress parameter must match the syntax /."} #WARNING!/SUBNET CAUSES ERROR FOR TEMP FILE ie Exception calling "WriteAllBytes" with "2" argument(s): "Could not find a part of the path 'C:\Users\wolfpack\AppData\Local\Temp\tmp6D40.tmp\10.127.131.60\32.pfx'. - if (!($split[0] -as [ipaddress] -as [bool])) { throw "Invalid IP address specified in RESTIPAddress parameter."} - if (($split[1] -le 0) -or ($split[1] -gt 32)) { throw "Invalid subnet bits specified in RESTIPAddress parameter."} - return $true - })] - [String] $RESTIPAddress = "", - [Parameter(Mandatory=$false,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [PSCredential] $Credential = $null, - [Parameter(Mandatory=$false)] - [Switch] $Force, - [Parameter(Mandatory=$false,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [String] $OperationID = "", - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String] $FCNCBins, - [Parameter(Mandatory=$true,ParameterSetName="Kerberos")] - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [String] $FCNCDBs, - [string] $ClusterNetworkName, - [Parameter(Mandatory=$false)] - [bool] $UseCertBySubject = $false - ) - - $RESTName = $RESTName.ToUpper() - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - $certpwdstring = -join ((48..122) | Get-Random -Count 30 | % {[char]$_}) - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $feature = get-windowsfeature "RSAT-NetworkController" - if ($null -eq $feature) { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['WINDOWSEDITION'].Code -LogMessage $Errors['WINDOWSEDITION'].Message #No errormessage because SDN Express generates error - throw $Errors['WINDOWSEDITION'].Message - } - if (!$feature.Installed) { - add-windowsfeature "RSAT-NetworkController" | out-null - } - - $isAlreadyDeployed = $false - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 10 -context $restname - - write-sdnexpresslog ("Checking if Controller already deployed by looking for REST response.") - try { - get-networkcontrollerCredential -ConnectionURI "https://$RestName" @CredentialParam | out-null - if (!$force) { - write-sdnexpresslog "Network Controller at $RESTNAME already exists. Reusing REST cert and continuing" - $isAlreadyDeployed = $true - } - } - catch { - write-sdnexpresslog "Network Controller does not exist, will continue." - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 20 -context $restname - if (-not $isAlreadyDeployed) { - write-sdnexpresslog "Creating local temp directory." - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $TempDir = $TempFile.FullName - New-Item -ItemType Directory -Force -Path $TempDir | out-null - - write-sdnexpresslog "Temp directory is: $($TempFile.FullName)" - write-sdnexpresslog "Creating REST cert on: $($computernames[0])" - Write-SDNExpressLog "ClusterNetworkName:$ClusterNetworkName" - - try { - $RestCertPfxData = invoke-command -computername $ComputerNames[0] @CredentialParam { - param( - [String] $RestName, - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - if ($null -eq $Cert) { - write-verbose "Creating new REST certificate." - $Cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$RESTName" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") - } else { - write-verbose "Existing certificate meets criteria. Exporting." - } - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - [System.io.file]::WriteAllBytes($TempFile.FullName, $cert.Export("PFX", $certpwdstring)) | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - write-verbose "Returning Cert Data." - write-output $CertData - } -ArgumentList $RestName, $certpwdstring, $Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['INVALIDKEYUSAGE'].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - } else { - write-sdnexpresslog "Finding existing REST cert" - Write-SDNExpressLog "ClusterNetworkName:$ClusterNetworkName" - - $RestCertPfxData = Get-RestCertificate -ComputerNames $ComputerNames -RestName $RESTName -certPwdString $certpwdstring -CredentialParam $CredentialParam - } - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 30 -context $restname - - write-sdnexpresslog "Temporarily exporting Cert to My store." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $RestCertPfxData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - $RESTCertPFX = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\my" -password $certpwd -exportable - Remove-Item $TempFile.FullName -Force - - $RESTCertThumbprint = $RESTCertPFX.Thumbprint - write-sdnexpresslog "REST cert thumbprint: $RESTCertThumbprint" - write-sdnexpresslog "Exporting REST cert to PFX and CER in temp directory." - - [System.io.file]::WriteAllBytes("$TempDir\$RESTName.pfx", $RestCertPFX.Export("PFX", $certpwdstring)) - Export-Certificate -Type CERT -FilePath "$TempDir\$RESTName" -cert $RestCertPFX | out-null - - if ($RESTCertPFX.Issuer -eq $RESTCertPFX.Subject) - { - write-sdnexpresslog "Importing REST cert (public key only) into Root store." - $RestCert = import-certificate -filepath "$TempDir\$RESTName" -certstorelocation "cert:\localmachine\root" - } - write-sdnexpresslog "Deleting REST cert from My store." - remove-item -path cert:\localmachine\my\$RESTCertThumbprint - - write-sdnexpresslog "Installing REST cert to my and root store of each NC node." - - foreach ($ncnode in $ComputerNames) { - write-sdnexpresslog "Installing REST cert to my and root store of: $ncnode" - try { - invoke-command -computername $ncnode @CredentialParam { - param( - [String] $RESTName, - [byte[]] $RESTCertPFXData, - [String] $RESTCertThumbprint, - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $RESTCertPFXData | set-content $TempFile.FullName -Encoding Byte - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $RestName.ToUpper() - - write-verbose "Found $($cert.count) certificate(s) in my store with subject name matching $RestName" - if ($Cert -eq $null) { - write-verbose "Importing new REST cert into My store." - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\my" -password $certpwd -Exportable - } else { - if ($cert.Thumbprint -ne $RestCertThumbprint) { - Remove-Item $TempFile.FullName -Force - throw "REST cert already exists in My store on $(hostname), but thumbprint does not match cert on other nodes." - } - } - - write-verbose "Setting permissions on REST cert." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) - Set-Acl $privKeyCertFile.FullName $privKeyAcl - - $Cert = get-childitem "Cert:\localmachine\root\$RestCertThumbprint" -erroraction Ignore - if ($cert -eq $Null) { - $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $cert.Import($TempFile.FullName, $certpwd, 0) - if ($cert.Issuer -eq $cert.Subject) { - write-verbose "REST cert does not yet exist in Root store, adding." - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - } - } - - Remove-Item $TempFile.FullName -Force - } -Argumentlist $RESTName, $RESTCertPFXData, $RESTCertThumbprint,$certpwdstring,$Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['CERTTHUMBPRINT'].code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 40 -context $restname - - - $AllNodeCerts = @() - - foreach ($ncnode in $ComputerNames) { - write-sdnexpresslog "Creating node cert for: $ncnode" - try - { - [byte[]] $CertData = invoke-command -computername $ncnode @CredentialParam { - param( - [String] $certpwdstring, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $NodeFQDN.ToUpper() - - write-verbose "Found $($cert.count) certificate(s) in my store with subject name matching $NodeFQDN" - - if ($Cert -eq $null) { - write-verbose "Creating new self signed certificate in My store." - $cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$NodeFQDN" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") -DNSNAME $RESTName - } else { - write-verbose "Using existing certificate with thumbprint $($cert.thumbprint)" - } - - write-verbose "Setting permissions on node cert." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) | out-null - Set-Acl $privKeyCertFile.FullName $privKeyAcl | out-null - - write-verbose "Exporting node cert." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - [System.io.file]::WriteAllBytes($TempFile.FullName, $cert.Export("PFX", $certpwdstring)) | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $CertData - } -ArgumentList $CertPwdString, $Global:fdGetSdnCert | Parse-RemoteOutput - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors['INVALIDKEYUSAGE'].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - - $isCertDataSelfSigned = IsSelfSignedCert -filePath $TempFile.FullName -secPwd $certpwd - if ($isCertDataSelfSigned) - { - $AllNodeCerts += import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - } - Remove-Item $TempFile.FullName -Force - - if ($isCertDataSelfSigned) { - foreach ($othernode in $ComputerNames) { - write-sdnexpresslog "Installing node cert for $ncnode into root store of $othernode." - - invoke-command -computername $othernode @CredentialParam { - param( - [String] $CertPwdString, - [Byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - $certpwd = ConvertTo-SecureString $certpwdstring -AsPlainText -Force - $cert = import-pfxcertificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" -password $certpwd - Remove-Item $TempFile.FullName -Force - } -ArgumentList $certPwdString,$CertData | Parse-RemoteOutput - } - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 50 -context $restname - - if (-not $isAlreadyDeployed) { - - mkdir $FCNCDBs -ErrorAction SilentlyContinue -Verbose - foreach ($ncnode in $ComputerNames) - { - Enable-NetworkControllerOnFailoverClusterLoggingOnDevice -DeviceName $ncnode -Device 'Server' - } - - if ($UseCertBySubject) - { - write-SDNExpressLog "Install-NetworkControllerOnFailoverCluster using cert by subject name $($RestName)" - - Install-NetworkControllerOnFailoverCluster -PackagePath $FCNCBins ` - -DatabasePath $FCNCDBs ` - -RestIPAddress $RestIPAddress ` - -ClientAuthentication None ` - -ClusterAuthentication X509 ` - -RestCertificateSubjectName $RestName ` - -ClusterNetworkName $ClusterNetworkName ` - -RestName $RESTName - } - else - { - write-SDNExpressLog "Install-NetworkControllerOnFailoverCluster using cert by thumbprint $($RESTCertThumbprint)" - - Install-NetworkControllerOnFailoverCluster -PackagePath $FCNCBins ` - -DatabasePath $FCNCDBs ` - -RestIPAddress $RestIPAddress ` - -ClientAuthentication None ` - -ClusterAuthentication X509 ` - -RestCertificateThumbPrint $RESTCertThumbprint ` - -ClusterNetworkName $ClusterNetworkName ` - -RestName $RESTName - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 90 -context $restname - - write-SDNExpressLog "Install-NetworkControllerOnFailoverCluster complete." - Write-SDNExpressLog "Network Controller cluster creation complete." - - #Verify that SDN REST endpoint is working before returning - Write-SDNExpressLog "Verifying Network Controller is operational." - - $dnsWorking = $true - if (!($RESTName -as [IPAddress] -as [bool])) - { - $dnsServers = (Get-DnsClientServerAddress -AddressFamily ipv4).ServerAddresses | select -uniq - - foreach ($dns in $dnsServers) - { - $dnsResponse = $null - $count = 0 - - while (($dnsResponse -eq $null) -and ($count -lt 90)) { - $dnsResponse = Resolve-DnsName -name $RESTName -Server $dns -ErrorAction Ignore - if ($dnsResponse -eq $null) { - write-sdnexpresslog "No response from the DNS server. Sleeping for 20 seconds" - sleep 20 - } - $count++ - } - - if ($count -eq 90) { - write-sdnexpresslog "REST name not resolving from $dns after 30 minutes." - $dnsWorking = $false - } else { - write-sdnexpresslog "REST name resolved from $dns after $count tries." - } - } - - if (!$dnsWorking) { - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - return - } - } - - if (!$dnsWorking) { - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - return - } - - write-sdnexpresslog ("Checking for REST response.") - $NotResponding = $true - while ($NotResponding) { - try { - $NotResponding = $false - clear-dnsclientcache - get-networkcontrollerCredential -ConnectionURI "https://$RestName" @CredentialParam | out-null - } - catch { - write-sdnexpresslog "Network Controller is not responding. Will try again in 10 seconds." - sleep 10 - $NotResponding = $true - } - } - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $restname - write-sdnexpresslog ("Network controller setup is complete and ready to use.") - write-sdnexpresslog "New-SDNExpressNetworkController Exit" -} - - - - - - # # # # ##### - # # ## # ###### ##### # # #### # # ###### # #### - # # # # # # # # # # ## # # # # # - # # # # # ##### # # # # # # # ##### # # - # # # # # # # # # # # # # # # # ### - # # # ## # # # # # # # ## # # # # - # # # ###### # ##### #### # # # # #### - - - -function New-SDNExpressVirtualNetworkManagerConfiguration -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [String] $MacAddressPoolStart, - [String] $MacAddressPoolEnd, - [Object] $NCHostCert, - [String] $NCUsername, - [String] $NCPassword, - [PSCredential] $Credential = $null, - [bool] $UseCertBySubject = $false - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - $uri = "https://$RestName" - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - write-sdnexpresslog "Writing Mac Pool." - $MacAddressPoolStart = [regex]::matches($MacAddressPoolStart.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - $MacAddressPoolEnd = [regex]::matches($MacAddressPoolEnd.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - - $MacPoolProperties = new-object Microsoft.Windows.NetworkController.MacPoolProperties - $MacPoolProperties.StartMacAddress = $MacAddressPoolStart - $MacPoolProperties.EndMacAddress = $MacAddressPoolEnd - $MacPoolObject = New-NetworkControllerMacPool -connectionuri $uri -ResourceId "DefaultMacPool" -properties $MacPoolProperties @CredentialParam -Force -passinnerexception - - write-sdnexpresslog "Writing controller credential." - $CredentialProperties = new-object Microsoft.Windows.NetworkController.CredentialProperties - - if ($UseCertBySubject) - { - $CredentialProperties.Type = "X509CertificateSubjectName" - $CredentialProperties.Value = $NCHostCert.Subject - } - else - { - $CredentialProperties.Type = "X509Certificate" - $CredentialProperties.Value = $NCHostCert.thumbprint - } - - $HostCertObject = New-NetworkControllerCredential -ConnectionURI $uri -ResourceId "NCHostCert" -properties $CredentialProperties @CredentialParam -force -passinnerexception - - write-sdnexpresslog "Writing domain credential." - $CredentialProperties = new-object Microsoft.Windows.NetworkController.CredentialProperties - $CredentialProperties.Type = "UsernamePassword" - $CredentialProperties.UserName = $NCUsername - $CredentialProperties.Value = $NCPassword - $HostUserObject = New-NetworkControllerCredential -ConnectionURI $uri -ResourceId "NCHostUser" -properties $CredentialProperties @CredentialParam -force -passinnerexception - - write-sdnexpresslog "Writing PA logical network." - try { - $LogicalNetworkObject = get-NetworkControllerLogicalNetwork -ConnectionURI $uri -ResourceID "HNVPA" @CredentialParam -passinnerexception - } - catch - { - $LogicalNetworkProperties = new-object Microsoft.Windows.NetworkController.LogicalNetworkProperties - $LogicalNetworkProperties.NetworkVirtualizationEnabled = $true - $LogicalNetworkObject = New-NetworkControllerLogicalNetwork -ConnectionURI $uri -ResourceID "HNVPA" -properties $LogicalNetworkProperties @CredentialParam -Force -passinnerexception - } - write-sdnexpresslog "New-SDNExpressVirtualNetworkManagerConfiguration Exit" -} - - - - - # # # # ###### # ##### - # # ## # ###### ##### # # # # # # #### # # ###### # #### - # # # # # # # # # # # # # # ## # # # # # - # # # # # ##### # ###### # # # # # # # # ##### # # - # # # # # # # # ####### # # # # # # # # # ### - # # # ## # # # # # # # # # # ## # # # # - # # # ###### # # # # ##### #### # # # # #### - - - -function Add-SDNExpressVirtualNetworkPASubnet -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [String] $AddressPrefix, - [String] $VLANID, - [String[]] $DefaultGateways, - [Object] $IPPoolStart, - [String] $IPPoolEnd, - [PSCredential] $Credential = $null, - [String] $LogicalNetworkName = "HNVPA", - [string[]] $Servers = $null, - [switch] $AllServers - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - $DefaultRestParams = @{ - 'ConnectionURI'="https://$RestName"; - 'PassInnerException'=$true; - 'Credential'=$credential - } - - if ($null -ne $Credential) { - $DefaultRestParams.Credential = $credential - } - - $PALogicalSubnets = get-networkcontrollerLogicalSubnet @DefaultRestParams -LogicalNetworkId $LogicalNetworkName - $PALogicalSubnet = $PALogicalSubnets | where-object {$_.properties.AddressPrefix -eq $AddressPrefix} - - if ($PALogicalSubnet -eq $null) { - write-sdnexpresslog "PA Logical subnet does not yet exist, creating." - $LogicalSubnetProperties = new-object Microsoft.Windows.NetworkController.LogicalSubnetProperties - $logicalSubnetProperties.VLANId = $VLANID - $LogicalSubnetProperties.AddressPrefix = $AddressPrefix - $LogicalSubnetProperties.DefaultGateways = $DefaultGateways - - $PALogicalSubnet = New-NetworkControllerLogicalSubnet @DefaultRestParams -LogicalNetworkId $LogicalNetworkName -ResourceId $AddressPrefix.Replace("/", "_") -properties $LogicalSubnetProperties -Force - } - - $IPpoolProperties = new-object Microsoft.Windows.NetworkController.IPPoolproperties - $ippoolproperties.startipaddress = $IPPoolStart - $ippoolproperties.endipaddress = $IPPoolEnd - - $IPPoolObject = New-networkcontrollerIPPool @DefaultRestParams -NetworkId $LogicalNetworkName -SubnetId $AddressPrefix.Replace("/", "_") -ResourceID $AddressPrefix.Replace("/", "_") -Properties $IPPoolProperties -force - - write-sdnexpresslog "Updating specified servers." - $ServerObjects = get-networkcontrollerserver @DefaultRestParams - - if (!$AllServers) { - $ServerObjects = $ServerObjects | ? {$_.properties.connections.managementaddresses -in $Servers} - } - - if ($ServerObjects -ne $null) { - write-sdnexpresslog "Found $($ServerObjects.count) servers." - } else { - write-sdnexpresslog "Found 0 servers." - - } - - foreach ($server in $ServerObjects) { - if (($server.properties.networkinterfaces.properties.logicalsubnets.count -eq 0) -or !($PALogicalSubnet.resourceref -in $server.properties.networkinterfaces.properties.logicalsubnets.resourceref)) { - write-sdnexpresslog "Adding subnet to $($server.resourceid)." - $server.properties.networkinterfaces[0].properties.logicalsubnets += $PALogicalSubnet - New-networkcontrollerserver @DefaultRestParams -resourceid $server.resourceid -properties $server.properties -force | out-null - } else { - write-sdnexpresslog "Subnet has already been added to $($server.resourceid)." - } - } - write-sdnexpresslog "$($MyInvocation.InvocationName) Exit" -} - - - - - ##### # ###### # # ##### - # # # # # ## ## ## # # ## #### ###### ##### # # #### # # ###### # #### - # # # # # # # # # # ## # # # # # # # # # # # ## # # # # # - ##### # ###### # # # # # # # # # # # ##### # # # # # # # # ##### # # - # # # # # # ###### # # # ###### # ### # ##### # # # # # # # # # ### - # # # # # # # # # # ## # # # # # # # # # # # # ## # # # # - ##### ####### ###### # # # # # # # # #### ###### # # ##### #### # # # # #### - - - - -function New-SDNExpressLoadBalancerManagerConfiguration -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [Parameter(Mandatory=$true)] - [ValidateScript({ - $split = $_.split('/') - if ($split.count -ne 2) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, PrivateVIPPrefix must be in CIDR format with the syntax of /."} - if (!($split[0] -as [ipaddress] -as [bool])) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, Invalid subnet portion of PrivateVIPPrefix parameter."} - if (($split[1] -le 0) -or ($split[1] -gt 32)) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, Invalid subnet bits portion of PrivateVIPPrefix parameter."} - return $true - })] - [String] $PrivateVIPPrefix, - [Parameter(Mandatory=$true)] - [ValidateScript({ - $split = $_.split('/') - if ($split.count -ne 2) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, PublicVIPPrefix must be in CIDR format with the syntax of /."} - if (!($split[0] -as [ipaddress] -as [bool])) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, Invalid subnet portion of PublicVIPPrefix parameter."} - if (($split[1] -le 0) -or ($split[1] -gt 32)) { throw "When calling function New-SDNExpressLoadBalancerManagerConfiguration, Invalid subnet bits portion of PublicVIPPrefix parameter."} - return $true - })] - [String] $PublicVIPPrefix, - [String] $SLBMVip = (get-ipaddressinsubnet -subnet $PrivateVIPPrefix -offset 1), - [String] $PrivateVIPPoolStart = (get-ipaddressinsubnet -subnet $PrivateVIPPrefix -offset 1), - [String] $PrivateVIPPoolEnd = (Get-IPLastAddressInSubnet -subnet $PrivateVIPPrefix), - [String] $PublicVIPPoolStart = (get-ipaddressinsubnet -subnet $PublicVIPPrefix -offset 1), - [String] $PublicVIPPoolEnd = (Get-IPLastAddressInSubnet -subnet $PublicVIPPrefix), - [PSCredential] $Credential = $null - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - $DefaultRestParams = @{ - 'ConnectionURI'="https://$RestName"; - 'PassInnerException'=$true; - } - if ($null -ne $Credential) { - $DefaultRestParams.Credential = $credential - } - #PrivateVIP LN - try - { - $PrivateVIPLNObject = Get-NetworkControllerLogicalNetwork @DefaultRestParams -ResourceID "PrivateVIP" - } - catch - { - $LogicalNetworkProperties = new-object Microsoft.Windows.NetworkController.LogicalNetworkProperties - $LogicalNetworkProperties.NetworkVirtualizationEnabled = $false - $LogicalNetworkProperties.Subnets = @() - $LogicalNetworkProperties.Subnets += new-object Microsoft.Windows.NetworkController.LogicalSubnet - $logicalNetworkProperties.Subnets[0].ResourceId = $PrivateVIPPrefix.Replace("/", "_") - $logicalNetworkProperties.Subnets[0].Properties = new-object Microsoft.Windows.NetworkController.LogicalSubnetProperties - $logicalNetworkProperties.Subnets[0].Properties.AddressPrefix = $PrivateVIPPrefix - $logicalNetworkProperties.Subnets[0].Properties.DefaultGateways = @(get-ipaddressinsubnet -subnet $PrivateVIPPrefix) - - $PrivateVIPLNObject = New-NetworkControllerLogicalNetwork @DefaultRestParams -ResourceID "PrivateVIP" -properties $LogicalNetworkProperties -force - } - - $IPpoolProperties = new-object Microsoft.Windows.NetworkController.IPPoolproperties - $ippoolproperties.startipaddress = $PrivateVIPPoolStart - $ippoolproperties.endipaddress = $PrivateVIPPoolEnd - - $PrivatePoolObject = new-networkcontrollerIPPool @DefaultRestParams -NetworkId "PrivateVIP" -SubnetId $PrivateVIPPrefix.Replace("/", "_") -ResourceID $PrivateVIPPrefix.Replace("/", "_") -Properties $IPPoolProperties -force - - #PublicVIP LN - try - { - $PublicVIPLNObject = get-NetworkControllerLogicalNetwork @DefaultRestParams -ResourceID "PublicVIP" - } - catch - { - $LogicalNetworkProperties = new-object Microsoft.Windows.NetworkController.LogicalNetworkProperties - $LogicalNetworkProperties.NetworkVirtualizationEnabled = $false - $LogicalNetworkProperties.Subnets = @() - $LogicalNetworkProperties.Subnets += new-object Microsoft.Windows.NetworkController.LogicalSubnet - $logicalNetworkProperties.Subnets[0].ResourceId = $PublicVIPPrefix.Replace("/", "_") - $logicalNetworkProperties.Subnets[0].Properties = new-object Microsoft.Windows.NetworkController.LogicalSubnetProperties - $logicalNetworkProperties.Subnets[0].Properties.AddressPrefix = $PublicVIPPrefix - $logicalNetworkProperties.Subnets[0].Properties.DefaultGateways = @(get-ipaddressinsubnet -subnet $PublicVIPPrefix) - $logicalnetworkproperties.subnets[0].properties.IsPublic = $true - - $PublicVIPLNObject = New-NetworkControllerLogicalNetwork @DefaultRestParams -ResourceID "PublicVIP" -properties $LogicalNetworkProperties -Force - } - - $IPpoolProperties = new-object Microsoft.Windows.NetworkController.IPPoolproperties - $ippoolproperties.startipaddress = $PublicVIPPoolStart - $ippoolproperties.endipaddress = $PublicVIPPoolEnd - - $PublicPoolObject = new-networkcontrollerIPPool @DefaultRestParams -NetworkId "PublicVIP" -SubnetId $PublicVIPPrefix.Replace("/", "_") -ResourceID $PublicVIPPrefix.Replace("/", "_") -Properties $IPPoolProperties -force - - #SLBManager Config - - $managerproperties = new-object Microsoft.Windows.NetworkController.LoadBalancerManagerProperties - $managerproperties.LoadBalancerManagerIPAddress = $SLBMVip - $managerproperties.OutboundNatIPExemptions = @("$SLBMVIP/32") - $managerproperties.VipIPPools = @($PrivatePoolObject, $PublicPoolObject) - - $SLBMObject = new-networkcontrollerloadbalancerconfiguration @DefaultRestParams -properties $managerproperties -resourceid "config" -Force - write-sdnexpresslog "$($MyInvocation.InvocationName) Exit" -} - - - - # ##### # ###### # # ### ###### ##### - # # ##### ##### # # # # # # # # # # # # # # ##### # # ###### ##### - # # # # # # # # # # # # # # # # # # # # ## # # # - # # # # # # ##### # ###### # # # ###### ##### # # ##### # # # ##### # - ####### # # # # # # # # # # # # # # # # # # # # # # - # # # # # # # # # # # # # # # # # # # # # # ## # # - # # ##### ##### ##### ####### ###### # ### # ##### #### ##### # # ###### # - - - -function Add-SDNExpressLoadBalancerVIPSubnet -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [String] $VIPPrefix, - [String] $VIPPoolStart = (get-ipaddressinsubnet -subnet $VIPPrefix -offset 1), - [String] $VIPPoolEnd = (Get-IPLastAddressInSubnet -subnet $VIPPrefix), - [Switch] $IsPrivate, - [String] $LogicalNetworkName = "", - [PSCredential] $Credential = $null - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - $DefaultRestParams = @{ - 'ConnectionURI'="https://$RestName"; - 'PassInnerException'=$true; - } - if ($null -ne $Credential) { - $DefaultRestParams.Credential = $credential - } - if ([String]::IsNullOrEmpty($LogicalNetworkName)) { - if ($isPrivate) { - $logicalnetworkname = "PrivateVIP" - } else { - $logicalnetworkname = "PublicVIP" - } - } - write-sdnexpresslog "Logicalnetwork is $logicalnetworkname" - - $VIPLogicalSubnets = get-networkcontrollerLogicalSubnet @DefaultRestParams -LogicalNetworkId $LogicalNetworkName - $VIPLogicalSubnet = $VIPLogicalSubnets | where-object {$_.properties.AddressPrefix -eq $VIPPrefix} - - if ($VIPLogicalSubnet -eq $null) { - write-sdnexpresslog "VIP Logical subnet does not yet exist, creating." - $LogicalSubnetProperties = new-object Microsoft.Windows.NetworkController.LogicalSubnetProperties - $LogicalSubnetProperties.AddressPrefix = $VIPPrefix - $LogicalSubnetProperties.DefaultGateways = @(get-ipaddressinsubnet -subnet $VIPPrefix) - $logicalsubnetproperties.IsPublic = !$IsPrivate - $LogicalSubnet = New-NetworkControllerLogicalSubnet @DefaultRestParams -LogicalNetworkId $LogicalNetworkName -ResourceId $VIPPrefix.Replace("/", "_") -properties $LogicalSubnetProperties -Force - } - - $IPpoolProperties = new-object Microsoft.Windows.NetworkController.IPPoolproperties - $ippoolproperties.startipaddress = $VIPPoolStart - $ippoolproperties.endipaddress = $VIPPoolEnd - - $PoolObject = new-networkcontrollerIPPool @DefaultRestParams -NetworkId $logicalnetworkname -SubnetId $VIPPrefix.Replace("/", "_") -ResourceID $VIPPrefix.Replace("/", "_") -Properties $IPPoolProperties -force - - #SLBManager Config - $manager = Get-NetworkControllerLoadBalancerConfiguration @DefaultRestParams - $manager.properties.VipIPPools += $PoolObject - $SLBMObject = new-networkcontrollerloadbalancerconfiguration @DefaultRestParams -properties $manager.properties -resourceid $manager.resourceid -Force - - write-sdnexpresslog "$($MyInvocation.InvocationName) Exit" -} - - - - ###### # # ##### ##### - # # # ## # # # # # #### # # ###### # #### - # # # # # # # # # # ## # # # # # - # # # # # # ##### # # # # # # ##### # # - # # # # # # # # # # # # # # # # ### - # # # # ## # # # # # # # ## # # # # - # ###### # # ##### ##### #### # # # # #### - - - -function New-SDNExpressiDNSConfiguration -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [String] $Username, - [String] $Password, - [String] $IPAddress, - [String] $ZoneName, - [PSCredential] $Credential = $null - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - - $CredentialProperties = new-object Microsoft.Windows.NetworkController.CredentialProperties - $CredentialProperties.Type = "UsernamePassword" - $CredentialProperties.UserName = $Username - $CredentialProperties.Value = $Password - $iDNSUserObject = New-NetworkControllerCredential -ConnectionURI $uri -ResourceId "iDNSUser" -properties $CredentialProperties @CredentialParam -force -passinnerexception - - $iDNSProperties = new-object microsoft.windows.networkcontroller.InternalDNSServerProperties - $iDNSProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $iDNSProperties.Connections[0].Credential = $iDNSUserObject - $iDNSProperties.Connections[0].CredentialType = $iDNSUserObject.properties.Type - $iDNSProperties.Connections[0].ManagementAddresses = $IPAddress - - $iDNSProperties.Zone = $ZoneName - - New-NetworkControllerIDnsServerConfiguration -connectionuri $RestName -ResourceId "configuration" -properties $iDNSProperties -force @CredentialParam -passinnerexception -} - - - - # # # # ###### ##### - # # ## ## # # #### ##### ##### # # #### # # ###### # #### - # # # # # # # # # # # # # # # # ## # # # # # - # # # # # ###### # # # # # # # # # # # ##### # # - # # # # # # # ##### # # # # # # # # # # ### - # # # # # # # # # # # # # # # ## # # # # - # # # # #### # # # ##### #### # # # # #### - - - -function Enable-SDNExpressVMPort { - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $ComputerName, - [String] $VMName, - [String] $VMNetworkAdapterName = "", - [int] $ProfileData = 1, - [string] $InstanceId = "{$([Guid]::Empty)}", - [PSCredential] $Credential = $null - ) - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - invoke-command -ComputerName $ComputerName @CredentialParam -ScriptBlock { - param( - [String] $VMName, - [String] $VMNetworkAdapterName, - [int] $ProfileData, - [String] $InstanceId - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $PortProfileFeatureId = "9940cd46-8b06-43bb-b9d5-93d50381fd56" - $NcVendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}" - - if ([string]::IsNullOREmpty($VMNetworkAdapterName)) - { - $vnic = Get-VMNetworkAdapter -VMName $VMName - if ($vnic.count -gt 1) { - throw "More than one VNIC on VM. Use VMNetworkAdapterName to specify which VNIC." - } - } else { - $vnic = Get-VMNetworkAdapter -VMName $VMName -Name $VMNetworkAdapterName - } - - $currentProfile = Get-VMSwitchExtensionPortFeature -FeatureId $PortProfileFeatureId -VMNetworkAdapter $vNic - - if ( $currentProfile -eq $null) - { - $portProfileDefaultSetting = Get-VMSystemSwitchExtensionPortFeature -FeatureId $PortProfileFeatureId - - $portProfileDefaultSetting.SettingData.ProfileId = $InstanceId - $portProfileDefaultSetting.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}" - $portProfileDefaultSetting.SettingData.CdnLabelString = "TestCdn" - $portProfileDefaultSetting.SettingData.CdnLabelId = 1111 - $portProfileDefaultSetting.SettingData.ProfileName = "Testprofile" - $portProfileDefaultSetting.SettingData.VendorId = $NcVendorId - $portProfileDefaultSetting.SettingData.VendorName = "NetworkController" - $portProfileDefaultSetting.SettingData.ProfileData = $ProfileData - - Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $portProfileDefaultSetting -VMNetworkAdapter $vNic | out-null - } - else - { - $currentProfile.SettingData.ProfileId = $InstanceId - $currentProfile.SettingData.ProfileData = $ProfileData - Set-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $currentProfile -VMNetworkAdapter $vNic | out-null - } - } -ArgumentList $VMName, $VMNetworkAdapterName, $ProfileData, $InstanceId | Parse-RemoteOutput -} - - - # # # - # # ##### ##### # # #### #### ##### - # # # # # # # # # # # # - # # # # # # ####### # # #### # - ####### # # # # # # # # # # - # # # # # # # # # # # # # - # # ##### ##### # # #### #### # - - - -Function Add-SDNExpressHost { - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [Parameter(Mandatory=$true,ParameterSetName="iDNS")] - [ValidateScript({ - if ($_ -eq $null) { return $true } - if ($_.StartsWith("https://")) { throw "The Rest Name must not start with https://" } - return $true - })] - [String] $RestName, - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [Parameter(Mandatory=$true,ParameterSetName="iDNS")] - [string] $ComputerName, - [Parameter(Mandatory=$true,ParameterSetName="Default")] - [Parameter(Mandatory=$true,ParameterSetName="iDNS")] - [System.Security.Cryptography.X509Certificates.X509Certificate2] $NCHostCert, - [Parameter(Mandatory=$true,ParameterSetName="iDNS")] - [ValidateScript({ - if (!($split[0] -as [ipaddress] -as [bool])) { throw "Invalid iDNSIPAddress specified."} - return $true - })] - [String] $iDNSIPAddress = "", - [Parameter(Mandatory=$true,ParameterSetName="iDNS")] - [String] $iDNSMacAddress = "", - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [Parameter(Mandatory=$false,ParameterSetName="iDNS")] - [ValidateScript({ - $split = $_.split('/') - if ($split.count -ne 2) { throw "HostPASubnetPrefix must be in CIDR format with the syntax of /."} - if (!($split[0] -as [ipaddress] -as [bool])) { throw "Invalid subnet portion of HostPASubnetPrefix parameter."} - if (($split[1] -le 0) -or ($split[1] -gt 32)) { throw "Invalid subnet bits portion of HostPASubnetPrefix parameter."} - return $true - })] - [String] $HostPASubnetPrefix = "", - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [Parameter(Mandatory=$false,ParameterSetName="iDNS")] - [String] $VirtualSwitchName = "", - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [Parameter(Mandatory=$false,ParameterSetName="iDNS")] - [PSCredential] $Credential = $null, - [Parameter(Mandatory=$false,ParameterSetName="Default")] - [Parameter(Mandatory=$false,ParameterSetName="iDNS")] - [String] $OperationID = "", - [Parameter(Mandatory=$false)] - [String[]] $NCNodes, - [Parameter(Mandatory=$false)] - [int] $port = 6645, - [Bool] $IsFC = $false - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyInvocation.UnboundArguments -ParamSet $psCmdlet - - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - - write-sdnexpresslog "Get the SLBM VIP" - - $SLBMConfig = $null - try { - $SLBMConfig = get-networkcontrollerloadbalancerconfiguration -connectionuri $uri @CredentialParam - $slbmvip = $slbmconfig.properties.loadbalancermanageripaddress - write-sdnexpresslog "SLBM VIP is $slbmvip" - } - catch - { - $slbmvip = "" - write-sdnexpresslog "SLB is not configured." - } - - # Get a list of "other nodes in the cluster" for FCNC purposes - if ($isFC) { - $nodesInSdnCluster = Get-NodesInSDNCluster -ComputerName $ComputerName -uri $uri -CredentialParam $credentialParam - } - - if ([String]::IsNullOrEmpty($VirtualSwitchName)) { - try { - $VirtualSwitchName = invoke-command -ComputerName $ComputerName @CredentialParam { - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $vmswitch = get-vmswitch - if (($vmswitch -eq $null) -or ($vmswitch.count -eq 0)) { - throw "No virtual switch found on this host. Please create the virtual switch before adding this host." - } - if ($vmswitch.count -gt 1) { - throw "More than one virtual switch exists on the specified host. Use the VirtualSwitchName parameter to specify which switch you want configured for use with SDN." - } - - write-output $vmswitch.Name - } | parse-remoteoutput - } catch { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["INVALIDVSWITCH"].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - } - - invoke-command -ComputerName $ComputerName @CredentialParam { - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $feature = get-windowsfeature RSAT-NetworkController - if ($feature -ne $null) { - write-verbose "Found RSAT-NetworkController role, adding it." - add-windowsfeature "RSAT-NetworkController" | out-null - } - - $feature = get-windowsfeature NetworkVirtualization - if ($feature -ne $null) { - write-verbose "Found network virtualization role, adding it." - add-windowsfeature NetworkVirtualization -IncludeAllSubFeature -IncludeManagementTools -Restart | out-null - } - } | parse-remoteoutput - - if ($IsFC) - { - Enable-NetworkControllerOnFailoverClusterLoggingOnDevice -DeviceName $ComputerName -Device 'Server' - } - - $NodeFQDN = invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [String] $RestName, - [String] $iDNSIPAddress, - [String] $iDNSMacAddress, - [String[]] $NCNodes, - [String] $port - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Setting registry keys and firewall." - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - $connections = "ssl:$($RestName):6640","pssl:$($port)" - write-verbose "Port: $($connections)" - $peerCertCName = $RestName.ToUpper() - $hostAgentCertCName = $NodeFQDN.ToUpper() - - Set-Item WSMan:\localhost\MaxEnvelopeSizekb -Value 7000 | out-null - - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters" -Name "Connections" -Value $connections -PropertyType "MultiString" -Force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters" -Name "PeerCertificateCName" -Value $peerCertCName -PropertyType "String" -Force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters" -Name "HostAgentCertificateCName" -Value $hostAgentCertCName -PropertyType "String" -Force | out-null - - if ($null -ne $NCNodes) { - # add Network Controller Nodes to reg key - new-itemproperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\' -Name "NetworkControllerNodeNames" -Value $NCNodes -PropertyType "MultiString" -Force | out-null - } - - if (![String]::IsNullOrEmpty($iDNSIPAddress) -and ![String]::IsNullOrEmpty($iDNSMacAddress)) { - new-item -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet" -name "InfraServices" -force | out-null - new-item -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices" -name "DnsProxyService" -force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\DnsProxyService" -Name "Port" -Value 53 -PropertyType "Dword" -Force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\DnsProxyService" -Name "ProxyPort" -Value 53 -PropertyType "Dword" -Force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\DnsProxyService" -Name "IP" -Value "169.254.169.254" -PropertyType "String" -Force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters\Plugins\Vnet\InfraServices\DnsProxyService" -Name "MAC" -Value $iDNSMacAddress -PropertyType "String" -Force | out-null - - new-item -path "HKLM:\SYSTEM\CurrentControlSet\Services" -name "DnsProxy" -force | out-null - new-item -path "HKLM:\SYSTEM\CurrentControlSet\Services\DnsProxy" -name "Parameters" -force | out-null - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\DNSProxy\Parameters" -Name "Forwarders" -Value $iDNSIPAddress -PropertyType "String" -Force | out-null - - Enable-NetFirewallRule -DisplayGroup 'DNS Proxy Service' -ErrorAction Ignore | out-null - } - - - $fwrule = Get-NetFirewallRule -Name "Firewall-REST" -ErrorAction SilentlyContinue - if ($fwrule -eq $null) { - New-NetFirewallRule -Name "Firewall-REST" -DisplayName "Network Controller Host Agent REST" -Group "NcHostAgent" -Action Allow -Protocol TCP -LocalPort 80 -Direction Inbound -Enabled True | out-null - } - - $fwrule = Get-NetFirewallRule -Name "Firewall-OVSDB" -ErrorAction SilentlyContinue - if ($fwrule -eq $null) { - New-NetFirewallRule -Name "Firewall-OVSDB" -DisplayName "Network Controller Host Agent OVSDB" -Group "NcHostAgent" -Action Allow -Protocol TCP -LocalPort 6640 -Direction Inbound -Enabled True | out-null - } - - $fwrule = Get-NetFirewallRule -Name "Firewall-HostAgent-TCP-IN" -ErrorAction SilentlyContinue - if ($fwrule -eq $null) { - New-NetFirewallRule -Name "Firewall-HostAgent-TCP-IN" -DisplayName "Network Controller Host Agent (TCP-In)" -Group "Network Controller Host Agent Firewall Group" -Action Allow -Protocol TCP -LocalPort Any -Direction Inbound -Enabled True | out-null - } - - $fwrule = Get-NetFirewallRule -Name "Firewall-HostAgent-WCF-TCP-IN" -ErrorAction SilentlyContinue - if ($fwrule -eq $null) { - New-NetFirewallRule -Name "Firewall-HostAgent-WCF-TCP-IN" -DisplayName "Network Controller Host Agent WCF(TCP-In)" -Group "Network Controller Host Agent Firewall Group" -Action Allow -Protocol TCP -LocalPort 80 -Direction Inbound -Enabled True | out-null - } - - $fwrule = Get-NetFirewallRule -Name "Firewall-HostAgent-TLS-TCP-IN" -ErrorAction SilentlyContinue - if ($fwrule -eq $null) { - New-NetFirewallRule -Name "Firewall-HostAgent-TLS-TCP-IN" -DisplayName "Network Controller Host Agent WCF over TLS (TCP-In)" -Group "Network Controller Host Agent Firewall Group" -Action Allow -Protocol TCP -LocalPort 443 -Direction Inbound -Enabled True | out-null - } - - write-verbose "Finished setting registry keys and firewall." - write-output $NodeFQDN - } -ArgumentList $RestName, $iDNSIPAddress, $iDNSMacAddress, $NCNodes, $port | parse-remoteoutput - - write-sdnexpresslog "Create and return host certificate." - - try { - [byte[]] $CertData = invoke-command -ComputerName $ComputerName @CredentialParam { - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - if ((Get-Module -name "SdnExpressModule") -ne $null) { - Import-Module -name "SdnExpressModule" - New-SdnExpressHostCertificate - } - else { - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - $cert = $null - $certs = get-childitem "cert:\localmachine\my" ` - | where-object {$_.Subject.ToUpper() -eq "CN=$($NodeFQDN)" } ` - | where-object {$_.NotAfter -ge (get-date) } ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.1"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.2"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.4.1.311.95.1.1.1"}} ` - | Sort-Object -Property NotAfter -Descending - - if ($certs -ne $null) { - $cert = $certs[0] - } - else { - $certs = get-childitem "cert:\localmachine\my" ` - | where-object {$_.Subject.ToUpper() -eq "CN=$($NodeFQDN)" } ` - | where-object {$_.NotAfter -ge (get-date) } ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.1"}} ` - | where-object {$_.EnhancedKeyUsageList | where-object {$_.ObjectId -eq "1.3.6.1.5.5.7.3.2"}} ` - | Sort-Object -Property NotAfter -Descending - - if ($certs -ne $null) { - $cert = $certs[0] - } - } - - if ($cert -eq $null) { - write-verbose "Creating new host certificate." - $cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$NodeFQDN" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") - } else { - write-verbose "Existing certificate meets criteria. Exporting." - } - - write-verbose "Setting cert permissions." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) | out-null - Set-Acl $privKeyCertFile.FullName $privKeyAcl | out-null - - write-verbose "Exporting certificate." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $cert | out-null - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $CertData - } - } | parse-remoteoutput - } catch { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["INVALIDKEYUSAGE"].Code -LogMessage $_.Exception.Message #No errormessage because SDN Express generates error - throw $_.Exception - } - - #Hold on to CertData, we will need it later when adding the host to the NC. - - write-sdnexpresslog "Install NC host cert into Root store on host." - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $NCHostCert | out-null - $NCHostCertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - if ($NCHostCert.Subject -eq $NCHostCert.Issuer) { - invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - write-verbose "Importing NC certificate into Root store." - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - Remove-Item $TempFile.FullName -Force - } -ArgumentList (,$NCHostCertData) | parse-remoteoutput - } - - # Install host-to-host certs if needed for FCNC - if ($IsFC) { - write-verbose "Importing new server's certificate into Root store of other servers." - # Install this host's cert onto all other hosts, and get their certs while we're there - - [byte[][]] $HostCerts = @() - - foreach ($node in $nodesInSdnCluster) { - [byte[]] $returnedCert = invoke-command -ComputerName $node @CredentialParam { - param( - [byte[]] $CertData, - [String] $funcDefGetSdnCert - ) - - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certData) - if ($cert.Issuer -eq $cert.Subject) { - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - write-verbose "Importing newly added host certificate into Root store of " + $NodeFQDN - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - Remove-Item $TempFile.FullName -Force - } - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $NodeFQDN - - #Only export if the cert is self signed - if ($Cert.Issuer -eq $Cert.Subject) { - write-verbose "Exporting host certificate for $($NodeFQDN)" - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $cert | out-null - - $HostCertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $HostCertData - } else { - write-verbose "Skipping host certificate export for $($NodeFQDN), cert not self signed" - } - } -ArgumentList ($CertData, $Global:fdGetSdnCert) | parse-remoteoutput - $hostCerts += ,$returnedCert - } - - # Install all other non-selfsigned host's certs onto this host - write-verbose "Importing all other self signed server's certificates into Root store of new server." - - foreach($hostCert in $hostCerts) { - invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - Remove-Item $TempFile.FullName -Force - } -ArgumentList (,$HostCert) | parse-remoteoutput - } - } - - write-sdnexpresslog "Restart NC Host Agent and enable VFP." - - $VirtualSwitchId = invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [String] $VirtualSwitchName - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $allnics = Get-VMNetworkAdapter -VMName * | ? {$_.SwitchName -eq $VirtualSwitchName} - - foreach ($nic in $allnics) { - $currentProfile = Get-VMSwitchExtensionPortFeature -FeatureId "9940cd46-8b06-43bb-b9d5-93d50381fd56" -VMNetworkAdapter $nic - - if ( $currentProfile -eq $null) - { - write-verbose "Adding Null port profile to $($nic.VMName) adapter $($nic.Name) so traffic is not blocked." - - #No port profile set yet, add a null profile so traffic isn't blocked - $portProfileDefaultSetting = Get-VMSystemSwitchExtensionPortFeature -FeatureId "9940cd46-8b06-43bb-b9d5-93d50381fd56" - $portProfileDefaultSetting.SettingData.ProfileId = "{$([Guid]::Empty)}" - $portProfileDefaultSetting.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}" - $portProfileDefaultSetting.SettingData.CdnLabelString = "TestCdn" - $portProfileDefaultSetting.SettingData.CdnLabelId = 1111 - $portProfileDefaultSetting.SettingData.ProfileName = "Testprofile" - $portProfileDefaultSetting.SettingData.VendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}" - $portProfileDefaultSetting.SettingData.VendorName = "NetworkController" - $portProfileDefaultSetting.SettingData.ProfileData = 2 #Disable VFP on port so VMs continue to work as before - - Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $portProfileDefaultSetting -VMNetworkAdapter $nic | out-null - } - else - { - #Leave as-is - write-verbose "$($nic.VMName) adapter $($nic.Name) already has port feature set, not changing." - } - } - write-verbose "Configuring and restarting host agent." - Stop-Service -Name NCHostAgent -Force | out-null - Set-Service -Name NCHostAgent -StartupType Automatic | out-null - Start-Service -Name NCHostAgent | out-null - - write-verbose "Enabling VFP." - Disable-VmSwitchExtension -VMSwitchName $VirtualSwitchName -Name "Microsoft Windows Filtering Platform" | out-null - Enable-VmSwitchExtension -VMSwitchName $VirtualSwitchName -Name "Microsoft Azure VFP Switch Extension" | out-null - - write-verbose "VFP is enabled." - write-output (get-vmswitch -Name $VirtualSwitchName).Id - } -ArgumentList $VirtualSwitchName | parse-remoteoutput - - if (![String]::IsNullOrEmpty($SLBMVIP)) { - write-sdnexpresslog "Configure and start SLB Host Agent." - - invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $SLBMVip, - [String] $RestName - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - $slbhpconfigtemplate = @" - - - - - $($SLBMVIP):8570 - - - $($SLBMVIP):8570 - - $RESTName - - - $NodeFQDN - - - 0 - 4088 - 500000 - - -"@ - - set-content -value $slbhpconfigtemplate -path 'c:\windows\system32\slbhpconfig.xml' -encoding UTF8 - - write-verbose "Configuring and starting SLB host agent." - Stop-Service -Name SLBHostAgent -Force - Set-Service -Name SLBHostAgent -StartupType Automatic - Start-Service -Name SLBHostAgent - write-verbose "SLB host agent has been started." - } -ArgumentList $SLBMVIP, $RESTName | parse-remoteoutput - } - else { - write-sdnexpresslog "Skipping SLB host configuration." - } - - write-sdnexpresslog "Prepare server object." - - $nchostcertObject = get-networkcontrollerCredential -Connectionuri $URI -ResourceId "NCHostCert" @CredentialParam -passinnerexception - $nchostuserObject = get-networkcontrollerCredential -Connectionuri $URI -ResourceId "NCHostUser" @CredentialParam -passinnerexception - - if ([string]::IsNullOrEmpty($HostPASubnetPrefix)) { - $PALogicalSubnets = @() - } else { - $PALogicalNetwork = get-networkcontrollerLogicalNetwork -Connectionuri $URI -ResourceId "HNVPA" @CredentialParam -passinnerexception - $PALogicalSubnets = @($PALogicalNetwork.Properties.Subnets | where-object {$_.properties.AddressPrefix -eq $HostPASubnetPrefix}) - } - - $ServerProperties = new-object Microsoft.Windows.NetworkController.ServerProperties - - $ServerProperties.Connections = @() - $ServerProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $ServerProperties.Connections[0].Credential = $nchostcertObject - $ServerProperties.Connections[0].CredentialType = $nchostcertObject.properties.Type - $ServerProperties.Connections[0].ManagementAddresses = @($NodeFQDN) - $ServerProperties.Connections[0].Port = $port - - $ServerProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $ServerProperties.Connections[1].Credential = $nchostuserObject - $ServerProperties.Connections[1].CredentialType = $nchostuserObject.properties.Type - $ServerProperties.Connections[1].ManagementAddresses = @($NodeFQDN) - - $ServerProperties.NetworkInterfaces = @() - $serverProperties.NetworkInterfaces += new-object Microsoft.Windows.NetworkController.NwInterface - $serverProperties.NetworkInterfaces[0].ResourceId = $VirtualSwitchName - $serverProperties.NetworkInterfaces[0].Properties = new-object Microsoft.Windows.NetworkController.NwInterfaceProperties - $ServerProperties.NetworkInterfaces[0].Properties.LogicalSubnets = $PALogicalSubnets - - write-sdnexpresslog "Certdata contains $($certdata.count) bytes." - - $ServerProperties.Certificate = [System.Convert]::ToBase64String($CertData) - - write-sdnexpresslog "New server object." - $Server = New-NetworkControllerServer -ConnectionURI $uri -ResourceId $VirtualSwitchId -Properties $ServerProperties @CredentialParam -Force -passinnerexception - - write-sdnexpresslog "Configure DNS PRoxy." - - invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $InstanceId - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\NcHostAgent\Parameters" -Name "HostId" -Value $InstanceId -PropertyType "String" -Force | out-null - - $dnsproxy = get-service DNSProxy -ErrorAction Ignore - if ($dnsproxy -ne $null) { - write-verbose "Stopping DNS proxy service (2016 only)." - $dnsproxy | Stop-Service -Force - } - - write-verbose "Restarting host agents." - $slbstatus = get-service slbhostagent - if ($slbstatus.status -eq "Running") { - Stop-Service SlbHostAgent -Force - } - Stop-Service NcHostAgent -Force - - Start-Service NcHostAgent - if ($slbstatus.status -eq "Running") { - Start-Service SlbHostAgent - } - - if ($dnsproxy -ne $null) { - write-verbose "Starting DNS proxy service (2016 only)." - Set-Service -Name "DnsProxy" -StartupType Automatic - $dnsproxy | Start-Service - } - write-verbose "DNS proxy config complete." - - } -ArgumentList $Server.InstanceId | parse-remoteoutput - - write-sdnexpresslog "New-SDNExpressHost Exit" -} - - - - # # - # # ##### # # # ##### # # - # # # # # # # # # - # # # # # # # # - # # # # # # # # - # # # # # # # # - ##### # # ###### # # # - - - -function Write-SDNExpressLog -{ - Param([String] $Message) - - $FormattedDate = date -Format "yyyyMMdd-HH:mm:ss" - $FormattedMessage = "[$FormattedDate] $Message" - write-verbose $FormattedMessage - - $formattedMessage | out-file ".\$logname" -Append -} - - -function Write-SDNExpressLogParameter -{ - Param( - [string] $paramname, - [Object] $value - - ) - if ($null -eq $value) { - Write-SDNExpressLog " -$($paramname): null" - } elseif ($value.gettype().Name -eq "Object[]") { - for ($i = 0; $i -lt $value.count; $i++ ) { - Write-SDNExpressLogParameter "$($paramname)[$i]" $value[$i] - } - } elseif ($value.getType().Name -eq "Hashtable") { - foreach ($key in $value.keys) { - Write-SDNExpressLogParameter "$paramname.$key" $value[$key] - } - } else { - Write-SDNExpressLog " -$($paramname): $($value)" - } -} -function Write-SDNExpressLogFunction -{ - Param( - [String] $FunctionName, - [Object] $BoundParameters, - [String] $UnboundArguments, - [object] $ParamSet - ) - - Write-SDNExpressLog "Enter Function: $FunctionName" - foreach ($param in $BoundParameters.keys) { - if ($param.ToUpper().Contains("PASSWORD") -or $param.ToUpper().Contains("KEY")) { - Write-SDNExpressLog " -$($param): ******" - } else { - $value = $BoundParameters[$param] - Write-SDNExpressLogParameter $param $value - } - } - Write-SDNExpressLog "Unbound Arguments: $UnboundArguments" - - if( Test-Path variable:\pscmdlet) { - if($null -ne $pscmdlet) { - write-SDNExpressLog "ParameterSet: $($paramset.ParameterSetName)" - } - } -} - -function write-LogProgress { - param([String] $OperationId, [String] $Source, [String] $Context, [Int] $Percent) - $message = "$OperationId;$Source;$Context;$Percent" - Microsoft.PowerShell.Management\Write-EventLog -LogName "Microsoft-ServerManagementExperience" -Source "SmeHciScripts-SDN" -EventId 0 -Category 0 -EntryType Information -Message $message -ErrorAction SilentlyContinue -} -function Write-LogError { - param( - [String] $OperationId, - [String] $Source, - [String] $ErrorCode, - [String] $LogMessage, - [String] $ErrorMessage = "" - ) - $message = "$OperationId;$Source;$ErrorCode;$LogMessage;$ErrorMessage" - write-sdnexpresslog "LogError: $message" - Microsoft.PowerShell.Management\Write-EventLog -LogName "Microsoft-ServerManagementExperience" -Source "SmeHciScripts-SDN" -EventId 0 -Category 0 -EntryType Error -Message $message -ErrorAction SilentlyContinue -} - -function Parse-RemoteOutput -{ - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline)] - $item - ) - begin { - write-sdnexpresslog "Begin Invoke-Command output:" - $items = @() - $ComputerStates = @{} - } - Process { - switch ([Convert]::ToInt32($ComputerStates[$item.pscomputername])) { - -1 { #Verbose output state - write-sdnexpresslog "[$($item.pscomputername)] $item" - $ComputerStates[$item.pscomputername] = 0 - } - 0 { # No state - if ($item -eq "[V]") { - $ComputerStates[$item.pscomputername] = -1 - } else { - $ComputerStates[$item.pscomputername] = [Convert]::ToInt32($item) - } - } - default { #count of output objects to add - $items += $item - $ComputerStates[$item.pscomputername] = $ComputerStates[$item.pscomputername] - 1 - } - } - } - end { - write-sdnexpresslog "Finished Invoke-Command output." - return $items - } -} - - -function IPv4toUInt32 { - param( - [string] $ip - ) - $b = ([ipaddress]$ip).GetAddressBytes() - [array]::Reverse($b) - return [bitconverter]::ToUInt32($b,0) - } - - function UInt32toIPv4 { - param( - [UInt32] $ip - ) - - $b = [bitconverter]::GetBytes($ip) - [array]::Reverse($b) - return ([ipaddress]$b).IPAddressToString - } - -function Get-IPAddressInSubnet -{ - param([string] $subnet, [uInt64] $offset) - write-sdnexpresslog "$($MyInvocation.InvocationName)" - write-sdnexpresslog " -Subnet: $subnet" - write-sdnexpresslog " -Offset: $Offset" - - $prefix = ($subnet.split("/"))[0] - - $ip = [ipaddress] $prefix - - $bytes = $ip.getaddressbytes() - $i = $bytes.count - 1 - while ($offset -gt 0) { - $rem = $offset % 256 - $bytes[$i] += $rem - $offset = $offset / 0xFF - $i-- - } - - $ip2 = [IPAddress] $bytes - - $return = $ip2.IPAddressToString - write-sdnexpresslog "$($MyInvocation.InvocationName) Returns $return" - $return -} - - -function Get-IPLastAddressInSubnet -{ - param([string] $subnet) - write-sdnexpresslog "$($MyInvocation.InvocationName)" - write-sdnexpresslog " -Subnet: $subnet" - - $prefix = ($subnet.split("/"))[0] - $bits = ($subnet.split("/"))[1] - - $ip = [IPAddress] $prefix - if ($ip.AddressFamily -eq "InterNetworkV6") { - $totalbits = 128 - } else { - $totalbits = 32 - } - - $bytes = $ip.getaddressbytes() - $rightbits = $totalbits - $bits - - write-sdnexpresslog "rightbits: $rightbits" - $i = $bytes.count - 1 - while ($rightbits -gt 0) { - if ($rightbits -gt 7) { - write-sdnexpresslog "full byte" - $bytes[$i] = $bytes[$i] -bor 0xFF - $rightbits -= 8 - } else { - write-sdnexpresslog "Final byte: $($bytes[$i])" - $bytes[$i] = $bytes[$i] -bor (0xff -shr (8-$rightbits)) - write-sdnexpresslog "Byte: $($bytes[$i])" - $rightbits = 0 - } - $i-- - } - - $ip2 = [IPAddress] $bytes - - $return = $ip2.IPAddressToString - write-sdnexpresslog "$($MyInvocation.InvocationName) Returns $return" - $return -} - - - -function WaitForComputerToBeReady -{ - param( - [string[]] $ComputerName, - [Switch]$CheckPendingReboot, - [PSCredential] $Credential = $null, - [Int64] $LastBootUpTime = 0, - [Int] $Timeout = 1800 # 30 minutes - ) - - write-SDNExpressLog "Entering WaitForComputerToBeReady." - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $endtime = (get-date).ticks + ($timeout * 10000000) - - foreach ($computer in $computername) { - write-sdnexpresslog "Waiting up to $timeout seconds for $Computer to become active." - - $continue = $true - while ($continue) { - try { - $ps = $null - $result = "" - - klist purge | out-null #clear kerberos ticket cache - Clear-DnsClientCache #clear DNS cache in case IP address is stale - - write-sdnexpresslog "Attempting to contact $Computer." - try { - $ps = new-pssession -computername $Computer @CredentialParam -ErrorAction Stop - } - catch { - write-sdnexpresslog "Unable to create PowerShell session on $Computer : $($_.Exception.Message)" - } - if ($ps -ne $null) { - try { - if ($CheckPendingReboot.IsPresent) { - $result = Invoke-Command -Session $ps -ScriptBlock { - if (Test-Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") { - "Reboot pending" - } - else { - hostname - } - } - } - elseif ($LastBootUpTime -gt 0) { - $result = Invoke-Command -Session $ps -ScriptBlock { (gcim Win32_OperatingSystem).LastBootUpTime.ticks } - write-sdnexpresslog "LastBootUpTime is $LastBootUpTime, Current BootUpTime is $result" - if ($result -ne $LastBootUpTime) { - $result = Invoke-Command -Session $ps -ScriptBlock { hostname } - } else { - "Reboot pending" - } - } - else { - $result = Invoke-Command -Session $ps -ScriptBlock { hostname } - } - } catch { - write-sdnexpresslog "Ignoring exception from Invoke-Command, machine may not be rebooting." - } - remove-pssession $ps - } - if ($result -eq $Computer.split(".")[0]) { - $continue = $false - break - } - if ($result -eq "Reboot pending") { - if ($CheckPendingReboot.IsPresent) { - write-sdnexpresslog "Reboot pending on $Computer according to registry. Waiting for restart." - } else { - write-sdnexpresslog "Reboot pending on $Computer according to last boot up time. Waiting for restart." - } - } - } - catch - { - write-sdnexpresslog "Ignoring exception while waiting for computer to be ready, machine may not be rebooting." - } - - if ((get-date).ticks -gt $endtime) { - $message = "$Computer is not ready after $timeout second timeout." - write-sdnexpresslog $message - throw $message - } - - write-sdnexpresslog "$Computer is not ready, sleeping for 10 seconds." - sleep 10 - } - write-sdnexpresslog "$Computer IS ACTIVE. Continuing with deployment." - } -} - - - - # # # - # # ##### ##### ## ## # # # # - # # # # # # # # # # # # # # - # # # # # # # # # # # ## - ####### # # # # # # # # ## - # # # # # # # # # # # # - # # ##### ##### # # #### # # - - - -Function Add-SDNExpressMux { - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [string] $ComputerName, - [Object] $NCHostCert, - [String] $PAMacAddress = "", - [String] $LocalPeerIP, - [String] $MuxASN, - [Object] $Routers, - [String] $PAGateway = "", - [PSCredential] $Credential = $null, - [Bool] $IsFC = $false - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - - $PASubnets = @() - $LogicalNetworkObject = get-NetworkControllerLogicalNetwork -ConnectionURI $uri -ResourceID "HNVPA" @CredentialParam - $PASubnets += $LogicalNetworkObject.properties.subnets.properties.AddressPrefix - foreach ($Router in $Routers) { - $PASubnets += "$($Router.RouterIPAddress)/32" - } - - Write-SDNExpressLog "PA Subnets to add to PA adapter in mux: $PASubnets" - - invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $LocalPeerIP, - [String] $PAGateway, - [String[]] $PASubnets - ) - - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - function private:IPv4toUInt32 { - param( [string] $ip) - $b = ([ipaddress]$ip).GetAddressBytes() - [array]::Reverse($b) - return [bitconverter]::ToUInt32($b,0) - } - - function private:UInt32toIPv4 { - param( [UInt32] $ip ) - - $b = [bitconverter]::GetBytes($ip) - [array]::Reverse($b) - return ([ipaddress]$b).IPAddressToString - } - - $ipa = get-netipaddress -ipaddress $LocalPeerIP - $nic = Get-NetAdapter -interfaceindex $ipa.interfaceindex -ErrorAction Ignore - - if ($nic -eq $null) - { - throw "No adapter with LocalPeer/PA IP address $LocalPeerIP found" - } - - if (![String]::IsNullOrEmpty($PAGateway)) { - $subnetprefix = UInt32toIPv4 ((IPv4toUInt32 $ipa.ipaddress) -shr (32-$ipa.prefixlength) -shl (32-$ipa.prefixlength)) - $subnetprefix = "$subnetprefix/$($ipa.prefixlength)" - - foreach ($PASubnet in $PASubnets) { - if ($pasubnet -ne $subnetprefix) { - remove-netroute -DestinationPrefix $PASubnet -InterfaceIndex $nic.ifIndex -Confirm:$false -erroraction ignore | out-null - new-netroute -DestinationPrefix $PASubnet -InterfaceIndex $nic.ifIndex -NextHop $PAGateway -erroraction ignore | out-null - - } - } - } - - $nicProperty = Get-NetAdapterAdvancedProperty -Name $nic.Name -AllProperties -RegistryKeyword *EncapOverhead -ErrorAction Ignore - if($nicProperty -eq $null) - { - New-NetAdapterAdvancedProperty -Name $nic.Name -RegistryKeyword *EncapOverhead -RegistryValue 160 | out-null - } - else - { - Set-NetAdapterAdvancedProperty -Name $nic.Name -AllProperties -RegistryKeyword *EncapOverhead -RegistryValue 160 - } - - add-windowsfeature SoftwareLoadBalancer -Restart | out-null - } -argumentlist $LocalPeerIP, $PAGateway, $PASubnets | parse-remoteoutput - - WaitforComputerToBeReady -ComputerName $ComputerName -CheckPendingReboot @CredentialParam - - if ($IsFC) - { - Enable-NetworkControllerOnFailoverClusterLoggingOnDevice -DeviceName $ComputerName -Device 'Mux' - } - - $MuxFQDN = invoke-command -computername $ComputerName @CredentialParam { - Return (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - } - - #wait for computer to restart. - - $CertData = invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $funcDefGetSdnCert - ) - - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Creating self signed certificate..."; - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $NodeFQDN - if ($cert -eq $null) { - $cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$NodeFQDN" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") - } - - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) - Set-Acl $privKeyCertFile.FullName $privKeyAcl - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $cert | out-null - - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $CertData - } -ArgumentList $Global:fdGetSdnCert | Parse-RemoteOutput - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $NCHostCert | out-null - $NCHostCertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - if ($NCHostCert.Issuer -eq $NCHostCert.Subject) { - invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - - Remove-Item $TempFile.FullName -Force - } -ArgumentList (,$NCHostCertData) | parse-remoteoutput - } - - $vmguid = invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $RestName, - [String] $funcDefGetSdnCert - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - . ([ScriptBlock]::Create($funcDefGetSdnCert)) - $Cert = GetSdnCert -subjectName $NodeFQDN - - write-output "RestName $($RestName) NodeFQDN $($NodeFQDN) Thumbprint $($Cert.Thumbprint)" - - New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SlbMux" -Force -Name SlbmThumb -PropertyType String -Value $RestName | out-null - New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SlbMux" -Force -Name MuxCert -PropertyType String -Value $NodeFQDN | out-null - - Get-ChildItem -Path WSMan:\localhost\Listener | where-object {$_.Keys.Contains("Transport=HTTPS") } | Remove-Item -Recurse -Force | out-null - New-Item -Path WSMan:\localhost\Listener -Address * -HostName $NodeFQDN -Transport HTTPS -CertificateThumbPrint $cert.Thumbprint -Force | out-null - - Get-Netfirewallrule -Group "@%SystemRoot%\system32\firewallapi.dll,-36902" | Enable-NetFirewallRule | out-null - - start-service slbmux | out-null - - write-output (get-childitem -Path "HKLM:\software\microsoft\virtual machine\guest" | get-itemproperty).virtualmachineid - } -ArgumentList $RestName, $Global:fdGetSdnCert | parse-remoteoutput - - write-sdnexpresslog "Add VirtualServerToNC"; - $nchostcertObject = get-networkcontrollerCredential -Connectionuri $URI -ResourceId "NCHostCert" @CredentialParam - $nchostuserObject = get-networkcontrollerCredential -Connectionuri $URI -ResourceId "NCHostUser" @CredentialParam - - $VirtualServerProperties = new-object Microsoft.Windows.NetworkController.VirtualServerProperties - $VirtualServerProperties.Connections = @() - $VirtualServerProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $VirtualServerProperties.Connections[0].Credential = $nchostcertObject - $VirtualServerProperties.Connections[0].CredentialType = $nchostcertObject.properties.Type - $VirtualServerProperties.Connections[0].ManagementAddresses = @($MuxFQDN) - $VirtualServerProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $VirtualServerProperties.Connections[1].Credential = $nchostuserObject - $VirtualServerProperties.Connections[1].CredentialType = $nchostuserObject.properties.Type - $VirtualServerProperties.Connections[1].ManagementAddresses = @($MuxFQDN) - write-sdnexpresslog "Certdata contains $($certdata.count) bytes." - $VirtualServerProperties.Certificate = [System.Convert]::ToBase64String($CertData) - $VirtualServerProperties.vmguid = $vmGuid - - $VirtualServer = new-networkcontrollervirtualserver -connectionuri $uri @CredentialParam -MarkServerReadOnly $false -ResourceId $MuxFQDN -Properties $VirtualServerProperties -force -passinnerexception - - $MuxProperties = new-object Microsoft.Windows.NetworkController.LoadBalancerMuxProperties - $muxProperties.RouterConfiguration = new-object Microsoft.Windows.NetworkController.RouterConfiguration - $muxProperties.RouterConfiguration.LocalASN = $MuxASN - $muxProperties.RouterConfiguration.PeerRouterConfigurations = @() - foreach ($router in $routers) { - $peerRouter = new-object Microsoft.Windows.NetworkController.PeerRouterConfiguration - $peerRouter.LocalIPAddress = $LocalPeerIP - $peerRouter.PeerASN = $Router.RouterASN - $peerRouter.RouterIPAddress = $Router.RouterIPAddress - $peerRouter.RouterName = $Router.RouterIPAddress.Replace(".", "_") - $muxProperties.RouterConfiguration.PeerRouterConfigurations += $PeerRouter - } - $muxProperties.VirtualServer = $VirtualServer - - $Mux = new-networkcontrollerloadbalancermux -connectionuri $uri @CredentialParam -ResourceId $MuxFQDN -Properties $MuxProperties -force -passinnerexception - write-sdnexpresslog "New-SDNExpressMux Exit" -} - - - # ##### ###### - # # ##### ##### # # ## ##### ###### # # ## # # # # #### #### # - # # # # # # # # # # # # # # # # # # # # # # # # - # # # # # # # #### # # # ##### # # # # # ###### # # # # # - ####### # # # # # # ###### # # # ## # ###### # # # # # # # - # # # # # # # # # # # # ## ## # # # # # # # # # - # # ##### ##### ##### # # # ###### # # # # # # #### #### ###### - - - -function New-SDNExpressGatewayPool -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [PSCredential] $Credential, - [String] $PoolName, - [Parameter(Mandatory=$true,ParameterSetName="TypeAll")] - [Switch] $IsTypeAll, - [Parameter(Mandatory=$true,ParameterSetName="TypeIPSec")] - [Switch] $IsTypeIPSec, - [Parameter(Mandatory=$true,ParameterSetName="TypeGre")] - [Switch] $IsTypeGre, - [Parameter(Mandatory=$true,ParameterSetName="TypeForwarding")] - [Switch] $IsTypeForwarding, - [Parameter(Mandatory=$false,ParameterSetName="TypeAll")] - [Parameter(Mandatory=$false,ParameterSetName="TypeGre")] - [String] $PublicIPAddress, - [Parameter(Mandatory=$false,ParameterSetName="TypeAll")] - [Parameter(Mandatory=$true,ParameterSetName="TypeGre")] - [String] $GreSubnetAddressPrefix, - [Parameter(Mandatory=$false,ParameterSetName="TypeGre")] - [String] $GrePoolStart = $null, - [Parameter(Mandatory=$false,ParameterSetName="TypeGre")] - [String] $GrePoolEnd = $null, - [String] $Capacity, - [Int] $RedundantCount = -1 - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - - $gresubnet = $null - if (-1 -eq $Redundantcount) { - write-sdnexpresslog "RedundantCount not set, defaulting to 1." - $RedundantCount = 1 - } - - if ($IsTypeAll -or $IsTypeIPSec) { - $PublicIPProperties = new-object Microsoft.Windows.NetworkController.PublicIPAddressProperties - $publicIPProperties.IdleTimeoutInMinutes = 4 - - if ([String]::IsNullOrEmpty($PublicIPAddress)) { - $PublicIPProperties.PublicIPAllocationMethod = "Dynamic" - } else { - $PublicIPProperties.PublicIPAllocationMethod = "Static" - $PublicIPProperites.IPAddress = $PublicIPAddress - } - $PublicIPAddressObject = New-NetworkControllerPublicIPAddress -connectionURI $uri -ResourceId $PoolName -Properties $PublicIPProperties -Force @CredentialParam -passinnerexception - } - - if ($IsTypeGre -or $IsTypeAll) { - if ([string]::IsNullOrEmpty($grePoolStart)) { - $GrePoolStart = (Get-IPAddressInSubnet -subnet $GreSubnetAddressPrefix -offset 1) - } - if ([string]::IsNullOrEmpty($grePoolEnd)) { - $GrePoolEnd = (Get-IPLastAddressInSubnet -subnet $GreSubnetAddressPrefix) - } - - $logicalNetwork = try { get-networkcontrollerlogicalnetwork -ResourceId "GreVIP" -connectionuri $uri @CredentialParam } catch {} - - if ($logicalNetwork -eq $null) { - $LogicalNetworkProperties = new-object Microsoft.Windows.NetworkController.LogicalNetworkProperties - $LogicalNetworkProperties.NetworkVirtualizationEnabled = $false - $LogicalNetwork = New-NetworkControllerLogicalNetwork -ConnectionURI $uri -ResourceID "GreVIP" -properties $LogicalNetworkProperties @CredentialParam -Force -passinnerexception - } - - foreach ($subnet in $logicalnetwork.properties.subnets) { - if ($Subnet.properties.AddressPrefix -eq $GreSubnetAddressPrefix) { - $GreSubnet = $subnet - } - } - - if ($GreSubnet -eq $Null) { - $LogicalSubnetProperties = new-object Microsoft.Windows.NetworkController.LogicalSubnetProperties - $LogicalSubnetProperties.AddressPrefix = $GreSubnetAddressPrefix - $logicalSubnetProperties.DefaultGateways = @(get-ipaddressinsubnet -subnet $GreSubnetAddressPrefix) - - $greSubnet = New-NetworkControllerLogicalSubnet -ConnectionURI $uri -LogicalNetworkId "GreVIP" -ResourceId $GreSubnetAddressPrefix.Replace("/", "_") -properties $LogicalSubnetProperties @CredentialParam -Force -passinnerexception - - $IPpoolProperties = new-object Microsoft.Windows.NetworkController.IPPoolproperties - $ippoolproperties.startipaddress = $GrePoolStart - $ippoolproperties.endipaddress = $GrePoolEnd - - $IPPoolObject = New-networkcontrollerIPPool -ConnectionURI $uri -NetworkId "GreVIP" -SubnetId $GreSubnetAddressPrefix.Replace("/", "_") -ResourceID $GreSubnetAddressPrefix.Replace("/", "_") -Properties $IPPoolProperties @CredentialParam -force -passinnerexception - } - } - - $GatewayPoolProperties = new-object Microsoft.Windows.NetworkController.GatewayPoolProperties - $GatewayPoolProperties.RedundantGatewayCount = "$RedundantCount" - $GatewayPoolProperties.GatewayCapacityKiloBitsPerSecond = $Capacity - - if ($IsTypeAll) { - $GatewayPoolProperties.Type = "All" - - $GatewayPoolProperties.IPConfiguration = new-object Microsoft.Windows.NetworkController.IPConfig - $GatewayPoolProperties.IPConfiguration.PublicIPAddresses = @() - $GatewayPoolProperties.IPConfiguration.PublicIPAddresses += $PublicIPAddressObject - - $GatewayPoolProperties.IpConfiguration.GreVipSubnets = @() - $GatewayPoolProperties.IPConfiguration.GreVipSubnets += $GreSubnet - } elseif ($IsTypeIPSec) { - $GatewayPoolProperties.Type = "S2sIpSec" - - $GatewayPoolProperties.IPConfiguration = new-object Microsoft.Windows.NetworkController.IPConfig - $GatewayPoolProperties.IPConfiguration.PublicIPAddresses = @() - $GatewayPoolProperties.IPConfiguration.PublicIPAddresses += $PublicIPAddressObject - } elseif ($IsTypeGre) { - $GatewayPoolProperties.Type = "S2sGre" - - $GatewayPoolProperties.IPConfiguration = new-object Microsoft.Windows.NetworkController.IPConfig - $GatewayPoolProperties.IpConfiguration.GreVipSubnets = @() - $GatewayPoolProperties.IPConfiguration.GreVipSubnets += $GreSubnet - } elseif ($IsTypeForwarding) { - $GatewayPoolProperties.Type = "Forwarding" - } - - $GWPoolObject = new-networkcontrollergatewaypool -connectionURI $URI -ResourceId $PoolName -Properties $GatewayPoolProperties -Force @CredentialParam -passinnerexception - write-sdnexpresslog "New-SDNExpressGatewayPool Exit" -} - - - ### ##### ###### # # ####### ##### - # # # # ##### # ## # # ###### ###### # # # # ## # # # # ##### ##### ###### #### #### # # ## ##### ###### # # ## # # - # ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # # # # # # # # # # # # ##### ##### ##### # # # # # ##### ## # # # # ##### #### #### # #### # # # ##### # # # # # - # # # # # # # ###### # # # # # # # # # # # ## ##### ##### # # # # # ###### # # # ## # ###### # - # # ## # # # # # # # # # # # # # # ## # # # # # # # # # # # # # # # # # ## ## # # # - ### # # # # # # # ###### # ###### ###### ##### ###### # # ####### # # # # # ###### #### #### ##### # # # ###### # # # # # - -function Initialize-SDNExpressGateway { - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [string] $ComputerName, - [string] $JoinDomain, - [string] $HostName, - [String] $FrontEndLogicalNetworkName = "HNVPA", - [String] $FrontEndAddressPrefix, - [PSCredential] $Credential = $null - ) - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - - $GatewayFQDN = "$computername.$JoinDomain" - - $LogicalSubnet = get-networkcontrollerlogicalSubnet -LogicalNetworkId $FrontEndLogicalNetworkName -ConnectionURI $uri @CredentialParam - $LogicalSubnet = $LogicalSubnet | where-object {$_.properties.AddressPrefix -eq $FrontEndAddressPrefix } - - write-sdnexpresslog "Found logical subnet $($logicalsubnet.resourceid)" - - $backendNic = $null - try { $backendNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_BackEnd" } catch { } - if (!$backendNic) { - write-sdnexpresslog "Creating backend NIC" - $NicProperties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceProperties - $NicProperties.privateMacAllocationMethod = "Dynamic" - $BackEndNic = new-networkcontrollernetworkinterface -connectionuri $uri @CredentialParam -ResourceId "$($GatewayFQDN)_BackEnd" -Properties $NicProperties -force -passinnerexception - - while ($backendNic.Properties.ProvisioningState -ne "Succeeded" -and $backendnic.Properties.ProvisioningState -ne "Failed") { - $backendNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_BackEnd" - } - } - - write-sdnexpresslog "Backend MAC Address is $($BackendNic.properties.PrivateMacAddress)" - - $frontendNic = $null - try { $frontendNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_FrontEnd" } catch { } - if (!$frontendNic) { - write-sdnexpresslog "Creating frontend NIC" - $NicProperties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceProperties - $NicProperties.privateMacAllocationMethod = "Dynamic" - $NicProperties.IPConfigurations = @() - $NicProperties.IPConfigurations += new-object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfiguration - $NicProperties.IPConfigurations[0].ResourceId = "FrontEnd" - $NicProperties.IPConfigurations[0].Properties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfigurationProperties - $NicProperties.IPConfigurations[0].Properties.Subnet = new-object Microsoft.Windows.NetworkController.Subnet - $nicProperties.IpConfigurations[0].Properties.Subnet.ResourceRef = $LogicalSubnet.ResourceRef - $NicProperties.IPConfigurations[0].Properties.PrivateIPAllocationMethod = "Dynamic" - $FrontEndNic = new-networkcontrollernetworkinterface -connectionuri $uri @CredentialParam -ResourceId "$($GatewayFQDN)_FrontEnd" -Properties $NicProperties -force -passinnerexception - - while ($frontendNic.Properties.ProvisioningState -ne "Succeeded" -and $frontendNic.Properties.ProvisioningState -ne "Failed") { - $frontendNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_FrontEnd" - } - } - - write-sdnexpresslog "Frontend IP Address is [$($frontendNic.properties.IPConfigurations[0].Properties.PrivateIPAddress)]" - write-sdnexpresslog "Frontend MAC Address is $($FrontendNic.properties.PrivateMacAddress)" - - if ([string]::IsNullOrEmpty($frontendNic.properties.IPConfigurations[0].Properties.PrivateIPAddress)) { - #need to find an address that is not in use - $ips = @() - - #1 - get-pacamapping from a host to find PAs and add to list of IPs to not use - $PACAIps = invoke-command -computername $hostname { - ((get-pacamapping) | select-object 'PA IP Address').'PA IP Address' - } - - if ($null -ne $PACAIps) { - $ips += $PACAIps - } - - #2 - get network interfaces and reservations from subnet so we know which IPs to skip over - foreach ($ipconfig in $logicalsubnet.properties.ipconfigurations) { - $ipconfig = get-networkcontrollernetworkinterfaceipconfiguration -connectionuri $uri @CredentialParam -NetworkInterfaceId $ipconfig.resourceRef.split('/')[2] -ResourceId $ipconfig.resourceRef.split('/')[4] - if (![string]::IsNullOrEmpty($ipconfig.properties.privateipaddress)) { - $ips += $ipconfig.properties.privateipaddress - } - } - - # Reserved IP addresses aren't in a IP configuration, but we still shouldn't use them for our front end IP - skip over - foreach ($res in $logicalsubnet.Properties.IpReservations) { - $res = get-networkcontrollerIpReservation -connectionUri $uri @CredentialParam -NetworkId $FrontEndLogicalNetworkName -SubnetId $LogicalSubnet.resourceId - if (![string]::IsNullOrEmpty($res.properties.reservedAddresses)) { - write-sdnexpresslog "Appending IP $($res.properties.reservedAddresses)" - $ips += $res.properties.reservedAddresses - } - } - - $lastIPString = Get-IPLastAddressInSubnet $logicalsubnet.properties.addressprefix - $firstIPString = get-ipaddressinsubnet $logicalsubnet.properties.addressprefix 1 - - write-sdnexpresslog "Last IP in PA subnet: $lastipstring" - #3 - convert to numbers and put in sorted array - $lastIP = IPv4toUInt32 $lastIPString - write-sdnexpresslog "First IP in PA subnet: $firstipstring" - $firstIP = IPv4toUInt32 $firstIPString - - $intips = @() - foreach ($ip in $ips) { - write-sdnexpresslog "Checking IP : $ip" - $checkIP = IPv4toUInt32 $ip - - if ($checkIP -ge $firstIP -and $checkip -lt $lastip) { - $intIPs += $checkIP - } - } - - $ips = $intips | Sort-Object -Unique - - #4 - iterate to find an unused address - $useaddress = $null - - foreach ($ipp in $logicalsubnet.properties.ippools) { - write-sdnexpresslog "Checking Pool range : $($ipp.properties.startipaddress) - $($ipp.properties.endipaddress))" - $PoolStart = IPv4toUInt32 $ipp.properties.startipaddress - $PoolEnd = IPv4toUInt32 $ipp.properties.endipaddress - - for ($i = $PoolEnd; $i -ge $PoolStart; $i--) { - if (!($i -in $ips)) { - write-sdnexpresslog "Address match : $i" - $useaddress = UInt32ToIPv4 $i - break - } - } - - if ($useaddress) { - write-sdnexpresslog "Updating frontend NIC to IP: $UseAddress" - #5 - set static address on network interface - $frontendNic.properties.IPConfigurations[0].Properties.PrivateIPAddress = $UseAddress - $frontendNic.properties.IPConfigurations[0].Properties.PrivateIPAllocationMethod = "Static" - $FrontEndNic = new-networkcontrollernetworkinterface -connectionuri $uri @CredentialParam -ResourceId $frontendNic.Resourceid -Properties $frontendNic.properties -force -passinnerexception - break - } - } - - } - - write-sdnexpresslog "Initialize-sdnexpressgateway results:" - - $Result = @{ - 'BackEndMac' = $BackendNic.properties.PrivateMacAddress; - 'FrontEndMac' = $FrontendNic.properties.PrivateMacAddress; - 'FrontEndIP' = $FrontendNic.properties.ipconfigurations[0].properties.privateIPAddress - } - - write-sdnexpresslog " BackEndMac: $($result.frontendmac)" - write-sdnexpresslog " FrontEndMac: $($result.backendmac)" - write-sdnexpresslog " FrontEndIP: $($result.frontendIP)" - - return $Result -} - - - # ##### - # # ##### ##### # # ## ##### ###### # # ## # # - # # # # # # # # # # # # # # # # # - # # # # # # # #### # # # ##### # # # # # - ####### # # # # # # ###### # # # ## # ###### # - # # # # # # # # # # # # ## ## # # # - # # ##### ##### ##### # # # ###### # # # # # - - - -Function New-SDNExpressGateway { - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [String] $RestName, - [string] $ComputerName, - [String] $HostName, - [Object] $NCHostCert, - [String] $PoolName, - [String] $FrontEndLogicalNetworkName, - [String] $FrontEndAddressPrefix, - [String] $FrontEndIp, - [String] $FrontEndMac, - [String] $BackEndMac, - [Parameter(Mandatory=$true,ParameterSetName="SinglePeer")] - [String] $RouterASN = $null, - [Parameter(Mandatory=$true,ParameterSetName="SinglePeer")] - [String] $RouterIP = $null, - [String] $LocalASN = $null, - [Parameter(Mandatory=$true,ParameterSetName="MultiPeer")] - [Object] $Routers, - [String] $PAGateway = "", - [String[]] $ManagementRoutes, - [PSCredential] $Credential = $null, - [Switch] $UseFastPath, - [Bool] $IsFC = $false - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - $uri = "https://$RestName" - $RebootRequired = invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $FrontEndMac, - [String] $BackEndMac - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $feature = get-windowsfeature -Name RemoteAccess - - if (!$feature.Installed) { - write-verbose "Adding RemoteAccess feature." - Add-WindowsFeature -Name RemoteAccess -IncludeAllSubFeature -IncludeManagementTools | out-null - return $true - } else { - return $false - } - - } | Parse-RemoteOutput - - if ($rebootrequired) { - write-sdnexpresslog "Restarting $computername, waiting up to 10 minutes for powershell remoting to return." - restart-computer -computername $computername @CredentialParam -force -wait -for powershell -timeout 600 -Protocol WSMan -verbose - write-sdnexpresslog "Restart complete, installing RemoteAccess multitenancy and GatewayService." - } - - if ($IsFC) - { - Enable-NetworkControllerOnFailoverClusterLoggingOnDevice -DeviceName $ComputerName -Device 'Gateway' - } - - $PASubnets = @() - $LogicalNetworkObject = get-NetworkControllerLogicalNetwork -ConnectionURI $uri -ResourceID "HNVPA" -Credential $Credential - - $PASubnets += $LogicalNetworkObject.properties.subnets.properties.AddressPrefix - foreach ($Router in $Routers) { - $PASubnets += "$($Router.RouterIPAddress)/32" - } - - - invoke-command -computername $ComputerName @CredentialParam { - param( - [String] $FrontEndMac, - [String] $BackEndMac, - [String[]] $ManagementRoutes, - [String] $PAGateway, - [String[]] $PASubnets - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - # Get-NetAdapter returns MacAddresses with hyphens '-' - $FrontEndMac = [regex]::matches($FrontEndMac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - $BackEndMac = [regex]::matches($BackEndMac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - - Set-Item WSMan:\localhost\MaxEnvelopeSizekb -Value 7000 | out-null - - write-verbose "Renaming Network Adapters" - - $adapters = Get-NetAdapter - - $adapter = $adapters | where-object {$_.MacAddress -eq $BackEndMac} - $adapter | Rename-NetAdapter -NewName "Internal" -Confirm:$false -ErrorAction Ignore | out-null - - $adapter = $adapters | where-object {$_.MacAddress -eq $FrontEndMac} - $adapter | Rename-NetAdapter -NewName "External" -Confirm:$false -ErrorAction Ignore | out-null - - Start-Sleep 10 - - write-verbose "Configure Managment Routes" - if($ManagementRoutes -ne $null) { - $mgmtNicIndex = (Get-NetAdapter | WHERE { $_.Name -ne "Internal" -AND $_.Name -ne "External"} ).ifIndex - [string] $mgmtNextHop = (Get-NetRoute -InterfaceIndex $mgmtNicIndex | where {$_.DestinationPrefix -eq '0.0.0.0/0'} | select NextHop).NextHop - foreach($route in $ManagementRoutes) { - write-verbose "new-netroute -DestinationPrefix $($route) -InterfaceIndex $($mgmtNicIndex) -NextHop $($mgmtNextHop) -erroraction ignore" - new-netroute -DestinationPrefix $route -InterfaceIndex $mgmtNicIndex -NextHop $mgmtNextHop -erroraction ignore | out-null - } - write-verbose "remove-netroute -DestinationPrefix 0.0.0.0/0 -InterfaceIndex $($mgmtNicIndex) -Confirm:$false -erroraction ignore" - remove-netroute -DestinationPrefix 0.0.0.0/0 -InterfaceIndex $mgmtNicIndex -Confirm:$false -erroraction ignore - Start-Sleep 10 - - $externalNicIndex = (Get-NetAdapter | where { $_.MacAddress -eq $FrontEndMac } ).ifIndex - if (![String]::IsNullOrEmpty($PAGateway)) { - foreach ($PASubnet in $PASubnets) { - write-verbose "new-netroute -DestinationPrefix $($PASubnet ) -InterfaceIndex $($externalNicIndex) -NextHop $($PAGateway) -erroraction ignore" - remove-netroute -DestinationPrefix $PASubnet -InterfaceIndex $externalNicIndex -Confirm:$false -erroraction ignore | out-null - new-netroute -DestinationPrefix $PASubnet -InterfaceIndex $externalNicIndex -NextHop $PAGateway -erroraction ignore | out-null - } - Start-Sleep 10 - } - } - - $RemoteAccess = get-RemoteAccess - if ($RemoteAccess -eq $null -or $RemoteAccess.VpnMultiTenancyStatus -ne "Installed") - { - write-verbose "Enabling remote access multi-tenancy" - Install-RemoteAccess -MultiTenancy | out-null - } else { - write-verbose "Remote Access multi-tenancy already enabled." - } - - Get-Netfirewallrule -Group "@%SystemRoot%\system32\firewallapi.dll,-36902" | Enable-NetFirewallRule - - if ($UseFastPath) { - $GatewayService = get-service GatewayService -erroraction Ignore - if ($gatewayservice -ne $null) { - write-verbose "Enabling gateway service." - Set-Service -Name GatewayService -StartupType Automatic | out-null - Start-Service -Name GatewayService | out-null - } - } - } -ArgumentList $FrontEndMac, $BackEndMac, $ManagementRoutes,$PAGateway, $PASubnets | Parse-RemoteOutput - - write-sdnexpresslog "Configuring certificates." - - $GatewayFQDN = invoke-command -computername $ComputerName @CredentialParam { - Return (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - } - - $vmGuid = invoke-command -computername $ComputerName @CredentialParam { - return (get-childitem -Path "HKLM:\software\microsoft\virtual machine\guest" | get-itemproperty).virtualmachineid - } - - invoke-command -computername $ComputerName @CredentialParam { - $raService = get-service RemoteAccess -erroraction Ignore - - if ($raService -ne $null) { - # PS versions before 6.0 do not make a distinction between automatic and automatic delayed, need to use sc.exe - # auto start for remoteaccess removes at least one minute of delay in making the GW ready after reboot - if ($raService.StartType -eq "Automatic") { - sc.exe config remoteaccess start=auto | out-null; - sc.exe config sstpsvc start=auto | out-null; - } - } - } - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $NCHostCert | out-null - $NCHostCertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - # Only self signed cert may be imported in root - if ($NCHostCert.Subect -eq $NCHostCert.Issuer) - { - invoke-command -ComputerName $ComputerName @CredentialParam { - param( - [byte[]] $CertData - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - - $CertData | set-content $TempFile.FullName -Encoding Byte - import-certificate -filepath $TempFile.FullName -certstorelocation "cert:\localmachine\root" | out-null - Remove-Item $TempFile.FullName -Force - } -ArgumentList (,$NCHostCertData) | Parse-RemoteOutput - } - write-sdnexpresslog "Adding Network Interfaces to network controller." - - # Get-VMNetworkAdapter returns MacAddresses without hyphens '-'. NetworkInterface prefers without hyphens also. - - $FrontEndMac = [regex]::matches($FrontEndMac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "" - $BackEndMac = [regex]::matches($BackEndMac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "" - - $LogicalSubnet = get-networkcontrollerlogicalSubnet -LogicalNetworkId $FrontEndLogicalNetworkName -ConnectionURI $uri @CredentialParam - $LogicalSubnet = $LogicalSubnet | where-object {$_.properties.AddressPrefix -eq $FrontEndAddressPrefix } - - try { - $BackEndNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_BackEnd" - } catch { - $NicProperties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceProperties - $nicproperties.PrivateMacAddress = $BackEndMac - $NicProperties.privateMacAllocationMethod = "Static" - $BackEndNic = new-networkcontrollernetworkinterface -connectionuri $uri @CredentialParam -ResourceId "$($GatewayFQDN)_BackEnd" -Properties $NicProperties -force -passinnerexception - } - - try { - $FrontEndNic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "$($GatewayFQDN)_FrontEnd" - } catch { - $NicProperties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceProperties - $nicproperties.PrivateMacAddress = $FrontEndMac - $NicProperties.privateMacAllocationMethod = "Static" - - $NicProperties.IPConfigurations = @() - $NicProperties.IPConfigurations += new-object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfiguration - $NicProperties.IPConfigurations[0].ResourceId = "FrontEnd" - $NicProperties.IPConfigurations[0].Properties = new-object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfigurationProperties - $NicProperties.IPConfigurations[0].Properties.Subnet = new-object Microsoft.Windows.NetworkController.Subnet - $nicProperties.IpConfigurations[0].Properties.Subnet.ResourceRef = $LogicalSubnet.ResourceRef - $NicProperties.IPConfigurations[0].Properties.PrivateIPAddress = $FrontEndIp - $NicProperties.IPConfigurations[0].Properties.PrivateIPAllocationMethod = "Static" - $FrontEndNic = new-networkcontrollernetworkinterface -connectionuri $uri @CredentialParam -ResourceId "$($GatewayFQDN)_FrontEnd" -Properties $NicProperties -force -passinnerexception - } - - write-sdnexpresslog "Setting port data on gateway VM NICs." - - $SetPortProfileBlock = { - param( - [String] $VMName, - [String] $MacAddress, - [String] $InstanceId - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $PortProfileFeatureId = "9940cd46-8b06-43bb-b9d5-93d50381fd56" - $NcVendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}" - - $vnic = Get-VMNetworkAdapter -VMName $VMName | where-object {$_.MacAddress -eq $MacAddress} - - $currentProfile = Get-VMSwitchExtensionPortFeature -FeatureId $PortProfileFeatureId -VMNetworkAdapter $vNic - - if ( $currentProfile -eq $null) - { - $portProfileDefaultSetting = Get-VMSystemSwitchExtensionPortFeature -FeatureId $PortProfileFeatureId - $portProfileDefaultSetting.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}" - $portProfileDefaultSetting.SettingData.CdnLabelString = "TestCdn" - $portProfileDefaultSetting.SettingData.CdnLabelId = 1111 - $portProfileDefaultSetting.SettingData.ProfileName = "Testprofile" - $portProfileDefaultSetting.SettingData.VendorId = $NcVendorId - $portProfileDefaultSetting.SettingData.VendorName = "NetworkController" - - $portProfileDefaultSetting.SettingData.ProfileId = "{$InstanceId}" - $portProfileDefaultSetting.SettingData.ProfileData = 1 - - Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $portProfileDefaultSetting -VMNetworkAdapter $vNic | out-null - } - else - { - $currentProfile.SettingData.ProfileId = "{$InstanceId}" - $currentProfile.SettingData.ProfileData = 1 - Set-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $currentProfile -VMNetworkAdapter $vNic | out-null - } - } - - invoke-command -ComputerName $HostName @CredentialParam -ScriptBlock $SetPortProfileBlock -ArgumentList $ComputerName, $BackEndMac, $BackEndNic.InstanceId | Parse-RemoteOutput - invoke-command -ComputerName $HostName @CredentialParam -ScriptBlock $SetPortProfileBlock -ArgumentList $ComputerName, $FrontEndMac, $FrontEndNic.InstanceId | Parse-RemoteOutput - - write-sdnexpresslog "Adding Virtual Server to Network Controller." - - $nchostUserObject = get-networkcontrollerCredential -Connectionuri $URI -ResourceId "NCHostUser" @CredentialParam - $GatewayPoolObject = get-networkcontrollerGatewayPool -Connectionuri $URI -ResourceId $PoolName @CredentialParam - - $VirtualServerProperties = new-object Microsoft.Windows.NetworkController.VirtualServerProperties - $VirtualServerProperties.Connections = @() - $VirtualServerProperties.Connections += new-object Microsoft.Windows.NetworkController.Connection - $VirtualServerProperties.Connections[0].Credential = $nchostUserObject - $VirtualServerProperties.Connections[0].CredentialType = $nchostUserObject.properties.Type - $VirtualServerProperties.Connections[0].ManagementAddresses = @($GatewayFQDN) - $VirtualServerProperties.vmguid = $vmGuid - - $VirtualServerObject = new-networkcontrollervirtualserver -connectionuri $uri @CredentialParam -MarkServerReadOnly $false -ResourceId $GatewayFQDN -Properties $VirtualServerProperties -force -passinnerexception - - write-sdnexpresslog "Adding Gateway to Network Controller." - - $GatewayProperties = new-object Microsoft.Windows.NetworkController.GatewayProperties - $GatewayProperties.NetworkInterfaces = new-object Microsoft.Windows.NetworkController.NetworkInterfaces - $GatewayProperties.NetworkInterfaces.InternalNetworkInterface = $BackEndNic - $GatewayProperties.NetworkInterfaces.ExternalNetworkInterface = $FrontEndNic - $GatewayProperties.Pool = $GatewayPoolObject - $GatewayProperties.VirtualServer = $VirtualServerObject - - if (($GatewayPoolObject.Properties.Type -eq "All") -or ($GatewayPoolObject.Properties.Type -eq "S2sIpsec" )) { - $GatewayProperties.BGPConfig = new-object Microsoft.Windows.NetworkController.GatewayBgpConfig - - $GatewayProperties.BGPConfig.BgpPeer = @() - - if ($psCmdlet.ParameterSetName -eq "SinglePeer") { - $GatewayProperties.BGPConfig.BgpPeer += new-object Microsoft.Windows.NetworkController.GatewayBgpPeer - $GatewayProperties.BGPConfig.BgpPeer[0].PeerExtAsNumber = "0.$RouterASN" - $GatewayProperties.BGPConfig.BgpPeer[0].PeerIP = $RouterIP - } else { - foreach ($router in $routers) { - $NewPeer = new-object Microsoft.Windows.NetworkController.GatewayBgpPeer - $NewPeer.PeerExtAsNumber = "0.$($Router.RouterASN)" - $NewPeer.PeerIP = $Router.RouterIPAddress - $GatewayProperties.BGPConfig.BgpPeer += $NewPeer - } - } - - $GatewayProperties.BgpConfig.ExtASNumber = "0.$LocalASN" - } - - $Gw = new-networkcontrollerGateway -connectionuri $uri @CredentialParam -ResourceId $GatewayFQDN -Properties $GatewayProperties -force -passinnerexception - - write-sdnexpresslog "New-SDNExpressGateway Exit" -} - - - - - # # # # # # - ## # ###### # # # # ## ## - # # # # # # # # # # # # - # # # ##### # # # # # # # - # # # # # ## # # # # # - # ## # ## ## # # # # - # # ###### # # # # # - -function New-SDNExpressVM -{ - [cmdletbinding(DefaultParameterSetName="Default")] - param( - [Parameter(Mandatory=$true)] - [String] $ComputerName, - [Parameter(Mandatory=$false)] - [String] $VMLocation = "", - [Parameter(Mandatory=$true)] - [ValidateScript({ - if ($_.length -gt 15) { throw "VMName must be 15 characters or less."} - if ($_ -match "[{|}~[\\\]^':;<=>?@!`"#$%``()+/.,*&]") { throw 'VMName cannot contain the following characters: { | } ~ [ \ ] ^ ' + "'" + ': ; < = > ? @ ! " # $ % ` ( ) + / . , * &'} - if ($_ -match " ") { throw 'VMName cannot contain spaces.'} - return $true - })] - [String] $VMName, - [Parameter(Mandatory=$true)] - [String] $VHDSrcPath, - [Parameter(Mandatory=$true)] - [String] $VHDName, - [Parameter(Mandatory=$false)] - [Int64] $VMMemory=8GB, - [Parameter(Mandatory=$false)] - [String] $SwitchName="", - [Object] $Nics, - [Parameter(Mandatory=$true,ParameterSetName="UserName")] - [String] $CredentialDomain, - [Parameter(Mandatory=$true,ParameterSetName="UserName")] - [String] $CredentialUserName, - [Parameter(Mandatory=$true,ParameterSetName="UserName")] - [String] $CredentialPassword, - [Parameter(Mandatory=$true,ParameterSetName="Creds")] - [PSCredential] $Credential = $null, - [Parameter(Mandatory=$true)] - [String] $JoinDomain, - [Parameter(Mandatory=$true)] - [String] $LocalAdminPassword, - [Parameter(Mandatory=$false)] - [String] $DomainAdminDomain = $null, - [Parameter(Mandatory=$false)] - [String] $DomainAdminUserName = $null, - [Parameter(Mandatory=$false)] - [String] $ProductKey="", - [Parameter(Mandatory=$false)] - [int] $VMProcessorCount = 8, - [Parameter(Mandatory=$false)] - [String] $Locale = [System.Globalization.CultureInfo]::CurrentCulture.Name, - [Parameter(Mandatory=$false)] - [String] $TimeZone = [TimeZoneInfo]::Local.Id, - [Parameter(Mandatory=$false)] - [String[]] $Roles = @(), - [Parameter(Mandatory=$false)] - [String] $OperationID = "" - ) - - Write-SDNExpressLogFunction -FunctionName $MyInvocation.MyCommand.Name -boundparameters $psboundparameters -UnboundArguments $MyINvocation.UnboundArguments -ParamSet $psCmdlet - - if ($psCmdlet.ParameterSetName -eq "UserName") { - $CredentialSecurePassword = $CredentialPassword | convertto-securestring -AsPlainText -Force - $credential = New-Object System.Management.Automation.PsCredential("$CredentialDomain\$CredentialUserName", $credentialSecurePassword) - } - - $vm = get-vm -computername $ComputerName -Name $VMName -erroraction Ignore - if ($null -ne $vm) { - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $VMName - write-sdnexpresslog "VM named $VMName already exists on $ComputerName." - return - } - - $hostprocessorcount = (get-vmhost -computername $computername).logicalprocessorcount - if ($vmprocessorcount -gt $hostprocessorcount) { - write-sdnexpresslog "VMProcessorCount is greater than logical processors on $ComputerName. Lowering VM processor count from $vmprocessorcount to $hostprocessorcount to match host." - $vmprocessorcount = $hostprocessorcount - } - - if ([string]::IsNullOrEmpty($DomainAdminUserName)) { - if ($null -eq $Credential) { - $DomainAdminDomain = $env:USERDOMAIN - $DomainAdminUsername = $env:USERNAME - } else { - $DomainAdminDomain = $credential.UserName.Split('\')[0] - $DomainAdminUsername = $credential.UserName.Split('\')[1] - } - } - - if ($null -eq $Credential) { - $CredentialParam = @{ } - } else { - $CredentialParam = @{ Credential = $credential} - } - - if ([String]::IsNullOrEmpty($VMLocation)) { - $VHDLocation = invoke-command -computername $computername @CredentialParam { - return (get-vmhost).virtualharddiskpath - } - $VMLocation = invoke-command -computername $computername @CredentialParam { - return (get-vmhost).virtualmachinepath - } - write-sdnexpresslog "Using Hyper-V configured VM Location: $VMLocation" - write-sdnexpresslog "Using Hyper-V configured VHD Location: $VHDLocation" - } else { - $VHDLocation = $VMLocation - } - - $LocalVMTempPath = "$vmLocation\Temp\$VMName" - $LocalVMPath = "$vmLocation\$VMName" - $LocalVHDPath = "$vhdlocation\$VMName\$VHDName" - $VHDFullPath = "$VHDSrcPath\$VHDName" - $VMPath = "$VHDLocation\$VMName" - $IsSMB = $VMLocation.startswith("\\") - $IsCSV = $false - - $VM = $null - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 10 -context $VMName - - $NodeFQDN = invoke-command -ComputerName $ComputerName @CredentialParam { - return (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - } - $thisFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - $IsLocal = $NodeFQDN -eq $thisFQDN - if ($IsLocal) { - write-sdnexpresslog "VM is created on same machine as script." - } - - if (!$IsSMB -and !$IsLocal) { - write-sdnexpresslog "Checking if path is CSV on $computername." - $IsCSV = invoke-command -computername $computername @CredentialParam { - param([String] $VMPath) - try { - $csv = get-clustersharedvolume -ErrorAction Ignore - } catch {} - - $volumes = $csv.sharedvolumeinfo.friendlyvolumename - foreach ($volume in $volumes) { - if ($VMPath.ToUpper().StartsWith("$volume\".ToUpper())) { - return $true - } - } - return $false - } -ArgumentList $VMPath - if ($IsCSV) { - write-sdnexpresslog "Path is CSV." - $VMPath = "\\$computername\$VMPath".Replace(":", "$") - } else { - write-sdnexpresslog "Path is not CSV." - $VMPath = "\\$ComputerName\VMShare\$VMName" - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 20 -context $VMName - write-sdnexpresslog "Using $VMPath as destination for VHD copy." - - $VHDVMPath = "$VMPath\$VHDName" - $VHDTempVMPath = "$LocalVMTempPath\$VHDName" - - write-sdnexpresslog "Checking for previously mounted image." - - $mounted = get-WindowsImage -Mounted - foreach ($mount in $mounted) - { - if ($mount.ImagePath -eq $VHDTempVMPath) { - DisMount-WindowsImage -Discard -path $mount.Path | out-null - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 30 -context $VMName - - if ([String]::IsNullOrEmpty($SwitchName)) { - write-sdnexpresslog "Finding virtual switch." - try { - $SwitchName = invoke-command -computername $computername @CredentialParam { - $VMSwitches = Get-VMSwitch - if ($VMSwitches -eq $Null) { - throw "No Virtual Switches found on the host. Can't create VM. Please create a virtual switch before continuing." - } - if ($VMSwitches.count -gt 1) { - throw "More than one virtual switch found on host. Please specify virtual switch name using SwitchName parameter." - } - - return $VMSwitches.Name - } - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["INVALIDVSWITCH"].Code -LogMessage $Errors["INVALIDVSWITCH"].Message #No errormessage because SDN Express generates error - throw $_.Exception - } - } - write-sdnexpresslog "Will attach VM to virtual switch: $SwitchName" - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 40 -context $VMName - - if (!($IsLocal -or $IsCSV -or $IsSMB)) { - write-sdnexpresslog "Creating VM root directory and share on host." - - invoke-command -computername $computername @CredentialParam { - param( - [String] $VMLocation, - [String] $UserName - ) - New-Item -ItemType Directory -Force -Path $VMLocation | out-null - If (-not (Test-Path -Path $VMLocation)) { - throw "$($VMLocation) should exist, but doesn't" - } - get-SmbShare -Name VMShare -ErrorAction Ignore | remove-SMBShare -Force - New-SmbShare -Name VMShare -Path $VMLocation -FullAccess $UserName -Temporary | out-null - } -ArgumentList $VHDLocation, ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 50 -context $VMName - - $Generation = 1 - if (($VHDName).EndsWith('vhdx')) { - $Generation = 2 # if a vhdx is provided, create a generation 2 vm, otherwise create a generation 1 vm - } - - write-sdnexpresslog "Creating VM directory and copying VHD. This may take a few minutes." - write-sdnexpresslog "Copy from $VHDFullPath to $LocalVMTempPath" - - New-Item -ItemType Directory -Force -Path $LocalVMTempPath | out-null - if (Test-Path -Path $VHDFullPath) { - Write-SDNExpressLog "$($VHDFullPath) exists, copying can continue" - } else { - Write-SDNExpressLog "$($VHDFullPath) doesn't appear to exist. This is needed to setup SDN." - throw "Failed to find $($VHDFullPath)" - } - - try { - robocopy $VHDSrcPath $LocalVMTempPath $VHDName /R:10 /W:30 /V /NP - - Write-SDNExpressLog "Robocopy ExitCode: $($LastExitCode)" - - $destVHDName = "$LocalVMTempPath\$VHDName" - if (Test-Path $destVHDName) { - Write-SDNExpressLog "$($destVHDName) was found" - } - else { - throw "File copy didn't appear to work. $($destVHDName) was not found" - } - } catch { - Write-SDNExpressLog "Failed to copy VHD. Exception Message: " - Write-SDNExpressLog $_ - throw "Copy of $($VHDFullPath) to $($LocalVMTempPath) failed" - } - - write-sdnexpresslog "Creating mount directory and mounting VHD." - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $MountPath = $TempFile.FullName - - New-Item -ItemType Directory -Force -Path $MountPath - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 60 -context $VMName - - New-Item -ItemType Directory -Force -Path $VMPath | out-null - copy-item -Path $VHDFullPath -Destination $VMPath | out-null - - write-sdnexpresslog "Creating mount directory and mounting VHD." - - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $MountPath = $TempFile.FullName - - New-Item -ItemType Directory -Force -Path $MountPath | out-null - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 60 -context $VMName - - write-sdnexpresslog "Creating VM: $computername" - try - { - invoke-command -ComputerName $ComputerName @CredentialParam -ScriptBlock { - param( - [String] $VMName, - [String] $LocalVMPath, - [Int64] $VMMemory, - [Int] $VMProcessorCount, - [String] $SwitchName, - [Object] $Nics - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Creating VM $VMName in $LocalVMPath." - #note: we'll add the VHDX later after we customize it - if (![string]::IsNullOrEmpty($nics[0].switchname)) { - $FirstSwitch = $Nics[0].SwitchName - } else { - $FirstSwitch = $SwitchName - } - write-verbose "Creating Generation $using:Generation VM $VMName Switch $FirstSwitch with Memory $VMMemory and VHD to be added later $using:VHDName." - $NewVM = New-VM -Generation $using:Generation -Name $VMName -Path $LocalVMPath -MemoryStartupBytes $VMMemory -novhd -SwitchName $FirstSwitch - write-verbose "Setting processor count to $VMProcessorCount." - $NewVM | Set-VM -processorcount $VMProcessorCount | out-null - - $first = $true - foreach ($nic in $Nics) { - if ($first) { - write-verbose "Configuring first network adapter." - $vnic = $NewVM | get-vmnetworkadapter - $vnic | rename-vmnetworkadapter -newname $Nic.Name - $first = $false - } else { - write-verbose "Configuring additional network adapters." - if (![string]::IsNullOrEmpty($nic.switchname)) { - $UseSwitch = $Nic.SwitchName - } else { - $UseSwitch = $SwitchName - } - #Note: add-vmnetworkadapter doesn't actually return the vnic object for some reason which is why this does a get immediately after. - $NewVM | Add-VMNetworkAdapter -SwitchName $UseSwitch -Name $Nic.Name | out-null - $vnic = $NewVM | get-vmnetworkadapter -Name $Nic.Name - } - - if (![string]::IsNullOrempty($nic.MacAddress)) { - $FormattedMac = [regex]::matches($nic.MacAddress.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - write-verbose "Configuring mac address as: $formattedmac from $nic.MacAddress" - $vnic | Set-vmnetworkadapter -StaticMacAddress $FormattedMac - } - - $portProfileDefaultSetting = Get-VMSystemSwitchExtensionPortFeature -FeatureId "9940cd46-8b06-43bb-b9d5-93d50381fd56" - - $portProfileDefaultSetting.SettingData.ProfileId = "{$([Guid]::Empty)}" - $portProfileDefaultSetting.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}" - $portProfileDefaultSetting.SettingData.CdnLabelString = "TestCdn" - $portProfileDefaultSetting.SettingData.CdnLabelId = 1111 - $portProfileDefaultSetting.SettingData.ProfileName = "Testprofile" - $portProfileDefaultSetting.SettingData.VendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}" - $portProfileDefaultSetting.SettingData.VendorName = "NetworkController" - - if ($nic.IsMuxPA) { - $portProfileDefaultSetting.SettingData.ProfileData = 2 - if ($nic.vlanid) { - #Profile data 2 means VFP is disbled on the port (for higher Mux throughput), and so you must set the VLAN ID using Set-VMNetworkAdapterVLAN for ports where VFP is disabled - write-verbose "Setting VLAN $($nic.vlanid) via Set-VMNetworkAdapterVLAN." - $vnic | Set-VMNetworkAdapterVLAN -Access -VLANID $nic.vlanid | out-null - } - } else { - $portProfileDefaultSetting.SettingData.ProfileData = 1 - if ($nic.vlanid) { - #Profile data 1 means VFP is enabled, but unblocked with default allow-all acls. For VFP enabled ports, VFP enforces VLAN isolation so you must set using set-VMNetworkAdapterIsolation - write-verbose "Setting VLAN $($nic.vlanid) via Set-VMNetworkIsolation." - $vnic | Set-VMNetworkAdapterIsolation -AllowUntaggedTraffic $true -IsolationMode VLAN -defaultisolationid $nic.vlanid | out-null - } - } - - write-verbose "Adding port feature." - - Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $portProfileDefaultSetting -VMNetworkAdapter $vNic | out-null - } - - #Start, then immediately stop the VM in order to allocate dynamic mac addresses - $NewVM | Start-VM | out-null - $newVM | stop-vm -turnoff -force | out-null - - } -ArgumentList $VMName, $LocalVMPath, $VMMemory, $VMProcessorCount, $SwitchName, $Nics | Parse-RemoteOutput - - } catch { - write-sdnexpresslog "Exception creating VM: $($_.Exception.Message)" - write-sdnexpresslog "Deleting VM." - $vm = get-vm -computername $ComputerName -Name $VMName -erroraction Ignore - if ($null -ne $vm) { - $vm | stop-vm -turnoff -force -erroraction Ignore - $vm | remove-vm -force -erroraction Ignore - } - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["GENERALEXCEPTION"].Code -LogMessage $_.Exception.Message -ErrorMessage $_.Exception.Message - throw $_.Exception - } - - write-sdnexpresslog "Generating unattend.xml" - - $count = 1 - $TCPIPInterfaces = "" - $dnsinterfaces = "" - $dnssection = "" - - foreach ($nic in $Nics) { - - write-host "NIC: $nic" - - $vmMacAddress = invoke-command -ComputerName $ComputerName @CredentialParam -ScriptBlock { - param( - [String] $VMName, - [String] $NicName - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Getting MAC address for VM $VMName NIC $NicName." - $vnic = get-vmnetworkadapter -vmname $VMName -vmnetworkadaptername $NicName - write-output ($vnic.macaddress) - } -ArgumentList $VMName, $Nic.Name | Parse-RemoteOutput - - write-sdnexpresslog "Done nic processing" - write-sdnexpresslog "MAC: $vmMacAddress" - - $MacAddress = [regex]::matches($vmMacAddress.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - - write-verbose "Formatted Mac Address is: $macaddress" - if ($Nic.keys -contains "IPAddress" -and ![String]::IsNullOrEmpty($Nic.IPAddress)) { - $sp = $NIC.IPAddress.Split("/") - $IPAddress = $sp[0] - $SubnetMask = $sp[1] - - if ($Nic.Keys -contains "Gateway" -and ![String]::IsNullOrEmpty($Nic.Gateway)) { - $gatewaysnippet = @" - - - 0 - 0.0.0.0/0 - 20 - $($Nic.Gateway) - - -"@ - } else { - $gatewaysnippet = "" - } - - $TCPIPInterfaces += @" - - - false - - $MacAddress - - $IPAddress/$SubnetMask - - $gatewaysnippet - -"@ - $alldns = "" - $dnsregistration = "false" - if ($Nic.Keys -contains "DNS" -and ![String]::IsNullOrEmpty($Nic.DNS)) { - foreach ($dns in $Nic.DNS) { - $alldns += '{0}' -f $dns, $count++ - } - - if ($Nic.DNS.count -gt 0) { - $dnsregistration = "true" - } - } - $dnsinterfaces += @" - - - $alldns - - $MacAddress - $DNSRegistration - -"@ - - $dnsSection = @" - - -$DNSInterfaces - - -"@ - } else { - $TCPIPInterfaces += @" - - - true - - $MacAddress - -"@ - - } - } - - $ProductKeyField = "" - if (![String]::IsNullOrEmpty($ProductKey)) { - $ProductKeyField = "$ProductKey" - } - - $unattendfile = @" - - - - - - $TCPIPInterfaces - - - $DNSSection - - $VMName - $ProductKeyField - - - - - Add AlwaysExpecteDomainController RegKey - 1 - cmd /c reg add HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters /v AlwaysExpectDomainController /t REG_DWORD /d 255 /f - - - - - - - - - $LocalAdminPassword - true</PlainText> - </AdministratorPassword> - <DomainAccounts> - <DomainAccountList wcm:action="add"> - <DomainAccount wcm:action="add"> - <Name>$DomainAdminUserName</Name> - <Group>Administrators</Group> - </DomainAccount> - <Domain>$DomainAdminDomain</Domain> - </DomainAccountList> - </DomainAccounts> - </UserAccounts> - <TimeZone>$TimeZone</TimeZone> - <OOBE> - <HideEULAPage>true</HideEULAPage> - <SkipUserOOBE>true</SkipUserOOBE> - <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> - <HideOnlineAccountScreens>true</HideOnlineAccountScreens> - <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> - <NetworkLocation>Work</NetworkLocation> - <ProtectYourPC>1</ProtectYourPC> - <HideLocalAccountScreen>true</HideLocalAccountScreen> - </OOBE> - </component> - <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <UserLocale>$Locale</UserLocale> - <SystemLocale>$Locale</SystemLocale> - <InputLocale>$Locale</InputLocale> - <UILanguage>$Locale</UILanguage> - </component> - </settings> - <cpi:offlineImage cpi:source="" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> - </unattend> -"@ - - try { - $WindowsImage = Mount-WindowsImage -ImagePath $VHDTempVMPath -Index 1 -path $MountPath - - $Edition = get-windowsedition -path $MountPath - - if (!(@("ServerDatacenterCor", "ServerDatacenter", "ServerAzureStackHCICor") -contains $Edition.Edition)) { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["WINDOWSEDITION"].Code -LogMessage $Errors["WINDOWSEDITION"].Message #No errormessage because SDN Express generates error - throw $Errors["WINDOWSEDITION"].Message - } - - if ($Roles.count -gt 0) { - write-sdnexpresslog "Adding Roles ($Roles) offline to save reboot later" - - foreach ($role in $Roles) { - Enable-WindowsOptionalFeature -Path $MountPath -FeatureName $role -All -LimitAccess | Out-Null - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 70 -context $VMName - - write-sdnexpresslog "Offline Domain Join" - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force - $DJoinOutput = djoin /provision /domain $JoinDomain /machine $VMName /savefile $tempfile.fullname /REUSE - if ($LASTEXITCODE -ne "0") { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["COMPUTEREXISTS"].Code -LogMessage $Errors["COMPUTEREXISTS"].Message #No errormessage because SDN Express generates error - throw $Errors["COMPUTEREXISTS"].Message - } - write-sdnexpresslog $DJoinOutput - $DJoinOutput = djoin /requestODJ /loadfile $tempfile.fullname /windowspath "$MountPath\Windows" /localos - if ($LASTEXITCODE -ne "0") { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["COMPUTEREXISTS"].Code -LogMessage $Errors["COMPUTEREXISTS"].Message #No errormessage because SDN Express generates error - throw $Errors["COMPUTEREXISTS"].Message - } - write-sdnexpresslog $DJoinOutput - Remove-Item $TempFile.FullName -Force - - - write-sdnexpresslog "Writing unattend.xml to $MountPath\unattend.xml" - Set-Content -value $UnattendFile -path "$MountPath\unattend.xml" | out-null - - New-Item -ItemType Directory -Force -Path "$MountPath\Windows\Setup\Scripts" | out-null - - $setupcompletecmdfile = 'PowerShell -file "\Windows\Setup\Scripts\SetupComplete.ps1"' - Set-Content -value $SetupCompleteCMDFile -path "$MountPath\Windows\Setup\Scripts\SetupComplete.cmd" | out-null - - $setupcompleteps1file = @' - -Function Test-Endpoint($endpoint) -{ - Write-Host "Testing ICMP to $($endpoint)" - [int]$retries = 5 - while($retries -gt 0) - { - $retries-- - if(Test-Connection $endpoint -quiet) - { - Write-Host "ICMP to $($endpoint) Successful" - return $true - } - Write-Host "ICMP to $($endpoint) Failed. Retries left $($retries)" - Start-Sleep 5 - - } - return $false - -} - -new-eventlog -logname "Application" -source "SDNExpress" -ErrorAction SilentlyContinue -Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "NetworkCategory check." -ErrorAction SilentlyContinue - -$hopLine = Select-String -Path C:\unattend.xml -Pattern "NextHopAddress" -$defaultGateway = $hopLine.Line.Trim().Replace("<NextHopAddress>", "").Replace("</NextHopAddress>", "") -$dnsServerAddress = (Get-DnsClientServerAddress -AddressFamily IPv4).ServerAddresses - -$try = 0 -while ($true) { - $try++ - - $Profiles = get-netconnectionprofile - - foreach ($profile in $profiles) { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "$($profile.interfacealias) NetworkCategory is $($profile.NetworkCategory)." -ErrorAction SilentlyContinue - if ($profile.NetworkCategory -eq "DomainAuthenticated") { - return - } - } - - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Not DomainAuthenticated. Reset attempt $try." -ErrorAction SilentlyContinue - - if(Test-Endpoint $defaultGateway -quiet) - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Can Ping Default Gateway $($defaultGateway)" -ErrorAction SilentlyContinue - } - else - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Can Not Ping Default Gateway $($defaultGateway)" -ErrorAction SilentlyContinue - } - - foreach ($profile in $profiles) { - disable-netadapter -interfaceindex $profile.InterfaceIndex - enable-netadapter -interfaceindex $profile.InterfaceIndex - } - - foreach($dnsAddr in $dnsServerAddress) - { - if(Test-Endpoint $dnsAddr -quiet) - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Can Ping DNS Server $($dnsAddr)" -ErrorAction SilentlyContinue - } - else - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Can Not Ping DNS Server $($dnsAddr)" -ErrorAction SilentlyContinue - } - } - - $domainName = "TempDomainName" - - $testResult = Test-ComputerSecureChannel - - if($testResult -eq $true) - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Test-ComputerSecureChannel results no problems with domain: $($domainName)" -ErrorAction SilentlyContinue - } - else - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Test-ComputerSecureChannel results failure with domain: $($domainName). Running Repair" -ErrorAction SilentlyContinue - - $domainPswd = ConvertTo-SecureString "TempDomainPassword" -AsPlainText -Force - $domainUser = "TempDomainUser" - $domainCreds = New-Object System.Management.Automation.PSCredential ($domainUser, $domainPswd) - - $testResult = Test-ComputerSecureChannel -Repair -Server $domainName -Credential $domainCreds - if($testResult -eq $true) - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Test-ComputerSecureChannel repaired failure for domain $($domainName) as expected" -ErrorAction SilentlyContinue - } - else - { - Write-EventLog -LogName "Application" -Source "SDNExpress" -EventId 0 -Category 0 -EntryType Information -Message "Test-ComputerSecureChannel failed to repair failure for domain: $($domainName)." -ErrorAction SilentlyContinue - } - # Sleep to let repair complete - Start-Sleep 15 - } - - foreach ($profile in $profiles) - { - Get-NetAdapter -InterfaceIndex $profile.InterfaceIndex | Disable-NetAdapter -Confirm:$false - Get-NetAdapter -InterfaceIndex $profile.InterfaceIndex | Enable-NetAdapter -Confirm:$false - } - Start-Sleep 60 -} -'@ - $SetupCompletePS1File = $SetupCompletePS1File -replace "TempDomainPassword", $CredentialPassword - $SetupCompletePS1File = $SetupCompletePS1File -replace "TempDomainUser", "$JoinDomain\$DomainAdminUserName" - $SetupCompletePS1File = $SetupCompletePS1File -replace "TempDomainName", "$JoinDomain" - Set-Content -value $SetupCompletePS1File -path "$MountPath\Windows\Setup\Scripts\SetupComplete.ps1" | out-null - } - catch - { - write-logerror -OperationId $operationId -Source $MyInvocation.MyCommand.Name -ErrorCode $Errors["GENERALEXCEPTION"].Code -LogMessage $_.Exception.Message -ErrorMessage $_.Exception.Message - throw $_.Exception - } - finally - { - write-sdnexpresslog "Cleaning up" - $mountPathExists = Test-Path $MountPath - $vhdPathExists = Test-Path $VHDTempVMPath - - if ($mountPathExists -and $vhdPathExists) - { - Write-SDNExpressLog "'$MountPath' and '$VHDTempVMPath' exists, now dismounting." - } - else { - Write-SDNExpressLog "'$VHDVMPath' should be mounted at '$mountPath', but something doesn't exist. VHDPath exists = '$vhdPathExists', Mountpoint exists = '$mountPathExists'" - Write-SDNExpressLog "Trying DisMount-WindowsImage anyway." - } - - # Sometimes dismount throws exception stating a file handle is still open. Retrying to give any running process to close, releasing handle. - $retryCount = 4 - - while ($retryCount -gt 0) - { - try { - DisMount-WindowsImage -Save -path $MountPath - Write-SDNExpressLog "Dismount successful" - break - } - catch - { - Write-SDNExpressLog "Dismount Failed" - Write-SDNExpressLog $_.Exception.Message - if ($retryCount -eq 1) { - throw $_.Exception - } - - Write-SDNExpressLog "Retrying dismount (after sleep of 45 seconds)" - $retryCount-- - Start-Sleep -Seconds 45 - } - } - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 80 -context $VMName - - try { - robocopy $LocalVMTempPath $VMPath $VHDName /R:10 /W:30 /V /NP - - $robocopyExitCode = $LastExitCode - - Write-SDNExpressLog "Robocopy ExitCode: $($LastExitCode)" - - $destVHDName = "$VMPath\$VHDName" - if (Test-Path $destVHDName) { - Write-SDNExpressLog "$($destVHDName) was found" - } - else { - throw "File copy didn't appear to work. $($destVHDName) was not found" - } - } catch { - Write-SDNExpressLog "Failed to copy VHD. Exception Message: " - Write-SDNExpressLog $_ - throw "Copy of $($LocalVMTempPath) to $($VMPath) failed" - } - - write-sdnexpresslog "Removing temp path" - Remove-Item $LocalVMTempPath -Force -Recurse - Remove-Item $MountPath -Force - write-sdnexpresslog "removing smb share" - Invoke-Command -computername $computername @CredentialParam { - Get-SmbShare -Name VMShare -ErrorAction Ignore | remove-SMBShare -Force | out-null - } - - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 90 -context $VMName - - invoke-command -ComputerName $ComputerName @CredentialParam -ScriptBlock { - param( - [String] $VMName, - [String] $VHDPath - ) - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - write-verbose "Adding VHD $vhdpath to $vmname." - $vm = get-vm $vmname - $vm | add-vmharddiskdrive -path $vhdpath - - write-verbose "Making VHD first boot device." - $vhdd = $vm | get-vmharddiskdrive - if ($using:Generation -eq 2) { - $vm | set-vmfirmware -firstbootdevice $vhdd - } - - write-verbose "Starting VM $vmname." - $vm | start-vm - } -ArgumentList $VMName, $LocalVHDPath | Parse-RemoteOutput - Write-LogProgress -OperationId $operationId -Source $MyInvocation.MyCommand.Name -Percent 100 -context $VMName - write-sdnexpresslog "Exit Function: $($MyInvocation.InvocationName)" -} - - -function Test-SDNExpressHealth -{ - param( - [String] $RestName, - [PSCredential] $Credential = $null - ) - write-sdnexpresslog "Test-SDNExpressHealth" - write-sdnexpresslog " -RestName: $RestName" - write-sdnexpresslog " -Credential: $($Credential.UserName)" - - $uri = "https://$RestName" - - $DefaultRestParams = @{ - 'ConnectionURI'=$uri; - 'Credential'=$Credential; - } - if ($null -ne $Credential) { - $DefaultRestParams.Credential = $credential - } - - write-sdnexpresslog "Server Status:" - $servers = get-networkcontrollerserver @DefaultRestParams - foreach ($server in $servers) { - write-sdnexpresslog "$($Server.properties.connections.managementaddresses) status: $($server.properties.configurationstate.status)" - } - write-sdnexpresslog "Mux Status:" - [int]$muxRetries = 10 - $muxSuccess = $false - while($muxRetries -gt 0) - { - $muxes = get-networkcontrollerloadbalancermux @DefaultRestParams - - foreach ($mux in $muxes) { - if($null -eq $mux.properties.configurationstate.status) - { - $muxRetries-- - break - } - else - { - write-sdnexpresslog "$($mux.ResourceId) status: $($mux.properties.configurationstate.status)" - $muxRetries = 0 - $muxSuccess = $true - break - } - } - if($muxSuccess -eq $false) - { - write-sdnexpresslog "Unable to get Mux Status. Waiting 30 seconds." - $muxRetries-- - Start-Sleep 30 - } - } - if($muxSuccess -eq $false) - { - write-sdnexpresslog "Unable to get Mux Status" - } - write-sdnexpresslog "Gateway Status:" - $gateways = get-networkcontrollergateway @DefaultRestParams - foreach ($gateway in $gateways) { - write-sdnexpresslog "$($gateway.ResourceId) status: $($gateway.properties.State), $($gateway.properties.HealthState)" - } -} -function New-SdnExpressHostCertificate -{ - param() - - function private:write-verbose { param([String] $Message) write-output "[V]"; write-output $Message} - function private:write-output { param([PSObject[]] $InputObject) write-output "$($InputObject.count)"; write-output $InputObject} - - $NodeFQDN = (get-ciminstance win32_computersystem).DNSHostName+"."+(get-ciminstance win32_computersystem).Domain - - $cert = GetSdnCert -subjectName $NodeFQDN.ToUpper() - if ($Cert -eq $Null) { - write-verbose "Creating new host certificate." - $Cert = New-SelfSignedCertificate -Type Custom -KeySpec KeyExchange -Subject "CN=$NodeFQDN" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\LocalMachine\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.95.1.1.1") - } else { - write-verbose "Existing certificate meets criteria. Exporting." - } - - write-verbose "Setting cert permissions." - $targetCertPrivKey = $Cert.PrivateKey - $privKeyCertFile = Get-Item -path "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" | where-object {$_.Name -eq $targetCertPrivKey.CspKeyContainerInfo.UniqueKeyContainerName} - $privKeyAcl = Get-Acl $privKeyCertFile - $permission = "NT AUTHORITY\NETWORK SERVICE","Read","Allow" - $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission - $privKeyAcl.AddAccessRule($accessRule) | out-null - Set-Acl $privKeyCertFile.FullName $privKeyAcl | out-null - - write-verbose "Exporting certificate." - $TempFile = New-TemporaryFile - Remove-Item $TempFile.FullName -Force | out-null - Export-Certificate -Type CERT -FilePath $TempFile.FullName -cert $cert | out-null - - $CertData = Get-Content $TempFile.FullName -Encoding Byte - Remove-Item $TempFile.FullName -Force | out-null - - write-output $CertData -} - -Export-ModuleMember -Function New-SDNExpressVM -Export-ModuleMember -Function New-SDNExpressNetworkController -Export-ModuleMember -Function New-FCNCNetworkController -Export-ModuleMember -Function Add-SDNExpressHost -Export-ModuleMember -Function Add-SDNExpressMux -Export-ModuleMember -Function New-SDNExpressGatewayPool -Export-ModuleMember -Function New-SDNExpressGateway -Export-ModuleMember -Function Initialize-SDNExpressGateway - -Export-ModuleMember -Function New-SDNExpressLoadBalancerManagerConfiguration -Export-ModuleMember -Function New-SDNExpressVirtualNetworkManagerConfiguration -Export-ModuleMember -Function New-SDNExpressiDNSConfiguration -Export-ModuleMember -Function Add-SDNExpressLoadBalancerVIPSubnet -Export-ModuleMember -Function Add-SDNExpressVirtualNetworkPASubnet - -Export-ModuleMember -Function Test-SDNExpressHealth -Export-ModuleMember -Function Enable-SDNExpressVMPort - -Export-ModuleMember -Function WaitForComputerToBeReady -Export-ModuleMember -Function Write-SDNExpressLog -Export-ModuleMember -Function Get-IPAddressInSubnet -Export-ModuleMember -Function Parse-RemoteOutput -Export-ModuleMember -Variable $Global:fdGetSdnCert -Export-ModuleMember -Function GetSdnCert -Export-ModuleMember -Function Write-SDNExpressLogFunction - diff --git a/src/utils/objects/utils/SDNExpressUI.psm1 b/src/utils/objects/utils/SDNExpressUI.psm1 deleted file mode 100644 index 9c9fe023..00000000 --- a/src/utils/objects/utils/SDNExpressUI.psm1 +++ /dev/null @@ -1,1206 +0,0 @@ - -function SDNExpressUI { - - [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') - [xml]$XAML = @' - <Window - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Title="SDN Express" ResizeMode="NoResize" Height="600" Width="800" WindowStartupLocation="CenterScreen" > - <Window.Resources> - <ControlTemplate x:Key="ErrorTemplate" TargetType="{x:Type Control}"> - <DockPanel> - <TextBlock Foreground="Red" TextAlignment="Center" Width="16" FontSize="18" DockPanel.Dock="Right">!</TextBlock> - <Border BorderThickness="1" BorderBrush="Red"> - <ScrollViewer x:Name="PART_ContentHost"/> - </Border> - </DockPanel> - </ControlTemplate> - <ControlTemplate x:Key="NormalTemplate" TargetType="{x:Type Control}"> - <DockPanel> - <TextBlock Foreground="Red" TextAlignment="Center" Width="16" FontSize="18" DockPanel.Dock="Right"></TextBlock> - <Border BorderThickness="1" BorderBrush="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"> - <ScrollViewer x:Name="PART_ContentHost" /> - </Border> - </DockPanel> - </ControlTemplate> - <Style TargetType="{x:Type TextBox}"> - <Setter Property="OverridesDefaultStyle" Value="True" /> - <Setter Property="Template" Value="{DynamicResource ErrorTemplate}" /> - </Style> - <Style TargetType="{x:Type PasswordBox}"> - <Setter Property="OverridesDefaultStyle" Value="True" /> - <Setter Property="Template" Value="{DynamicResource ErrorTemplate}" /> - </Style> - </Window.Resources> - <Grid> - <StackPanel Name="panel0" HorizontalAlignment="Left" Width="169.149" Background="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"> - <Rectangle Height="10" Margin="0,0,159,0" /> - <Grid> - <Rectangle Name="mark1" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" /> - <Label Content="Introduction" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark2" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="VM Creation" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark3" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Management Network" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark4" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Provider Network" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark5" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Network Controller" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark6" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Software Load Balancer" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark7" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Gateways" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark8" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="BGP" Margin="10,0,0,0"/> - </Grid> - <Grid> - <Rectangle Name="mark9" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Height="27.976" Margin="0,0,159,0" Visibility="Hidden"/> - <Label Content="Review" Margin="10,0,0,0"/> - </Grid> - </StackPanel> - <StackPanel Name="panel1" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <TextBlock FontSize="20" Margin="10,0,0,0"><Run Text="Welcome to the SDN Express deployment wizard"/></TextBlock> - <TextBlock Margin="10,0,10,0" TextWrapping="WrapWithOverflow"> - <LineBreak/> - <Run Text="For additional information on any of these steps, click on the Docs link below. Before you can complete this wizard you must perform some prerequisite configuration steps in your network:"/><LineBreak/> - </TextBlock> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - Allocate a block of static IP addresses from your management subnet for each Network Controller, Mux and Gateway VM to be created. - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - Allocate a subnet and vlan for Hyper-V Network Virtualization Provider Addresses (HNV PA). - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - Allocate a set of subnets for Private VIPs, Public VIPs and GRE VIPs. Do not configure these on a VLAN, instead enable them to be advertized by SDN through BGP. - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - Configure HNV PA network's routers for BGP, with a 16-bit ASN for the router and one for SDN. SDN should peer with the loopback address of each router. - </TextBlock> - </BulletDecorator> - <TextBlock Margin="10,0,0,0" TextWrapping="WrapWithOverflow"> - <LineBreak/> - <Run Text="Physical switch configuration examples are "/> - <Hyperlink Name="uri4" NavigateUri="https://github.com/Microsoft/SDN/tree/master/SwitchConfigExamples">available on Github.</Hyperlink><LineBreak/> - <LineBreak/> - <Run Text="In addition you will need to have the following ready:"/><LineBreak/> - </TextBlock> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - A set of Hyper-V hosts configured with a virtual switch. - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - A virtual hard disk containing Windows Server 2016 or 2019, Datacenter Edition. - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - An Active Directory domain to join and credentials with Domain Join permission. - </TextBlock> - </BulletDecorator> - <BulletDecorator Margin="10,0,0,0"> - <BulletDecorator.Bullet><Ellipse Height="5" Width="5" Fill="Black"/></BulletDecorator.Bullet> - <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Margin="19,0,0,0"> - Domain credentials with DNS update and host administrator priviliges. - </TextBlock> - </BulletDecorator> - <TextBlock Margin="10,0,0,0" TextWrapping="WrapWithOverflow"> - <LineBreak/> - <Run Text="When you have completed the above you can proceed by clicking Next."/> - <LineBreak/> - <LineBreak/> - <Run Text="Help make SDN Express better by "/> - <Hyperlink Name="uri2" NavigateUri="mail:sdnfeedback@microsoft.com">providing feedback.</Hyperlink><LineBreak/> - </TextBlock> - </StackPanel> - <StackPanel Name="panel2" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="VM Creation" FontSize="18" Margin="10,0"/> - <Label Content="SDN Express is going to create a number of VMs. This information is used for customizing those VMs." Margin="10,0"/> - <Grid Margin="0,10"/> - <Grid Margin="0,2"> - <Label Content="VHD Location" Margin="10,0,0,0" HorizontalAlignment="Left" Width="122.089"/> - <TextBox Name="txtVHDLocation" Text="" Margin="192.739,0,119.71,0" > - - </TextBox> - <Button Name="btnBrowse" Content="Browse..." Margin="0,0,10,0" HorizontalAlignment="Right" Width="104.71" Height="25.426" VerticalAlignment="Bottom"/> - </Grid> - <Grid Margin="0,2"> - <Label Content="VM Path (on host)" Margin="10,0,0,0" HorizontalAlignment="Left" Width="122.089"/> - <TextBox Name="txtVMPath" Text="" Margin="192.739,0,119.71,0"/> - </Grid> - <Grid Margin="0,2"> - <Label Content="VM Name Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="122.089"/> - <TextBox Name="txtVMNamePrefix" Text="" Margin="192.739,0,281.032,0"/> - </Grid> - <Grid Margin="0,10"/> - <Grid Margin="0,2"> - <Label Content="VM Domain" Margin="10,0,0,0" HorizontalAlignment="Left" Width="178.852"/> - <TextBox Name="txtVMDomain" Text="" Margin="192.739,0,119.71,0"/> - </Grid> - <Grid Margin="0,2"> - <Label Content="Domain Join Username" Margin="10,0,0,0" HorizontalAlignment="Left" Width="178.852"/> - <TextBox Name="txtDomainJoinUsername" Text="" Margin="192.739,0,281.032,0"/> - </Grid> - <Grid Margin="0,2"> - <Label Content="Domain Join Password" Margin="10,0,0,0" HorizontalAlignment="Left" Width="178.852"/> - <PasswordBox Name="txtDomainJoinPassword" Margin="192.739,0,281.032,0"/> - </Grid> - <Grid Margin="0,10"/> - <Grid Margin="0,2"> - <Label Content="Local Admin Password" Margin="10,0,0,0" HorizontalAlignment="Left" Width="177.739"/> - <PasswordBox Name="txtLocalAdminPassword" Margin="192.739,0,282.145,0"/> - </Grid> - </StackPanel> - <StackPanel Name="panel3" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Management Network" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"> - <Run Text="Provide information about the management network the SDN infrastructure will use to communicate. This information is used to provide each VM with a network adapter configured for this network."/> - </TextBlock> - <StackPanel Margin="0,10"/> - <Label Content="Subnet Information" Margin="10,0"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="VLAN ID" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementVLANID" Text="" Width="75"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2" > - <Label Content="Subnet Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementSubnetPrefix" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2" > - <Label Content="Gateway" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementGateway" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="IP Address Pool" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="First Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementIPPoolStart" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Last Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementIPPoolEnd" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="DNS Servers" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2" > - <Label Content="DNS Server 1" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementDNS1" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2" > - <Label Content="DNS Server 2" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementDNS2" Width="150" Template="{DynamicResource NormalTemplate}"/> - <Label Content="Optional" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130" FontStyle="Italic"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2" > - <Label Content="DNS Server 3" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtManagementDNS3" Width="150" Template="{DynamicResource NormalTemplate}"/> - <Label Content="Optional" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130" FontStyle="Italic"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel4" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Provider Network" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"><Run Text="Provide information about the provider network which is used for all workload VM communication."/></TextBlock> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Subnet Information" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="VLAN ID" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtPAVLANID" Text="" Width="75"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Subnet Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtPASubnetPrefix" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Default Gateway" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtPAGateway" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="IP Address Pool" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="First IP Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtPAIPPoolStart" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Last IP Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtPAIPPoolEnd" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="MAC Address Pool" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="First MAC Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtMACPoolStart" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Last MAC Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="130"/> - <TextBox Name="txtMACPoolEnd" Text="" Width="150"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel5" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Network Controller" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"> - <Run Text="Provide information to be used for the creation of the Network Controller and the Hyper-V hosts to be added to the controller."/> - </TextBlock> - <Grid Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Network Controller" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <RadioButton Name="rdoMultiNode" Content="Multi-node" HorizontalAlignment="Left" VerticalAlignment="Center" Width="91.96" IsChecked="True"/> - <RadioButton Name="rdoSingleode" Content="Single-node" HorizontalAlignment="Left" VerticalAlignment="Center" Width="91.96"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="REST Name (FQDN)" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtRESTName" Text="" Width="240"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Hyper-V Hosts" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtHyperVHosts" Width="300" Height="160" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" VerticalContentAlignment="Top"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Host Credentials" Margin="10,0"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Username" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtHostUsername" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Password" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <PasswordBox Name="txtHostPassword" Width="150"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel6" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Software Load Balancer" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"> - <Run Text="The Software Load Balancer is an SDN integrated L3 and L4 load balancer that is also used for network address translation (NAT). Muxes are the routers for the virtual IP (VIP) endpoints. Use this panel to define how many muxes you want to deploy. All Muxes are active and traffic is spread across them automatically."/> - </TextBlock> - <Grid Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Load Balancer Muxes" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBlock Name="txtMuxCount" VerticalAlignment="Center" Margin="10,0" Text="{Binding ElementName=sliMuxCount, Path=Value, UpdateSourceTrigger=PropertyChanged}" /> - <Slider Name="sliMuxCount" Width="280" Minimum="1" Maximum="8" Value="2" TickFrequency="1" VerticalAlignment="Center" TickPlacement="BottomRight" SmallChange="1" IsSnapToTickEnabled="True"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Private VIP Subnet" FontSize="14" Margin="10,0"/> - </StackPanel> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"> - <Run Text="Private VIPs are used internally by the SDN infrastructure. This subnet must not be configured on a VLAN in the physical switch as it will be advertized by the Muxes through BGP."/> - </TextBlock> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Subnet Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtPrivateVIPs" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Public VIP Subnet" Margin="10,0" FontSize="14" /> - </StackPanel> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"> - <Run Text="Public VIPs are used to directly access workloads as load balanced VIPs or for NAT. If these need to be reached directly from the internet, then you must obtain an internet routable subnet from your Internet Service Provider (ISP). This subnet must not be configured on a VLAN in the physical switch as it will be advertized by the Muxes through BGP."/> - </TextBlock> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Subnet Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtPublicVIPs" Text="" Width="150"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel7" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Gateways" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"><Run Text="Gateways are used for routing between a virtual network and another network (local or remote). SDN Express creates a default gateway pool that supports all connection types. Within this pool you can select how many gateways are reserved on standby in case an active gateway fails."/></TextBlock> - <Grid Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Gateways" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBlock Name="txtGatewayCount" VerticalAlignment="Center" Margin="10,0" Text="{Binding ElementName=sliGatewayCount, Path=Value, UpdateSourceTrigger=PropertyChanged}" /> - <Slider Name="sliGatewayCount" Margin="35,0" Width="240" Minimum="2" Maximum="8" Value="2" TickFrequency="1" VerticalAlignment="Center" TickPlacement="BottomRight" SmallChange="1" IsSnapToTickEnabled="True"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Gateways on standby" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBlock Name="txtRedundantCount" VerticalAlignment="Center" Margin="10,0" Text="{Binding ElementName=sliRedundantCount, Path=Value, UpdateSourceTrigger=PropertyChanged}" /> - <Slider Name="sliRedundantCount" Width="0" Minimum="1" Maximum="7" Value="1" VerticalAlignment="Center" TickPlacement="BottomRight" SmallChange="1" IsSnapToTickEnabled="True" /> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="GRE Endpoints" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - </StackPanel> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"><Run Text="GRE connections require an endpoint IP address that will be allocated from subnet specified below. This subnet must not be configured on a VLAN in the physical switch as the endpoints will be advertised to the physical network through BGP."/></TextBlock> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Subnet Prefix" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtGREVIPs" Text="" Width="150"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel8" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Border Gateway Protocol (BGP)" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"><Run Text="BGP is used by the Software Load Balancer to advertise VIPs to the physical network. It is also used by the gateways for advertising GRE endpoints."/></TextBlock> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="SDN ASN" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtSDNASN" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router 1" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router IP Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtRouterIP1" Text="" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router ASN" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtRouterASN1" Text="" Width="150"/> - </StackPanel> - <StackPanel Margin="0,10"/> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router 2" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router IP Address" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtRouterIP2" Text="" Width="150" Template="{DynamicResource NormalTemplate}"/> - <Label Content="Optional" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150" FontStyle="Italic"/> - </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,2"> - <Label Content="Router ASN" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150"/> - <TextBox Name="txtRouterASN2" Text="" Width="150" Template="{DynamicResource NormalTemplate}"/> - <Label Content="Optional" Margin="10,0,0,0" HorizontalAlignment="Left" Width="150" FontStyle="Italic"/> - </StackPanel> - </StackPanel> - <StackPanel Name="panel9" HorizontalAlignment="Left" Height="522.101" VerticalAlignment="Top" Margin="169.149,0,0,0" Width="615.137"> - <Label Content="Review" FontSize="18" Margin="10,0"/> - <TextBlock Margin="14,0" TextWrapping="WrapWithOverflow"><Run Text="You have entered everything required for SDN Express to configure SDN on this system. If you would like to save this configuration, select Export. You can re-run SDN Express later with this file using the ConfigurationDataFile parameter."/></TextBlock> - <Grid Margin="0,10"/> - <TextBox Name="txtReview" Text="" Margin="14,0,0,0" Height="300" Template="{DynamicResource NormalTemplate}"/> - <Grid Margin="0,5"/> - <Button Name="btnExport" Content="Export..." Margin="0,0,14,0" HorizontalAlignment="Right" Width="153.868" Height="34.328" /> - <TextBlock Margin="10,0,0,0" TextWrapping="WrapWithOverflow"> - <Run Text="Help make SDN Express better by "/> - <Hyperlink Name="uri3" NavigateUri="mail:sdnfeedback@microsoft.com">providing feedback.</Hyperlink><LineBreak/> - </TextBlock> - - </StackPanel> - <TextBlock Margin="179.149,0,0,74.328" HorizontalAlignment="Left" VerticalAlignment="Bottom"> - <Run Text="For additional help and guidance, refer to the "/> - <Hyperlink Name="uri1" NavigateUri="https://docs.microsoft.com/en-us/windows-server/networking/sdn/plan/plan-software-defined-networking">Plan SDN topic on docs.microsoft.com.</Hyperlink> - </TextBlock> - <Button Name="btnBack1" Content="Back" Margin="0,0,168.868,10" HorizontalAlignment="Right" Width="153.868" Height="34.328" VerticalAlignment="Bottom"/> - <Button Name="btnNext1" Content="Next" Margin="0,0,10,10" HorizontalAlignment="Right" Width="153.868" Height="34.328" VerticalAlignment="Bottom"/> - </Grid> - </Window> -'@ - - -function ConfigDataToString { - param ( - [object] $InputData, - [string] $indent = "" - ) - if ($InputData.GetType().Name.EndsWith("String")) { - return "$indent $InputData" - } - - foreach ($i in $InputData.GetEnumerator()) { - if ($i.Value.GetType().Name.EndsWith("[]")) { - $result += ("`r`n$indent {0}:`r`n" -f $i.key) - foreach ($v in ($i.value)) { - $result += "$(ConfigDataToString $v "$indent ")`r`n" - } - $result += "`r`n" - } else { - if ($i.Value.GetType().Name.EndsWith("Object")) { - $result += ("$indent {0,-20}: {1}`r`n" -f $i.key, (convertto-psd1 $i.Value "$indent ")) - } - else { - if (!$i.key.Contains("Password")) { - $result += ("$indent {0,-20}: {1}`r`n" -f $i.key, $i.Value) - } - } - } - } - return $result -} - -function convertto-psd1 { -param( - [object] $InputData, - [string] $Indent = "" -) - if ($InputData.GetType().Name.EndsWith("String")) { - return "'$InputData'" - } - - $result = "$indent@{`r`n" - - foreach ($i in $InputData.GetEnumerator()) { - if ($i.Value.GetType().Name.EndsWith("Object[]")) { - $result += "$indent $($i.key) = @(" - $first = $true - foreach ($v in ($i.value)) { - if (!$first) { $result += ","} - $result += "`r`n" - $result += convertto-psd1 $v "$indent " - $first = $false - } - $result += "`r`n$indent )`r`n" - } elseif ($i.Value.GetType().Name.EndsWith("String[]")) { - $result += "$indent $($i.key) = @(" - $first = $true - foreach ($v in ($i.value)) { - if (!$first) { $result += ", "} - $result += "'$v'" - $first = $false - } - $result += " )`r`n" - } else { - if ($i.Value.GetType().Name.EndsWith("Object")) { - $result += "$indent $($i.key) = $(convertto-psd1 $i.Value "$indent ")`r`n" - } - else { - $result += "$indent $($i.key) = '$($i.Value)'`r`n" - } - } - } - $result += "$indent}" - return $result -} - - -#WARNING: this may be too slow -$ValidateFileExistsBlock = { - if(Test-path $this.Text) { - $this.Template=$global:defaulttxttemplate - } else { - $this.Template=$form.FindResource("ErrorTemplate") - } -} - - -function ValidateNotBlank { -param( - [Object] $ctl, - [String] $message = "This field is required." -) - if([String]::IsNullOrEmpty($ctl.text)) { - $ctl.Template = $form.FindResource("ErrorTemplate") - if ([String]::IsNullOrEmpty($ctl.Tooltip)) { - $ctl.tooltip = "Invalid value: this field is required.`r`nDetail: $message" - } - return $true - } else { - $ctl.tooltip = $message - $ctl.Template = $global:defaulttxttemplate - return $false - } -} - -function ValidatePassword { -param( - [Object] $ctl -) - if([String]::IsNullOrEmpty($ctl.password)) { - $ctl.Template=$form.FindResource("ErrorTemplate") - $ctl.tooltip = "Invalid value: This field is required." - return $true - } else { - $ctl.tooltip = "" - $ctl.Template=$global:defaulttxttemplate - return $false - } -} - - -function ValidateVLAN { -param( - [Object] $ctl -) - if ([Regex]::Match($ctl.text, "^\d{1,4}$").Success) { - $value = [Int32]::Parse($ctl.text) - if ($value -le 4096) { - $ctl.Template=$global:defaulttxttemplate - $ctl.tooltip = "" - return $false - } - $ctl.tooltip = "Invalid value: VLAN ID must be a value between 0 and 4096." - } else { - $ctl.tooltip = "Invalid value: VLAN ID can't contain non-numeric characters." - } - $ctl.Template=$form.FindResource("ErrorTemplate") - return $true -} - -function ValidateRegex { - param( - [Object] $ctl, - [string] $Regex, - [bool] $IsOptional = $false, - [string] $errormessage = "Field syntax is incorrect.", - [string] $message = "" - ) - if ($IsOptional -and [string]::IsNullOrEmpty($ctl.text)) { - $ctl.ToolTip = "Invalid value: $errormessage`r`nDetail: $message" - $ctl.Template=$global:defaulttxttemplate - return $FALSE - } - - if([Regex]::Match($ctl.text, $regex).Success) { - $ctl.Template=$global:defaulttxttemplate - $ctl.tooltip = $message - return $FALSE - } else { - $ctl.ToolTip = "Invalid value: $errormessage`r`nDetail: $message" - $ctl.Template=$form.FindResource("ErrorTemplate") - return $TRUE - } -} - -function ValidateIPAddress { - param( - [Object] $ctl, - [bool] $IsOptional = $false, - [string] $message = "" - ) - return ValidateRegex $ctl "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" $IsOptional "IP address syntax is not correct." $message -} - -function ValidateSubnetPrefix { - param( - [Object] $ctl, - [bool] $IsOptional = $false, - [string] $message = "" - ) - return ValidateRegex $ctl "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$" $IsOptional "Subnet prefix does not match required format of <subnet>/<bits>." $message -} - -function ValidateASN { - param( - [Object] $ctl, - [bool] $IsOptional = $false - ) - if ($IsOptional -and [string]::IsNullOrEmpty($ctl.text)) { - $ctl.Template=$global:defaulttxttemplate - $ctl.ToolTip = "" - return $FALSE - } - - if ([Regex]::Match($ctl.text, "^\d{1,5}$").Success) { - $value = [Int32]::Parse($ctl.text) - if (($value -lt 65535) -and ($value -gt 0)) { - $ctl.ToolTip = "" - $ctl.Template=$global:defaulttxttemplate - return $false - } - $ctl.ToolTip = "ASN is outside the valid range of values. It must be an integer number between 1 and 65534." - } else { - $ctl.ToolTip = "ASN contains non-numeric characters. It must be an integer number between 1 and 65534." - } - $ctl.Template=$form.FindResource("ErrorTemplate") - return $true -} - -function ValidateMACAddress { - param( - [Object] $ctl, - [bool] $IsOptional = $false - ) - if ($IsOptional -and [string]::IsNullOrEmpty($ctl.text)) { - $ctl.Template=$global:defaulttxttemplate - return $false - } - - $phys = [regex]::matches($ctl.text.ToUpper().Replace(":", "").Replace("-", ""), '.{1,2}').groups.value -join "-" - - if((![bool]($phys -as [physicaladdress])) -or ($phys.length -gt 17)) { - $ctl.tooltip = "Invalid mac address. Must contain 12 hexadecimal digits, can be optionally separated by : or - every two digits. Example: 00:11:22:33:44:55" - $ctl.Template=$form.FindResource("ErrorTemplate") - return $true - } else { - $ctl.tooltip = "" - $ctl.Template=$global:defaulttxttemplate - return $false - } -} - -function IsIPAddressInSubnet { - param( - [String] $IP, - [String] $subnet - ) - - $parts = $subnet.split("/") - if ($parts.count -ne 2) { - return $false - } - - $prefix = $parts[0] - - if (!($ip -as [IPAddress]) -or !($prefix -as [IPAddress])) { - return $false - } - - $bits = [int] $parts[1] - - $ipbytes = ($IP -as [IPaddress]).getaddressbytes() - $prebytes = ($prefix -as [IPaddress]).getaddressbytes() - - $fullbytes = [int] ((32-$bits) / 8) - $partbits = [int] ((32-$bits) % 8) - - for ($i=3; $i -ge (4-$fullbytes); $i--) { - $ipbytes[$i] = 0 - $prebytes[$i] = 0 - } - - $bitmask = [byte] 0xff -shl $partbits - $ipbytes[$i] = $ipbytes[$i] -band $bitmask - $prebytes[$i] = $prebytes[$i] -band $bitmask - - for ($i = 0; $i -lt $ipbytes.count ; $i++) { - if ($ipbytes[$i] -ne $prebytes[$i]) { - return $false - } - } - return $true -} - -function ValidateIPAddressInSubnet { - param( - [Object] $ctl, - [string] $subnet - ) - - if(!(IsIPAddressInSubnet $ctl.text $subnet)) { - $ctl.tooltip = "IP Address must fall within the specified subnet prefix of $subnet." - $ctl.Template=$form.FindResource("ErrorTemplate") - return $true - } else { - $ctl.tooltip = "" - $ctl.Template=$global:defaulttxttemplate - return $false - } -} - -function ValidateIPAddressIsGreater { - param( - [Object] $ctl, - [string] $lower - ) - - $greater = $ctl.text - - if (!($lower -as [IPAddress]) -or !($greater -as [IPAddress])) { - $ctl.Template=$form.FindResource("ErrorTemplate") - return $true - } - - $lbytes = ($lower -as [IPaddress]).getaddressbytes() - $gbytes = ($greater -as [IPaddress]).getaddressbytes() - - for ($i = 0; $i -lt $lbytes.count ; $i++) { - if ($gbytes[$i] -lt $lbytes[$i]) { - $ctl.Template=$form.FindResource("ErrorTemplate") - $ctl.tooltip = "This IP address must be squentially higher than $lower." - return $true - } - if ($gbytes[$i] -gt $lbytes[$i]) { - $ctl.Template=$global:defaulttxttemplate - $ctl.tooltip = "" - return $false - } - } - -} - -$ValidatePanel2 = { - $results = @() - $results += ValidateNotBlank $txtVHDLocation "This field must contain the full path and filename of the VHD or VHDX to use for VM creation." - $results += ValidateNotBlank $txtVMPath "This field must contain the path on the Hyper-V host where VM files will be placed. This can be a UNC or CSV path as long as the host has the necessary access privileges for the share and file system." - $results += ValidateNotBlank $txtVMNamePrefix "This field must contain a prefix which is applied to the beginning of the VM and computer name of VMs created by SDN Express." - $results += ValidateNotBlank $txtVMDomain "This field must contain the name of the active directory domain to which the VMs will join." - #Needs domain user validation - $results += ValidateNotBlank $txtDomainJoinUsername "This field must contain the domain and username of a domain account that has permission to join machines to the above specified domain. Example: CONTOSO\alyoung" - $results += ValidatePassword $txtDomainJoinPassword - $results += ValidatePassword $txtLocalAdminPassword - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - -$ValidatePanel3 = { - $results = @() - $results += ValidateVLAN $txtManagementVLANID - $results += ValidateSubnetPrefix $txtManagementSubnetPrefix $false "Enter the subnet prefix of the management subnet. Example: 192.168.0.0/24" - $results += ValidateIPAddress $txtManagementGateway $false "Enter the IP address of managemetn subnet's gateway." - $results += ValidateIPAddress $txtManagementIPPoolStart $false "Enter the first IP address to assign to the management interface of the SDN infrastructure VMs created by SDN Express." - $results += ValidateIPAddress $txtManagementIPPoolEnd $false "Enter the last IP address to assign to the management interface of the SDN infrastructure VMs created by SDN Express. There must be enough addresses in this pool to assign one address to each VM created." - $results += ValidateIPAddress $txtManagementDNS1 $false "Enter a DNS server to assign to the SDN infrastructure VMs created by SDN express." - $results += ValidateIPAddress $txtManagementDNS2 $true "Optionally enter additional DNS servers to assign to the SDN infrastructure VMs created by SDN Express." - $results += ValidateIPAddress $txtManagementDNS3 $true "Optionally enter additional DNS servers to assign to the SDN infrastructure VMs created by SDN Express." - - $results += ValidateIPAddressInSubnet $txtManagementGateway $txtManagementSubnetPrefix.Text - $results += ValidateIPAddressInSubnet $txtManagementIPPoolStart $txtManagementSubnetPrefix.Text - $results += ValidateIPAddressInSubnet $txtManagementIPPoolEnd $txtManagementSubnetPrefix.Text - $results += ValidateIPAddressIsGreater $txtManagementIPPoolEnd $txtManagementIPPoolStart.Text - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - -$ValidatePanel4 = { - $results = @() - $results += ValidateVLAN $txtPAVLANID - $results += ValidateSubnetPrefix $txtPASubnetPrefix - $results += ValidateIPAddress $txtPAGateway - $results += ValidateIPAddress $txtPAIPPoolStart - $results += ValidateIPAddress $txtPAIPPoolEnd - $results += ValidateMACAddress $txtMacPoolStart - $results += ValidateMACAddress $txtMacPoolEnd - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - -$ValidatePanel5 = { - $results = @() - $results += ValidateNotBlank $txtRESTName "This field must contain the fully qualified domain name to be assigned to the REST interface of the network controller." - $results += ValidateNotBlank $txtHyperVHosts "This field must contain a list of Hyper-V hosts to be added to the network controller. They must be separated by newlines, commas or semicolons." - $results += ValidateNotBlank $txtHostUsername "This domain and username is used by the network controller to access the Hyper-V hosts and SDN gateways running on the hsots. Example: CONTOSO\AlYoung" - $results += ValidatePassword $txtHostPassword - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - -$ValidatePanel6 = { - $results = @() - $results += ValidateSubnetPrefix $txtPrivateVIPs - $results += ValidateSubnetPrefix $txtPublicVIPs - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} -$ValidatePanel7 = { - $results = @() - $results += ValidateSubnetPrefix $txtGREVIPs - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - -$ValidatePanel8 = { - $results = @() - $results += ValidateASN $txtSDNASN - $results += ValidateIPAddress $txtRouterIP1 - $results += ValidateASN $txtRouterASN1 - $results += ValidateIPAddress $txtRouterIP2 $true - $results += ValidateASN $txtRouterASN2 $true - - foreach ($result in $results) { - if ($result) { - $btnNext1.IsEnabled = $false - return - } - } - $btnNext1.IsEnabled = $true -} - - function AddTxtValidation { - param( - $objtxt, - $block - ) - $objtxt.Add_TextChanged($block) - } - - -function GetNextIP { - param ( - $Ip - ) - if (!($IP -as [IPAddress])) - { - return "" - } - - $mb = ($IP -as [IPaddress]).getaddressbytes() - - for ($c = $mb.count; $c -gt 0; $c--) { - if ($mb[$c-1] -eq 0xff) { - $mb[$c-1] = 0 - } else { - $mb[$c-1]++ - return ($mb -as [ipaddress]).ToString() - } - } - } - -function GetNextMAC { -param ( - $Mac - ) - $mac = [regex]::matches($mac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - - if (!($mac -as [physicaladdress])) { - return "" - } - - $mb = ($mac -as [physicaladdress]).getaddressbytes() - - for ($c = $mb.count; $c -gt 0; $c--) { - if ($mb[$c-1] -eq 0xff) { - $mb[$c-1] = 0 - } else { - $mb[$c-1]++ - $newmac = ($mb -as [physicaladdress]).ToString() - return [regex]::matches($newmac.ToUpper().Replace(":", "").Replace("-", ""), '..').groups.value -join "-" - } - } -} - - function GenerateConfigData { - $ConfigData = [ordered] @{} - - $Path = $txtVHDLocation.Text - if (![string]::IsNullOrEmpty($path)) { - $PathParts = $path.Split("\") - - $ConfigData.ScriptVersion = "2.0" - - $ConfigData.VHDPath = $Path.substring(0, $Path.length-$PathParts[$PathParts.Count-1].length-1) - $ConfigData.VHDFile = $PathParts[$PathParts.Count-1] - } - - $ConfigData.VMLocation = $txtVMPath.Text - $ConfigData.JoinDomain = $txtVMDomain.text - - $ConfigData.ManagementVLANID = $txtManagementVLANID.text - $ConfigData.ManagementSubnet = $txtManagementSubnetPrefix.text - $ConfigData.ManagementGateway = $txtManagementGateway.text - $ConfigData.ManagementDNS = @() - $ConfigData.ManagementDNS += $txtManagementDNS1.text - if (![String]::IsNullOrEmpty($txtManagementDNS2.text)) { $ConfigData.ManagementDNS += $txtManagementDNS2.text } - if (![String]::IsNullOrEmpty($txtManagementDNS3.text)) { $ConfigData.ManagementDNS += $txtManagementDNS3.text } - - $ConfigData.DomainJoinUsername = $txtDomainJoinUsername.text - $ConfigData.DomainJoinSecurePassword = $txtDomainJoinPassword.Password | ConvertTo-SecureString -AsPlainText -Force | convertfrom-securestring - - $ConfigData.LocalAdminSecurePassword = $txtLocalAdminPassword.Password | ConvertTo-SecureString -AsPlainText -Force | convertfrom-securestring - - $ConfigData.LocalAdminDomainUser = $txtHostUserName.text - - $ConfigData.RestName = $txtRESTName.Text - - $hosttxt = $txtHyperVHosts.text - $hosttxt = $hosttxt.Replace("`r", "").Replace(" ", "") - $hosts = $hosttxt.Split("`n,;") - $ConfigData.HyperVHosts = $hosts - - - $nexthost = 0 - $nextIP = $txtManagementIPPoolStart.Text - $nextPA = $txtPAIPPoolStart.Text - $nextMAC = $txtMacPoolStart.Text - - $ConfigData.NCs = @() - $ConfigData.NCs += [ordered] @{ComputerName="$($txtVMNamePrefix.Text)NC01"; HostName=$hosts[$nexthost]; ManagementIP=$nextIP; MACAddress=$nextMac} - - $nextip = GetNextIP $nextip - $nextmac = GetNextMac $nextmac - $nexthost = ($nexthost + 1) % $hosts.count - - if ($rdoMultiNode.IsChecked) { - - $ConfigData.NCs += [ordered] @{ComputerName="$($txtVMNamePrefix.Text)NC02"; HostName=$hosts[$nexthost]; ManagementIP=$nextIP; MACAddress=$nextMac} - $nextip = GetNextIP $nextip - $nextmac = GetNextMac $nextmac - $nexthost = ($nexthost + 1) % $hosts.count - - $ConfigData.NCs += [ordered] @{ComputerName="$($txtVMNamePrefix.Text)NC03"; HostName=$hosts[$nexthost]; ManagementIP=$nextIP; MACAddress=$nextMac} - $nextip = GetNextIP $nextip - $nextmac = GetNextMac $nextmac - $nexthost = ($nexthost + 1) % $hosts.count - } - - $ConfigData.Muxes = @() - for ($c = 1; $c -le $sliMuxCount.Value; $c++) { - - $mgmtmac = $nextmac - $nextmac = getnextmac $nextmac - $pamac = $nextmac - $nextmac = getnextmac $nextmac - - $ConfigData.Muxes += [ordered] @{ComputerName="$($txtVMNamePrefix.Text)Mux{0:00}" -f $c; HostName=$hosts[$nexthost]; ManagementIP=$nextip; MACAddress=$mgmtmac; PAIPAddress=$nextpa; PAMACAddress=$pamac} - - $nexthost = ($nexthost + 1) % $hosts.count - $nextip = getnextip $nextip - $nextpa = getnextip $nextpa - - } - - $papoolstart = $nextpa - - $ConfigData.Gateways = @() - for ($c = 1; $c -le $sliGatewayCount.Value; $c++) { - $mgmtmac = $nextmac - $nextmac = getnextmac $nextmac - $femac = $nextmac - $nextmac = getnextmac $nextmac - $bemac = $nextmac - $nextmac = getnextmac $nextmac - - $ConfigData.Gateways += [ordered] @{ComputerName="$($txtVMNamePrefix.Text)GW{0:00}" -f $c; HostName=$hosts[$nexthost]; ManagementIP=$nextip; MACAddress=$mgmtmac; FrontEndIp=$nextpa; FrontEndMac=$femac; BackEndMac=$bemac} - - $nexthost = ($nexthost + 1) % $hosts.count - $nextip = getnextip $nextip - $nextpa = getnextip $nextpa - - } - - $ConfigData.NCUsername = $txtHostUsername.Text - $ConfigData.NCSecurePassword = $txtHostPassword.Password | ConvertTo-SecureString -AsPlainText -Force | convertfrom-securestring - - $ConfigData.PAVLANID = $txtPAVLANID.text - $ConfigData.PASubnet = $txtPASubnetPrefix.text - $ConfigData.PAGateway = $txtPAGateway.text - $ConfigData.PAPoolStart = $papoolstart - $ConfigData.PAPoolEnd = $txtPAIPPoolEnd.Text - - $ConfigData.SDNMacPoolStart = $nextMAC - $ConfigData.SDNMacPoolEnd = $txtMacPoolEnd.Text - - $ConfigData.SDNASN = $txtSDNASN.text - $ConfigData.Routers = @( - [ordered] @{ RouterASN=$txtRouterASN1.text; RouterIPAddress=$txtRouterIP1.text} - ) - if (![String]::IsNullOrEmpty($txtRouterIP2.text)) { - $ConfigData.Routers += [ordered] @{ RouterASN=$txtRouterASN2.text; RouterIPAddress=$txtRouterIP2.text} - } - - $ConfigData.PrivateVIPSubnet = $txtPrivateVIPs.text - $ConfigData.PublicVIPSubnet = $txtPublicVIPs.text - - $ConfigData.PoolName = "DefaultAll" - $ConfigData.GRESubnet = $txtGREVIPs.text - - - $ConfigData.Capacity = 10000 - - - return $ConfigData - } - - - function SetPanel - { - param( - $PanelIndex - ) - if ($panelIndex -eq 1) { $mark1.Visibility = "Visible"; $panel1.Visibility = "Visible"; } else { $mark1.Visibility = "Hidden"; $panel1.Visibility = "Hidden" } - if ($panelIndex -eq 2) { $mark2.Visibility = "Visible"; $panel2.Visibility = "Visible"; invoke-command $ValidatePanel2 } else { $mark2.Visibility = "Hidden"; $panel2.Visibility = "Hidden" } - if ($panelIndex -eq 3) { $mark3.Visibility = "Visible"; $panel3.Visibility = "Visible"; invoke-command $ValidatePanel3 } else { $mark3.Visibility = "Hidden"; $panel3.Visibility = "Hidden" } - if ($panelIndex -eq 4) { $mark4.Visibility = "Visible"; $panel4.Visibility = "Visible"; invoke-command $ValidatePanel4 } else { $mark4.Visibility = "Hidden"; $panel4.Visibility = "Hidden" } - if ($panelIndex -eq 5) { $mark5.Visibility = "Visible"; $panel5.Visibility = "Visible"; invoke-command $ValidatePanel5 } else { $mark5.Visibility = "Hidden"; $panel5.Visibility = "Hidden" } - if ($panelIndex -eq 6) { $mark6.Visibility = "Visible"; $panel6.Visibility = "Visible"; invoke-command $ValidatePanel6 } else { $mark6.Visibility = "Hidden"; $panel6.Visibility = "Hidden" } - if ($panelIndex -eq 7) { $mark7.Visibility = "Visible"; $panel7.Visibility = "Visible"; invoke-command $ValidatePanel7 } else { $mark7.Visibility = "Hidden"; $panel7.Visibility = "Hidden" } - if ($panelIndex -eq 8) { $mark8.Visibility = "Visible"; $panel8.Visibility = "Visible" } else { $mark8.Visibility = "Hidden"; $panel8.Visibility = "Hidden" } - if ($panelIndex -eq 9) { - $mark9.Visibility = "Visible"; - $panel9.Visibility = "Visible"; - $btnNext1.Content = "Deploy" - $txtReview.Text = ConfigDataToString (GenerateConfigData) - } else { - $mark9.Visibility = "Hidden"; - $panel9.Visibility = "Hidden"; - $btnNext1.Content = "Next" - } - if ($panelIndex -eq 10) { $global:Deploy = $true; $form.Close() } - } - - - #Read XAML - $reader=(New-Object System.Xml.XmlNodeReader $xaml) - try{$Form=[Windows.Markup.XamlReader]::Load( $reader )} - catch{Write-Host "Unable to load Windows.Markup.XamlReader. Some possible causes for this problem include: .NET Framework is missing PowerShell must be launched with PowerShell -sta, invalid XAML code was encountered."; exit} - - $xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name ($_.Name) -Value $Form.FindName($_.Name)} - - $global:PanelIndex = 1 - $global:Deploy = $false - $global:defaulttxttemplate = $form.FindResource("NormalTemplate") - - $btnBack1.IsEnabled = $false - - $uri1.Add_Click({ Start-Process -FilePath $this.NavigateUri}) - $uri2.Add_Click({ Start-Process -FilePath $this.NavigateUri}) - $uri3.Add_Click({ Start-Process -FilePath $this.NavigateUri}) - $uri4.Add_Click({ Start-Process -FilePath $this.NavigateUri}) - - $btnBack1.Add_Click({$global:PanelIndex=$global:panelIndex - 1; SetPanel $global:panelIndex; if ($global:panelIndex -eq 1) { $btnBack1.IsEnabled = $false }}) - $btnNext1.Add_Click({$global:PanelIndex=$global:panelIndex + 1; SetPanel $global:panelIndex; if ($global:panelIndex -gt 1) { $btnBack1.IsEnabled = $true }}) - $btnBrowse.Add_Click({ - [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null - - $ofd = New-Object System.Windows.Forms.OpenFileDialog - $ofd.initialDirectory = $txtVHDLocation.text - $ofd.filter = "Virtual Hard Disks (*.vhdx; *.vhd)|*.vhdx;*.vhd" - $ofd.ShowDialog() | Out-Null - $txtVHDLocation.text = $ofd.Filename - }) - $btnExport.Add_Click({ - [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null - - $ofd = New-Object System.Windows.Forms.SaveFileDialog - $ofd.filter = "Powershell (*.psd1)|*.psd1" - $result = $ofd.ShowDialog() - - if ($result) - { - $fn = $ofd.filename - $ConfigData = GenerateConfigData - - "" | out-file $fn - Convertto-psd1 $ConfigData | out-file $fn -append - - $Result = $null - } - }) - - - # Panel 2 Validation - AddTxtValidation $txtVHDLocation $ValidatePanel2 - AddTxtValidation $txtVMPath $ValidatePanel2 - AddTxtValidation $txtVMNamePrefix $ValidatePanel2 - AddTxtValidation $txtVMDomain $ValidatePanel2 - AddTxtValidation $txtDomainJoinUsername $ValidatePanel2 #Needs domain user validation - $txtDomainJoinPassword.Add_PasswordChanged($ValidatePanel2) - $txtLocalAdminPassword.Add_PasswordChanged($ValidatePanel2) - - # Panel 3 Validation - AddTxtValidation $txtManagementVLANID $ValidatePanel3 - AddTxtValidation $txtManagementSubnetPrefix $ValidatePanel3 - AddTxtValidation $txtManagementGateway $ValidatePanel3 - AddTxtValidation $txtManagementIPPoolStart $ValidatePanel3 - AddTxtValidation $txtManagementIPPoolEnd $ValidatePanel3 - AddTxtValidation $txtManagementDNS1 $ValidatePanel3 - AddTxtValidation $txtManagementDNS2 $ValidatePanel3 - AddTxtValidation $txtManagementDNS3 $ValidatePanel3 - - # Panel 4 Validation - AddTxtValidation $txtPAVLANID $ValidatePanel4 - AddTxtValidation $txtPASubnetPrefix $ValidatePanel4 - AddTxtValidation $txtPAGateway $ValidatePanel4 - AddTxtValidation $txtPAIPPoolStart $ValidatePanel4 - AddTxtValidation $txtPAIPPoolEnd $ValidatePanel4 - - $txtMacPoolStart.Text = "00:1D:D8:B7:1C:00" - $txtMacPoolEnd.Text = "00:1D:D8:B7:1F:FF" - - AddTxtValidation $txtMacPoolStart $ValidatePanel4 - AddTxtValidation $txtMacPoolEnd $ValidatePanel4 - - # Panel 5 Validation - AddTxtValidation $txtRESTName $ValidatePanel5 - AddTxtValidation $txtHyperVHosts $ValidatePanel5 # Needs multiline host validation - AddTxtValidation $txtHostUsername $ValidatePanel5 # Needs domain user validation - $txtHostPassword.Add_PasswordChanged($ValidatePanel5) - - # Panel 6 Validation - AddTxtValidation $txtPrivateVIPs $ValidatePanel6 - AddTxtValidation $txtPublicVIPs $ValidatePanel6 - - # Panel 7 Validation - AddTxtValidation $txtGREVIPs $ValidatePanel7 - - # Panel 8 Validation - AddTxtValidation $txtSDNASN $ValidatePanel8 - AddTxtValidation $txtRouterIP1 $ValidatePanel8 - AddTxtValidation $txtRouterASN1 $ValidatePanel8 - AddTxtValidation $txtRouterIP2 $ValidatePanel8 - AddTxtValidation $txtRouterASN2 $ValidatePanel8 - - SetPanel $PanelIndex - - $sliGatewayCount.Add_ValueChanged({ - $newmax = $sliGatewayCount.Value-1 - if ($sliRedundantCount.Value -gt $newmax) { - $sliRedundantCount.Value = $newmax - } - $sliRedundantCount.Maximum = $newmax - $sliRedundantCount.Width = ($newmax-1) * 40 - - }) - - $Form.ShowDialog() | out-null - - if ($global:deploy) { - return GenerateConfigData - } -} \ No newline at end of file diff --git a/src/utils/objects/utils/Sample - SDN Gateways.psd1 b/src/utils/objects/utils/Sample - SDN Gateways.psd1 deleted file mode 100644 index e2c9f59a..00000000 --- a/src/utils/objects/utils/Sample - SDN Gateways.psd1 +++ /dev/null @@ -1,129 +0,0 @@ -@{ - ScriptVersion = '3.0' - - #Location from where the VHD will be copied. VHDPath can be a local directory where SDN Express is run or an SMB share. - VHDPath = 'C:\images' - #Name of the VHDX as the golden image to use for VM creation. Use the convert-windowsimage utility to create this from an iso or install.wim. - VHDFile = 'RS5_RELEASE_SVC_HCI_17784.1068.200716-1400_serverazurestackhcicor_en-us_HCI.vhdx' - - #This is the location on the Hyper-V host where the VM files will be stored, including the VHD. A subdirectory will be created for each VM using the VM name. This location can be a local path on the host, a cluster volume, or an SMB share with appropriate permissions. - VMLocation = 'c:\VMs' - - #Specify the name of the active directory domain where you want the SDN infrastructure VMs to be joined. Domain join takes place offline prior to VM creation. - JoinDomain = 'sa18.nttest.microsoft.com' - - #IMPORTANT: if you deploy multiple network controllers onto the same network segments, you must change the SDNMacPool range to prevent overlap. - SDNMacPoolStart = "00-11-22-00-01-00" - SDNMacPoolEnd = "00-11-22-00-01-FF" - - #ManagmentSubnet, ManagementGateway, and ManagementDNS are not required if DHCP is configured for the management adapters below. - ManagementSubnet = '10.127.134.128/25' - ManagementGateway = '10.127.134.129' - ManagementDNS = @('10.127.130.7', '10.127.130.8') - #Use 0, or comment out ManagementVLANID to configure the management adapter for untagged traffic - ManagementVLANID = 7 - - #Usernames must be in the format Domain\User, Example: Contoso\Greg - #IMPORTANT: DomainJoinUsername is used for admin operations on the Hyper-V host when creating VMs, it is no longer used for domain joining, instead the current user that is running the script requires domain join permission. - DomainJoinUsername = 'sa18\george' - LocalAdminDomainUser = 'sa18\george' - NCUsername = 'sa18\george' - - #RestName must contain the FQDN that will be assigned to the SDN REST floating IP. - RestName = 'sa20n28sdn-test.sa18.nttest.microsoft.com' - - NCs = @( - #Optional parameters for each NC: - # MacAddress - if not specified Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # HostName - if not specified, taken round robin from list of hypervhosts - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - @{ComputerName='sa20n28-NC001'; HostName='SA20n28-2'; ManagementIP='10.127.134.201'; MACAddress = '001DD8220000'}, - @{ComputerName='sa20n28-NC002'; HostName='SA20n28-3'; ManagementIP='10.127.134.202'; MACAddress = '001DD8220001'}, - @{ComputerName='sa20n28-NC003'; HostName='SA20n28-3'; ManagementIP='10.127.134.203'; MACAddress = '001DD8220002'} - ) - Muxes = @( - #Optional parameters for each Mux: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAMacAddress - if not specified PA Adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAIPAddress - if not specified the PA IP Address is taken from the beginning of the HNV PA Pool. The start of the pool is incremented to not include this address. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, PAMacAddress must be outside of the SDN Mac Pool range. PAIPAddress must be outside of the HNV PA IP Pool Start and End range. - @{ComputerName='sa20n28-Mux01'; HostName='SA20n28-2'; ManagementIP='10.127.134.204'; MACAddress = '001DD8220003'; PAMacAddress = '001DD8220005'; PAIPAddress='10.10.202.62'}, - @{ComputerName='sa20n28-Mux02'; HostName='SA20n28-3'; ManagementIP='10.127.134.205'; MACAddress = '001DD8220004'; PAMacAddress = '001DD8220006'; PAIPAddress='10.10.202.63'} - ) - Gateways = @( - #Optional parameters for each Gateway: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # BackEndMac - if not specified Back End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # FrontEndMac - if not specified Front End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, frontendmac, backendmac must be within the SDN Mac Pool range. FrontEndIP must be within the HNV PA IP Pool Start and End range. - @{ComputerName='sa20n28-GW01'; HostName='SA20n28-2'; ManagementIP='10.127.134.206'; MACAddress='001DD8220005'; BackEndMac='0011220001FA'; FrontEndMac='0011220001FB'}, - @{ComputerName='sa20n28-GW02'; HostName='SA20n28-3'; ManagementIP='10.127.134.207'; MACAddress='001DD8220006'; BackEndMac='0011220001F9'; FrontEndMac='0011220001F8'} - ) - - # Names of the initial Hyper-V hosts to add to the SDN deployment. If you will be using additional Hyper-V hosts on different HNV PA subnets, you must add those after the initial deployment using the Add-SDNExpressHost function in the SDNExpressModule. - HyperVHosts = @( - 'SA20n28-1', - 'SA20n28-2', - 'SA20n28-3', - 'SA20n28-4' - ) - - # Intiail HNV PA subnet to add for the network virtualization overlay to use. You can add additional HNV PA subnets after deployment using the Add-SDNExpressVirtualNetworkPASubnet function in the sdnexpressmodule. - PASubnet = '10.10.202.0/25' - PAVLANID = '11' - PAGateway = '10.10.202.1' - PAPoolStart = '10.10.202.49' - PAPoolEnd = '10.10.202.61' - - # Load Balancer and Gateway BGP information - # SDN ASN to be used for load balancing VIPs, public IPs and GRE gateway advertisements. Peering will take place from the HNV PA IP addresses assigned above. It is recommended that your network administrator configure a peer group for the HNV PA subnet. - SDNASN = '64628' - - # Router BGP peering endpoint ASN and IP address that is configured for peering by your network administrator. On some routers it is recommended to peer with the loopback address. - Routers = @( - @{ RouterASN='64647'; RouterIPAddress='10.10.202.1'} - ) - - # Initial set of VIP subnets to use for load balancing and public IPs - PublicVIPSubnet = '10.127.134.24/29' - PrivateVIPSubnet = '12.0.0.0/29' - - # Subnet to use for GRE gateway connection endpoints. This subnet is only used if you configure GRE gateway connections. - GRESubnet = '15.127.134.24/29' - - # Gateway VM network capacity, used by SDN controller for capacity management of gateway connections. - Capacity = '10000000' - - - # Optional fields. Uncomment items if you need to override the defaults. - - # Initial gateway pool name, if not specified will use DefaultAll. Additional pools can be added after the initial deployment using the SDNExpressModule. - # PoolName = '' - - # Specify ProductKey if you have a product key to use for newly created VMs. If this is not specified you may need - # to connect to the VM console to proceed with eval mode. - # ProductKey = '#####-#####-#####-#####-#####' - - # Switch name is only required if more than one virtual switch exists on the Hyper-V hosts. - SwitchName = "ConvergedSwitch" - - # Amount of Memory and number of Processors to assign to VMs that are created. - # If not specified a default of 8 procs and 8GB RAM are used. - # VMMemory = 4GB - # VMProcessorCount = 4 - - # If Locale and Timezone are not specified the local time zone of the deployment machine is used. - # Locale = '' - # TimeZone = '' - - # Passwords can be optionally included if stored encrypted as text encoded secure strings. Passwords will only be used - # if SDN Express is run on the same machine where they were encrypted, otherwise it will prompt for passwords. - # DomainJoinSecurePassword = '' - # LocalAdminSecurePassword = '' - # NCSecurePassword = '' - -} diff --git a/src/utils/objects/utils/Sample - Software Load Balancer.psd1 b/src/utils/objects/utils/Sample - Software Load Balancer.psd1 deleted file mode 100644 index e75b042c..00000000 --- a/src/utils/objects/utils/Sample - Software Load Balancer.psd1 +++ /dev/null @@ -1,129 +0,0 @@ -@{ - ScriptVersion = '3.0' - - #Location from where the VHD will be copied. VHDPath can be a local directory where SDN Express is run or an SMB share. - VHDPath = 'C:\images' - #Name of the VHDX as the golden image to use for VM creation. Use the convert-windowsimage utility to create this from an iso or install.wim. - VHDFile = 'RS5_RELEASE_SVC_HCI_17784.1068.200716-1400_serverazurestackhcicor_en-us_HCI.vhdx' - - #This is the location on the Hyper-V host where the VM files will be stored, including the VHD. A subdirectory will be created for each VM using the VM name. This location can be a local path on the host, a cluster volume, or an SMB share with appropriate permissions. - VMLocation = 'c:\VMs' - - #Specify the name of the active directory domain where you want the SDN infrastructure VMs to be joined. Domain join takes place offline prior to VM creation. - JoinDomain = 'sa18.nttest.microsoft.com' - - #IMPORTANT: if you deploy multiple network controllers onto the same network segments, you must change the SDNMacPool range to prevent overlap. - SDNMacPoolStart = "00-11-22-00-01-00" - SDNMacPoolEnd = "00-11-22-00-01-FF" - - #ManagmentSubnet, ManagementGateway, and ManagementDNS are not required if DHCP is configured for the management adapters below. - ManagementSubnet = '10.127.134.128/25' - ManagementGateway = '10.127.134.129' - ManagementDNS = @('10.127.130.7', '10.127.130.8') - #Use 0, or comment out ManagementVLANID to configure the management adapter for untagged traffic - ManagementVLANID = 7 - - #Usernames must be in the format Domain\User, Example: Contoso\Greg - #IMPORTANT: DomainJoinUsername is used for admin operations on the Hyper-V host when creating VMs, it is no longer used for domain joining, instead the current user that is running the script requires domain join permission. - DomainJoinUsername = 'sa18\george' - LocalAdminDomainUser = 'sa18\george' - NCUsername = 'sa18\george' - - #RestName must contain the FQDN that will be assigned to the SDN REST floating IP. - RestName = 'sa20n28sdn-test.sa18.nttest.microsoft.com' - - NCs = @( - #Optional parameters for each NC: - # MacAddress - if not specified Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # HostName - if not specified, taken round robin from list of hypervhosts - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - @{ComputerName='sa20n28-NC001'; HostName='SA20n28-2'; ManagementIP='10.127.134.201'; MACAddress = '001DD8220000'}, - @{ComputerName='sa20n28-NC002'; HostName='SA20n28-3'; ManagementIP='10.127.134.202'; MACAddress = '001DD8220001'}, - @{ComputerName='sa20n28-NC003'; HostName='SA20n28-3'; ManagementIP='10.127.134.203'; MACAddress = '001DD8220002'} - ) - Muxes = @( - #Optional parameters for each Mux: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAMacAddress - if not specified PA Adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAIPAddress - if not specified the PA IP Address is taken from the beginning of the HNV PA Pool. The start of the pool is incremented to not include this address. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, PAMacAddress must be outside of the SDN Mac Pool range. PAIPAddress must be outside of the HNV PA IP Pool Start and End range. - @{ComputerName='sa20n28-Mux01'; HostName='SA20n28-2'; ManagementIP='10.127.134.204'; MACAddress = '001DD8220003'; PAMacAddress = '001DD8220005'; PAIPAddress='10.10.202.62'}, - @{ComputerName='sa20n28-Mux02'; HostName='SA20n28-3'; ManagementIP='10.127.134.205'; MACAddress = '001DD8220004'; PAMacAddress = '001DD8220006'; PAIPAddress='10.10.202.63'} - ) - Gateways = @() - #Optional parameters for each Gateway: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # BackEndMac - if not specified Back End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # FrontEndMac - if not specified Front End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, frontendmac, backendmac must be within the SDN Mac Pool range. FrontEndIP must be within the HNV PA IP Pool Start and End range. - # @{ComputerName='Contoso-GW01'; ManagementIP='10.127.132.174'; MACAddress = '001DD8220003'}, - # @{ComputerName='Contoso-GW02'; ManagementIP='10.127.132.175'; MACAddress = '001DD8220004'} - #) - - # Names of the initial Hyper-V hosts to add to the SDN deployment. If you will be using additional Hyper-V hosts on different HNV PA subnets, you must add those after the initial deployment using the Add-SDNExpressHost function in the SDNExpressModule. - HyperVHosts = @( - 'SA20n28-1', - 'SA20n28-2', - 'SA20n28-3', - 'SA20n28-4' - ) - - # Intiail HNV PA subnet to add for the network virtualization overlay to use. You can add additional HNV PA subnets after deployment using the Add-SDNExpressVirtualNetworkPASubnet function in the sdnexpressmodule. - PASubnet = '10.10.202.0/25' - PAVLANID = '11' - PAGateway = '10.10.202.1' - PAPoolStart = '10.10.202.49' - PAPoolEnd = '10.10.202.61' - - # Load Balancer and Gateway BGP information - # SDN ASN to be used for load balancing VIPs, public IPs and GRE gateway advertisements. Peering will take place from the HNV PA IP addresses assigned above. It is recommended that your network administrator configure a peer group for the HNV PA subnet. - SDNASN = '64628' - - # Router BGP peering endpoint ASN and IP address that is configured for peering by your network administrator. On some routers it is recommended to peer with the loopback address. - Routers = @( - @{ RouterASN='64647'; RouterIPAddress='10.10.202.1'} - ) - - # Initial set of VIP subnets to use for load balancing and public IPs - PrivateVIPSubnet = '12.35.24.25/29' - PublicVIPSubnet = '10.127.134.24/29' - - # Subnet to use for GRE gateway connection endpoints. This subnet is only used if you configure GRE gateway connections. - # GRESubnet = '' - - # Gateway VM network capacity, used by SDN controller for capacity management of gateway connections. - # Capacity = '' - - - # Optional fields. Uncomment items if you need to override the defaults. - - # Initial gateway pool name, if not specified will use DefaultAll. Additional pools can be added after the initial deployment using the SDNExpressModule. - # PoolName = '' - - # Specify ProductKey if you have a product key to use for newly created VMs. If this is not specified you may need - # to connect to the VM console to proceed with eval mode. - # ProductKey = '#####-#####-#####-#####-#####' - - # Switch name is only required if more than one virtual switch exists on the Hyper-V hosts. - SwitchName = "ConvergedSwitch" - - # Amount of Memory and number of Processors to assign to VMs that are created. - # If not specified a default of 8 procs and 8GB RAM are used. - # VMMemory = 4GB - # VMProcessorCount = 4 - - # If Locale and Timezone are not specified the local time zone of the deployment machine is used. - # Locale = '' - # TimeZone = '' - - # Passwords can be optionally included if stored encrypted as text encoded secure strings. Passwords will only be used - # if SDN Express is run on the same machine where they were encrypted, otherwise it will prompt for passwords. - # DomainJoinSecurePassword = '' - # LocalAdminSecurePassword = '' - # NCSecurePassword = '' - -} diff --git a/src/utils/objects/utils/Sample - Traditional VLAN networks.psd1 b/src/utils/objects/utils/Sample - Traditional VLAN networks.psd1 deleted file mode 100644 index b83e2c43..00000000 --- a/src/utils/objects/utils/Sample - Traditional VLAN networks.psd1 +++ /dev/null @@ -1,129 +0,0 @@ -@{ - ScriptVersion = '3.0' - - #Location from where the VHD will be copied. VHDPath can be a local directory where SDN Express is run or an SMB share. - VHDPath = 'C:\images' - #Name of the VHDX as the golden image to use for VM creation. Use the convert-windowsimage utility to create this from an iso or install.wim. - VHDFile = 'RS5_RELEASE_SVC_HCI_17784.1068.200716-1400_serverazurestackhcicor_en-us_HCI.vhdx' - - #This is the location on the Hyper-V host where the VM files will be stored, including the VHD. A subdirectory will be created for each VM using the VM name. This location can be a local path on the host, a cluster volume, or an SMB share with appropriate permissions. - VMLocation = 'c:\VMs' - - #Specify the name of the active directory domain where you want the SDN infrastructure VMs to be joined. Domain join takes place offline prior to VM creation. - JoinDomain = 'sa18.nttest.microsoft.com' - - #IMPORTANT: if you deploy multiple network controllers onto the same network segments, you must change the SDNMacPool range to prevent overlap. - SDNMacPoolStart = "00-11-22-00-01-00" - SDNMacPoolEnd = "00-11-22-00-01-FF" - - #ManagmentSubnet, ManagementGateway, and ManagementDNS are not required if DHCP is configured for the management adapters below. - ManagementSubnet = '10.127.134.128/25' - ManagementGateway = '10.127.134.129' - ManagementDNS = @('10.127.130.7', '10.127.130.8') - #Use 0, or comment out ManagementVLANID to configure the management adapter for untagged traffic - ManagementVLANID = 7 - - #Usernames must be in the format Domain\User, Example: Contoso\Greg - #IMPORTANT: DomainJoinUsername is used for admin operations on the Hyper-V host when creating VMs, it is no longer used for domain joining, instead the current user that is running the script requires domain join permission. - DomainJoinUsername = 'sa18\george' - LocalAdminDomainUser = 'sa18\george' - NCUsername = 'sa18\george' - - #RestName must contain the FQDN that will be assigned to the SDN REST floating IP. - RestName = 'sa20n28sdn-1.sa18.nttest.microsoft.com' - - NCs = @( - #Optional parameters for each NC: - # MacAddress - if not specified Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # HostName - if not specified, taken round robin from list of hypervhosts - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - @{ComputerName='sa20n28-NC01'; HostName='SA20n28-1'; ManagementIP='10.127.134.201'; MACAddress = '001DD8220000'}, - @{ComputerName='sa20n28-NC02'; HostName='SA20n28-2'; ManagementIP='10.127.134.202'; MACAddress = '001DD8220001'}, - @{ComputerName='sa20n28-NC03'; HostName='SA20n28-3'; ManagementIP='10.127.134.203'; MACAddress = '001DD8220002'} - ) - Muxes = @() - #Optional parameters for each Mux: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAMacAddress - if not specified PA Adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAIPAddress - if not specified the PA IP Address is taken from the beginning of the HNV PA Pool. The start of the pool is incremented to not include this address. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, PAMacAddress must be outside of the SDN Mac Pool range. PAIPAddress must be outside of the HNV PA IP Pool Start and End range. - #@{ComputerName='Contoso-Mux01'; ManagementIP='10.127.132.172'}, - #@{ComputerName='Contoso-Mux02'; ManagementIP='10.127.132.173'} - #) - Gateways = @() - #Optional parameters for each Gateway: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # BackEndMac - if not specified Back End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # FrontEndMac - if not specified Front End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, frontendmac, backendmac must be within the SDN Mac Pool range. FrontEndIP must be within the HNV PA IP Pool Start and End range. - # @{ComputerName='Contoso-GW01'; ManagementIP='10.127.132.174'}, - # @{ComputerName='Contoso-GW02'; ManagementIP='10.127.132.175'} - #) - - # Names of the initial Hyper-V hosts to add to the SDN deployment. If you will be using additional Hyper-V hosts on different HNV PA subnets, you must add those after the initial deployment using the Add-SDNExpressHost function in the SDNExpressModule. - HyperVHosts = @( - 'SA20n28-1', - 'SA20n28-2', - 'SA20n28-3', - 'SA20n28-4' - ) - - # Intiail HNV PA subnet to add for the network virtualization overlay to use. You can add additional HNV PA subnets after deployment using the Add-SDNExpressVirtualNetworkPASubnet function in the sdnexpressmodule. - # PASubnet = '10.10.202.0/25' - # PAVLANID = '11' - # PAGateway = '10.10.202.1' - # PAPoolStart = '10.10.202.49' - # PAPoolEnd = '10.10.202.63' - - # Load Balancer and Gateway BGP information - # SDN ASN to be used for load balancing VIPs, public IPs and GRE gateway advertisements. Peering will take place from the HNV PA IP addresses assigned above. It is recommended that your network administrator configure a peer group for the HNV PA subnet. - # SDNASN = '64628' - - # Router BGP peering endpoint ASN and IP address that is configured for peering by your network administrator. On some routers it is recommended to peer with the loopback address. - #Routers = @( - # @{ RouterASN='64623'; RouterIPAddress='10.10.182.1'} - #) - - # Initial set of VIP subnets to use for load balancing and public IPs - # PrivateVIPSubnet = '' - # PublicVIPSubnet = '' - - # Subnet to use for GRE gateway connection endpoints. This subnet is only used if you configure GRE gateway connections. - # GRESubnet = '' - - # Gateway VM network capacity, used by SDN controller for capacity management of gateway connections. - # Capacity = '' - - - # Optional fields. Uncomment items if you need to override the defaults. - - # Initial gateway pool name, if not specified will use DefaultAll. Additional pools can be added after the initial deployment using the SDNExpressModule. - # PoolName = '' - - # Specify ProductKey if you have a product key to use for newly created VMs. If this is not specified you may need - # to connect to the VM console to proceed with eval mode. - # ProductKey = '#####-#####-#####-#####-#####' - - # Switch name is only required if more than one virtual switch exists on the Hyper-V hosts. - SwitchName = "ConvergedSwitch" - - # Amount of Memory and number of Processors to assign to VMs that are created. - # If not specified a default of 8 procs and 8GB RAM are used. - # VMMemory = 4GB - # VMProcessorCount = 4 - - # If Locale and Timezone are not specified the local time zone of the deployment machine is used. - # Locale = '' - # TimeZone = '' - - # Passwords can be optionally included if stored encrypted as text encoded secure strings. Passwords will only be used - # if SDN Express is run on the same machine where they were encrypted, otherwise it will prompt for passwords. - # DomainJoinSecurePassword = '' - # LocalAdminSecurePassword = '' - # NCSecurePassword = '' - -} diff --git a/src/utils/objects/utils/Sample - Virtualized networks.psd1 b/src/utils/objects/utils/Sample - Virtualized networks.psd1 deleted file mode 100644 index ce8cd36e..00000000 --- a/src/utils/objects/utils/Sample - Virtualized networks.psd1 +++ /dev/null @@ -1,129 +0,0 @@ -@{ - ScriptVersion = '3.0' - - #Location from where the VHD will be copied. VHDPath can be a local directory where SDN Express is run or an SMB share. - VHDPath = 'C:\images' - #Name of the VHDX as the golden image to use for VM creation. Use the convert-windowsimage utility to create this from an iso or install.wim. - VHDFile = 'RS5_RELEASE_SVC_HCI_17784.1068.200716-1400_serverazurestackhcicor_en-us_HCI.vhdx' - - #This is the location on the Hyper-V host where the VM files will be stored, including the VHD. A subdirectory will be created for each VM using the VM name. This location can be a local path on the host, a cluster volume, or an SMB share with appropriate permissions. - VMLocation = 'c:\VMs' - - #Specify the name of the active directory domain where you want the SDN infrastructure VMs to be joined. Domain join takes place offline prior to VM creation. - JoinDomain = 'sa18.nttest.microsoft.com' - - #IMPORTANT: if you deploy multiple network controllers onto the same network segments, you must change the SDNMacPool range to prevent overlap. - SDNMacPoolStart = "00-11-22-00-01-00" - SDNMacPoolEnd = "00-11-22-00-01-FF" - - #ManagmentSubnet, ManagementGateway, and ManagementDNS are not required if DHCP is configured for the management adapters below. - ManagementSubnet = '10.127.134.128/25' - ManagementGateway = '10.127.134.129' - ManagementDNS = @('10.127.130.7', '10.127.130.8') - #Use 0, or comment out ManagementVLANID to configure the management adapter for untagged traffic - ManagementVLANID = 7 - - #Usernames must be in the format Domain\User, Example: Contoso\Greg - #IMPORTANT: DomainJoinUsername is used for admin operations on the Hyper-V host when creating VMs, it is no longer used for domain joining, instead the current user that is running the script requires domain join permission. - DomainJoinUsername = 'sa18\george' - LocalAdminDomainUser = 'sa18\george' - NCUsername = 'sa18\george' - - #RestName must contain the FQDN that will be assigned to the SDN REST floating IP. - RestName = 'sa20n28sdn-1.sa18.nttest.microsoft.com' - - NCs = @( - #Optional parameters for each NC: - # MacAddress - if not specified Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # HostName - if not specified, taken round robin from list of hypervhosts - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - @{ComputerName='sa20n28-NC01'; HostName='SA20n28-1'; ManagementIP='10.127.134.201'; MACAddress = '001DD8220000'}, - @{ComputerName='sa20n28-NC02'; HostName='SA20n28-2'; ManagementIP='10.127.134.202'; MACAddress = '001DD8220001'}, - @{ComputerName='sa20n28-NC03'; HostName='SA20n28-3'; ManagementIP='10.127.134.203'; MACAddress = '001DD8220002'} - ) - Muxes = @() - #Optional parameters for each Mux: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAMacAddress - if not specified PA Adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # PAIPAddress - if not specified the PA IP Address is taken from the beginning of the HNV PA Pool. The start of the pool is incremented to not include this address. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, PAMacAddress must be outside of the SDN Mac Pool range. PAIPAddress must be outside of the HNV PA IP Pool Start and End range. - #@{ComputerName='Contoso-Mux01'; ManagementIP='10.127.132.172'}, - #@{ComputerName='Contoso-Mux02'; ManagementIP='10.127.132.173'} - #) - Gateways = @() - #Optional parameters for each Gateway: - # HostName - if not specified, taken round robin from list of hypervhosts - # MacAddress - if not specified Management adapter Mac Address is taken from start of SDNMacPool. SDN Mac Pool start is incremented to not include this mac. - # BackEndMac - if not specified Back End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # FrontEndMac - if not specified Front End Adapter Mac Address is taken from start of SDNMacPool. This Mac remains within the SDN Mac Pool. - # ManagementIP - if not specified, Management adapter will be configured for DHCP on the ManagementVLANID VLAN. If DHCP is used it is strongly recommended that you configure a reservation for the assigned IP address on the DHCP server. - #IMPORTANT NOTE: if specified, frontendmac, backendmac must be within the SDN Mac Pool range. FrontEndIP must be within the HNV PA IP Pool Start and End range. - # @{ComputerName='Contoso-GW01'; ManagementIP='10.127.132.174'}, - # @{ComputerName='Contoso-GW02'; ManagementIP='10.127.132.175'} - #) - - # Names of the initial Hyper-V hosts to add to the SDN deployment. If you will be using additional Hyper-V hosts on different HNV PA subnets, you must add those after the initial deployment using the Add-SDNExpressHost function in the SDNExpressModule. - HyperVHosts = @( - 'SA20n28-1', - 'SA20n28-2', - 'SA20n28-3', - 'SA20n28-4' - ) - - # Intiail HNV PA subnet to add for the network virtualization overlay to use. You can add additional HNV PA subnets after deployment using the Add-SDNExpressVirtualNetworkPASubnet function in the sdnexpressmodule. - PASubnet = '10.10.202.0/25' - PAVLANID = '11' - PAGateway = '10.10.202.1' - PAPoolStart = '10.10.202.49' - PAPoolEnd = '10.10.202.63' - - # Load Balancer and Gateway BGP information - # SDN ASN to be used for load balancing VIPs, public IPs and GRE gateway advertisements. Peering will take place from the HNV PA IP addresses assigned above. It is recommended that your network administrator configure a peer group for the HNV PA subnet. - # SDNASN = '64628' - - # Router BGP peering endpoint ASN and IP address that is configured for peering by your network administrator. On some routers it is recommended to peer with the loopback address. - #Routers = @( - # @{ RouterASN='64623'; RouterIPAddress='10.10.182.1'} - #) - - # Initial set of VIP subnets to use for load balancing and public IPs - # PrivateVIPSubnet = '' - # PublicVIPSubnet = '' - - # Subnet to use for GRE gateway connection endpoints. This subnet is only used if you configure GRE gateway connections. - # GRESubnet = '' - - # Gateway VM network capacity, used by SDN controller for capacity management of gateway connections. - # Capacity = '' - - - # Optional fields. Uncomment items if you need to override the defaults. - - # Initial gateway pool name, if not specified will use DefaultAll. Additional pools can be added after the initial deployment using the SDNExpressModule. - # PoolName = '' - - # Specify ProductKey if you have a product key to use for newly created VMs. If this is not specified you may need - # to connect to the VM console to proceed with eval mode. - # ProductKey = '#####-#####-#####-#####-#####' - - # Switch name is only required if more than one virtual switch exists on the Hyper-V hosts. - SwitchName = "ConvergedSwitch" - - # Amount of Memory and number of Processors to assign to VMs that are created. - # If not specified a default of 8 procs and 8GB RAM are used. - # VMMemory = 4GB - # VMProcessorCount = 4 - - # If Locale and Timezone are not specified the local time zone of the deployment machine is used. - # Locale = '' - # TimeZone = '' - - # Passwords can be optionally included if stored encrypted as text encoded secure strings. Passwords will only be used - # if SDN Express is run on the same machine where they were encrypted, otherwise it will prompt for passwords. - # DomainJoinSecurePassword = '' - # LocalAdminSecurePassword = '' - # NCSecurePassword = '' - -} diff --git a/src/utils/objects/utils/SdnExpress.psd1 b/src/utils/objects/utils/SdnExpress.psd1 deleted file mode 100644 index 2b4b4558..00000000 --- a/src/utils/objects/utils/SdnExpress.psd1 +++ /dev/null @@ -1,132 +0,0 @@ -# -# Module manifest for module 'SdnExpress' -# -# Generated by: Microsoft Windows Networking Developer Team (SDN) -# -# Generated on: 6/22/2023 -# - -@{ - -# Script module or binary module file associated with this manifest. -RootModule = '.\SDNExpress.psm1' - -# Version number of this module. -ModuleVersion = '1.1.22' - -# Supported PSEditions -# CompatiblePSEditions = @() - -# ID used to uniquely identify this module -GUID = 'c235c83a-0473-4db4-93b8-7eee95707839' - -# Author of this module -Author = 'Microsoft Windows Networking Developer Team (SDN)' - -# Company or vendor of this module -CompanyName = 'Microsoft Corp' - -# Copyright statement for this module -Copyright = 'Microsoft Corporation (c) 2023 All rights reserved.' - -# Description of the functionality provided by this module -Description = 'SDN Express' - -# Minimum version of the Windows PowerShell engine required by this module -# PowerShellVersion = '' - -# Name of the Windows PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the Windows PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# CLRVersion = '' - -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' - -# Modules that must be imported into the global environment prior to importing this module -# RequiredModules = @() - -# Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() - -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -# NestedModules = @() - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @() - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = @() - -# Variables to export from this module -# VariablesToExport = @() - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @() - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# List of all files packaged with this module -# FileList = @() - -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - # Tags = @() - - # A URL to the license for this module. - # LicenseUri = '' - - # A URL to the main website for this project. - # ProjectUri = '' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - # ReleaseNotes = '' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} - diff --git a/src/utils/objects/utils/netscan.ps1 b/src/utils/objects/utils/netscan.ps1 deleted file mode 100644 index 6fe8385d..00000000 --- a/src/utils/objects/utils/netscan.ps1 +++ /dev/null @@ -1,64 +0,0 @@ -$ip = $(ipconfig | where {$_ -match 'IPv4.+\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' } | out-null; $Matches[1]) - -$oct0=([ipaddress] $ip).GetAddressBytes()[0] -$oct1=([ipaddress] $ip).GetAddressBytes()[1] -$oct2=([ipaddress] $ip).GetAddressBytes()[2] -$oct3=([ipaddress] $ip).GetAddressBytes()[3] - -$ipcutup="$oct0 $oct1 $oct2 $oct3" -$ipcut="$oct0.$oct1.$oct2" -$ipaddresscut= "$oc0 $oc1 $oc2" -$sNet = 1..255 -$all = $sNet.Count -$i = 1 - -$hosts = @() -$ips = @() -$top1000 = @(1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26,30,32,33,37,42,43,49,53,70,79,80,81,82,83,84,85,88,89,90,99,100,106,109,110,111,113,119,125,135,139,143,144,146,161,163,179,199,211,212,222,254,255,256,259,264,280,301,306,311,340,366,389,406,407,416,417,425,427,443,444,445,458,464,465,481,497,500,512,513,514,515,524,541,543,544,545,548,554,555,563,587,593,616,617,625,631,636,646,648,666,667,668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800,801,808,843,873,880,888,898,900,901,902,903,911,912,981,987,990,992,993,995,999,1000,1001,1002,1007,1009,1010,1011,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1102,1104,1105,1106,1107,1108,1110,1111,1112,1113,1114,1117,1119,1121,1122,1123,1124,1126,1130,1131,1132,1137,1138,1141,1145,1147,1148,1149,1151,1152,1154,1163,1164,1165,1166,1169,1174,1175,1183,1185,1186,1187,1192,1198,1199,1201,1213,1216,1217,1218,1233,1234,1236,1244,1247,1248,1259,1271,1272,1277,1287,1296,1300,1301,1309,1310,1311,1322,1328,1334,1352,1417,1433,1434,1443,1455,1461,1494,1500,1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687,1688,1700,1717,1718,1719,1720,1721,1723,1755,1761,1782,1783,1801,1805,1812,1839,1840,1862,1863,1864,1875,1900,1914,1935,1947,1971,1972,1974,1984,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013,2020,2021,2022,2030,2033,2034,2035,2038,2040,2041,2042,2043,2045,2046,2047,2048,2049,2065,2068,2099,2100,2103,2105,2106,2107,2111,2119,2121,2126,2135,2144,2160,2161,2170,2179,2190,2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381,2382,2383,2393,2394,2399,2401,2492,2500,2522,2525,2557,2601,2602,2604,2605,2607,2608,2638,2701,2702,2710,2717,2718,2725,2800,2809,2811,2869,2875,2909,2910,2920,2967,2968,2998,3000,3001,3003,3005,3006,3007,3011,3013,3017,3030,3031,3052,3071,3077,3128,3168,3211,3221,3260,3261,3268,3269,3283,3300,3301,3306,3322,3323,3324,3325,3333,3351,3367,3369,3370,3371,3372,3389,3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689,3690,3703,3737,3766,3784,3800,3801,3809,3814,3826,3827,3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000,4001,4002,4003,4004,4005,4006,4045,4111,4125,4126,4129,4224,4242,4279,4321,4343,4443,4444,4445,4446,4449,4550,4567,4662,4848,4899,4900,4998,5000,5001,5002,5003,5004,5009,5030,5033,5050,5051,5054,5060,5061,5080,5087,5100,5101,5102,5120,5190,5200,5214,5221,5222,5225,5226,5269,5280,5298,5357,5405,5414,5431,5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678,5679,5718,5730,5800,5801,5802,5810,5811,5815,5822,5825,5850,5859,5862,5877,5900,5901,5902,5903,5904,5906,5907,5910,5911,5915,5922,5925,5950,5952,5959,5960,5961,5962,5963,5987,5988,5989,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565,6566,6567,6580,6646,6666,6667,6668,6669,6689,6692,6699,6779,6788,6789,6792,6839,6881,6901,6969,7000,7001,7002,7004,7007,7019,7025,7070,7100,7103,7106,7200,7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777,7778,7800,7911,7920,7921,7937,7938,7999,8000,8001,8002,8007,8008,8009,8010,8011,8021,8022,8031,8042,8045,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8093,8099,8100,8180,8181,8192,8193,8194,8200,8222,8254,8290,8291,8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651,8652,8654,8701,8800,8873,8888,8899,8994,9000,9001,9002,9003,9009,9010,9011,9040,9050,9071,9080,9081,9090,9091,9099,9100,9101,9102,9103,9110,9111,9200,9207,9220,9290,9415,9418,9485,9500,9502,9503,9535,9575,9593,9594,9595,9618,9666,9876,9877,9878,9898,9900,9917,9929,9943,9944,9968,9998,9999,10000,10001,10002,10003,10004,10009,10010,10012,10024,10025,10082,10180,10215,10243,10566,10616,10617,10621,10626,10628,10629,10778,11110,11111,11967,12000,12174,12265,12345,13456,13722,13782,13783,14000,14238,14441,14442,15000,15002,15003,15004,15660,15742,16000,16001,16012,16016,16018,16080,16113,16992,16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221,20222,20828,21571,22939,23502,24444,24800,25734,25735,26214,27000,27352,27353,27355,27356,27715,28201,30000,30718,30951,31038,31337,32768,32769,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,33354,33899,34571,34572,34573,35500,38292,40193,40911,41511,42510,44176,44442,44443,44501,45100,48080,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49163,49165,49167,49175,49176,49400,49999,50000,50001,50002,50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055,55056,55555,55600,56737,56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389) - -$sNet | ForEach-Object { - if ((ping "$ipcut.$_" -n 1 -w 200 |Select-String 'ms'|Out-String).Trim() -gt 10) { - $ips += "$ipcut.$_" - $discoveredhost = (((arp -a).Trim() | Select-String "$ipcut.$_ ") | Out-String).Replace('dynamic','').Replace('-',':').Replace(' ', ' - ').Replace(' ', ' - ').Replace(' ', ' - ').Trim() - Write-Host "[+]" $discoveredhost "is up!" - $hosts += $discoveredhost - } - if ($i -eq 50) { - Write-Host "[*] Scanned 50 hosts." - } - elseif ($i -eq 100) { - Write-Host "[*] Scanned 100 hosts." - } - elseif ($i -eq 150) { - Write-Host "[*] Scanned 150 hosts." - } - elseif ($i -eq 200) { - Write-Host "[*] Scanned 200 hosts." - } - $i++ -} - -$j = 0 - -Write-Host "[*] Scanned 255 hosts." -Write-Host "[*] Discovered hosts: " - -$hosts | ForEach-Object { - Write-Host " - " $hosts[$j] - $j++ -} - -Write-Host "[*] Running portscan on discovered hosts..." - -$ips | ForEach-Object { - Write-Host "[*] Scanning for open ports on $_..." - for ($port = 1 ; $port -lt 1000 ; $port++){ - $TCPClient = New-Object Net.Sockets.TCPClient - $isopen = $TCPClient.ConnectAsync("$_",$top1000[$port]).Wait(150) - if ($isopen) { - Write-Host "[+]Port " $top1000[$port] " is open on $_!" - } - $TCPClient.Dispose() - } -} -Write-Host "[+]Done!" diff --git a/src/utils/objects/utils/register-svc.ps1 b/src/utils/objects/utils/register-svc.ps1 deleted file mode 100644 index f3d9d0d6..00000000 --- a/src/utils/objects/utils/register-svc.ps1 +++ /dev/null @@ -1,67 +0,0 @@ -Param( - [parameter(Mandatory = $true)] $ManagementIP, - [ValidateSet("l2bridge", "overlay",IgnoreCase = $true)] $NetworkMode="l2bridge", - [parameter(Mandatory = $false)] $ClusterCIDR="10.244.0.0/16", - [parameter(Mandatory = $false)] $KubeDnsServiceIP="10.96.0.10", - [parameter(Mandatory = $false)] $LogDir="C:\k", - [parameter(Mandatory = $false)] $KubeletSvc="kubelet", - [parameter(Mandatory = $false)] $KubeProxySvc="kube-proxy", - [parameter(Mandatory = $false)] $FlanneldSvc="flanneld" -) - -$GithubSDNRepository = 'Microsoft/SDN' -if ((Test-Path env:GITHUB_SDN_REPOSITORY) -and ($env:GITHUB_SDN_REPOSITORY -ne '')) -{ - $GithubSDNRepository = $env:GITHUB_SDN_REPOSITORY -} - -$helper = 'c:\k\helper.psm1' -if (!(Test-Path $helper)) -{ - Start-BitsTransfer "https://raw.githubusercontent.com/$GithubSDNRepository/master/Kubernetes/windows/helper.psm1" -Destination c:\k\helper.psm1 -} -ipmo $helper - -$Hostname=$(hostname).ToLower() -$NetworkMode = $NetworkMode.ToLower() -cd c:\k - -# register flanneld -.\nssm.exe install $FlanneldSvc C:\flannel\flanneld.exe -.\nssm.exe set $FlanneldSvc AppParameters --kubeconfig-file=c:\k\config --iface=$ManagementIP --ip-masq=1 --kube-subnet-mgr=1 -.\nssm.exe set $FlanneldSvc AppEnvironmentExtra NODE_NAME=$Hostname -.\nssm.exe set $FlanneldSvc AppDirectory C:\flannel -.\nssm.exe start $FlanneldSvc - -# register kubelet -.\nssm.exe install $KubeletSvc C:\k\kubelet.exe -$kubeletOptions = Kubelet-Options $KubeDnsServiceIp $LogDir -$nssmArgs = @( - 'set' - $KubeletSvc - 'AppParameters' -) + $kubeletOptions.Options -& .\nssm.exe $nssmArgs -.\nssm.exe set $KubeletSvc AppDirectory C:\k -.\nssm.exe start $KubeletSvc - -# register kube-proxy -.\nssm.exe install $KubeProxySvc C:\k\kube-proxy.exe -.\nssm.exe set $KubeProxySvc AppDirectory c:\k - -if ($NetworkMode -eq "l2bridge") -{ - .\nssm.exe set $KubeProxySvc AppEnvironmentExtra KUBE_NETWORK=cbr0 - .\nssm.exe set $KubeProxySvc AppParameters --v=4 --proxy-mode=kernelspace --hostname-override=$Hostname --kubeconfig=c:\k\config --cluster-cidr=$ClusterCIDR --log-dir=$LogDir --logtostderr=false -} -elseif ($NetworkMode -eq "overlay") -{ - if((Test-Path c:/k/sourceVip.json)) - { - $sourceVipJSON = Get-Content sourceVip.json | ConvertFrom-Json - $sourceVip = $sourceVipJSON.ip4.ip.Split("/")[0] - } - .\nssm.exe set $KubeProxySvc AppParameters --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override=$Hostname --kubeconfig=c:\k\config --network-name=vxlan0 --source-vip=$sourceVip --enable-dsr=false --cluster-cidr=$ClusterCIDR --log-dir=$LogDir --logtostderr=false -} -.\nssm.exe set $KubeProxySvc DependOnService $KubeletSvc -.\nssm.exe start $KubeProxySvc \ No newline at end of file diff --git a/src/utils/objects/utils/start-kubelet.ps1 b/src/utils/objects/utils/start-kubelet.ps1 deleted file mode 100644 index f0ac004e..00000000 --- a/src/utils/objects/utils/start-kubelet.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -Param( - [ValidateSet("l2bridge", "overlay",IgnoreCase = $true)] [parameter(Mandatory = $true)] $NetworkMode, - [parameter(Mandatory = $false)] $KubeDnsServiceIP="10.96.0.10", - [parameter(Mandatory = $false)] $LogDir = "C:\k", - [parameter(Mandatory = $false)] $KubeletFeatureGates = "", - [switch] $RegisterOnly -) - -$GithubSDNRepository = 'Microsoft/SDN' -if ((Test-Path env:GITHUB_SDN_REPOSITORY) -and ($env:GITHUB_SDN_REPOSITORY -ne '')) -{ - $GithubSDNRepository = $env:GITHUB_SDN_REPOSITORY -} - -$helper = 'c:\k\helper.psm1' -if (!(Test-Path $helper)) -{ - Start-BitsTransfer "https://raw.githubusercontent.com/$GithubSDNRepository/master/Kubernetes/windows/helper.psm1" -Destination c:\k\helper.psm1 -} -ipmo $helper - -if ($RegisterOnly.IsPresent) -{ - RegisterNode - exit -} - -$kubeletOptions = Kubelet-Options $KubeDnsServiceIp $LogDir -if ($KubeletFeatureGates -ne "") -{ - $kubeletOptions.Options += "--feature-gates=$KubeletFeatureGates" -} - -& c:\k\kubelet.exe $kubeletOptions.Options diff --git a/src/utils/objects/utils/start-kubeproxy.ps1 b/src/utils/objects/utils/start-kubeproxy.ps1 deleted file mode 100644 index a76df61b..00000000 --- a/src/utils/objects/utils/start-kubeproxy.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -Param( - [ValidateSet("l2bridge", "overlay",IgnoreCase = $true)] [parameter(Mandatory = $true)] $NetworkMode, - [parameter(Mandatory = $true)] $NetworkName, - [parameter(Mandatory = $false)] $clusterCIDR="10.244.0.0/16", - [parameter(Mandatory = $false)] $LogDir = "C:\k" -) - -$networkName = $NetworkName.ToLower() -$networkMode = $NetworkMode.ToLower() - -ipmo c:\k\hns.psm1 -Get-HnsPolicyList | Remove-HnsPolicyList - -if ($NetworkMode -eq "l2bridge") -{ - $env:KUBE_NETWORK=$networkName - c:\k\kube-proxy.exe --v=4 --proxy-mode=kernelspace --hostname-override=$(hostname) --kubeconfig=c:\k\config --cluster-cidr=$clusterCIDR --log-dir=$LogDir --logtostderr=false -} -elseif ($NetworkMode -eq "overlay") -{ - if((Test-Path c:/k/sourceVip.json)) - { - $sourceVipJSON = Get-Content sourceVip.json | ConvertFrom-Json - $sourceVip = $sourceVipJSON.ip4.ip.Split("/")[0] - } - # Needs Kubernetes v1.14 or above. - c:\k\kube-proxy.exe --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override=$(hostname) --kubeconfig=c:\k\config --network-name=$networkName --source-vip=$sourceVip --enable-dsr=false --cluster-cidr=$clusterCIDR --log-dir=$LogDir --logtostderr=false -} \ No newline at end of file diff --git a/src/utils/objects/utils/start.ps1 b/src/utils/objects/utils/start.ps1 deleted file mode 100644 index 3c098911..00000000 --- a/src/utils/objects/utils/start.ps1 +++ /dev/null @@ -1,67 +0,0 @@ -Param( - [parameter(Mandatory = $true)] $ManagementIP, - [ValidateSet("l2bridge", "overlay",IgnoreCase = $true)] [parameter(Mandatory = $false)] $NetworkMode="l2bridge", - [parameter(Mandatory = $false)] $ClusterCIDR="10.244.0.0/16", - [parameter(Mandatory = $false)] $KubeDnsServiceIP="10.96.0.10", - [parameter(Mandatory = $false)] $ServiceCIDR="10.96.0.0/12", - [parameter(Mandatory = $false)] $InterfaceName="Ethernet", - [parameter(Mandatory = $false)] $LogDir = "C:\k", - [parameter(Mandatory = $false)] $KubeletFeatureGates = "" -) - -$BaseDir = "c:\k" -$NetworkMode = $NetworkMode.ToLower() -$NetworkName = "cbr0" - -$GithubSDNRepository = 'Microsoft/SDN' -if ((Test-Path env:GITHUB_SDN_REPOSITORY) -and ($env:GITHUB_SDN_REPOSITORY -ne '')) -{ - $GithubSDNRepository = $env:GITHUB_SDN_REPOSITORY -} - -if ($NetworkMode -eq "overlay") -{ - $NetworkName = "vxlan0" -} - -# Use helpers to setup binaries, conf files etc. -$helper = "c:\k\helper.psm1" -if (!(Test-Path $helper)) -{ - Start-BitsTransfer "https://raw.githubusercontent.com/$GithubSDNRepository/master/Kubernetes/windows/helper.psm1" -Destination c:\k\helper.psm1 -} -ipmo $helper - -$install = "c:\k\install.ps1" -if (!(Test-Path $install)) -{ - Start-BitsTransfer "https://raw.githubusercontent.com/$GithubSDNRepository/master/Kubernetes/windows/install.ps1" -Destination c:\k\install.ps1 -} - -# Download files, move them, & prepare network -powershell $install -NetworkMode "$NetworkMode" -clusterCIDR "$ClusterCIDR" -KubeDnsServiceIP "$KubeDnsServiceIP" -serviceCIDR "$ServiceCIDR" -InterfaceName "'$InterfaceName'" -LogDir "$LogDir" - -# Register node -powershell $BaseDir\start-kubelet.ps1 -RegisterOnly -NetworkMode $NetworkMode -ipmo C:\k\hns.psm1 - -# Start Infra services -# Start Flanneld -StartFlanneld -ipaddress $ManagementIP -NetworkName $NetworkName -Start-Sleep 1 -if ($NetworkMode -eq "overlay") -{ - GetSourceVip -ipAddress $ManagementIP -NetworkName $NetworkName -} - -# Start kubelet -$startKubeletArgs = "-File $BaseDir\start-kubelet.ps1 -NetworkMode $NetworkMode -KubeDnsServiceIP $KubeDnsServiceIP -LogDir $LogDir" -if ($KubeletFeatureGates -ne "") -{ - $startKubeletArgs += " -KubeletFeatureGates $KubeletFeatureGates" -} -Start powershell -ArgumentList $startKubeletArgs -Start-Sleep 10 - -# Start kube-proxy -start powershell -ArgumentList " -File $BaseDir\start-kubeproxy.ps1 -NetworkMode $NetworkMode -clusterCIDR $ClusterCIDR -NetworkName $NetworkName -LogDir $LogDir" diff --git a/src/utils/objects/utils/stop.ps1 b/src/utils/objects/utils/stop.ps1 deleted file mode 100644 index f03b68b0..00000000 --- a/src/utils/objects/utils/stop.ps1 +++ /dev/null @@ -1,4 +0,0 @@ - -taskkill /im kubelet.exe /f -taskkill /im kube-proxy.exe /f -taskkill /im flanneld.exe /f \ No newline at end of file