# Purpose We're going to be looking at how to create a server setup file that doesn't trigger any prompts that aren't user friendly. This setup file will contain another signed file that will launch a basic web server. The setup file will create the server file and a firewall rule for the server file. We will be building two files (`setup.go` and `server.go`) separately . # The Server File We're creating our web server file, building it and signing the application. ## Creating the Server File Create a file named `server.go` and add the following: ``` //go:generate goversioninfo package main import ( "flag" "log" "net/http" ) func main() { port := flag.String("p", "8100", "port to serve on") directory := flag.String("d", ".", "the directory of static file to host") flag.Parse() http.Handle("/", http.FileServer(http.Dir(*directory))) log.Printf("Serving %s on HTTP port: %s\n", *directory, *port) log.Fatal(http.ListenAndServe(":"+*port, nil)) } ``` *Windows 10 will happily create server.go.txt if you don't turn off hidden file extensions and leave you wondering what's wrong with your Go install.* First of all, you'll want to install Golang: https://golang.org/dl/ Then you'll want to install [goversioninfo](https://github.com/josephspurrier/goversioninfo) by running the following in a command prompt: ``` go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo ``` This will allow us to set the name of the program, version, publisher name, etc. ``` # Add this to the top of your server go file. //go:generate goversioninfo # Then generate the configuration by running the following in a command prompt: go generate ``` This will create a configuration file named `versioninfo.json` in the current directory. There are three things you will want to edit: 1. The version of the application, 2. The "publisher" or company name and 3. The product name. ![](versioninfo.png) Near the top of the file, you will see `FileVersion` and `ProductVersion`. You can set normal major, minor, patch and build versions for those values. The `FileVersion` is the version of the file and `ProductVersion` is the version of the application as a whole. You can most likely use the same version for both unless you're doing something unusual. You will set the same values again under `StringFileInfo`. Next, you can set the "publisher name" by filling in the `CompanyName` value with the name of your organization. Lastly, you can give your application a name, like "Go Web Server" under the `ProductName` value. ``` # Next, build your server app. go build ``` You will want to sign your application, the next section will show you how. ## Signing the Setup File ### Getting a Code Signing Certificate Be aware that you will likely need to create a Dun & Bradstreet listing to get an "organization" code-signing certificate: https://www.dandb.com/businessdirectory/products/ (this is free) You can purchase a code-signing certificate here: https://cheapsslsecurity.com/comodo/codesigningcertificate.html The validation process will take 1-3 business days if your information is correct and you give them your D-U-N-S (Dun & Bradstreet) number. After you receive an email containing a link to the certificate, follow these directions in the **exact same** browser as the one you used to request the certificate : https://cheapsslsecurity.com/downloads.aspx?ispdf=true&iscs=true&filenm=Comodo_Code_Signing_Collection_Guide.pdf ### Signing the File [Screenshot] Next, you will need to install Visual Studio. You can download Visual Studio here: https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=16 In the install process, you will be greeted with this screen: ![](windowsdev.png) Choose the "Universal Windows Platform Development" workload. After you have finished installing Visual Studio, open a "Developer Command Prompt for VS". ![](developerprompt.png) ``` # Sign a file with your certificate. SignTool sign /t http://timestamp.comodoca.com /f codesigning.p12 /p file.exe ``` ![](signfile.png) You should see something like this: ![](donesigning.png) # The Setup File Now we're going to create the setup file that will create the firewall rule we need and "create" the server file for us. ## Firewall Rule We are using Powershell to create the firewall rule, so we're going to install `go-powershell`. ``` # Install go-powershell go get github.com/aquasecurity/go-powershell ``` Create a file named `setup.go` and include the following: ``` //go:generate goversioninfo -manifest=setup.exe.manifest //Add a new firewall rule in Go. package main import ( "os" "fmt" "log" "static" // Create fileb0x before this will work. "io/ioutil" ps "github.com/aquasecurity/go-powershell" "github.com/aquasecurity/go-powershell/backend" ) func main() { // Grab files from virtual filesystem files, err := static.WalkDirs("", false) if err != nil { log.Fatal(err) log.Println("ALL FILES", files) } // here we'll read the file from the virtual file system b, err := static.ReadFile("server.exe") if err != nil { log.Fatal(err) } // Copy file from virtual filesystem to real filesystem err = ioutil.WriteFile("server.exe", b, 0644) if err != nil { fmt.Println("Error creating", "server.exe") fmt.Println(err) return } // choose a backend back := &backend.Local{} // start a local powershell process shell, err := ps.New(back) if err != nil { panic(err) } defer shell.Exit() // Set 'dir' to the current working directory. dir, err := os.Getwd() if err != nil { log.Fatal(err) } // Create the correct Poweshell rule with the working directory from 'dir' var cmd string = "-WindowStyle Hidden New-NetFirewallRule -DisplayName 'Name of Rule' -Direction Inbound -Program '" + dir + "\\server.exe' -Action Allow > NULL" // Run the command. stdout, stderr, err := shell.Execute(cmd) if err != nil { panic(err) fmt.Println(stderr) } fmt.Println(stdout) } ``` Then create another file called `setup.exe.manifest` containing: ``` ``` Rename `server.go` to `server.go_` ``` # Build the setup application. go build -o setup.exe -ldflags "-s -w -H=windowsgui" ``` ## Put Server File In Setup File fileb0x