As part of our automated build procedure we are trashing and reconstructing our IIS site with powershell scripts.
Once i have created the AppPool and the website complete with binding information I want to set the SSL certificate for the https binding. I can't find any concrete examples onl;ine anywhere that demonstrate this.
Any ideas?
Looking for a benevolent powershell god...
You can merge previous examples with creation of an https binding in a web site.
import-module webadministration
$computerName = $Env:Computername
$domainName = $Env:UserDnsDomain
New-WebBinding -Name "MyWebSite" -IP "*" -Port 443 -Protocol https
Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -match "CN\=$Computername\.$DomainName" } | select -First 1 | New-Item IIS:\SslBindings\0.0.0.0!443
Here is how to do it simply:
First identify thecertificate that you want to assign and obtain it's thumbprint
e.g. Your certificate might be in cert:\LocalMachine\Root
You can obtain the thumbprint with the following:
$thumb = (Get-ChildItem cert:\LocalMachine\Root | where-object { $_.Subject -like "YOUR STRING HERE*" } | Select-Object -First 1).Thumbprint
<<< Now one can assign the certificate to an ip address and port comme ci >>>
$IPAddress = 101.100.1.90
$port = 443
Push-Location IIS:\SslBindings
Get-Item cert:\LocalMachine\Root\$thumb | New-Item $IPAddress!$port
Pop-Location
Hope this is of help to anyone
You can make the script simpler like this:
Get-ChildItem cert:\LocalMachine\Root | where { $_.Subject -like "YOUR STRING HERE*" } | select -First 1 | New-Item IIS:\SslBindings\0.0.0.0!443
Use 0.0.0.0 to target all hosted IP's (equivalent to "*" in IIS Manager) or replace it with a specific IP if needed.
I've found an example here on how one can assign the certificate.
http://learn.iis.net/page.aspx/491/powershell-snap-in-configuring-ssl-with-the-iis-powershell-snap-in/
However, it doesn't seem very elegant having to hard code the certificate thumbprint
... so if any one knows of a better method, I'd be glad to hear.
Related
I'm currently running a number of servers, each running NGINX used as reverse proxies to other websites. However, if I need to change a backend IP address or change other variables within NGINX, I need to manually SSH into the server and change the configurations OR log onto NGINX Proxy Manager.
What I'm looking to do is create a central website that will enable me to edit NGINX variables such as 'proxy_pass' and send the updated value to the selected remote server, updating the NGINX config and reloading the service.
Is there any current way to do this and how could I implement that? What comes to mind is some kind of CURL request to the remote server, and then I'm not sure how I'd automatically rewrite the correct portion of NGINX config etc.
Any help would be appreciated!
If you have root access on those servers, all you need is a service or a script that will fill the new values. The simplest way I see fit is to do it with a bash script and a template for the config file.
Template config file: /home/user/nginx_config/nginx.config.sample:
-- your generic config settings
proxy_pass
location /your/location {
proxy_pass {{proxy_pass}};
}
-- rest of standard file
The bash script for filling the template: /home/user/nginx_config/generator.sh
new_ip=$1
template_path="/home/user/nginx_config/nginx.config.sample"
config_path="/etc/nginx/nginx.conf"
if [[ -z $1 ]]
then echo "Missing IP param"; exit;
fi
cp "$config_path" "${config_path}.bak"
sed "s/{{proxy_pass}}/$new_ip/g" "$template_path" > "$config_path"
echo "Done! Updated $config_path file to $1:"
cat "$config_path"
Then, all you need to do is to make a local script to connect using ssh and run the generator script (with 1.2.3.4 as your new IP address)
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user#your_server "bash /home/user/nginx_config/generator.sh 1.2.3.4"
I have a website with non www url , i tried to redirect it using following steps -
For DNS i have used go daddy where
Type name value ttl
A # xx.xx.xx.xx 600 seconds
CNAME www # 1 Hour
In my Nginx configuraion i made following changes -
server {
listen 443;
server_name XAXA.com www.XAXA.com;
if ($host = XAXA.com) {
return 301 https://$host$request_uri;
}
return 404;
}
I am able to login my site with XAXA.com but whenever i try with www.XAXA.com i get - Your connection is not private
I am using let's encrypt for SSl.
The "connection is not private" warning is related to the certificate you present. Your browser is unable to verify that the certificate presented by the server is valid for www.xaxa.com
Without knowing the exact contents of your certificate I guess that your certificate doesn't have the proper Subject Alternative Name set up.
I'll be using openssl as an example of how to view contents of a certificate but you can use whatever you want.
I assume your certificate's Subject looks something like this
$ openssl s_client -connect xaxa.com:443 -showcerts | openssl x509 -subject -noout
CN = xaxa.com
This is fine and doesn't need to be changed. Depending on your browser it may not even be part of the validation process when verifying the certificate against the host.
I also assume your certificate's Subject Alternative Name looks something like this
$ openssl s_client -connect xaxa.com:443 -showcerts 2>/dev/null | openssl x509 -text -noout 2>/dev/null | grep -A 1 'Subject Alternative Name'
X509v3 Subject Alternative Name:
DNS:xaxa.com
What you want to achieve is a list in that Subject Alternative Name field:
$ openssl s_client -connect xaxa.com:443 -showcerts 2>/dev/null | openssl x509 -text -noout 2>/dev/null | grep -A 1 'Subject Alternative Name'
X509v3 Subject Alternative Name:
DNS:xaxa.com, DNS:www.xaxa.com
If you have several subdomains you could supply a wildcard value instead of www, ie. DNS:*.xaxa.com
How you actually achieve that with regards to Let's Encrypt depends on which ACME client implementation you're using.
I wrote a little ASP.NET Core 2 application. It runs as a service, so no IIS. It runs on a PC with Windows 7 SP1.
var host = WebHost.CreateDefaultBuilder(args)
.UseContentRoot(pathToContentRoot)
.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.None;
options.Authentication.AllowAnonymous = true;
options.MaxConnections = null;
options.MaxRequestBodySize = 30000000;
options.UrlPrefixes.Add("http://*:5050");
})
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
if (isService)
{
host.RunAsService();
}
else
{
host.Run();
}
As you can see, I want to listen on port 5050. This is working fine without SSL.
My question is, how can I enable https for my application? Again: No IIS, no Domain-Name (no internet connection). Communication is just inside the internal network, so I want to use a self-signed certificate.
I read the documentation (HTTP.sys documentation;Netsh Commands;New-SelfSignedCertificate), but there is always something different to my situation (they use Krestel, or it is for using IIS). Also, I dont know how to get the App-ID (needed for netsh) for my Application. I tryed this: StackOverflow Get GUID but it doesn't work.
var assembly = typeof(Program).Assembly;
// following line produces: System.IndexOutOfRangeException
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
var id = attribute.Value;
Console.WriteLine(id);
So I am a bit confused about all the possabilitys and different configurations. And the docs don't consider my specific case.
I created a certificate, and I guess I need to store it on the "my" Store. (Where is that? cert:\LocalMachine\My) And then I need to assign my Applicaion ID and Port to it.
But I have no idea how to do that exactly. Can anyone help?
So I solve the problem in the following way:
First, if you want to know your own GUID, you will get it with the following code:
var id = typeof(RuntimeEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<GuidAttribute>().Value;
Create a SelfSigned Certificate
Now create a SelfSigned-Certificate (Skip this if you already got one, or purchased one)
Run the following OpenSSL command to generate your private key and public certificate. Answer the questions and enter the Common Name when prompted.
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
Combine your key and certificate in a PKCS#12 (P12) bundle:
openssl pkcs12 -inkey key.pem -in certificate.pem -export -out certificate.p12
Install the certificate on the client:
For Windows 8 and higher:
Add Certificate to Windows Cert Store with PowerShell
PS C:> $certpwd = ConvertTo-SecureString -String "passwort" -Force –AsPlainText
PS C:> Import-PfxCertificate –FilePath D:\data\cert\certificate.p12 cert:\localMachine\my -Password $certpwd
Get Fingerprint (Hash) of certificate
PS C:\WINDOWS\system32> dir Cert:\LocalMachine\my
Install certificate (replace Hash, IP and Port with your values)
PS C:\WINDOWS\system32> $guid = [guid]::NewGuid()
PS C:\WINDOWS\system32> $certHash =
"A1D...B672E"
PS C:\WINDOWS\system32> $ip = "0.0.0.0"
PS C:\WINDOWS\system32> $port = "5050"
PS C:\WINDOWS\system32> "http add sslcert ipport=$($ip):$port
certhash=$certHash appid={$guid}" | netsh
You are done.
For Windows 7
Add Certificate to Windows Cert Store (note: use .pem file for this operation, because .p12 file seems to be not supported from certutil)
.\certutil.exe -addstore -enterprise -f "Root" C:\lwe\cert\certificate.pem
If his line throws the following error:
SSL Certificate add failed, Error 1312
A specified logon session does not exist. It may already have been terminated.
You have to do the steps manually (please insert the .p12 file when doing it manually, not .pem) :
Run mmc.exe
Go to File-> Add/Remove Snap-In
Choose the Certificates snap-in.
Select Computer Account
Navigate to: Certificates (Local Computer)\Personal\Certificates
Right click the Certificates folder and choose All Tasks -> Import.
Follow the wizard instructions to select the certificate. Be sure you check the export checkbox during wizard.
To get the hash of yor certificate, run the Internet Explorer, press Alt + X and go to Internet Options -> Content -> Certificates. Search your certificate and read the hash.
Now you can run the same commands as for Windows 8+:
Install certificate (replace Hash, IP and Port with your values)
PS C:\WINDOWS\system32> $guid = [guid]::NewGuid()
PS C:\WINDOWS\system32> $certHash =
"A1D...B672E"
PS C:\WINDOWS\system32> $ip = "0.0.0.0"
PS C:\WINDOWS\system32> $port = "5050"
PS C:\WINDOWS\system32> "http add sslcert ipport=$($ip):$port
certhash=$certHash appid={$guid}" | netsh
Edit your Code
After all, you have to set the UrlPrefixes to https. So in your Program.cs file you need to have:
var host = WebHost.CreateDefaultBuilder(args)
.UseContentRoot(pathToContentRoot)
.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.None;
options.Authentication.AllowAnonymous = true;
options.MaxConnections = null;
options.MaxRequestBodySize = 30000000;
options.UrlPrefixes.Add("https://*:5050");
})
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
I've configured on 2 servers(srv50/51),
one of them is Master and the second one is slave,
Here the configuration of my configuration file /etc/maxscale.cnf :
[Read-Only Service]
type=service
router=readconnroute
servers=server50, server51
user=YYYYYYYYYYYYY
passwd=XXXXXXXXXXXXXX
router_options=slave
[Write-Only Service]
type=service
router=readconnroute
servers=server50, server51
user=YYYYYYYYYYYYY
passwd=XXXXXXXXXXXXXX
router_options=master
[Read-Only Listener]
type=listener
service=Read-Only Service
protocol=MySQLClient
port=4008
[Write-Only Listener]
type=listener
service=Write-Only Service
protocol=MySQLClient
port=4009
As i understool the router_options look who is the master and send the writing query to the master
Maxscale (via maxadmin) seems to discover the 2 serveur and understand witch one is the Master :
MaxScale> list servers
Servers.
-------------------+-----------------+-------+-------------+--------------------
Server | Address | Port | Connections | Status
-------------------+-----------------+-------+-------------+--------------------
server51 | 192.168.0.51 | 3306 | 0 | Slave, Running
server50 | 192.168.0.50 | 3306 | 0 | Master, Running
-------------------+-----------------+-------+-------------+--------------------
But even if I connect in Mysql in local on my Maxscale Write-Only Listener port (4009), Listener are in Stopped mode, is it normal ?
MaxScale> list listeners
Listeners.
---------------------+--------------------+-----------------+-------+--------
Service Name | Protocol Module | Address | Port | State
---------------------+--------------------+-----------------+-------+--------
Read-Only Service | MySQLClient | * | 4008 | Stopped
Write-Only Service | MySQLClient | * | 4009 | Stopped
MaxAdmin Service | maxscaled | * | 6603 | Running
---------------------+--------------------+-----------------+-------+--------
I've try to create a database in srv51 (slave), and it was created only on srv51, not in srv50.
Is something wrong in my configuration ? It's strange because it's not my first cluster, and on other cluster all write go to the master (but listeners are Running). Do i don't understand well the meaning of "router_options=master" ? How to start listeners ? I prefere to keep the 51 in Write list to detect topology change
===== UPDATE =====
After watching Log file /var/log/maxscale/maxscale1.log
I found that my monitor user didn't have the correct password :
[MySQL Monitor]
type=monitor
module=mysqlmon
servers=server50, server51
user=MONITOR
passwd=MONITOR_PASS
monitor_interval=10000
I corrected password for user and restarted maxscale, Now everything is running :
MaxScale> list listeners
Listeners.
---------------------+--------------------+-----------------+-------+--------
Service Name | Protocol Module | Address | Port | State
---------------------+--------------------+-----------------+-------+--------
Read-Only Service | MySQLClient | * | 4008 | Running
Write-Only Service | MySQLClient | * | 4009 | Running
MaxAdmin Service | maxscaled | * | 6603 | Running
---------------------+--------------------+-----------------+-------+--------
But write query are still done on Slave and not on Master
Thanks to MariaDb support, I was trying to connect like this :
mysql -h localhost --port=4009 -u USER -p
But Maxscale & Mysql were installed in the same server, even if Mysql bind port 3306, when you specify 'localhost', the connection is done on Mysql port 3306 and not in Maxscale port 4009, the port is ignore !!
The solution is to connect like this :
mysql -h 127.0.0.1 --port=4009 -u USER -p
or like this :
mysql -h localhost --protocol=tcp --port=4009 -u USER -p
I've try both solution and they works.
The solution about the listener not Running is on update of the question.
If writes are done on the slaves, the simplest explanation would be that you're executing writes on the wrong port or your configuration is wrong. To diagnose these problems, enable the info log level by adding log_info=true under the [maxscale] section.
If enabling the info log and inspecting the log files does not provide any clues, I'd suggest opening a bug report on the Maxscale Jira.
I have to deploy a few sites using TFS Release Management Client, all of them in them same machine so same IIS. They will be all on port 80 but the requests are served for different host names (domains).
Using IISConfig tool, it is possible to change the port but not the host name, do you know a quick way already implemented to achieve that without creating a custom tool?
As confirmed here, it is not possible but if you scroll down there is a suggestion how to quickly work around the limitation.
Creating 2 actions
-Command "& { Import-Module WebAdministration; New-WebBinding -Name '__Name__' -IPAddress '__IPAddress__' -Port '__Port__' -HostHeader '__HostHeader__' }"
and
-Command "& { Import-Module WebAdministration; Remove-WebBinding -Name '__Name__' -IPAddress '__IPAddress__' -Port '__Port__' -HostHeader '__HostHeader__' } "